Inicio de la guía 1. Topología de la solución 2. Aspire como plano de control local 3. Configuración y contratos compartidos 4. Metadatos con SQLite y EF Core 5. API e interfaz de carga 6. Almacenamiento de objetos con MinIO 7. Pipeline de ingesta del worker 8. Extracción y división de texto 9. Artefactos literarios 10. Abstracciones de proveedores de IA 11. Almacenamiento vectorial con Qdrant 12. Flujo de preguntas y recuperación 13. Prompts y citas 14. Pruebas del pipeline 15. Notas de desarrollo local Todas las guías
Navegación de la guíaÍndice y capítulos
Capítulo 5

API e interfaz de carga

El endpoint de carga está en RAG.Api/Program.cs:

Nota de traducción: Esta versión en español fue traducida con ayuda de un LLM y revisada para conservar los términos técnicos, el código y los nombres de archivos en inglés cuando corresponde.
Imagen decorativa del capítulo sobre API e interfaz de carga
El endpoint de carga encola trabajo en vez de hacerlo
app.MapPost("/api/documents", async (HttpRequest request, RagDbContext dbContext, IObjectStorage storage, IOptions<RagOptions> options, CancellationToken cancellationToken) =>
{
    var documentId = Guid.NewGuid();
    var objectKey = $"{documentId:N}/{fileName}";
    await storage.UploadAsync(objectKey, stream, contentType, cancellationToken);
    return Results.Accepted($"/api/documents/{documentId}");
});

El endpoint de carga está en RAG.Api/Program.cs:

POST /api/documents

El endpoint:

  1. verifica que la solicitud sea multipart form data;
  2. requiere un archivo PDF o TXT;
  3. aplica el límite de carga configurado;
  4. escribe el archivo original en almacenamiento de objetos;
  5. crea un DocumentRecord con estado Pending;
  6. devuelve 202 Accepted.

La API evita deliberadamente hacer extracción y embeddings dentro de la solicitud. Encola trabajo creando una fila pendiente en la base de datos.

Nota de producción: el límite de carga protege el cuerpo de la solicitud, pero este ejemplo todavía confía lo suficiente en el archivo cargado como para guardarlo y procesarlo después. Un sistema de producción normalmente agregaría validación de contenido más fuerte, escaneo de malware, cuotas por usuario más estrictas y respuestas de error genéricas en vez de devolver detalles internos de excepciones. Este proyecto mantiene el comportamiento simple porque es un proyecto de aprendizaje, no software de producción.

La UI en RAG.Api/wwwroot es intencionalmente sencilla:

La UI consulta GET /api/documents cada pocos segundos. Para libros grandes, la ingesta puede tardar, así que el worker actualiza:

Nota de producción: polling es simple y funciona bien para este ejemplo local, pero una UI de producción normalmente se suscribiría a actualizaciones de estado. Por ejemplo, la API podría publicar eventos de progreso del documento mediante SignalR, WebSockets, Server-Sent Events o un servicio de notificaciones respaldado por un message broker, y el navegador podría recibir actualizaciones cuando ocurren en lugar de pedir repetidamente la lista completa de documentos.

Esto permite que la UI muestre progreso útil en lugar de dejar un libro atrapado en un estado vago de Processing.

Controles de borrar y reindexar

La API ahora expone controles del ciclo de vida del documento además de carga y consulta de estado:

DELETE /api/documents/{id}
POST   /api/documents/{id}/reindex

DocumentManagementService controla esas operaciones. La eliminación borra la fila de metadatos, elimina el objeto original y remueve los puntos vectoriales del documento. La reindexación restablece estado y progreso a Pending para que el worker pueda reconstruir chunks y vectores desde el archivo original.

Esto importa porque los sistemas RAG necesitan workflows de mantenimiento. Cuando cambian el chunking, la extracción, los prompts, los embeddings o los artefactos generados, los usuarios necesitan una forma de reconstruir el índice derivado sin subir otra vez el mismo documento.