Math Service — API Endpoints
Referencia completa de todos los endpoints del Math Service con ejemplos de request/response.
Base URL: http://localhost:8083 (local) / http://math_service:8083 (Docker Compose)
OpenAPI interactivo: http://localhost:8083/docs
General
GET /
Información de la API y estado del servicio.
Response 200 OK:
{
"name": "Math Service",
"version": "0.1.0",
"description": "Mathematical analysis service (FAQ generation, topic extraction)",
"status": "running"
}
GET /health
Health check detallado que verifica la conectividad con todos los servicios dependientes.
Response 200 OK (healthy):
{
"status": "healthy",
"mongo_connected": true,
"ollama_connected": true,
"rag_service_connected": true,
"message": "MongoDB: OK, Ollama: OK, RAG: OK"
}
Response 200 OK (degraded):
{
"status": "degraded",
"mongo_connected": true,
"ollama_connected": false,
"rag_service_connected": true,
"message": "MongoDB: OK, Ollama: FAIL, RAG: OK"
}
El servicio arranca igualmente cuando algún componente no está disponible. El endpoint siempre devuelve
200y refleja el estado real en el cuerpo.
GET /metrics
Métricas Prometheus del servicio (instrumentación automática de FastAPI).
Incluye: número de requests, latencias por endpoint, etc.
FAQs
POST /faqs/generate
Genera FAQs para una asignatura agrupando preguntas históricas de estudiantes con Fuzzy C-Means.
Request Body:
{
"subject": "iv",
"min_cluster_size": 3
}
| Campo | Tipo | Default | Descripción |
|---|---|---|---|
subject | string \| null | null | Código de la asignatura. null procesa todas. |
min_cluster_size | int | 3 | Mínimo de preguntas para considerar un clúster válido. |
Flujo interno:
- Lee
conversationsen MongoDB filtrando porsubjectywas_test != true. - Genera embeddings de las preguntas via Ollama (
nomic-embed-text). - Determina el k óptimo con el método del codo.
- Aplica
SphericalFuzzyCMeans(variante coseno de FCM). - Para cada clúster válido (≥
min_cluster_size), selecciona la pregunta más cercana al centroide. - Persiste las FAQs en MongoDB con
status: "draft".
Response 200 OK:
{
"status": "success",
"subject": "iv",
"questions_analyzed": 87,
"clusters_formed": 6,
"faqs_generated": 5,
"faqs": [
"¿Cómo funciona Docker Compose?",
"¿Qué diferencia hay entre imagen y contenedor?",
"¿Cómo configuro variables de entorno en Docker?",
"¿Qué es un volumen en Docker?",
"¿Cómo depuro un contenedor en ejecución?"
]
}
Response 500 — Sin preguntas:
{
"detail": "No questions found to generate FAQs from."
}
Response 500 — Ollama no disponible:
{
"detail": "NLP service error: ..."
}
Ejemplo cURL:
curl -X POST http://localhost:8083/faqs/generate \
-H "Content-Type: application/json" \
-d '{"subject": "iv", "min_cluster_size": 3}'
GET /faqs/{subject_id}
Lista las FAQs existentes para una asignatura, ordenadas por cluster_size descendente.
Path Parameters:
subject_id— Código de la asignatura (e.g.,"iv")
Response 200 OK:
[
{
"id": "65f1a2b3c4d5e6f7a8b9c0d1",
"question": "¿Cómo funciona Docker Compose?",
"answer": "Docker Compose permite definir y ejecutar aplicaciones multi-contenedor...",
"subject": "iv",
"cluster_size": 12,
"status": "published",
"created_at": "2026-03-10T14:30:00Z"
},
{
"id": "65f1a2b3c4d5e6f7a8b9c0d2",
"question": "¿Qué diferencia hay entre imagen y contenedor?",
"answer": "",
"subject": "iv",
"cluster_size": 8,
"status": "draft",
"created_at": "2026-03-10T14:30:00Z"
}
]
Las FAQs con
status: "draft"han sido generadas pero aún no revisadas por el profesor.
Ejemplo cURL:
curl http://localhost:8083/faqs/iv
PUT /faqs/{subject_id}/{faq_id}
Actualiza los campos de una FAQ existente.
Path Parameters:
subject_id— Código de la asignaturafaq_id— ObjectId de la FAQ en MongoDB
Request Body (todos los campos son opcionales):
{
"question": "¿Cómo funciona Docker Compose y cuándo debo usarlo?",
"answer": "Docker Compose es una herramienta para definir aplicaciones multi-contenedor...",
"status": "published"
}
Response 200 OK:
{
"status": "success",
"message": "FAQ updated"
}
Response 400:
{
"detail": "Invalid FAQ ID"
}
Response 404:
{
"detail": "FAQ not found"
}
Ejemplo cURL:
curl -X PUT http://localhost:8083/faqs/iv/65f1a2b3c4d5e6f7a8b9c0d1 \
-H "Content-Type: application/json" \
-d '{"answer": "Docker Compose es una herramienta...", "status": "published"}'
PATCH /faqs/{subject_id}/{faq_id}/publish
Cambia el estado de una FAQ a "published".
Response 200 OK:
{
"status": "success",
"message": "FAQ published"
}
Ejemplo cURL:
curl -X PATCH http://localhost:8083/faqs/iv/65f1a2b3c4d5e6f7a8b9c0d1/publish
PATCH /faqs/{subject_id}/{faq_id}/unpublish
Cambia el estado de una FAQ a "draft".
Response 200 OK:
{
"status": "success",
"message": "FAQ unpublished"
}
DELETE /faqs/{subject_id}/{faq_id}
Elimina una FAQ por su ObjectId.
Response 200 OK:
{
"status": "success",
"message": "FAQ deleted"
}
Response 404:
{
"detail": "FAQ not found"
}
Ejemplo cURL:
curl -X DELETE http://localhost:8083/faqs/iv/65f1a2b3c4d5e6f7a8b9c0d1
Topics
POST /topics/extract
Extrae los tópicos principales de los documentos de una asignatura usando NMF sobre fragmentos del RAG Service.
Request Body:
{
"subject": "iv",
"vectorizer_type": "tfidf",
"k": null,
"cost_function": "frobenius"
}
| Campo | Tipo | Default | Descripción |
|---|---|---|---|
subject | string | requerido | Código de la asignatura |
vectorizer_type | "tfidf" \| "bow" | "tfidf" | Tipo de vectorizador de texto |
k | int \| null | null | Número de tópicos. null → selección automática por método del codo |
cost_function | "frobenius" \| "kl" | "frobenius" | Función de coste para NMF |
Flujo interno:
- Obtiene fragmentos del RAG Service via
POST /searchcontop_k=500. - Vectoriza con TF-IDF o BoW (
max_features=500, min_df=2). - Determina k automáticamente o usa el valor proporcionado.
- Aplica NMF → matrices W (doc-tópico) y H (tópico-término).
- Para cada tópico: extrae los 5 términos con mayor peso y genera un título descriptivo via Mistral API.
- Construye el mapa conceptual (nodos: asignatura, tópicos, términos; aristas ponderadas).
- Persiste el resultado en MongoDB (
topicscollection).
Response 200 OK:
{
"status": "success",
"subject": "iv",
"clusters_formed": 5,
"topics": [
{
"cluster": 0,
"topic_name": "Contenedores Docker",
"terms": ["docker", "contenedor", "imagen", "volumen", "compose"],
"weight": 0.34
},
{
"cluster": 1,
"topic_name": "Redes y Comunicación",
"terms": ["red", "puerto", "exposición", "bridge", "host"],
"weight": 0.28
}
],
"concept_map": {
"nodes": [
{"id": "iv", "group": "subject", "label": "iv"},
{"id": "Contenedores Docker", "group": "topic", "label": "Contenedores Docker"},
{"id": "term_docker", "group": "term", "label": "docker"}
],
"links": [
{"source": "iv", "target": "Contenedores Docker", "value": 1.0},
{"source": "Contenedores Docker", "target": "term_docker", "value": 0.85}
]
},
"doc_topic_matrix": [
[0.8, 0.1, 0.05, 0.03, 0.02],
[0.1, 0.7, 0.2, 0.0, 0.0]
],
"created_at": "2026-03-12T10:30:00Z",
"source_chunks": 142,
"message": null
}
Response 500 — Sin chunks:
{
"detail": "No chunks found for subject"
}
Response 500 — RAG no disponible:
{
"detail": "RAG service unavailable: ..."
}
Ejemplo cURL:
curl -X POST http://localhost:8083/topics/extract \
-H "Content-Type: application/json" \
-d '{"subject": "iv", "vectorizer_type": "tfidf"}'
GET /topics/{subject_id}
Lista las extracciones de tópicos históricas para una asignatura, ordenadas por created_at descendente.
Path Parameters:
subject_id— Código de la asignatura
Response 200 OK:
Lista de objetos TopicResult (misma estructura que el response de POST /topics/extract).
[
{
"status": "success",
"subject": "iv",
"clusters_formed": 5,
"topics": [...],
"concept_map": {...},
"doc_topic_matrix": [[...]],
"created_at": "2026-03-12T10:30:00Z",
"source_chunks": 142,
"message": null
}
]
Ejemplo cURL:
curl http://localhost:8083/topics/iv
Resumen de endpoints
| Método | Endpoint | Descripción |
|---|---|---|
GET | / | Información del servicio |
GET | /health | Health check detallado |
GET | /metrics | Métricas Prometheus |
POST | /faqs/generate | Generar FAQs automáticas |
GET | /faqs/{subject_id} | Listar FAQs de una asignatura |
PUT | /faqs/{subject_id}/{faq_id} | Actualizar una FAQ |
PATCH | /faqs/{subject_id}/{faq_id}/publish | Publicar una FAQ |
PATCH | /faqs/{subject_id}/{faq_id}/unpublish | Despublicar una FAQ |
DELETE | /faqs/{subject_id}/{faq_id} | Eliminar una FAQ |
POST | /topics/extract | Extraer tópicos de una asignatura |
GET | /topics/{subject_id} | Historial de extracciones de tópicos |
Códigos de error comunes
| Código | Causa |
|---|---|
400 | ObjectId inválido en path |
404 | FAQ no encontrada (subject+id no existen en DB) |
500 | Error en pipeline (Ollama/RAG no disponible, sin datos) |