feat: Sistema LaTeX mejorado con sanitización automática y corrección de TikZ

Cambios principales:

## Nuevos archivos
- services/ai/parallel_provider.py: Ejecución paralela de múltiples proveedores AI
- services/ai/prompt_manager.py: Gestión centralizada de prompts (resumen.md como fuente)
- latex/resumen.md: Template del prompt para resúmenes académicos LaTeX

## Mejoras en generación LaTeX (document/generators.py)
- Nueva función _sanitize_latex(): Corrige automáticamente errores comunes de AI
  - Agrega align=center a nodos TikZ con saltos de línea (\\)
  - Previene errores 'Not allowed in LR mode' antes de compilar
- Soporte para procesamiento paralelo de proveedores AI
- Conversión DOCX en paralelo con generación PDF
- Uploads a Notion en background (non-blocking)
- Callbacks de notificación para progreso en Telegram

## Mejoras en proveedores AI
- claude_provider.py: fix_latex() con instrucciones específicas para errores TikZ
- gemini_provider.py: fix_latex() mejorado + rate limiting + circuit breaker
- provider_factory.py: Soporte para parallel provider

## Otros cambios
- config/settings.py: Nuevas configuraciones para Gemini models
- services/webdav_service.py: Mejoras en manejo de conexión
- .gitignore: Ignora archivos LaTeX auxiliares (.aux, .toc, .out, .pdf)

## Archivos de ejemplo
- latex/imperio_romano.tex, latex/clase_revolucion_rusa_crisis_30.tex
- resumen_curiosidades.tex (corregido y compilado exitosamente)
This commit is contained in:
renato97
2026-02-07 20:50:27 +00:00
parent 915f827305
commit dcf887c510
15 changed files with 4309 additions and 409 deletions

32
main.py
View File

@@ -407,9 +407,11 @@ def run_main_loop() -> None:
# Step 3: Generate AI summary and documents
telegram_service.send_message(
f"🤖 Generando resumen con IA..."
f"🤖 Generando resumen académico LaTeX..."
)
doc_generator = DocumentGenerator(
notification_callback=lambda msg: telegram_service.send_message(msg)
)
doc_generator = DocumentGenerator()
success, summary, output_files = (
doc_generator.generate_summary(
transcription_text, base_name
@@ -428,13 +430,13 @@ def run_main_loop() -> None:
except Exception:
pass
# Upload all files in parallel using batch upload
upload_tasks = []
# Upload transcription TXT
if transcription_file.exists():
remote_txt = f"{settings.RESUMENES_FOLDER}/{transcription_file.name}"
webdav_service.upload(
transcription_file, remote_txt
)
logger.info(f"Uploaded: {remote_txt}")
upload_tasks.append((transcription_file, remote_txt))
# Upload DOCX
docx_path = Path(
@@ -442,10 +444,7 @@ def run_main_loop() -> None:
)
if docx_path.exists():
remote_docx = f"{settings.DOCX_FOLDER}/{docx_path.name}"
webdav_service.upload(
docx_path, remote_docx
)
logger.info(f"Uploaded: {remote_docx}")
upload_tasks.append((docx_path, remote_docx))
# Upload PDF
pdf_path = Path(
@@ -453,8 +452,7 @@ def run_main_loop() -> None:
)
if pdf_path.exists():
remote_pdf = f"{settings.DOCX_FOLDER}/{pdf_path.name}"
webdav_service.upload(pdf_path, remote_pdf)
logger.info(f"Uploaded: {remote_pdf}")
upload_tasks.append((pdf_path, remote_pdf))
# Upload Markdown
md_path = Path(
@@ -462,8 +460,14 @@ def run_main_loop() -> None:
)
if md_path.exists():
remote_md = f"{settings.RESUMENES_FOLDER}/{md_path.name}"
webdav_service.upload(md_path, remote_md)
logger.info(f"Uploaded: {remote_md}")
upload_tasks.append((md_path, remote_md))
# Execute parallel uploads
if upload_tasks:
upload_results = webdav_service.upload_batch(
upload_tasks, max_workers=4, timeout=120
)
logger.info(f"Parallel upload complete: {len(upload_results)} files")
# Final notification
telegram_service.send_message(