fix: Mejoras en generación de PDFs y resúmenes

- Corrige PDFGenerator para pasar contenido (no ruta)
- Agrega prompt siguiendo código.md (español, estructura académica)
- Limpia thinking tokens de respuesta AI
- Agrega skip de archivos ya procesados en watcher
- Implementa tablas LaTeX en PDFs (reportlab Table)
- Agrega load_dotenv() en main.py
- Actualiza .env con MiniMax config
- Agrega transcriptions/ a .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
renato97
2026-02-25 17:12:00 +00:00
parent ee8fc183be
commit 1f6bfa771b
5 changed files with 207 additions and 11 deletions

View File

@@ -69,8 +69,39 @@ class AISummaryService:
logger.debug("AISummaryService not configured, returning original text")
return text
default_prompt = "Resume el siguiente texto de manera clara y concisa:"
prompt = prompt_template.format(text=text) if prompt_template else f"{default_prompt}\n\n{text}"
# Prompt siguiendo código.md - resumen académico en español
default_prompt = """Eres un asistente académico especializado en crear resúmenes de estudio de alta calidad.
INSTRUCCIONES OBLIGATORIAS:
1. Escribe ÚNICAMENTE en español
2. El resumen debe seguir esta estructura:
- Título y objetivo de estudio
- Índice con 6-12 secciones
- Desarrollo conceptual (definiciones, mecanismos)
- Casos de aplicación (ejemplos concretos)
- Errores frecuentes
- Checklist de repaso
3. Cada concepto debe explicar: qué es, por qué importa, cómo se aplica
4. Evita listas sin explicación - siempre incluir el "por qué"
5. Para TABLAS usa formato LaTeX tabular:
\\begin{{tabular}}{{|c|l|l|}}
\\hline
Encabezado 1 & Encabezado 2 & Encabezado 3 \\\\
\\hline
dato1 & dato2 & dato3 \\\\
\\hline
\\end{{tabular}}
6. NO uses tablas ASCII ni markdown con | pipes
7. El resumen debe poder leerse en 15-25 minutos
8. NO incluyas rutas de archivos ni referencias técnicas
9. Sé conciso pero con densidad informativa útil para exámenes
Transcripción de clase:
{text}
Genera el resumen siguiendo las instrucciones arriba."""
prompt = prompt_template.format(text=text) if prompt_template else default_prompt.format(text=text)
payload = {
"model": self.model,
@@ -96,6 +127,29 @@ class AISummaryService:
result = response.json()
summary = result.get("choices", [{}])[0].get("message", {}).get("content", "")
# Limpiar respuesta: eliminar thinking tokens y ruido
# Buscar el primer encabezado markdown y cortar ahí
first_header = summary.find("\n# ")
if first_header == -1:
first_header = summary.find("# ")
if first_header > 0:
summary = summary[first_header:]
# Eliminar bloques de think/error si persisten
lines = summary.split("\n")
clean_lines = []
skip = False
for line in lines:
if line.strip().startswith("<think>") or line.strip().endswith("</think>"):
skip = True
continue
if skip and line.strip() and not line.startswith(" "):
skip = False
if not skip:
clean_lines.append(line)
summary = "\n".join(clean_lines)
logger.info("Summarization completed successfully (output length: %d)", len(summary))
return summary