Un agente de indexación
Los datos pueden adoptar distintas formas, y cada una necesita una estrategia adecuada para extraerlos o recuperarlos desde algún repositorio de datos. Elegir una estrategia incompatible con los datos es la causa más frecuente de los fallos silenciosos en un agente de indexación de producción.
Un agente de indexación aplica la idea de flujo de trabajo a una fuente de conocimiento externo mediante un pipeline definido por el desarrollador. Primero genera embeddings e indexa información; después recupera fragmentos de información pertinentes (según la entrada recibida) que usa como contexto para producir una respuesta. El ejemplo muestra primero este proceso para texto no estructurado y luego presenta la recuperación como una herramienta que puede ser invocada por un bucle ReAct externo. Esta sección profundiza más tarde en diferentes formatos de datos.
- La generación sin recuperación responde con el contexto actual y el entrenamiento del modelo.
- El RAG tradicional ejecuta un paso fijo de recuperación antes de cada respuesta generada.
- La recuperación controlada por el agente expone la recuperación como herramienta, de modo que el bucle decide si necesita otra consulta.
Profundo · Historia¿Seguir la evolución de RAG desde el entrenamiento conjunto hasta la recuperación?
El origen de RAG: un sistema entrenado de extremo a extremo
La versión de RAG más habitual hoy omite gran parte del diseño original. Conocer esa diferencia cambia la forma de entender el recuperador que vas a conectar.
Cuando Lewis y sus colaboradores acuñaron el término generación aumentada por recuperación (del inglés Retrieval Augmented Generation, RAG) en 2020, no describían un modelo con un buscador añadido. El recuperador y el generador se entrenaban juntos para la tarea. Lee primero la figura de izquierda a derecha y después observa la flecha superior.
La clave del diseño está en la flecha «Retroalimentación de extremo a extremo por q y pθ». Una sola función de coste (loss) actualizaba ambas partes. El codificador de consultas aprendía qué fragmentos de información podía aprovechar el generador, y el generador aprendía a apoyarse en la evidencia recuperada en vez de depender solo de su memoria.
El recuperador nació como parte del modelo y se adaptaba a la tarea, mucho antes de que se describiera como una herramienta de búsqueda colocada delante de un modelo.
Por qué hoy día la mayoría de los sistemas RAG descarta el entrenamiento conjunto
Hoy casi nadie entrena sistemas RAG de ese modo por dos razones prácticas. No se puede retroalimentar a través de un modelo avanzado al que se accede mediante una API. Incluso con un modelo alojado por ti, el entrenamiento conjunto del recuperador y el generador resulta costoso y fácil de desestabilizar.
La práctica convergió en un montaje más sencillo: tomar un modelo existente, mantenerlo congelado y anteponerle un recuperador para que el prompt llegue cargado de evidencia, sin entrenar nada. Las partes se construyen por separado y se conectan después. Con el tiempo, «RAG» pasó a designar ese acoplamiento, y no al sistema optimizado conjuntamente que describía el artículo.
El pipeline de recuperación y generación que vas a construir
Teniendo en cuenta las limitaciones comentadas, observa el montaje completo. Un recuperador opera delante del modelo congelado en dos líneas temporales. Una construye el índice con antelación; la otra atiende solicitudes usando ese índice. La figura muestra ambas.
Offline: construye el índice una vez, genera los embeddings de cada fragmento de datos y los guarda para realizar búsquedas rápidas.
En vivo: genera el embedding de una pregunta, recupera los K mejores fragmentos de datos y se los entrega al modelo junto con la pregunta.
El resto de esta sección construye este recorrido por partes.
Aplicado · Alcance¿Elegir paquetes, límites y formas de datos?
Define el paquete de contexto antes de elegir el almacenamiento
Antes de elegir una primitiva de recuperación, define un paquete: el conjunto completo y acotado de contexto que circulará por el pipeline.
- Para un sistema sencillo de preguntas y respuestas de un solo turno, el paquete puede ser pequeño: la pregunta, unos pocos fragmentos recuperados y la respuesta.
- Para un agente autónomo, el paquete es la memoria de trabajo que conserva durante varios turnos: restricciones, decisiones anteriores, resultados parciales, herramientas disponibles y reglas operativas.
- Para un agente de indexación de alcance arbitrario, el paquete de salida puede contener solo los fragmentos recuperados, sus fuentes, puntuaciones de relevancia y quizá un resumen. Un paquete interno distinto puede representar el pipeline lineal de la solicitud o un bucle ReAct que evalúa la relevancia y reintenta hasta reunir suficiente contexto.
La idea impone una disciplina: definir el paquete antes de elegir la base de datos. Elegir primero un almacén vectorial y esperar que cubra todo origina muchas historias de «funcionó en la demostración, pero falló en producción». La siguiente taxonomía permite comprobar si una primitiva puede entregar el paquete que exige la tarea.
Dónde encaja MCP en un sistema de recuperación
MCP le proporciona a un sistema de recuperación una interfaz definida para descubrir y consultar fuentes de contexto externas. Sin embargo, el agente todavía necesita un motor de ejecución que decida cuándo recuperar esa información, valide los resultados y los integre con el estado actual de la tarea en curso. Otras interfaces se encargan de los componentes restantes del sistema: los paquetes de habilidades (skills) agrupan instrucciones de capacidades reutilizables, el sistema A2A (Agent-to-Agent) puede derivar el trabajo a especialistas remotos, y los protocolos de interfaz de usuario transmiten en tiempo real (stream) el estado generado de vuelta a la aplicación.
La figura separa esas fronteras. Léela de izquierda a derecha para seguir la entrada de contexto mediante MCP y la entrega de tareas mediante A2A; de abajo arriba, para seguir la intermediación de capacidades mediante skills, la ejecución en el runtime y la experiencia generada. Elige la frontera que corresponda al paquete y al estado del sistema que debe transportar.
Asocia una primitiva de recuperación a la forma de los datos
Cada tipo de datos exige una primitiva de extracción adecuada. Si eliges la vía equivocada, el sistema seguirá devolviendo resultados plausibles mientras omite lo que pide la consulta, sin emitir ningún error. La tabla siguiente relaciona cada tipo de datos con su primitiva de extracción.
| Forma | Ejemplos | Primitiva adecuada |
|---|---|---|
| Prosa no estructurada | Documentos, artículos, comentarios de código, transcripciones | Vector denso y reranking con cross-encoder |
| Documentos jerárquicos | Contratos legales, manuales técnicos, especificaciones anidadas | Índice de árbol con punteros al elemento padre |
| Tablas estructuradas o gobernadas | Registros de clientes, libros contables, tablas de recursos humanos | Capa semántica sobre la fuente de verdad |
| Datos relacionales o grafos | Organigramas, dependencias de código, grafos de conocimiento | Recorrido de grafos (Cypher, GraphQL o personalizado) |
El ejemplo de prosa no estructurada lleva un corpus a través de la recuperación y la generación hasta obtener una respuesta fundamentada.
Cada solicitud recorre los mismos cuatro pasos:
- Convertir la consulta en un vector mediante un embedding.
- Buscar en el índice los fragmentos más similares.
- Añadir esos fragmentos al prompt.
- Generar una respuesta fundamentada en ellos.
Los agentes de indexación que gestionan otras primitivas suelen conservar esta estructura y cambiar la lógica de búsqueda, representación y verificación. Experimenta con la opción que mejor se ajuste a tus datos.
El embedding, la primitiva fundamental para el resto
Cada agente de indexación para prosa no estructurada parte de la misma primitiva. Un embedding es una dirección numérica aprendida para un fragmento de texto: es un vector de longitud fija creado de forma que textos semánticamente similares queden próximos en el espacio vectorial. Esto tiene dos consecuencias prácticas:
Ambas operaciones dependen de una sola primitiva: el modelo de embeddings. El curso dirige las llamadas mediante helpers.embed al endpoint de embeddings alojado por NVIDIA, por lo que todo funciona en el navegador sin un laboratorio ni un servidor local.
Aplicado · Contrato¿Revisar el contrato de solicitud de embeddings?
El endpoint acepta una solicitud JSON con tres campos y devuelve un array de vectores:
inputcontiene un conjunto (batch) de textos, con tipostring[].modelidentifica el modelo de embeddings, con tipostring.input_typees"query"o bien"passage".- La respuesta contiene un array
data; cada entrada del mismo incluye unembeddingde tiponumber[].
Los modelos de embeddings de NVIDIA asignan vectores distintos al mismo texto según el
input_type que le pases. El objetivo durante el entrenamiento es acercar una pregunta hacia los pasajes que la responden, en lugar de hacia textos que simplemente repiten sus palabras. Por eso, una puntuación de coseno entre dos entradas con el tipo correcto refleja muy bien la relevancia. Generar el embedding de una consulta con el tipo "passage" (o viceversa) altera la función de puntuación de forma silenciosa, lo que produce un recall más bajo sin mostrar ningún mensaje de error.
Un recuperador completo en treinta líneas de top-K por coseno
Una «base de datos vectorial» presenta una interfaz elaborada para una tarea sencilla: almacena cada pasaje junto a su embedding y devuelve los top-K más cercanos al embedding de la consulta según la similitud coseno. En el navegador, el núcleo cabe en treinta líneas de JavaScript.
La celda siguiente construye un agente de indexación sobre unos pocos documentos. Edita el corpus y la consulta; después observa qué pasajes llegan a las primeras posiciones y por qué.
Un índice vectorial almacena en caché las salidas de un modelo de embeddings. Los sistemas de producción deben protegerse contra varios fallos:
- Al cambiar el modelo, cada vector almacenado pierde su significado hasta que se vuelvan a generar los embeddings de todos los pasajes.
- Si el proveedor actualiza el modelo silenciosamente, las puntuaciones pueden cambiar sin error.
- Si dos servicios comparten un índice pero fijan identificadores de modelo distintos, uno recibirá resultados sin sentido.
Un índice fiable registra el identificador del modelo junto a cada vector y se niega a mezclar versiones. El modelo fijado en este curso es
nvidia/llama-nemotron-embed-1b-v2, servido mediante el proxy alojado del curso en build.nvidia.com.
Aplicado · Fragmentos¿Recuperar fragmentos pequeños con su contexto superior?
Buscar fragmentos pequeños y devolver el documento padre
Un agente de indexación top-K básico afronta una tensión entre recall y precisión que ningún modelo de embeddings elimina. Debes elegir entre fragmentos breves y documentos largos:
- Los fragmentos breves producen embeddings precisos, pero aportan poco contexto: el vector representa una sola idea concreta.
- Los documentos largos conservan el contexto, pero generan embeddings difusos: el vector promedia muchas ideas.
El patrón de producción indexa en dos niveles. Genera embeddings de fragmentos pequeños para mantener la precisión y, cuando uno coincide, devuelve el documento padre para que el modelo vea el contexto completo.
El ejercicio usa tres documentos padre, cada uno dividido en fragmentos breves, y una consulta que devuelve el documento padre correspondiente.
Aplicado · Agente¿Dejar que el modelo decida cuándo recuperar información?
Presenta el índice como una herramienta que el modelo puede invocar
Un índice aislado solo responde cuando algo lo consulta. Se convierte en un agente de indexación cuando se presenta como una herramienta que el modelo puede elegir. Así, el modelo decide cuándo merece la pena recuperar datos. La celda lo hace en cinco etapas:
- El corpus se procesa una vez y se conserva en un índice en memoria.
- Se declara una herramienta
retrieve(question, k)mediante un esquema JSON. - El agente recibe la pregunta y decide si invoca la herramienta.
- Si la invoca, ejecuta la recuperación por coseno; los pasajes top-K se añaden como mensaje de herramienta.
- Una segunda llamada al LLM redacta la respuesta final a partir de los pasajes recuperados.
El patrón de «recuperador como herramienta» se traslada directamente a producción. Sustituir la función en memoria por un pipeline de servidor con FAISS, BM25 y reranking solo cambia el ejecutor; el esquema, el bucle del agente y la respuesta final permanecen iguales.
Aplicado · Formas¿Comparar las demás formas de índice?
Cómo se construyen las otras tres formas
Ya has construido la vía de la prosa no estructurada desde el corpus hasta la respuesta. Las otras tres aparecen aquí para que puedas reconocerlas y elegir la primitiva adecuada. Cada una tiene un patrón de producción establecido:
- Documentos jerárquicos. Un segmentador conserva la jerarquía de títulos y combina extracción atómica de tablas, punteros al elemento padre y un índice doble para búsqueda estructural y semántica. Se indexan fragmentos hijos para mejorar el recall y se recupera el padre correspondiente para que el modelo lea la cláusula dentro de su sección.
- Recuperación de imágenes de página para figuras y gráficos. Una configuración con dos espacios vectoriales genera embeddings de la página renderizada y de su texto. Así, la consulta también puede recuperar una figura o diapositiva cuando la respuesta esté en el contenido visual.
- Tablas estructuradas y gobernadas. No se construyen en este curso. El patrón de producción sitúa una capa semántica entre el agente y los datos por fila, y expone solo las métricas seleccionadas que requiere el paquete.
- Datos relacionales o grafos. En lugar de un almacén vectorial, el agente invoca una herramienta de recorrido de grafos escrita en Cypher, GraphQL o una interfaz propia. Recibe un subgrafo cuyas aristas explícitas llegan al prompt y conservan las relaciones entre entidades.
Profundo · GraphRAG¿Explorar la recuperación sobre todo el corpus con GraphRAG?
Cuando top-K es la herramienta equivocada: GraphRAG y preguntas globales
Cada recuperador de esta página responde a una pregunta local cuya respuesta aparece en unos pocos pasajes que top-K puede encontrar, como qué dice un contrato sobre la rescisión o qué artículo introdujo HyDE. Otra clase de pregunta no tiene respuesta en ningún pasaje aislado. Si preguntas por los temas principales de mil documentos, la respuesta emerge del corpus completo.
Top-K devuelve solo las tres mejores coincidencias. El modelo resume esos fragmentos sin ver los otros 997 pasajes del corpus. GraphRAG (Edge et al. 2024) cambia la forma del problema en vez de aumentar K. Durante la indexación usa un LLM para:
- leer el corpus y extraer entidades y las relaciones entre ellas en un grafo de conocimiento;
- detectar las comunidades del grafo, es decir, grupos de entidades densamente conectadas;
- resumir cada comunidad por separado.
En el momento de la consulta, el sistema resume las comunidades pertinentes y reduce las respuestas parciales a una sola. Es un proceso map-reduce sobre la estructura, no una búsqueda por similitud.
La celda muestra la diferencia en un corpus pequeño mediante el pipeline real. Responde a una pregunta global de dos maneras: recuperación top-K básica y map-reduce de GraphRAG sobre comunidades identificadas. Observa cómo top-K usa los fragmentos cuyas palabras coinciden con la pregunta, mientras que las comunidades recuperan el tema del corpus completo. Edita el corpus, las comunidades o la pregunta y vuelve a ejecutar.
Un modelo congelado con un recuperador top-K responde bien a preguntas locales, pero no a preguntas globales. Reestructurar el corpus en comunidades resumidas permite obtener la respuesta global a cambio de una indexación más costosa que se ejecuta una sola vez.
Antes de continuar
- La similitud coseno puntúa dos vectores de la misma manera sin importar cuál sea la consulta. El modelo de NVIDIA usa
input_typepara distinguir consulta y pasaje. ¿Qué aporta esa asimetría? - El índice genera una vez los embeddings del corpus, mientras que la ruta en vivo procesa cada pregunta. ¿Qué cambios exigen reindexar el corpus y cuáles solo requieren un nuevo embedding de consulta?
- Top-K siempre devuelve K pasajes, aunque todas las puntuaciones sean débiles. ¿Qué señal debería examinar el agente antes de incorporarlos al prompt?
Profundo · Fuentes¿Rastrear las fuentes de investigación sobre recuperación?
Referencias
- Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks (NeurIPS 2020). Artículo canónico sobre recuperación seguida de generación; la figura anterior se redibujó a partir de él.
- Karpukhin et al., Dense Passage Retrieval (EMNLP 2020). Formulación de doble codificador que sustenta la asimetría entre embeddings de consulta y pasaje.
- Johnson, Douze & Jégou, Billion-scale similarity search with GPUs (FAISS, 2017). Estructura de índice vectorial empleada por las bases de datos vectoriales.
- Gao et al., HyDE: Precise Zero-Shot Dense Retrieval without Relevance Labels (2022). Genera una respuesta hipotética y crea su embedding en vez del de la pregunta; resulta útil para consultas breves o ambiguas.
- Lin et al., Pretrained Transformers for Text Ranking (2020). Patrón de reranking que un stack de recuperación usa como segunda etapa.
- Edge et al., From Local to Global: A Graph RAG Approach to Query-Focused Summarization (2024). Construye un grafo de conocimiento con un LLM y resume sus comunidades para responder preguntas globales sobre el corpus.
Lista completa en Para ir más lejos · Referencias.
Prueba · recuperación en vivo
Formula una pregunta. El artefacto usa el mismo endpoint de la página para generar su embedding y clasifica un corpus pequeño mediante similitud coseno. Las barras muestran todas las puntuaciones. Después, el modelo responde a partir de los pasajes mejor clasificados y los cita. Cambia la pregunta y observa cómo varía el orden.
El corpus se procesó offline y se distribuye junto a la página como índice preconstruido; solo la pregunta necesita un embedding en vivo. Así puedes observar la separación entre indexación y servicio. Las preguntas de ejemplo también incluyen vectores preconstruidos y recuperan resultados antes de añadir una clave; al editar un pasaje, solo se vuelve a procesar ese pasaje.