Especificación de Proyecto — dashboar_faq.php

Generación de FAQs basadas en el campo manual (HTML) de cursos_sence usando Gemini, con inserción inmediata en faq_preguntas.
Sin codificar Listo para implementación Minimiza llamadas a la API Inserción inmediata

Índice

1) Objetivo

Construir un script dashboar_faq.php que, dado curso_id por GET, lea el campo manual (HTML) desde cursos_sence, genere al menos $cant_pre pares Pregunta/Respuesta (P/R) con ayuda de Gemini y los inserte inmediatamente en faq_preguntas, minimizando el número de llamadas a la API y el impacto al servidor.

2) Alcance

3) Entorno y prerrequisitos

3.1 Includes existentes

  • Conexión MySQL: include("include/conecta_mysql_otec.php") → objeto $mysqli.
  • Gemini Keys/Modelo: include('include/key_geminis.inc') con:
    if (function_exists('opcache_reset')) { opcache_reset(); }
    define('GEMINI_MODEL', 'gemini-2.5-flash');
    define('GOOGLE_AI_API_KEY', 'clave KEY');
    define('GOOGLE_AI_API_URL', 'https://generativelanguage.googleapis.com/v1beta/models/' . GEMINI_MODEL . ':generateContent?key=' . GOOGLE_AI_API_KEY);
    define('IA_LOG_FILE', __DIR__ . '/peticiones_ia.log');
  • Directorio: todos los archivos del proyecto residen en el mismo directorio que dashboar_faq.php.

3.2 Tablas implicadas

  • cursos_sence: contiene campo manual (HTML) asociado al curso.
  • faq_preguntas: tabla de destino para P/R.
    Ver supuestos de campos en Anexo.

4) Parámetros de configuración

5) Flujo end-to-end

  1. Entrada:
    • Parámetros vía $_GET: curso_id (int obligatorio).
    • Parámetros de configuración (sección 4) con valores por defecto si no provienen de GET.
  2. Lectura del manual:
    • Consulta: SELECT manual FROM cursos_sence WHERE id = ?. Si no existe o vacío, finalizar con mensaje claro y log.
    • El valor de manual es HTML.
  3. Limpieza/Normalización HTML:
    • Eliminar <script>, <style>, atributos peligrosos.
    • Convertir a texto estructurado:
      • H1/H2/H3 → líneas con prefijos #, ##, ###.
      • Listas → prefijos -
      • Conservar títulos y listas para guiar a la IA.
    • Partir en chunks de ~$chunk_len respetando límites naturales (cortes en H2/H3 idealmente).
    • Generar un extracto-esqueleto inicial (titulares y párrafos intro) para la llamada 1.
  4. Llamada 1 (Índice/Mapa temático):
    • Objetivo: 6–8 temas con subtemas y qas_deseadas por subtema que sumen ~$cant_pre + 10%.
    • Entrada: extracto del manual + reglas de salida JSON (ver Prompts).
    • Salida: JSON con temas[]/subtemas[]/total_qas_sugeridas.
  5. Llamadas 2..N (Generación de Q/A en lotes):
    • Agrupar 2–3 subtemas por request y pedir ~$lote_qas Q/A por llamada (JSONL).
    • Para cada request, adjuntar solo los chunks relevantes.
    • Iterar hasta alcanzar $cant_pre o agotar subtemas.
  6. Parseo y validación:
    • Leer JSONL línea a línea. Ignorar vacías. Validar presencia de pregunta, respuesta.
    • Aplicar límites de longitud según $cant_car_pre y $cant_car_res (recortar si es seguro o descartar).
    • Normalizar y preparar para deduplicación/inserción.
  7. Deduplicación (sin cambiar esquema):
    • Cargar set de preguntas existentes (normalizadas) para el curso_id actual.
    • Descartar entradas nuevas cuya pregunta normalizada ya exista en BD o se repita en el lote actual.
  8. Inserción inmediata:
    • Determinar orden_base = COALESCE(MAX(orden),0) para el curso.
    • Insertar por lotes (por ejemplo, 10–25 filas) en transacción.
    • Campos/valores:
      • curso_id: el recibido por GET.
      • pregunta, respuesta: desde IA (limpias).
      • categoria, palabras_clave: propuestos por IA (si faltan, usar tema/subtema).
      • orden: incremental desde orden_base + 1.
      • estado: activo.
      • fecha_creacion: NOW().
    • Guardar los IDs insertados de esta corrida para mostrarlos luego.
  9. Corte por objetivo:
    • Detener cuando se alcance $cant_pre P/R válidas insertadas.
    • Si el último lote sobrepasa, insertar solo lo necesario para completar la meta.
  10. Salida:
    • Resumen de la ejecución.
    • Listado (tabla) con las P/R recién insertadas (IDs de esta ejecución), incluyendo orden, categoria, palabras_clave.

6) Diseño de prompts (IA)

6.1 Instrucción de sistema (común)

Eres un asistente experto en construir FAQs basadas exclusivamente en el contenido proporcionado.
Si una respuesta no está sustentada por el documento, omítela.
Respeta estrictamente el formato solicitado (JSON o JSONL) sin agregar texto adicional ni comentarios.

6.2 Llamada 1 — Índice/Mapa temático (salida JSON)

Objetivo: Devolver un plan de cobertura que sume ~$cant_pre (+10%) Q/A.

INPUT:
- Extracto del manual (HTML ya simplificado a texto con títulos/listas).
- Cantidad objetivo aproximada: $cant_pre (+10% margen).
- Reglas:
  • 6–8 temas principales.
  • Cada tema con subtemas. Cada subtema con "qas_deseadas" (número).
  • Evitar redundancias. Priorizar secciones más densas/relevantes.
  • Salida estricta JSON con la forma:

{
  "temas": [
    {
      "nombre": "Tema 1",
      "subtemas": [
        {"nombre": "Subtema 1.1", "qas_deseadas": 5},
        {"nombre": "Subtema 1.2", "qas_deseadas": 4}
      ]
    }
  ],
  "total_qas_sugeridas": 64
}

OUTPUT:
- Solo JSON válido como el ejemplo de arriba.
      

6.3 Llamadas 2..N — Generación de Q/A (salida JSONL)

Objetivo: Generar ~$lote_qas Q/A por llamada hasta completar $cant_pre.

INPUT:
- Subconjunto del índice (ej. 2–3 subtemas objetivo en esta llamada).
- Chunks del manual relevantes a esos subtemas (HTML ya limpio).
- Límites:
  • pregunta: ≤ $cant_car_pre caracteres (clara, única).
  • respuesta: ≤ $cant_car_res caracteres (precisa, con pasos si aplica).
- Reglas:
  • Sin redundancias respecto a Q/A previas.
  • Omitir Q/A si el manual no sustenta la respuesta.
  • Salida estricta JSONL (una línea por objeto), sin encabezados/epílogos, con:

{
  "pregunta": "¿...?",
  "respuesta": "Texto fundamentado en el manual ...",
  "categoria": "Tema/Subtema",
  "palabras_clave": "término1, término2, término3"
}

OUTPUT:
- Solo JSONL (una Q/A por línea).
      

7) Validaciones e inserción

8) Deduplicación

No se modifica el esquema. Deduplicación en aplicación:

  1. Antes de insertar, cargar pregunta de BD para el curso_id y normalizar (lowercase, sin tildes, trim, colapsar espacios).
  2. Normalizar cada pregunta nueva y:
    • Si ya existe en el set de BD → descartar.
    • Si ya existe en el lote actual → descartar.

Opcional (no requerido): registro de las descartadas por duplicado en log para auditoría.

9) Logging y resiliencia

10) Salida/UX del script

  1. Resumen ejecutivo: curso_id, $cant_pre, llamadas usadas, Q/A pedidas, insertadas, descartadas por duplicado/validación, tiempo total.
  2. Listado de nuevas FAQs (solo las insertadas en esta corrida): tabla con columnas ID, orden, pregunta, categoria, palabras_clave.

Nota: se recomienda no listar respuestas completas si resultan muy extensas; mostrar recorte y ofrecer “ver más” si se decide en la implementación.

11) Seguridad

12) Criterios de aceptación

13) Plan de pruebas

Casos positivos

  • Curso con manual extenso → genera e inserta ≥ $cant_pre.
  • Curso con manual medio → genera varias llamadas y alcanza el objetivo.
  • Re-ejecución sobre el mismo curso → no inserta duplicados; continúa orden a partir del máximo existente.

Casos negativos / borde

  • curso_id inexistente → mensaje claro, sin llamadas a la IA.
  • Manual vacío → mensaje claro, sin llamadas a la IA.
  • Respuesta IA con líneas malformadas → descartar esas líneas, continuar con el resto.
  • 429/5xx de API → reintentos con backoff; si excedido, terminar con resumen parcial.

14) Operación y mantenimiento

15) Anexos: estructuras y supuestos

15.1 Estructura esperada de faq_preguntas (según dump compartido)

Campos previstos (si difieren en tu BD real, mapear durante la implementación):

15.2 Reglas de normalización para deduplicación

15.3 Políticas de truncado

15.4 Estrategia para minimizar llamadas

15.5 Presentación final


Este documento describe completamente el comportamiento esperado para implementar dashboar_faq.php sin requerir consultas adicionales. No incluye código ejecutable; provee especificaciones, reglas y formatos de entrada/salida para desarrollo inmediato.