430 lines
14 KiB
Markdown
430 lines
14 KiB
Markdown
# API del RAG
|
|
|
|
**Proyecto:** Workspace de tools IA para empresas
|
|
**Modulo:** RAG
|
|
**Ultima actualizacion:** 2026-09-21
|
|
**Ultima modificacion por:** Agente RAG 2
|
|
**Estado:** Produccion en `0.1.0`; version `0.2.0` preparada localmente
|
|
|
|
Esta guia explica como descubrir y consumir la API. El contrato tecnico completo y canonico se publica en OpenAPI 3.1.1; este documento prioriza el camino rapido, las decisiones de uso y los ejemplos habituales.
|
|
|
|
## Acceso rapido
|
|
|
|
Base URL de produccion:
|
|
|
|
```text
|
|
https://rag.por-correo.com
|
|
```
|
|
|
|
| Recurso | URL | Uso |
|
|
|---|---|---|
|
|
| Ayuda resumida | `GET /help` | Descubrimiento rapido para personas y agentes |
|
|
| Contrato OpenAPI | `GET /openapi.json` | Esquemas, parametros, respuestas y errores |
|
|
| Playground | `GET /playground` | Pruebas manuales desde navegador |
|
|
|
|
`GET /help` indica expresamente que debe consultarse `/openapi.json` para obtener los parametros, cuerpos, respuestas, errores y ejemplos completos de cada endpoint.
|
|
|
|
La API general sigue sin autenticacion completa. Las operaciones administrativas del ciclo de vida usan una proteccion acotada con `Authorization: Bearer <LIFECYCLE_ADMIN_TOKEN>`; esto no sustituye la autenticacion general pendiente.
|
|
|
|
## Elegir la operacion correcta
|
|
|
|
| Necesidad | Endpoint recomendado |
|
|
|---|---|
|
|
| Comprobar servicio y capacidades | `GET /health` |
|
|
| Ver scopes ingeridos | `GET /sources` |
|
|
| Ver versiones de una fuente | `GET /sources/{sourceId}/versions` |
|
|
| Activar, rollback o purgar versiones | `/sources/*` con token administrativo |
|
|
| Recuperar contexto para otro agente | `POST /retrieve` |
|
|
| Obtener una respuesta final con citas | `POST /answer` |
|
|
| Comparar una respuesta sin RAG | `POST /answer/direct` |
|
|
| Conversar con bootstrap e historial | `POST /chat` |
|
|
| Ingerir una ruta accesible por el servidor | `POST /ingest` |
|
|
| Subir un archivo o carpeta ZIP | `POST /ingest/upload` |
|
|
| Eliminar una fuente antes de reingestar | `POST /cleanup` legacy, o purga de version no activa |
|
|
| Consultar o actualizar evaluaciones | `/logs/*` |
|
|
|
|
## Catalogo completo
|
|
|
|
La API queda formada por las operaciones de descubrimiento, ingesta, retrieval, evaluacion y ciclo de vida:
|
|
|
|
| Metodo | Ruta | Descripcion |
|
|
|---|---|---|
|
|
| `GET` | `/help` | Catalogo resumido derivado de OpenAPI |
|
|
| `GET` | `/openapi.json` | Contrato OpenAPI 3.1.1 |
|
|
| `GET` | `/playground` | Interfaz web de prueba |
|
|
| `GET` | `/health` | Estado, version, commit, proveedores, parsers y chunking |
|
|
| `GET` | `/sources` | Scopes disponibles en Qdrant |
|
|
| `GET` | `/sources/{sourceId}` | Fuente registrada en el catalogo |
|
|
| `GET` | `/sources/{sourceId}/versions` | Versiones de una fuente |
|
|
| `GET` | `/sources/{sourceId}/versions/{versionId}` | Detalle de una version |
|
|
| `POST` | `/sources/{sourceId}/versions/{versionId}/activate` | Activacion administrativa con precondicion |
|
|
| `POST` | `/sources/{sourceId}/rollback` | Rollback administrativo sin recalcular embeddings |
|
|
| `POST` | `/sources/{sourceId}/versions/{versionId}/retry` | Reintento explicito de version fallida o huerfana con fuente durable |
|
|
| `DELETE` | `/sources/{sourceId}/versions/{versionId}` | Purga administrativa de una version no activa |
|
|
| `GET` | `/models/answer` | Modelo por defecto y modelos seleccionables |
|
|
| `POST` | `/ingest` | Ingesta desde una ruta del servidor |
|
|
| `POST` | `/ingest/upload` | Upload `multipart/form-data` |
|
|
| `POST` | `/cleanup` | Borrado controlado por scope |
|
|
| `POST` | `/retrieve` | Recuperacion de contexto |
|
|
| `POST` | `/answer` | Respuesta apoyada en retrieval |
|
|
| `POST` | `/answer/direct` | Respuesta del modelo sin retrieval |
|
|
| `POST` | `/chat` | Conversacion con contexto opcional |
|
|
| `GET` | `/logs/recent` | Logs recientes de evaluacion |
|
|
| `POST` | `/logs/manual` | Registro manual de una evaluacion |
|
|
| `PATCH` | `/logs/{id}` | Seguimiento y resolucion de un log |
|
|
|
|
## Contratos comunes
|
|
|
|
### Scope
|
|
|
|
Permite limitar una consulta o una operacion a fuentes concretas:
|
|
|
|
```json
|
|
{
|
|
"sourceId": "customer-a:manual:v1",
|
|
"sourceRef": "customer-a-errors.md",
|
|
"tags": ["customer-a", "support"]
|
|
}
|
|
```
|
|
|
|
Todos los campos son opcionales en consultas. Para `POST /cleanup` es obligatorio enviar al menos `sourceId` o `sourceRef`; las etiquetas solas no autorizan un borrado.
|
|
|
|
### Modos e intents
|
|
|
|
| Campo | Valores | Default |
|
|
|---|---|---|
|
|
| `mode` en retrieval y answer | `documental`, `codigo`, `auto` | `auto` |
|
|
| `mode` en chat | `documental`, `codigo`, `auto` | `documental` |
|
|
| `intent` | `specific`, `bootstrap` | `specific` |
|
|
| `mode` en ingesta | `mechanical`, `interactive` | `mechanical` |
|
|
|
|
### Errores
|
|
|
|
Los errores JSON siguen esta forma:
|
|
|
|
```json
|
|
{
|
|
"ok": false,
|
|
"error": "Description of the error"
|
|
}
|
|
```
|
|
|
|
Actualmente la mayoria de fallos de validacion o de proveedores se devuelven como `500`. `POST /cleanup` y `POST /ingest/upload` tambien pueden devolver `400`, y `PATCH /logs/{id}` devuelve `404` si no encuentra el log. Mejorar la validacion queda fuera de este bloque para no cambiar silenciosamente el comportamiento existente.
|
|
|
|
Con `KNOWLEDGE_LIFECYCLE_ENFORCED=true`, la API devuelve errores mas especificos para el catalogo:
|
|
|
|
| Codigo HTTP | Caso |
|
|
|---|---|
|
|
| `400` | Falta `expectedActiveVersionId` cuando `activate=true` |
|
|
| `409` | Cambio concurrente de version activa, version en curso o intento de purgar una activa |
|
|
| `422` | Fuente vacia, sin documentos soportados o sin contenido util |
|
|
| `503` | PostgreSQL, Qdrant, embeddings o version activa inconsistente |
|
|
|
|
## Recuperar contexto
|
|
|
|
`POST /retrieve` es la operacion recomendada cuando otro agente o flujo generara la respuesta final.
|
|
|
|
```bash
|
|
curl -sS -X POST "https://rag.por-correo.com/retrieve" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"mode": "documental",
|
|
"intent": "specific",
|
|
"query": "What does error FAT07 mean?",
|
|
"scope": {
|
|
"sourceId": "customer-a:manual:v1"
|
|
},
|
|
"useModelInRetrieve": false
|
|
}'
|
|
```
|
|
|
|
Campos principales:
|
|
|
|
| Campo | Requerido | Funcion |
|
|
|---|---|---|
|
|
| `query` | Si | Consulta de recuperacion |
|
|
| `mode` | No | Tipo de conocimiento |
|
|
| `intent` | No | Consulta concreta o mapa bootstrap |
|
|
| `scope` | No | Limita las fuentes |
|
|
| `useModelInRetrieve` | No | Añade `modelSummary` generado por un modelo |
|
|
| `model` | No | Override usado solo para `modelSummary` |
|
|
| `bootstrapMeta` | No | Trazabilidad del bootstrap en logs |
|
|
|
|
Respuesta resumida:
|
|
|
|
```json
|
|
{
|
|
"mode": "documental",
|
|
"intent": "specific",
|
|
"summary": "Retrieved 5 relevant chunks.",
|
|
"topics": ["support-errors.md"],
|
|
"criticalPoints": [],
|
|
"items": [
|
|
{
|
|
"chunkId": "chk:example",
|
|
"documentId": "doc:example",
|
|
"sourceId": "customer-a:manual:v1",
|
|
"title": "support-errors.md",
|
|
"content": "...",
|
|
"score": 0.87
|
|
}
|
|
],
|
|
"followUpRefs": ["doc:example"],
|
|
"scope": {
|
|
"sourceId": "customer-a:manual:v1"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Obtener una respuesta
|
|
|
|
`POST /answer` ejecuta retrieval y genera una respuesta final con citas.
|
|
|
|
```json
|
|
{
|
|
"mode": "documental",
|
|
"intent": "specific",
|
|
"query": "Explain the documented resolution for FAT07",
|
|
"scope": {
|
|
"sourceId": "customer-a:manual:v1"
|
|
},
|
|
"model": "openai/gpt-4.1-mini"
|
|
}
|
|
```
|
|
|
|
Tambien acepta `preloadedContext` y `bootstrapMeta`. La respuesta incluye `model`, `answer`, resumen del retrieval, temas, puntos criticos, citas y scope.
|
|
|
|
`POST /answer/direct` no consulta el vector store:
|
|
|
|
```json
|
|
{
|
|
"query": "Explain what a RAG service is",
|
|
"model": "openai/gpt-4.1-mini",
|
|
"preloadedContext": "Optional context supplied by the caller"
|
|
}
|
|
```
|
|
|
|
Su respuesta real solo contiene:
|
|
|
|
```json
|
|
{
|
|
"model": "openai/gpt-4.1-mini",
|
|
"answer": "..."
|
|
}
|
|
```
|
|
|
|
## Chat con bootstrap
|
|
|
|
`POST /chat` reutiliza contexto precargado, historial reciente y, opcionalmente, una nueva consulta al RAG:
|
|
|
|
```json
|
|
{
|
|
"message": "What should I check next?",
|
|
"history": [
|
|
{
|
|
"role": "user",
|
|
"content": "Give me an initial map of this project"
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": "The project contains..."
|
|
}
|
|
],
|
|
"mode": "documental",
|
|
"preloadedContext": "Previously loaded bootstrap",
|
|
"allowAdditionalRetrieve": true,
|
|
"scope": {
|
|
"sourceId": "project-docs"
|
|
}
|
|
}
|
|
```
|
|
|
|
Respuesta:
|
|
|
|
```json
|
|
{
|
|
"model": "openai/gpt-4.1-mini",
|
|
"answer": "...",
|
|
"usedBootstrapContext": true,
|
|
"usedAdditionalRetrieve": true,
|
|
"retrieved": {
|
|
"summary": "...",
|
|
"items": []
|
|
}
|
|
}
|
|
```
|
|
|
|
## Ingesta
|
|
|
|
### Ruta del servidor
|
|
|
|
`POST /ingest` requiere `sourceType` y `sourceRef`:
|
|
|
|
```json
|
|
{
|
|
"sourceId": "project-docs",
|
|
"sourceType": "folder",
|
|
"sourceRef": "/data/project-docs",
|
|
"mode": "mechanical",
|
|
"tags": ["project", "documentation"],
|
|
"activate": true,
|
|
"expectedActiveVersionId": null
|
|
}
|
|
```
|
|
|
|
`readPath` es un campo interno para separar la ruta fisica de lectura de la referencia logica. Los consumidores normales no deben enviarlo.
|
|
|
|
Con ciclo de vida activo:
|
|
|
|
- `activate` por defecto es `true`.
|
|
- si `activate=true`, `expectedActiveVersionId` es obligatorio: `null` para primera activacion y UUID para reemplazar una version existente.
|
|
- una ingesta identica a la version activa responde `noOp: true` y no escribe nuevos puntos.
|
|
- `activate=false` deja la version en `ready` para activarla despues con una operacion administrativa.
|
|
- la respuesta exitosa cambia a `201 Created` e incluye `sourceId`, `versionId`, `versionNumber`, `state`, `previousVersionId`, `activated` y `noOp`.
|
|
|
|
### Upload
|
|
|
|
`POST /ingest/upload` usa `multipart/form-data`:
|
|
|
|
| Campo | Requerido | Formato |
|
|
|---|---|---|
|
|
| `file` | Si | Archivo binario o ZIP |
|
|
| `sourceId` | No | Identificador logico |
|
|
| `mode` | No | `mechanical` o `interactive` |
|
|
| `tags` | No | Lista separada por comas |
|
|
| `isZipFolder` | No | Texto `true` o `false` |
|
|
| `activate` | No | Texto `true` o `false` |
|
|
| `expectedActiveVersionId` | Si activa | UUID o texto `null` |
|
|
|
|
```bash
|
|
curl -sS -X POST "https://rag.por-correo.com/ingest/upload" \
|
|
-F "file=@./support-errors.md" \
|
|
-F "sourceId=customer-a:manual:v1" \
|
|
-F "mode=mechanical" \
|
|
-F "tags=customer-a,support"
|
|
```
|
|
|
|
Con enforcement desactivado, ambas variantes conservan `202`. Con enforcement activado, responden `201` y usan el catalogo PostgreSQL como autoridad de version activa. El upload añade `uploadedResource`.
|
|
|
|
## Ciclo de vida de fuentes
|
|
|
|
El catalogo PostgreSQL es la autoridad para saber que fuentes existen, que versiones tienen y cual es la version activa. Qdrant conserva los puntos fisicos versionados, pero retrieval solo consulta versiones activas resueltas desde PostgreSQL.
|
|
|
|
### Listado y detalle
|
|
|
|
```text
|
|
GET /sources
|
|
GET /sources/{sourceId}
|
|
GET /sources/{sourceId}/versions
|
|
GET /sources/{sourceId}/versions/{versionId}
|
|
```
|
|
|
|
`GET /sources` mantiene los campos usados por el playground (`sourceId`, `sourceRef`, `chunkModes`, `tags`) y añade `activeVersionId`, `activeVersionNumber`, `state`, `needsReingest` y `updatedAt`.
|
|
|
|
### Activacion y rollback
|
|
|
|
```bash
|
|
curl -sS -X POST "https://rag.por-correo.com/sources/src:default:folder:docs/versions/<version-id>/activate" \
|
|
-H "Authorization: Bearer $LIFECYCLE_ADMIN_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"expectedActiveVersionId":"<active-version-id>"}'
|
|
```
|
|
|
|
Rollback usa la misma activacion atomica del puntero PostgreSQL:
|
|
|
|
```json
|
|
{
|
|
"targetVersionId": "uuid-version-anterior",
|
|
"expectedActiveVersionId": "uuid-version-activa-actual"
|
|
}
|
|
```
|
|
|
|
### Purga
|
|
|
|
`DELETE /sources/{sourceId}/versions/{versionId}` exige token administrativo y solo acepta versiones no activas. La purga marca la version como `purging`, borra puntos Qdrant con `wait=true`, verifica que no quedan puntos y finalmente deja la version como `purged`.
|
|
|
|
### Reintento explicito
|
|
|
|
`POST /sources/{sourceId}/versions/{versionId}/retry` acepta versiones `failed`, `pending` o `indexing`. Si recibe una fuente durable (`sourceType`, `sourceRef` y opcionalmente `readPath`) cierra versiones huerfanas como fallidas y crea una version nueva mediante `/ingest`. Si no recibe fuente durable, devuelve `202` con instrucciones: los uploads temporales no se reintentan en sitio porque el original ya no esta garantizado.
|
|
|
|
## Limpieza controlada
|
|
|
|
`POST /cleanup` elimina los chunks que coinciden con un scope solo en modo legacy y con `INGEST_WRITES_ENABLED=true`:
|
|
|
|
```json
|
|
{
|
|
"scope": {
|
|
"sourceId": "customer-a:manual:v1"
|
|
}
|
|
}
|
|
```
|
|
|
|
Respuesta:
|
|
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"deleted": 36
|
|
}
|
|
```
|
|
|
|
Esta operacion es destructiva. Verifica primero el scope con `GET /sources`.
|
|
|
|
## Evaluacion
|
|
|
|
`GET /logs/recent?limit=20` devuelve los logs recientes. Si no se indica `limit`, usa 20.
|
|
|
|
`POST /logs/manual` registra una observacion humana:
|
|
|
|
```json
|
|
{
|
|
"operation": "retrieve",
|
|
"reason": "manual_review_requested",
|
|
"query": "What does error FAT07 mean?",
|
|
"mode": "documental",
|
|
"intent": "specific",
|
|
"scope": {
|
|
"sourceId": "customer-a:manual:v1"
|
|
},
|
|
"note": "The first result is too generic"
|
|
}
|
|
```
|
|
|
|
`PATCH /logs/{id}` actualiza su seguimiento:
|
|
|
|
```json
|
|
{
|
|
"reviewStatus": "resolved",
|
|
"severity": "high",
|
|
"reviewedBy": "maintainer",
|
|
"resolutionNote": "Retrieval ranking adjusted and validated.",
|
|
"fixReference": "commit-or-ticket-reference"
|
|
}
|
|
```
|
|
|
|
Valores admitidos:
|
|
|
|
| Campo | Valores |
|
|
|---|---|
|
|
| `reviewStatus` | `pending`, `in_progress`, `resolved`, `ignored` |
|
|
| `severity` | `low`, `medium`, `high` |
|
|
|
|
## Integracion recomendada con n8n
|
|
|
|
Para una `HTTP Request Tool` conectada a un AI Agent:
|
|
|
|
1. Usa `POST /retrieve`.
|
|
2. Fija `mode`, `intent` y `scope` en el nodo.
|
|
3. Permite que el agente complete solo `query`.
|
|
4. Mantiene `useModelInRetrieve=false` para evitar procesar la consulta con dos modelos.
|
|
5. Entrega `items[].content` y sus metadatos al agente final.
|
|
|
|
Usa `POST /answer` solamente cuando el propio RAG deba generar la respuesta final.
|
|
|
|
## Fuente de verdad y mantenimiento
|
|
|
|
- `GET /openapi.json` es el contrato publico para integraciones y herramientas.
|
|
- `GET /help` es el indice rapido derivado del mismo contrato.
|
|
- Este documento explica flujos y decisiones de uso.
|
|
- `src/app.ts` contiene la implementacion efectiva.
|
|
- Cualquier cambio de endpoint debe actualizar OpenAPI y esta guia en el mismo bloque de trabajo.
|