361 lines
17 KiB
Markdown
361 lines
17 KiB
Markdown
# Sistema RAG base
|
|
|
|
**Proyecto:** Workspace de tools IA para empresas
|
|
**Modulo:** RAG
|
|
**Ultima actualizacion:** 2026-09-25
|
|
**Ultima modificacion por:** Agente RAG 3
|
|
**Estado:** RAG y OCR `0.2.1` revision `960e04a5a9fc3a3ef108fa4ef19d5ff42dbdb1ae` desplegados y verificados; candidatas descartadas purgadas y FacturaTech v1 activa
|
|
|
|
---
|
|
|
|
## Proposito
|
|
|
|
Definir un sistema RAG base, bien planteado y reutilizable, que pueda integrarse con rapidez en proyectos de clientes y tambien servir como base para tools internas del workspace.
|
|
|
|
La prueba inicial con la carpeta `docs/` de este workspace se utilizara solo como ejemplo practico y entorno real de validacion, no como limite del sistema.
|
|
|
|
Desde la v1, el sistema debe contemplar tambien PDFs como parte valida de las fuentes documentales de entrada.
|
|
|
|
---
|
|
|
|
## Que es lo que queremos lograr
|
|
|
|
Queremos construir una base RAG que permita:
|
|
|
|
- indexar informacion relevante de un proyecto
|
|
- recuperar contexto util en funcion de una consulta
|
|
- entregar ese contexto a un agente o servicio para mejorar sus respuestas o decisiones
|
|
- integrarse con rapidez en otros proyectos sin rehacer la arquitectura cada vez
|
|
|
|
En terminos practicos, el objetivo es disponer de una pieza reutilizable que convierta documentacion, conocimiento interno y otras fuentes en contexto accesible para agentes y servicios de IA.
|
|
|
|
---
|
|
|
|
## Vision del sistema
|
|
|
|
Este sistema RAG debe quedar preparado para trabajar con diferentes tipos de fuentes, por ejemplo:
|
|
|
|
- documentacion de proyecto
|
|
- bases de conocimiento internas
|
|
- contenido operativo de clientes
|
|
- archivos tecnicos
|
|
- datos exportados desde otros sistemas
|
|
|
|
La carpeta `docs/` del workspace servira como primer caso real de prueba porque permite validar resultados con un conjunto de informacion pequeno, claro y facil de revisar.
|
|
|
|
---
|
|
|
|
## Objetivos principales
|
|
|
|
1. Diseñar una base RAG reutilizable y desacoplada del proyecto de prueba.
|
|
2. Permitir que pueda conectarse a otros servicios de IA o agentes con una integracion sencilla.
|
|
3. Hacer que el sistema funcione con fuentes reales, empezando por `docs/`.
|
|
4. Facilitar continuidad entre sesiones, agentes y proyectos gracias a recuperacion de contexto relevante.
|
|
5. Dejar lista una arquitectura que luego pueda crecer hacia casos mas complejos.
|
|
|
|
---
|
|
|
|
## Caso de prueba inicial
|
|
|
|
La primera validacion se hara con la carpeta `docs/` de este workspace.
|
|
|
|
La idea es comprobar si un agente puede:
|
|
|
|
- localizar rapidamente informacion relevante
|
|
- entender que se ha hecho y que queda pendiente
|
|
- responder con base documental sin releer todo manualmente
|
|
- usar la documentacion del workspace como conocimiento ampliado en tiempo de consulta
|
|
|
|
Esto servira para evaluar si la base conceptual y tecnica del RAG esta bien construida.
|
|
|
|
---
|
|
|
|
## Principios del sistema
|
|
|
|
- Reutilizable: debe servir para este workspace y para proyectos de clientes.
|
|
- Modular: ingesta, indexacion, recuperacion y consumo deben poder evolucionar por separado.
|
|
- Simple al inicio: la primera version debe ser pequena y validable.
|
|
- Escalable: debe poder crecer a nuevas fuentes y nuevos casos de uso.
|
|
- Trazable: el contexto recuperado debe indicar de donde sale.
|
|
- Facil de integrar: debe poder conectarse rapidamente a agentes, tools o servicios.
|
|
|
|
---
|
|
|
|
## Resultado esperado
|
|
|
|
Si el sistema esta bien planteado, deberiamos poder usarlo como una capa de contexto ampliado para agentes y servicios, logrando que consulten conocimiento relevante de forma rapida y util, sin depender de tener toda la informacion cargada manualmente en cada sesion.
|
|
|
|
---
|
|
|
|
## Resumen operativo
|
|
|
|
El RAG funciona de forma autonoma. OCR es una extension opcional que solo interviene cuando RAG determina que una o mas paginas de un PDF no tienen texto nativo suficiente.
|
|
|
|
```text
|
|
Fuente
|
|
-> ingesta y versionado
|
|
-> extraccion de texto
|
|
-> [OCR opcional por pagina]
|
|
-> composicion del documento
|
|
-> revision si intervino OCR
|
|
-> chunks y embeddings
|
|
-> Qdrant
|
|
-> activacion
|
|
-> retrieve / answer
|
|
```
|
|
|
|
Si todo el contenido puede leerse de forma nativa, el servicio OCR no participa y la ingesta sigue el flujo RAG normal.
|
|
|
|
## Componentes y responsabilidades
|
|
|
|
| Componente | Responsabilidad |
|
|
|---|---|
|
|
| API RAG | Recibe ingestas y consultas; expone estado, revision, activacion y recuperacion. |
|
|
| Servicio de ingesta | Lee fuentes, identifica documentos, calcula hashes y prepara versiones. |
|
|
| Procesado | Normaliza contenido, conserva estructura y genera chunks. |
|
|
| Proveedor de embeddings | Convierte chunks en vectores. |
|
|
| PostgreSQL | Conserva fuentes, versiones, estados, trabajos OCR, hashes, diagnosticos y decisiones de revision. |
|
|
| Qdrant | Conserva chunks y embeddings versionados. Solo la version activa participa en retrieval. |
|
|
| Reconciliador | Recupera trabajo interrumpido y verifica invariantes entre PostgreSQL, Qdrant y artefactos. |
|
|
| Servicio OCR | Procesa paginas rasterizadas o con texto nativo insuficiente. No indexa ni activa contenido. |
|
|
| Almacenamiento RAG | Conserva originales y evidencias durables bajo `/data/ingestions`. |
|
|
| Almacenamiento OCR | Conserva temporalmente trabajos bajo `/data/jobs` hasta que RAG confirma la transferencia. |
|
|
|
|
## Funcionamiento interno del RAG sin OCR
|
|
|
|
### 1. Recepcion e identidad
|
|
|
|
RAG recibe una fuente mediante ingesta directa o upload. La fuente tiene una identidad logica estable y cada intento genera o reutiliza una version controlada.
|
|
|
|
Antes de indexar, RAG:
|
|
|
|
1. valida tipo, tamano y parametros;
|
|
2. lee los documentos;
|
|
3. calcula hashes del original y de la configuracion de procesamiento;
|
|
4. registra fuente, intento y version en PostgreSQL;
|
|
5. evita duplicar una version equivalente cuando la identidad ya existe.
|
|
|
|
### 2. Extraccion nativa
|
|
|
|
Cada tipo de documento usa su lector correspondiente. En un PDF, la extraccion conserva la separacion por paginas; no divide artificialmente un texto agregado para simularlas.
|
|
|
|
Si todas las paginas contienen texto nativo suficiente, el flujo sigue sin contactar OCR.
|
|
|
|
### 3. Normalizacion y composicion
|
|
|
|
El texto extraido se normaliza para obtener hashes reproducibles y una representacion estable. Se conserva el orden de documentos y paginas, junto con metadatos como titulo, tipo MIME, origen, etiquetas y version.
|
|
|
|
### 4. Chunking
|
|
|
|
El modo `documental` divide por estructura natural, parrafos y limites de tamano. El modo `codigo` prioriza bloques top-level y conserva nombres y rangos de lineas cuando estan disponibles.
|
|
|
|
Cada chunk queda ligado a:
|
|
|
|
- fuente;
|
|
- version;
|
|
- documento;
|
|
- posicion dentro del documento;
|
|
- politica de procesamiento;
|
|
- modelo y dimensiones de embeddings.
|
|
|
|
### 5. Embeddings e indexacion
|
|
|
|
RAG solicita embeddings para todos los chunks y escribe puntos versionados en Qdrant. Antes de dar la version por preparada, compara el numero esperado de chunks con el numero almacenado.
|
|
|
|
PostgreSQL es la autoridad del ciclo de vida; Qdrant es el indice vectorial. Una escritura parcial no convierte una version en activa.
|
|
|
|
### 6. Versiones y activacion
|
|
|
|
Una fuente puede tener varias versiones, pero solo una activa. Los estados principales son:
|
|
|
|
| Estado | Significado |
|
|
|---|---|
|
|
| `pending` | Version creada, aun no preparada. |
|
|
| `indexing` | Procesamiento o escritura en curso. |
|
|
| `ready` | Indexada y verificada, pero no activa. |
|
|
| `active` | Version usada por retrieval. |
|
|
| `failed` | El intento termino sin sustituir la activa. |
|
|
| `rejected` | La candidata fue rechazada durante revision. |
|
|
| `purging` / `purged` | Eliminacion controlada de una version no activa. |
|
|
|
|
La activacion exige una precondicion sobre la version activa esperada. Esto evita sobrescribir silenciosamente una version que cambio durante el procesamiento.
|
|
|
|
### 7. Recuperacion y respuesta
|
|
|
|
`retrieve` consulta exclusivamente versiones activas y devuelve chunks trazables. `answer` usa `retrieve`, construye contexto con citas y pide al modelo de respuesta que conteste apoyandose en ese contexto.
|
|
|
|
OCR no participa en consultas. Su trabajo termina antes de indexar el conocimiento.
|
|
|
|
## Cuando entra OCR
|
|
|
|
OCR se decide por pagina, no por documento completo. RAG mide el texto nativo y la cobertura rasterizada. Una pagina necesita OCR cuando no cumple simultaneamente los umbrales nativos:
|
|
|
|
```text
|
|
caracteres no blancos >= 120
|
|
caracteres alfanumericos >= 80
|
|
palabras o tokens >= 20
|
|
proporcion de caracteres invalidos <= 0.01
|
|
```
|
|
|
|
Aunque cumpla esos umbrales, tambien se selecciona cuando la cobertura rasterizada es `>= 0.05`, porque puede contener informacion visual que la capa de texto no representa.
|
|
|
|
RAG agrupa las paginas seleccionadas de cada PDF en un trabajo OCR. Las paginas nativas suficientes no se envian.
|
|
|
|
## Flujo interno RAG -> OCR -> RAG
|
|
|
|
### 1. Preparacion durable
|
|
|
|
Antes de contactar OCR, RAG guarda el original y su manifiesto bajo `/data/ingestions`, crea la version y persiste el trabajo local con:
|
|
|
|
- documento y paginas solicitadas;
|
|
- hash del PDF;
|
|
- configuracion `ocr-v2`;
|
|
- clave idempotente;
|
|
- version y documento propietarios del trabajo.
|
|
|
|
La API responde `202 Accepted` con `versionId`, `statusUrl` y fase `ocr_queued`. El cliente no mantiene abierta la peticion durante el procesamiento.
|
|
|
|
### 2. Envio al servicio OCR
|
|
|
|
RAG envia al endpoint privado `POST /v1/jobs`:
|
|
|
|
- PDF original;
|
|
- lista cerrada y ordenada de paginas;
|
|
- hashes e identidad de configuracion;
|
|
- clave de idempotencia.
|
|
|
|
OCR responde con un `jobId` y estado `queued`, `running`, `succeeded` o `failed`. Repetir la misma solicitud reutiliza el mismo trabajo compatible.
|
|
|
|
### 3. Procesamiento OCR
|
|
|
|
OCR tiene cola durable SQLite, un worker y concurrencia uno. Renderiza cada pagina una sola vez a PNG; ese mismo render alimenta PaddleOCR y se conserva temporalmente como imagen de revision.
|
|
|
|
OCR produce por pagina:
|
|
|
|
- texto;
|
|
- lineas;
|
|
- posiciones;
|
|
- confianza;
|
|
- metricas de cobertura y calidad.
|
|
|
|
OCR no llama actualmente a RAG cuando termina. RAG consulta el estado mediante `GET /v1/jobs/:jobId`.
|
|
|
|
### 4. Recuperacion del resultado
|
|
|
|
Cuando el trabajo llega a `succeeded`, RAG:
|
|
|
|
1. descarga y valida el resultado estructurado;
|
|
2. descarga secuencialmente las imagenes requeridas;
|
|
3. valida identidad, pagina, configuracion y SHA-256;
|
|
4. publica resultado e imagenes en almacenamiento durable;
|
|
5. relee los artefactos publicados antes de marcarlos como transferidos;
|
|
6. elimina el trabajo remoto solo despues de completar la evidencia local.
|
|
|
|
Si RAG cae, el resultado remoto se reutiliza con la misma identidad. No se repite PaddleOCR mientras el trabajo y sus artefactos sigan disponibles.
|
|
|
|
### 5. Composicion de paginas nativas y OCR
|
|
|
|
RAG elige un metodo por pagina:
|
|
|
|
| Tipo de pagina | Texto usado en la candidata |
|
|
|---|---|
|
|
| Nativa suficiente | Texto extraido directamente del PDF. |
|
|
| Requiere OCR | Lineas devueltas por OCR, ordenadas por posicion. |
|
|
| Vacia verificada | Cadena vacia con diagnostico de pagina vacia. |
|
|
|
|
No mezcla texto nativo y OCR dentro de la misma pagina, porque produciria duplicados. Si una pagina necesita OCR, el texto OCR sustituye al texto nativo insuficiente de esa pagina. Despues RAG ordena todas las paginas y compone un unico documento.
|
|
|
|
### 6. Calidad y candidata revisable
|
|
|
|
RAG clasifica todas las paginas antes de decidir el estado:
|
|
|
|
- `accepted`: calidad suficiente;
|
|
- `warning`: revisable, pero no bloqueante;
|
|
- `blocked`: no permite crear candidata.
|
|
|
|
Una candidata valida pasa a `review_required`. En ese estado todavia no tiene chunks activos ni participa en respuestas.
|
|
|
|
La revision puede proponer correcciones exactas por linea. Aprobarla genera un artefacto revisado inmutable y transiciona a `indexing`; entonces se crean chunks, embeddings y puntos de Qdrant. Con `activateRequested=false`, termina en `ready`. La activacion es una operacion posterior y separada.
|
|
|
|
## Seguimiento, temporizadores y recuperacion
|
|
|
|
### Comportamiento desplegado
|
|
|
|
Este comportamiento se publico en `bfb2d48` y permanece desplegado en la revision vigente `960e04a5a9fc3a3ef108fa4ef19d5ff42dbdb1ae`.
|
|
|
|
Al aceptar una ingesta OCR, RAG intenta despacharla inmediatamente. Si OCR sigue en `queued` o `running`, el dispatcher guarda `next_attempt_at` con un backoff entre 2 y 15 segundos.
|
|
|
|
El dispatcher consulta entonces el menor `next_attempt_at` pendiente y mantiene un unico temporizador hasta ese vencimiento. Al despertar reclama mediante PostgreSQL solo los trabajos vencidos; `FOR UPDATE SKIP LOCKED`, los leases y `activeDrain` evitan doble procesamiento entre instancias o llamadas simultaneas. Los estados terminales no conservan temporizador.
|
|
|
|
Al arrancar RAG, el scheduler ejecuta un drain y reconstruye el siguiente despertar desde PostgreSQL. `remoteJobId` e idempotency key permanecen durables, por lo que un reinicio entre consultas continua el trabajo remoto existente sin repetir PaddleOCR.
|
|
|
|
El reconciliador general conserva su intervalo independiente:
|
|
|
|
```text
|
|
LIFECYCLE_RECONCILE_INTERVAL_MS=300000
|
|
```
|
|
|
|
Ese ciclo ya no es el mecanismo normal de latencia. Permanece como red de seguridad para leases vencidos, caidas, candidatas incompletas, retencion e invariantes PostgreSQL/Qdrant.
|
|
|
|
Se eliminaron `pollUntilTerminal()`, `OCR_PAGE_TIMEOUT_MS` y `OCR_TOTAL_TIMEOUT_MS`: no se mantiene un bucle de polling en memoria ni configuracion que aparente imponer timeouts que RAG no aplica.
|
|
|
|
### Algoritmo durable
|
|
|
|
El scheduler:
|
|
|
|
1. consulte el proximo `next_attempt_at`;
|
|
2. programe un temporizador hasta ese instante;
|
|
3. reclame trabajos vencidos con lock de PostgreSQL;
|
|
4. vuelva a consultar OCR;
|
|
5. reprograme solo los trabajos pendientes;
|
|
6. deje de seguir un trabajo cuando termine;
|
|
7. reconstruya su plan al reiniciar.
|
|
|
|
El reconciliador de cinco minutos no se elimina ni se detiene cuando termina un trabajo. Aunque no haya trabajos OCR, sigue ejecutandose y normalmente no encuentra nada que recuperar.
|
|
|
|
No se recomienda introducir primero un callback OCR -> RAG. Un callback exige otro endpoint interno, autenticacion, reintentos e idempotencia inversa. El scheduler pull durable mejora la latencia conservando el aislamiento actual.
|
|
|
|
## Modelo de revision por fases
|
|
|
|
En la fase actual, el OCR es un servicio best-effort y la ingesta se orquesta mediante un agente. El flujo debe poder terminar sin una GUI ni una persona esperando para corregir cada documento. Los quality gates detectan fallos estructurales y señales estadisticas, pero no garantizan exactitud semantica: un reconocedor puede devolver un caracter incorrecto con confianza alta.
|
|
|
|
La aceptacion operativa exige conservar imagen, texto, lineas, bounding boxes, confianzas, hashes y estado revisable. No exige que todo texto OCR sea literalmente perfecto. El agente puede inspeccionar esa evidencia y usar el contrato de revision existente; aprobar, indexar y activar contenido siguen siendo operaciones separadas sujetas a sus autorizaciones.
|
|
|
|
Una consola futura podra presentar el mismo contrato a una persona antes de guardar contenido en RAG. Tambien podra incorporarse un modelo visual como segundo revisor para casos ambiguos, usando el recorte de imagen, el texto y su contexto. Ninguno de esos componentes forma parte del cierre de la fase actual y nunca debe introducir sustituciones silenciosas.
|
|
|
|
En documentos hibridos, `imageUrl` es `null` para paginas nativas y solo referencia una imagen protegida para paginas enviadas a OCR. La revision valida imagenes exclusivamente en esas paginas; exigir una imagen OCR para contenido nativo haria fallar una candidata integra.
|
|
|
|
## Fallos y garantias
|
|
|
|
| Situacion | Conducta esperada |
|
|
|---|---|
|
|
| Reenvio del mismo PDF y configuracion | Reutiliza identidad y trabajo compatible. |
|
|
| Reinicio de RAG | Recupera trabajos y finalizacion desde PostgreSQL y artefactos. |
|
|
| Reinicio de OCR | Recupera una vez el trabajo mediante lease; una segunda interrupcion falla cerrado. |
|
|
| Respuesta con identidad distinta | `OCR_RESPONSE_INTEGRITY_FAILED`; no publica contenido. |
|
|
| Calidad bloqueante | Version `failed`; activa anterior intacta. |
|
|
| Advertencia de calidad | Candidata `review_required`; exige revision. |
|
|
| Fallo durante indexacion | Version no activa; reconciliador valida y recupera o falla. |
|
|
| Cambio concurrente de activa | No activa silenciosamente; exige nueva precondicion. |
|
|
|
|
## Estado productivo verificado
|
|
|
|
- RAG y OCR `0.2.1` estan desplegados desde la revision `960e04a5a9fc3a3ef108fa4ef19d5ff42dbdb1ae`.
|
|
- PostgreSQL, Qdrant, OCR y reconciliador estan sanos.
|
|
- FacturaTech v8 completo OCR y revision, pero fue rechazada sin aprobar, indexar ni activar; v1 sigue activa.
|
|
- Una prueba productiva sintetica demostro el flujo hibrido: pagina 1 nativa, pagina 2 OCR y `review_required` en menos de 18 segundos, sin activacion y con cola final vacia.
|
|
- La limpieza de versiones OCR descubrio dos defectos en la decision de paginas blank y el orden de purga. Ambos estan corregidos y verificados en produccion.
|
|
- Las dos candidatas sinteticas y FacturaTech v2-v8 estan `purged`; sus directorios duraderos descartados fueron eliminados. No quedan estados bloqueantes y v1 conserva `36/36` puntos.
|
|
|
|
## Fuentes de detalle
|
|
|
|
| Necesidad | Documento |
|
|
|---|---|
|
|
| Flujo de entrada e identidades | [`INGESTA.md`](./INGESTA.md) |
|
|
| Normalizacion y chunking | [`PROCESADO.md`](./PROCESADO.md) |
|
|
| Retrieval y respuestas | [`SALIDA.md`](./SALIDA.md) |
|
|
| Estados, umbrales y contrato OCR | [`CONTRATO_CICLO_VIDA_Y_OCR.md`](./CONTRATO_CICLO_VIDA_Y_OCR.md) |
|
|
| Operacion de produccion | [`OPERATIVA.md`](./OPERATIVA.md) |
|
|
| Orden de trabajo pendiente | [`PENDIENTES_RAG.md`](./PENDIENTES_RAG.md) |
|
|
|
|
Este documento explica el funcionamiento general vigente. El contrato conserva la autoridad sobre invariantes y criterios de aceptacion; la operativa conserva la autoridad sobre el entorno desplegado.
|