Apache ProxyPass targets host port 8069; update compose, CI, CORS defaults, deployment docs, and production .env files for https://sinbad2.ujaen.es/generadorexamenesllm/.
GenExamenes IA
Backend para generar exámenes con IA, procesar la salida de un LLM y exportar preguntas a Moodle XML.
Guía detallada de flujo, endpoints, ejemplos y errores: GUIA_API_Y_FLUJO.md
El proyecto está centrado en backend. La carpeta frontend se mantiene vacía a nivel de aplicación, aunque existe un servicio en Docker Compose para reservar el despliegue futuro.
Stack
- FastAPI
- PostgreSQL
- SQLAlchemy
- Cliente LLM para Sinbad2IA UJA (
POST /api/chat, modeloqwen3.5:35b) - Docker Compose con servicios
backend,frontendydb
Puesta en Marcha
Copia el ejemplo de variables dentro de la carpeta del backend:
cp backend/.env.example backend/.env
Después levanta los servicios:
docker compose up --build
La API queda disponible en:
http://sinbad2.ujaen.es:8068
Configuración
El archivo de entorno debe estar en backend/.env.
Variables principales:
JWT_SECRET_KEY: secreto para firmar tokens JWT (mínimo 32 caracteres).JWT_EXPIRE_MINUTES: duración del token de acceso.GOOGLE_CLIENT_ID: Client ID de OAuth 2.0 en Google Cloud Console (para/auth/google).DATABASE_URL: conexión PostgreSQL usada por el backend.LLM_BASE_URL: URL base del servidor (por defecto ``; el cliente usa/api/chat).LLM_MODEL: modelo (por defectoqwen3.5:35b).LLM_TIMEOUT_SECONDS: tiempo máximo de espera (por defecto 180 s).LLM_API_KEY: opcional, solo si el servidor exige autenticación.ALLOWED_ORIGINS: orígenes permitidos por CORS.MAX_STORAGE_BYTES_PER_TEMPLATE: cupo total de almacenamiento por examen (materiales + imágenes).
Todas las rutas bajo /exam requieren autenticación de usuario con:
Authorization: Bearer <access_token>
Si ya tenías una base de datos creada antes de añadir usuarios, recrea el volumen:
docker compose down -v
docker compose up --build
Flujo de Usuario
- Registrarse o iniciar sesión.
- Crear una plantilla de examen (queda asociada al usuario).
- Subir materiales de referencia (PDF, DOCX, TXT, PNG, JPG…) a la plantilla.
- Generar un prompt guiado para el LLM (incluye el texto extraído de los ficheros).
- Generar preguntas automáticamente con el LLM o parsear una salida externa en JSON/TXT.
- Guardar las preguntas validadas en PostgreSQL.
- Consultar el historial de exámenes creados.
- Exportar el examen a Moodle XML, TXT o JSON.
Endpoints
GET /health
Comprueba que la API está levantada.
POST /auth/register
Registra un usuario con email y contraseña.
POST /auth/login
Devuelve un token JWT para usar en las rutas protegidas.
POST /auth/google
Recibe el id_token de Google (Sign in with Google en el frontend), verifica la cuenta y devuelve el mismo JWT de la API.
GET /auth/me
Devuelve los datos del usuario autenticado.
GET /exam/history
Lista el historial de exámenes del usuario (plantillas, preguntas y exportaciones).
POST /exam/templates/{template_id}/materials
Sube un fichero (multipart/form-data, campo file). Formatos: PDF, DOCX, TXT, MD, PNG, JPG, WEBP. Extrae texto y lo guarda como contexto.
GET /exam/templates/{template_id}/materials
Lista los materiales subidos a una plantilla.
DELETE /exam/templates/{template_id}/materials/{material_id}
Elimina un material.
POST /exam/templates/{template_id}/images
Sube una imagen para preguntas visuales (file, opcional caption). No se usa OCR: la imagen se muestra en el examen y se embebe en el XML de Moodle.
GET /exam/templates/{template_id}/images
Lista las imágenes de la plantilla.
GET /exam/images/{image_id}/content
Devuelve la imagen (requiere JWT). Para previsualizar en el frontend o en Moodle tras importar.
DELETE /exam/templates/{template_id}/images/{image_id}
Elimina una imagen.
PATCH /exam/questions/{question_id}/image
Vincula o desvincula una imagen a una pregunta existente ({"image_id": "uuid"} o null).
POST /exam/templates
Crea una plantilla con materia, nivel educativo, tipos de pregunta, puntuación, penalización y dificultad.
GET /exam/templates
Lista las plantillas del usuario autenticado.
GET /exam/templates/{template_id}
Obtiene una plantilla concreta.
GET /exam/templates/{template_id}/storage
Muestra cuánto espacio usa el examen (materiales + imágenes) y el límite configurado.
POST /exam/prompts/{template_id}
Genera un prompt estructurado para IA.
POST /exam/generate
Llama al LLM configurado, parsea la respuesta y guarda las preguntas.
POST /exam/parse
Procesa una salida externa de IA en formato json o txt.
GET /exam/export/xml/{template_id}
Exporta las preguntas en Moodle XML.
GET /exam/export/txt/{template_id}
Exporta las preguntas en texto plano.
GET /exam/export/json/{template_id}
Exporta las preguntas en JSON.
Seguridad
- Registro e inicio de sesión con contraseña hasheada (bcrypt).
- Autenticación JWT por usuario.
- Cada examen pertenece a un único usuario; no se puede acceder al de otro.
- Rate limiting por cliente.
- Límite de tamaño de petición.
- Validación de entrada con Pydantic.
- Manejo uniforme de errores HTTP.
- Sanitización básica de prompts y respuestas antes de persistir/exportar.