feat: Add .env.example configuration file and integrate Redis service into Docker Compose for improved task management. Update desktop application to support document indexing and extraction workflows, enhancing user experience with a new extraction wizard and stepper components. Revise README and documentation for clarity on setup and usage.

This commit is contained in:
erik
2026-07-05 22:39:07 -05:00
parent 9aca926988
commit d95f8f6ad8
70 changed files with 9807 additions and 499 deletions
+54
View File
@@ -110,6 +110,60 @@ class Estimator:
def _accumulate_usage(self, agg, new_usage):
accumulate_usage(agg, new_usage)
def estimate_from_file(
self,
file_path: str,
doc_count: int = 1,
selected_paths: Optional[List[str]] = None,
tiff_page_range: Optional[tuple] = None,
model: Optional[str] = None,
) -> Dict[str, Any]:
"""Estima tokens y costos procesando un único archivo subido desde el cliente.
Si `model` se especifica y es distinto al modelo actual del extractor,
crea un extractor temporal con ese modelo para obtener el uso real de tokens.
"""
from api.desktop_ingest import _service_for_model
service = _service_for_model(self.service, model)
prof = get_profile('invoice')
paths = selected_paths or []
prompt = PromptBuilder.build(paths, {}, profile_name=prof.get('name', 'invoice'))
data, usage_ext = service.extract_full_from_pdf(
file_path,
instruction=prompt,
tiff_page_range=tiff_page_range,
)
if isinstance(data, dict):
data['radicado'] = 'sample'
else:
data = {"radicado": 'sample', "data": data}
norm = normalize_to_schema(data, paths=paths, profile_name=prof.get('name', 'invoice'))
usage_norm = None
if isinstance(norm, dict):
usage_norm = norm.get("_usage")
result = self._build_result(usage_ext, usage_norm, doc_count, 'sample')
# Enriquecer con modelo efectivo y conteo de páginas para el frontend
effective_model = model or getattr(service.extractor, 'model', None) or getattr(self.service.extractor, 'model', None)
result['extractor_model'] = effective_model
result['normalizer_model'] = settings.api.normalizer_model or 'gpt-5.4-mini'
# Estimar numero de paginas a partir de prompt_tokens de imagen:
# GPT-4o cobra ~85 tok base + ~170 tok por tile 512x512.
# Una A4 a 150 DPI (~1240x1754) genera ~6 tiles → ~1105 tokens.
# Aproximamos: pages = max(1, round(image_tokens / 1000))
prompt_tokens = int((usage_ext or {}).get('prompt_tokens') or 0)
text_prompt_est = len(prompt) // 4 # 1 token ≈ 4 chars
image_tokens_est = max(0, prompt_tokens - text_prompt_est)
pages_est = max(1, round(image_tokens_est / 1000))
result['pages_per_doc'] = pages_est
return result
def _build_result(self, usage_ext, usage_norm, total_docs, first_radicado):
model_ext = getattr(self.service.extractor, "model", None)
cost_ext = compute_cost_from_usage(usage_ext, "extract", model=model_ext)