Introduce a full Vite/React UI for exams, auth, materials, images, generation, and export. Adapt backend for Sinbad2IA chat API, bcrypt passwords, CORS on port 5173, and schema migrations.
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://localhost:8000
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.