Producto derivado del piloto BIREME–INFOMED. Versión actual: 0.11.0 (flujo completo desde PDF: OCR híbrido con segmentación + resumen jerárquico con coexistencia de estrategias + QA + export LILACS + API).
🚀 Guía rápida de uso (1 página, con ejemplos ejecutables):
GUIA-USO.md
Un módulo Python que convierte el texto de un documento (ya transcrito) en un resumen estructurado conforme a un contrato JSON estable, eligiendo la plantilla según el tipo de documento y respondiendo en el idioma del documento, preservando los resúmenes de origen multilingües verbatim.
src/pdfsum/
contract.py # DOMINIO: tipos + PUERTOS Summarizer/Transcriber + contrato JSON
classify.py # DOMINIO: origen (nativo/escaneado), idioma, tipo -> plantilla
templates.py # DOMINIO: plantillas A (artículo/IMRAD), B (manual), C (folleto)
abstracts.py # DOMINIO: extracción verbatim de RESUMO/ABSTRACT/RESUMEN...
excerpt.py # DOMINIO: estrategia de porción por tipo (no corte ciego)
pipeline.py # DOMINIO: orquesta clasificación + porción + resumen + abstracts
adapters/ # EXTERNO: Ollama, OCR (poppler+Tesseract), fakes para tests
cli.py # CLI
Regla de dependencia: el dominio no importa adaptadores (verificado por
test_architecture.py vía AST). Cambiar de modelo local a cloud = nuevo
adaptador, sin tocar el núcleo.
IMPORTANTE: pdfsum requiere un Summarizer configurado. Elige UNO:
Requisitos hardware:
- GPU ≥ 8 GB VRAM (ej: RTX 5060, RTX 4060, etc.)
- Ollama instalado y ejecutándose:
ollama serve - Modelos descargados:
ollama pull qwen2.5:7b # ~6.3 GB (esencial) ollama pull qwen3-vl:8b-instruct # ~8.8 GB (opcional, para OCR)
Ventajas:
- ✅ Sin costo de API
- ✅ Privacidad total (datos locales)
- ✅ Rápido (si GPU buena)
- ✅ Sin internet requerido para procesamiento
Desventajas:
- ❌ Inversión en hardware GPU
- ❌ Modelos ocupan 6-9 GB en disco
Requisitos:
- API key del proveedor elegido, en variable de entorno (nunca en
.pdfsum-config.json):OPENAI_API_KEY/OPENROUTER_API_KEY/ANTHROPIC_API_KEY. - Conexión a internet.
Configuración rápida:
export PDFSUM_SUMMARIZER_BACKEND="openrouter" # openai | openrouter | anthropic
export OPENROUTER_API_KEY="sk-or-..."
pdfsum doctor # confirma backend + API key configuradaDefault por proveedor — openrouter usa qwen/qwen-2.5-7b-instruct (el
mismo peso abierto que Ollama local, corriendo en la nube);
openai/anthropic no hostean Qwen, usan gpt-4o-mini/claude-haiku-4-5
por defecto. Cualquiera es overrideable con --model/cloud_model.
Ventajas:
- ✅ No requiere GPU
- ✅ Modelos de última generación (o los mismos pesos abiertos, vía OpenRouter)
- ✅ Sin mantenimiento de modelos
Desventajas:
- ❌ Costo por uso (más caro)
- ❌ Datos salen a internet
- ❌ Latencia de red
👉 Ver INSTALL.md Sección 2 para configuración detallada
pip install pdfsum
pdfsum --help
pdfsum doctorgit clone https://github.com/idourra/pdf-summarizer.git && cd pdf-summarizer
uv sync # crea .venv + instala (determinista vía uv.lock)
uv run pdfsum doctor # REQUIERE: Ollama corriendo O servicios remotos configurados
uv run pdfsum verify # confirma resultados sobre la muestra incluida
uves la vía recomendada para desarrollo: instalación ~1-2s (vs 30-60s con pip) y reproducibilidad garantizada poruv.lock.
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
pdfsum doctor
pdfsum verifyMás rápido — wrapper que arma el docker run largo por ti:
bin/pdfsum-docker doctor
bin/pdfsum-docker run --in ./mis_pdfs --workspace ./data --lang porO manual:
docker build -t pdfsum .
docker run --rm pdfsum pdfsum doctor
# Modo A (default, sin GPU passthrough): usa un Ollama ya corriendo en el host
cp .env.example .env && docker compose up --build
# Modo B (bundled, requiere GPU + NVIDIA Container Toolkit):
echo 'OLLAMA_HOST=http://ollama:11434' > .env
docker compose --profile gpu up --build
# Modo C (cloud puro, sin Ollama en absoluto):
printf 'PDFSUM_SUMMARIZER_BACKEND=openrouter\nOPENROUTER_API_KEY=sk-or-...\n' > .env
docker compose up --buildLos tres modos son configurables vía .env (OLLAMA_HOST o
PDFSUM_SUMMARIZER_BACKEND+API key) sin tocar
compose.yml; el servicio ollama embebido (con GPU) es opt-in detrás de
--profile gpu, nunca obligatorio. Detalle completo (incluye el fix de la
dependencia Pillow para el fallback de OCR por región) →
INSTALL.md Sección 10.
pdfsum doctor dice "XX ollama: no encontrado"
→ Configura un backend cloud (env var + opcionalmente .pdfsum-config.json, Opción B arriba)
Guía completa (requisitos de sistema, modelos, troubleshooting):
→ INSTALL.md Sección 2 (Modelos Local vs Remoto)
# FLUJO COMPLETO desde PDFs (la fuente): transcribe (OCR) + resume + report
# Requiere poppler + tesseract (OCR) y Ollama + qwen2.5:7b (resumen).
uv run pdfsum run --in ./pdfs --workspace ./data --lang por
# -> ./data/ocr/<doc_id>.txt (transcripciones cacheadas)
# -> ./data/summaries/<doc_id>.json (resúmenes + _qa)
# -> ./data/summaries/report.json (métricas del lote)
# solo transcribir (PDF -> ocr/*.txt), sin resumir
uv run pdfsum transcribe --in ./pdfs --workspace ./data
# resumen de un texto ya transcrito (paso 2 aislado)
uv run pdfsum summarize --text transcripcion.txt --pages 4 --out resumen.json
# dry-run sin modelo (contrato + clasificación, para probar el flujo)
uv run pdfsum summarize --text transcripcion.txt --dry-run
# lote: directorio de .txt con cola idempotente + QA gates
uv run pdfsum batch --in ./_ocr_out --out ./_resumenes
# -> un .json por doc (con bloque _qa) + report.json (métricas del lote)
# export a registros LILACS (borrador para revisión humana)
uv run pdfsum export --in ./_resumenes --out lilacs.json
# registros bibliográficos BIBFRAME (JSON-LD), uno por documento/PDF
# (metadata embebida del PDF con precedencia si pasas --pdfs; borrador)
uv run pdfsum bibframe --in ./_resumenes --pdfs ./mis_pdfs --out ./_bibframe
# API de consulta local (solo lectura) sobre el lote
uv run pdfsum serve --batch-dir ./_resumenes --port 8765
# GET /api/summaries | /api/summaries/<doc_id> | /api/reportSalida: JSON con doc_id, idioma_principal, tipo_documento, plantilla,
secciones, idiomas_resumo_origem, abstracts_origem, meta.
El report.json incluye report_version, fecha UTC de generación y unidad de
duración. Cada entrada de documents informa tiempo_total y
tiempos_por_fase; en metrics, tiempo_total_por_fase y
tiempo_medio_por_fase permiten comparar los cuellos de botella del lote. El
flujo PDF mide transcripcion, lectura_ocr, resumen, qa y
escritura_resultado, e indica con transcription_cached si reutilizó OCR. El
lote de textos mide lectura_texto, cola, resumen, qa y
escritura_resultado, e indica con cache_hit si reutilizó el resultado.
Los comandos run y batch mantienen tres archivos de observabilidad en el
directorio del reporte:
events.jsonl: eventos append-only conrun_id, documento, fase, error y estado. Cada línea se vacía y sincroniza inmediatamente en disco.infrastructure.jsonl: muestras periódicas de CPU, RAM, carga, swap, disco, temperatura del host y aceleradores. Consulta/api/psdel Ollama para registrar modelos cargados, contexto y VRAM asignada aunque Ollama esté en otro contenedor; sinvidia-smiestá disponible, añade por GPU utilización, VRAM, temperatura, potencia, ventilador, clocks y throttling.report.json: checkpoint atómico actualizado al comenzar el lote y después de cada documento.progressmuestra descubiertos, concluidos, fallidos y pendientes;infrastructureresume picos y mínimos de la ejecución.
Una falla en un documento queda registrada y no detiene los documentos
siguientes. Ante interrupción normal, el reporte queda con estado
interrupted; ante una caída abrupta, incluso SIGKILL, queda disponible el
último checkpoint ya sincronizado, además de los eventos anteriores. Como
ningún software puede ejecutar después de una pérdida total de energía, el
documento que estaba en curso puede aparecer solo como document_started;
todos los que ya emitieron document_completed permanecen confirmados.
En Docker, la VRAM de Ollama se observa automáticamente mediante OLLAMA_HOST.
Para permitir también las métricas físicas de NVIDIA dentro de pdfsum, usa el
override opt-in (requiere NVIDIA Container Toolkit):
docker compose -f compose.yml -f compose.gpu-observability.yml \
--profile gpu up --buildSin ese override, el reporte indica nvidia_smi_available: false, pero conserva
las métricas del host y la VRAM comunicada por Ollama. La consulta a /api/ps
se puede desactivar con PDFSUM_OLLAMA_METRICS=0.
Semantic Versioning (MAJOR.MINOR.PATCH):
| Cambio | Ejemplo |
|---|---|
MAJOR |
Cambio incompatible en el contrato JSON de salida |
MINOR |
Nueva fase/capacidad compatible (p. ej. 0.9 → 0.10 = resumen jerárquico) |
PATCH |
Correcciones sin cambio de contrato (p. ej. 0.11.0 → 0.11.1 = fix dependencia dev) |
Historial completo en CHANGELOG.md. Cada versión integrada
se marca con git tag -a vX.Y.Z.
make lint # ruff
make test # unittest (criterios del eval-spec)
make check # lint + test- Fase 0 (motor): ✅ completada — 11/11 criterios
(
evals/eval-spec-fase0-motor.yaml). - Fase 1 (enrutado inteligente): ✅ completada — 12/12 criterios
(
evals/eval-spec-fase1-enrutado.yaml). Estrategia de porción por tipo (artículo: abstract+intro+conclusiones; manual: portada+índice+intro; folleto: completo) + puertoTranscribercon adaptador OCR (poppler+Tesseract). Resuelve el truncado de manuales largos del piloto. - Fase 2 (operación por lotes): ✅ completada — 13/13 criterios
(
evals/eval-spec-fase2-lotes.yaml). Cola idempotente con reintentos, QA gates automáticos (esquema/refusal/idioma/abstracts), métricas yreport.json. CLIpdfsum batch. - Fase 3 (interfaz): ✅ completada — 13/13 criterios
(
evals/eval-spec-fase3-interfaz.yaml). Flujo de revisión, export LILACS (borrador) y API de consulta local. CLIpdfsum export/pdfsum serve. - Fase 4 (mejora continua): ✅ completada — 12/12 criterios
(
evals/eval-spec-fase4-mejora.yaml). Resumen por bloques (documentos gigantes completos) + set de control con métricas de cobertura. - Fase 10 (resumen jerárquico por capítulos): ✅ completada — 12/12
criterios (
evals/eval-spec-fase10-resumen-jerarquico-capitulos.yaml). Estrategia--long-strategy hierarchicalpara libros/documentos largos (detección de capítulos + resumen y consolidación por capítulo). - Fase 11 (migración a uv): ✅ completada (
evals/eval-spec-fase11-migracion-uv.yaml). Gestor de dependencias moderno,uv.lockpara reproducibilidad. - Fase 12 (distribución moderna): ✅ completada
(
evals/eval-spec-fase12-distribucion-moderna-uv.yaml). Backendhatchling,uv buildgenera wheel/sdist, publicación en PyPI (pip install pdfsum). - Ver
docs/ESTADO.mdydocs/PROPUESTA-PRODUCTO.md.