533 lines
17 KiB
Markdown
533 lines
17 KiB
Markdown
# Ingesta
|
|
|
|
**Proyecto:** Workspace de tools IA para empresas
|
|
**Modulo:** RAG
|
|
**Ultima actualizacion:** 2026-04-02
|
|
**Ultima modificacion por:** Agente tools IA para potenciar servicios empresariales
|
|
**Estado:** En definicion
|
|
|
|
---
|
|
|
|
## Proposito
|
|
|
|
Definir que es la ingesta dentro del sistema RAG, que responsabilidades tiene y que debe dejar preparado para el resto de modulos.
|
|
|
|
---
|
|
|
|
## Que es la ingesta
|
|
|
|
La ingesta es el punto de entrada del conocimiento al RAG.
|
|
|
|
Su funcion es recibir fuentes de informacion y convertirlas en entradas manejables para el sistema, dejandolas listas para su posterior procesado, indexacion y recuperacion.
|
|
|
|
No debe encargarse de todo el pipeline. Su objetivo es incorporar y registrar correctamente las fuentes.
|
|
|
|
---
|
|
|
|
## Responsabilidades de la ingesta
|
|
|
|
La ingesta debe ocuparse de:
|
|
|
|
1. Recibir una fuente de informacion.
|
|
2. Identificar su tipo.
|
|
3. Leer su contenido o referencia.
|
|
4. Registrar metadatos basicos.
|
|
5. Entregar el resultado a la fase de procesado.
|
|
|
|
---
|
|
|
|
## Tipos de fuente previstos
|
|
|
|
La primera version puede empezar por documentos, pero la ingesta debe nacer pensada para admitir mas tipos de fuente.
|
|
|
|
Fuentes previstas:
|
|
- archivos locales
|
|
- carpetas
|
|
- documentacion de proyecto
|
|
- codigo fuente de proyecto
|
|
- repositorios
|
|
- endpoints o APIs
|
|
- bases de datos
|
|
- otras fuentes conectables en el futuro
|
|
|
|
---
|
|
|
|
## Alcance de la primera version
|
|
|
|
La primera version de la ingesta debe centrarse en:
|
|
|
|
- leer archivos de documentacion
|
|
- leer PDFs con texto extraible
|
|
- leer codigo fuente del proyecto
|
|
- recorrer carpetas concretas
|
|
- registrar que fuente entro al sistema
|
|
- dejar preparada la extension a nuevas fuentes mas adelante
|
|
|
|
Caso practico inicial:
|
|
- carpeta `docs/` del workspace como primera fuente real de prueba
|
|
- carpeta `RAG/src/` como primera fuente real de prueba para el modo `codigo`
|
|
|
|
---
|
|
|
|
## Salida esperada de la ingesta
|
|
|
|
La ingesta no debe devolver aun conocimiento recuperable final. Debe devolver una representacion normalizada de la fuente para el siguiente modulo.
|
|
|
|
Esa salida deberia incluir como minimo:
|
|
|
|
- identificador de fuente
|
|
- tipo de fuente
|
|
- origen o ruta
|
|
- contenido bruto o accesible
|
|
- fecha de lectura
|
|
- metadatos basicos disponibles
|
|
|
|
---
|
|
|
|
## Metadatos minimos aceptados
|
|
|
|
La primera propuesta aceptada para metadatos minimos del sistema es esta:
|
|
|
|
- `source_id`
|
|
- `source_type`
|
|
- `source_path` o `source_ref`
|
|
- `document_id`
|
|
- `chunk_id`
|
|
- `title`
|
|
- `updated_at`
|
|
- `hash`
|
|
- `status`
|
|
- `version`
|
|
- `tags`
|
|
|
|
Metadatos recomendados adicionales para la capa de embeddings:
|
|
|
|
- `embedding_provider`
|
|
- `embedding_model`
|
|
- `embedding_dimensions`
|
|
|
|
No todos tendran el mismo peso en la v1, pero conviene que el diseño nazca preparado para soportarlos.
|
|
|
|
**Por que se adopta este conjunto:**
|
|
|
|
- `source_id`, `document_id` y `chunk_id` permiten trazabilidad y actualizacion por niveles.
|
|
- `source_type` y `source_path` o `source_ref` permiten entender de donde salio cada entrada.
|
|
- `title` mejora legibilidad, depuracion y futuras recuperaciones.
|
|
- `updated_at`, `hash`, `status` y `version` preparan el sistema para cambios, invalidez y evolucion de contenido.
|
|
- `tags` deja abierta una capa ligera de clasificacion sin obligar a una taxonomia compleja en la v1.
|
|
|
|
---
|
|
|
|
## Jerarquia de identificacion
|
|
|
|
Se adopta una jerarquia simple de 3 niveles:
|
|
|
|
1. `source`
|
|
- origen logico de ingesta
|
|
- ejemplos: carpeta `docs/`, carpeta `src/`, repositorio, API, tabla o coleccion externa
|
|
|
|
2. `document`
|
|
- unidad concreta dentro de la fuente
|
|
- ejemplos: `docs/HISTORIAL_SESIONES.md`, `src/app/main.ts`, `manual_cliente.pdf`
|
|
|
|
3. `chunk`
|
|
- fragmento recuperable del documento
|
|
|
|
Esta separacion permite actualizar una pieza concreta sin tener que tratar toda la fuente como si hubiera cambiado por completo.
|
|
|
|
**Por que se adopta esta jerarquia:**
|
|
|
|
- una carpeta o repositorio no debe ser la unica unidad de control, porque los cambios reales suelen ocurrir a nivel de documento.
|
|
- un mismo documento debe poder actualizarse sin reingestar toda la fuente completa.
|
|
- el chunk debe ser la unidad de recuperacion, no de identidad principal del conocimiento.
|
|
- esta estructura se parece a un sistema de versionado por niveles, y deja abierta la puerta a historico, reindexacion parcial y auditoria.
|
|
|
|
---
|
|
|
|
## Criterio para los identificadores
|
|
|
|
Se trabajara con estos tres identificadores:
|
|
|
|
- `source_id`: identifica la fuente logica
|
|
- `document_id`: identifica el documento concreto
|
|
- `chunk_id`: identifica cada fragmento recuperable
|
|
|
|
La carpeta `docs/` puede ser una `source`, pero `docs/HISTORIAL_SESIONES.md` debe tener su propio `document_id` para poder detectar cambios, reindexar y mantener trazabilidad fina.
|
|
|
|
**Por que se decide asi:**
|
|
|
|
- si `source_id` absorbiera toda la identidad, perderiamos control fino sobre los documentos internos.
|
|
- si solo identificaramos chunks, perderiamos una unidad intermedia clave para actualizacion, limpieza y observabilidad.
|
|
- separar estos tres identificadores permite mantener el sistema simple pero preparado para crecer.
|
|
|
|
---
|
|
|
|
## Propuesta concreta para construir los identificadores
|
|
|
|
Se adopta esta propuesta inicial.
|
|
|
|
### `source_id`
|
|
|
|
**Formato:**
|
|
`src:<tenant>:<source_kind>:<source_name>`
|
|
|
|
**Ejemplos:**
|
|
- `src:default:folder:workspace-docs`
|
|
- `src:default:folder:project-code`
|
|
- `src:default:manual:client-upload`
|
|
- `src:cliente-a:repo:backend-api`
|
|
- `src:cliente-a:api:java-docs`
|
|
|
|
**Que representa:**
|
|
- el origen logico de ingesta
|
|
- no un archivo concreto
|
|
- debe mantenerse estable aunque cambien documentos internos
|
|
|
|
**Que significa `tenant`:**
|
|
- es el espacio logico de separacion de datos
|
|
- sirve para distinguir clientes, proyectos, entornos o contextos aislados dentro del mismo RAG
|
|
- en la v1 puede usarse simplemente `default` cuando aun no necesitemos separar nada
|
|
|
|
**Para que nos sirve en nuestro sistema:**
|
|
- deja preparado el RAG para dar servicio a varios clientes o aplicaciones sin mezclar su informacion
|
|
- permite que una misma arquitectura y un mismo servicio RAG trabajen para varios consumidores
|
|
- facilita crecer hacia un modelo centralizado en el que mejoramos el RAG una vez y varios clientes o apps se benefician
|
|
|
|
**Ejemplo practico de multi-tenant:**
|
|
- `src:cliente-a:folder:workspace-docs`
|
|
- `src:cliente-b:folder:workspace-docs`
|
|
|
|
Ambos pueden tener un archivo llamado `docs/manual.md`, pero seguiran siendo distintos porque pertenecen a tenants diferentes.
|
|
|
|
Esto evita mezclar conocimiento de clientes o proyectos distintos dentro del mismo sistema.
|
|
|
|
**Reglas:**
|
|
- `tenant`: `default` si no hay cliente o espacio separado aun
|
|
- `source_kind`: tipo logico de fuente, por ejemplo `folder`, `repo`, `manual`, `api`, `db`
|
|
- `source_name`: nombre corto, legible y estable
|
|
|
|
### `document_id`
|
|
|
|
**Formato:**
|
|
`doc:<source_id>:<document_key>`
|
|
|
|
**Ejemplos:**
|
|
- `doc:src:default:folder:workspace-docs:docs/historial_sesiones.md`
|
|
- `doc:src:default:folder:project-code:src/app/main.ts`
|
|
- `doc:src:default:manual:client-upload:manual_cliente.pdf`
|
|
- `doc:src:cliente-a:api:java-docs:list`
|
|
|
|
**Que representa:**
|
|
- el documento o unidad concreta dentro de una fuente
|
|
- es la unidad principal para detectar cambios, desapariciones o reingesta selectiva
|
|
|
|
**Reglas:**
|
|
- usar ruta relativa si existe
|
|
- si no existe ruta, usar nombre normalizado o referencia estable
|
|
- evitar espacios y diferencias cosmeticas innecesarias en el identificador
|
|
|
|
### `chunk_id`
|
|
|
|
**Formato:**
|
|
`chk:<document_id>:<chunk_mode>:<chunk_index>`
|
|
|
|
**Ejemplos:**
|
|
- `chk:doc:src:default:folder:workspace-docs:docs/historial_sesiones.md:documental:0001`
|
|
- `chk:doc:src:default:folder:project-code:src/app/main.ts:codigo:0003`
|
|
|
|
**Que representa:**
|
|
- cada fragmento recuperable del documento
|
|
|
|
**Reglas:**
|
|
- `chunk_mode`: permite distinguir si el chunk fue generado en modo `documental` o `codigo`
|
|
- `chunk_index`: indice secuencial con padding para mantener orden legible
|
|
|
|
**Ejemplo practico simple:**
|
|
|
|
Supongamos esta fuente:
|
|
|
|
- `source_id`: `src:default:folder:workspace-docs`
|
|
|
|
Y dentro de ella dos documentos:
|
|
|
|
- `document_id`: `doc:src:default:folder:workspace-docs:docs/readme.md`
|
|
- `document_id`: `doc:src:default:folder:workspace-docs:docs/historial_sesiones.md`
|
|
|
|
Si `docs/readme.md` se parte en 3 chunks documentales:
|
|
|
|
- `chk:doc:src:default:folder:workspace-docs:docs/readme.md:documental:0001`
|
|
- `chk:doc:src:default:folder:workspace-docs:docs/readme.md:documental:0002`
|
|
- `chk:doc:src:default:folder:workspace-docs:docs/readme.md:documental:0003`
|
|
|
|
Y `docs/historial_sesiones.md` se parte en 2 chunks documentales:
|
|
|
|
- `chk:doc:src:default:folder:workspace-docs:docs/historial_sesiones.md:documental:0001`
|
|
- `chk:doc:src:default:folder:workspace-docs:docs/historial_sesiones.md:documental:0002`
|
|
|
|
El `0001` no compite con el `0001` del otro documento.
|
|
|
|
El indice solo tiene sentido dentro de su propio `document_id`.
|
|
|
|
Eso permite:
|
|
- saber a que documento pertenece cada chunk
|
|
- conservar el orden interno del documento
|
|
- distinguir chunks de distintos modos si algun dia un mismo documento se procesa de manera diferente
|
|
|
|
---
|
|
|
|
## Normalizacion recomendada
|
|
|
|
Para mantener consistencia:
|
|
|
|
- usar minusculas cuando no rompa semantica importante
|
|
- reemplazar espacios por guion bajo o guion medio segun convenga
|
|
- usar rutas relativas como referencia principal cuando existan
|
|
- evitar caracteres redundantes o variables del entorno que rompan estabilidad
|
|
- no incluir hashes dentro del identificador principal
|
|
|
|
El `hash` debe vivir como metadato, no como parte del ID. Asi el identificador se mantiene estable y el hash sirve para detectar cambios.
|
|
|
|
---
|
|
|
|
## Propuesta para `document_key`
|
|
|
|
Se adopta esta regla general:
|
|
|
|
- si el documento pertenece a una fuente con estructura de rutas, usar su ruta relativa normalizada dentro de la fuente
|
|
- si el documento no tiene ruta natural, usar un nombre o referencia estable normalizada
|
|
- si la fuente es derivada o externa, usar una referencia corta y estable que identifique la unidad documental
|
|
|
|
### Formato esperado
|
|
|
|
`document_key` debe ser:
|
|
|
|
- legible
|
|
- estable
|
|
- relativo a la fuente cuando sea posible
|
|
- suficientemente especifico para no colisionar dentro de una misma `source`
|
|
|
|
### Reglas de normalizacion
|
|
|
|
1. Usar ruta relativa respecto de la fuente cuando exista.
|
|
2. Unificar separadores a `/`.
|
|
3. Eliminar prefijos absolutos del sistema.
|
|
4. Mantener la extension del archivo si aplica.
|
|
5. Convertir a minusculas cuando no rompa semantica importante.
|
|
6. Reemplazar espacios por `_`.
|
|
7. Evitar caracteres redundantes o decorativos.
|
|
8. No incluir hashes, timestamps volatiles ni parametros temporales.
|
|
|
|
### Ejemplos
|
|
|
|
#### Fuente tipo carpeta
|
|
|
|
- fuente: `src:default:folder:workspace-docs`
|
|
- archivo real: `/home/pancho/Documentos/Empresa/Desarrollo/IA/docs/HISTORIAL_SESIONES.md`
|
|
- `document_key`: `docs/historial_sesiones.md`
|
|
|
|
#### Fuente tipo repo
|
|
|
|
- fuente: `src:default:repo:backend-api`
|
|
- archivo real: `/repo/src/app/main.ts`
|
|
- `document_key`: `src/app/main.ts`
|
|
|
|
#### Documento suelto manual
|
|
|
|
- fuente: `src:default:manual:client-upload`
|
|
- archivo real: `Manual Cliente Final.pdf`
|
|
- `document_key`: `manual_cliente_final.pdf`
|
|
|
|
#### Fuente derivada o externa
|
|
|
|
- fuente: `src:default:api:java-docs`
|
|
- unidad documental: documentacion de `ArrayList`
|
|
- `document_key`: `java/util/arraylist`
|
|
|
|
### Por que se decide asi
|
|
|
|
- mantiene trazabilidad sin depender de rutas absolutas del entorno
|
|
- evita que mover el proyecto de maquina o carpeta rompa la identidad del documento
|
|
- funciona tanto para archivos estructurados como para documentos sueltos o fuentes externas
|
|
- deja el sistema preparado para futuras ingestas derivadas sin cambiar el modelo base
|
|
|
|
**Aclaracion importante:**
|
|
|
|
- `document_key` es una identidad interna estable
|
|
- no debe ser la unica referencia para recargar el fichero real
|
|
- para reingesta o recarga debe mantenerse tambien el localizador original del recurso
|
|
|
|
---
|
|
|
|
## Documentos sueltos y fuentes por defecto
|
|
|
|
El sistema debe soportar tambien documentos sueltos que no pertenezcan de forma natural a una carpeta o coleccion preexistente.
|
|
|
|
Ejemplo:
|
|
- un PDF entregado por un cliente
|
|
|
|
En esos casos:
|
|
|
|
- el documento seguira teniendo su propio `document_id`
|
|
- no se dejara `source_id` vacio o nulo
|
|
- se usara una fuente logica por defecto para agrupar este tipo de entradas
|
|
|
|
La idea es que el sistema pueda distinguir entre:
|
|
|
|
- documentos nacidos dentro de una fuente estructurada
|
|
- documentos incorporados como entradas sueltas
|
|
|
|
Esto evita nulos, mantiene consistencia y deja abierta la posibilidad de definir despues varias fuentes logicas para documentos manuales, aportados por cliente o cargados desde otras vias.
|
|
|
|
**Por que se decide asi:**
|
|
|
|
- un documento suelto sigue necesitando un origen logico dentro del sistema.
|
|
- evitar `null` en `source_id` simplifica reglas internas, validaciones y futuras integraciones.
|
|
- agrupar documentos sueltos bajo una fuente logica por defecto permite empezar simple y luego especializar si hace falta.
|
|
|
|
---
|
|
|
|
## Vision de integracion futura
|
|
|
|
Este diseño de ingesta tambien debe facilitar que el RAG pueda integrarse mas adelante con herramientas y entornos de trabajo del propio equipo, por ejemplo OpenCode por proyecto.
|
|
|
|
La idea es que, aunque la documentacion exista fisicamente en disco, el RAG pueda ofrecer una capa practica de acceso al conocimiento del proyecto a medida que ese conocimiento crezca.
|
|
|
|
Esto refuerza varias decisiones tomadas en este modulo:
|
|
|
|
- trazabilidad por fuente, documento y chunk
|
|
- soporte para carpetas completas y documentos sueltos
|
|
- preparacion para actualizacion de contenido
|
|
- diseño desacoplado del tipo concreto de consumidor
|
|
|
|
---
|
|
|
|
## Relacion con el modulo de actualizacion
|
|
|
|
La ingesta debe quedar preparada para convivir con un futuro sistema de actualizacion.
|
|
|
|
Eso implica que, desde el inicio, conviene contemplar:
|
|
|
|
- deteccion de nuevas fuentes
|
|
- deteccion de cambios en fuentes ya conocidas
|
|
- posibilidad de releer una fuente
|
|
- trazabilidad de cuando y desde donde entro una version concreta
|
|
|
|
No es necesario implementar todo esto en la primera version, pero si diseñarlo para no bloquear su evolucion posterior.
|
|
|
|
---
|
|
|
|
## Principios de diseño
|
|
|
|
- Simple en la primera version.
|
|
- Desacoplada del tipo concreto de fuente.
|
|
- Preparada para crecimiento.
|
|
- Trazable desde el origen.
|
|
- Compatible con futuras actualizaciones y versionado.
|
|
|
|
---
|
|
|
|
## Uso de modelo durante la ingesta
|
|
|
|
Se acepta que el sistema RAG podra usar un modelo tambien en la fase de entrada, no solo en la fase de salida o consumo.
|
|
|
|
Su funcion no seria responder al usuario final, sino ayudar a:
|
|
|
|
- entender mejor el contenido entrante
|
|
- detectar tema principal y puntos clave
|
|
- extraer estructura util
|
|
- identificar elementos criticos o destacables
|
|
- preparar mejor el conocimiento que luego consumira el RAG
|
|
|
|
**Criterio actual:**
|
|
|
|
- en la primera fase no debemos depender obligatoriamente de modelos caros para esta tarea
|
|
- mas adelante puede existir un modelo fijo de uso interno dentro del pipeline de ingesta
|
|
- tambien queda abierta una futura interfaz interactiva de alimentacion en la que el usuario pueda escoger un modelo mas potente si quiere enriquecer el procesamiento
|
|
|
|
**Implicacion de diseño:**
|
|
|
|
La ingesta no debe quedar pensada solo como lectura mecanica de archivos. Debe poder evolucionar hacia una ingesta asistida por modelo.
|
|
|
|
---
|
|
|
|
## Modos de ingesta previstos
|
|
|
|
Se adopta este criterio de funcionamiento:
|
|
|
|
- por defecto, la ingesta funcionara en modo mecanico
|
|
- ese modo seguira pudiendo usar un modelo predefinido dentro del pipeline si asi se define
|
|
- la arquitectura debe quedar preparada desde el inicio para recibir parametros de modo o de interaccion
|
|
- si esos parametros existen, la ingesta podra comportarse como una ingesta enriquecida o interactiva
|
|
|
|
Esto permite que la primera version funcione sin rehacer la arquitectura cuando se amplie.
|
|
|
|
### Modo por defecto
|
|
|
|
Si no se reciben parametros especiales desde una interfaz:
|
|
|
|
- la ingesta actua de forma automatica
|
|
- usa el modelo predefinido si corresponde
|
|
- no espera decisiones del usuario
|
|
|
|
### Modo interactivo o enriquecido
|
|
|
|
Si se reciben parametros desde una interfaz o flujo enriquecido:
|
|
|
|
- la ingesta puede detectar que no esta en modo basico
|
|
- puede permitir cambio de modelo
|
|
- puede recibir instrucciones, marcas o directrices del usuario
|
|
- puede priorizar o etiquetar informacion importante antes de indexar
|
|
|
|
### Objetivo de este diseño
|
|
|
|
Separar desde el inicio:
|
|
|
|
- funcionamiento base estable y automatizable
|
|
- enriquecimiento opcional sin romper el flujo normal de ingesta
|
|
|
|
Esto evita tener que rehacer el codigo cuando el sistema evolucione.
|
|
|
|
---
|
|
|
|
## Enriquecimiento ligero opcional
|
|
|
|
Se deja abierta una via para un enriquecimiento ligero opcional desde etapas tempranas, siempre que no entorpezca la ingesta.
|
|
|
|
La forma mas simple de hacerlo seria:
|
|
|
|
- mantener la ingesta mecanica como camino principal
|
|
- ejecutar el enriquecimiento solo si llega un parametro explicito
|
|
- limitar ese enriquecimiento a tareas pequenas y acotadas
|
|
|
|
Ejemplos adecuados para ese enriquecimiento ligero:
|
|
|
|
- extraer tema principal
|
|
- proponer palabras clave
|
|
- detectar posibles puntos criticos
|
|
- generar una descripcion corta del documento
|
|
|
|
Ejemplos que no conviene meter en esta fase ligera:
|
|
|
|
- analisis profundo costoso
|
|
- interacciones largas con usuario
|
|
- multiples rondas de refinado
|
|
- procesos que bloqueen innecesariamente la ingesta base
|
|
|
|
**Criterio recomendado:**
|
|
|
|
El enriquecimiento ligero debe ser:
|
|
|
|
- opcional
|
|
- rapido
|
|
- barato
|
|
- no bloqueante
|
|
- facil de omitir sin afectar al pipeline principal
|
|
|
|
---
|
|
|
|
## Preguntas a cerrar
|
|
|
|
1. Si la ingesta trabajara por archivos individuales, carpetas, colecciones o todo a la vez.
|
|
2. Como construiremos exactamente `source_id`, `document_id` y `chunk_id`.
|
|
3. Que nombre tendran las fuentes logicas por defecto para documentos sueltos.
|
|
4. Como distinguiremos entre fuente nueva, fuente actualizada y fuente obsoleta.
|