RAG
Al configurar una fuente RAG (Generación Aumentada por Recuperación) en Docker Agent, tu agente obtiene automáticamente una herramienta de búsqueda para esa base de conocimientos. El agente decide cuándo buscar, recupera solo la información relevante y la utiliza para responder preguntas o completar tareas, todo sin necesidad de que gestiones manualmente lo que se incluye en el prompt.
Esta guía explica cómo funciona el sistema RAG de Docker Agent, cuándo usarlo y cómo configurarlo eficazmente para tu contenido.
NoteRAG es una característica avanzada que requiere configuración y ajustes. Los valores predeterminados funcionan bien para comenzar, pero adaptar la configuración a tu contenido y caso de uso específicos mejora significativamente los resultados.
El problema: exceso de contexto
Tu agente puede trabajar con todo tu código fuente, pero no puede meterlo todo en su ventana de contexto. Incluso con límites de 200K tokens, los proyectos medianos son demasiado grandes. Buscar código relevante oculto en cientos de archivos desperdicia contexto.
Las herramientas del sistema de archivos ayudan a los agentes a leer archivos, pero el agente tiene que adivinar qué archivos leer. No puede buscar por significado, solo por nombre de archivo. Pregunta "encuentra la lógica de reintento" y el agente leerá archivos esperando toparse con el código correcto.
Grep encuentra coincidencias de texto exactas pero pasa por alto conceptos relacionados. Buscar "authentication" (autenticación) no encontrará código que use "auth" o "login". O bien obtienes cientos de coincidencias o ninguna, y grep no comprende la estructura del código: solo hace coincidir cadenas allí donde aparezcan.
RAG indexa tu contenido con anticipación y permite la búsqueda semántica. El agente busca contenido preindexado por su significado, no por palabras exactas. Recupera solo fragmentos relevantes que respetan la estructura del código. Sin desperdiciar contexto en la exploración.
Cómo funciona RAG en Docker Agent
Configura una fuente RAG en tu configuración de Docker Agent:
rag:
codebase:
docs: [./src, ./pkg]
strategies:
- type: chunked-embeddings
embedding_model: openai/text-embedding-3-small
vector_dimensions: 1536
database: ./code.db
agents:
root:
model: openai/gpt-5
instruction: You are a coding assistant. Search the codebase when needed.
rag: [codebase]Cuando haces referencia a rag: [codebase], Docker Agent:
- Al iniciar - Indexa tus documentos (solo en la primera ejecución, bloquea hasta completarse).
- Durante la conversación - Le proporciona al agente una herramienta de búsqueda.
- Cuando el agente realiza una búsqueda - Recupera los fragmentos relevantes y los añade al contexto.
- Con los cambios en los archivos - Reindexa automáticamente los archivos modificados.
El agente decide cuándo buscar basándose en la conversación. Tú no gestionas lo que entra en el contexto: el agente se encarga de ello.
El proceso de indexación
En la primera ejecución, Docker Agent:
- Lee archivos de las rutas configuradas.
- Respeta los patrones de
.gitignore(se puede deshabilitar). - Divide los documentos en fragmentos (chunks).
- Crea representaciones buscables utilizando la estrategia elegida.
- Almacena todo en una base de datos local.
Las ejecuciones posteriores reutilizan el índice. Si los archivos cambian, Docker Agent lo detecta y reindexa solo lo que haya cambiado, manteniendo tu base de conocimientos actualizada sin intervención manual.
Estrategias de recuperación
Diferentes contenidos requieren diferentes enfoques de recuperación. Docker Agent admite tres estrategias, cada una optimizada para diferentes casos de uso. Los valores predeterminados funcionan bien, pero comprender las ventajas y desventajas te ayuda a elegir el enfoque correcto.
Búsqueda semántica (chunked-embeddings)
Convierte el texto en vectores que representan significados, lo que permite buscar por concepto en lugar de por palabras exactas:
strategies:
- type: chunked-embeddings
embedding_model: openai/text-embedding-3-small
vector_dimensions: 1536
database: ./docs.db
chunking:
size: 1000
overlap: 100Durante la indexación, los documentos se dividen en fragmentos y cada fragmento es convertido en un vector de 1536 dimensiones por el modelo de incrustación (embedding model). Estos vectores son esencialmente coordenadas en un espacio de alta dimensión donde los conceptos similares se posicionan cerca unos de otros.
Cuando buscas '¿cómo autentico a los usuarios?', tu consulta secciona en un vector y la base de datos encuentra fragmentos con vectores cercanos mediante similitud de coseno (midiendo el ángulo entre vectores). El modelo de incrustación aprendió que 'authentication' (autenticación), 'auth' y 'login' son conceptos relacionados, por lo que buscar uno encuentra los demás.
Ejemplo: La consulta '¿cómo autentico a los usuarios?' encuentra tanto 'La autenticación de usuario requiere un token de API válido' como 'La autenticación basada en tokens valida las solicitudes', a pesar de la redacción diferente. No encontrará 'Las pruebas de autenticación están fallando' porque tiene un significado diferente a pesar de contener la palabra.
Esto funciona bien para la documentación donde los usuarios hacen preguntas usando una terminología diferente a la de tus documentos. La desventaja es que puede pasar por alto términos técnicos exactos y, a veces, deseas coincidencias virtuales, no semánticas. Requiere llamadas a la API de incrustación durante la indexación.
Búsqueda por palabras clave (BM25)
Algoritmo estadístico que busca coincidencias y las clasifica según la frecuencia y rareza del término:
strategies:
- type: bm25
database: ./bm25.db
k1: 1.5
b: 0.75
chunking:
size: 1000
overlap: 100Durante la indexación, los documentos se tokenizan y el algoritmo calcula con qué frecuencia aparece cada término (frecuencia del término) y qué tan raro es en todos los documentos (frecuencia inversa de documento). El índice de puntuación se almacena en una base de datos SQLite local.
Cuando buscas 'HandleRequest function', el algoritmo encuentra fragmentos que contienen estos términos exactos y los puntúa en función de la frecuencia del término, la rareza del término y la longitud del documento. Encontrar 'HandleRequest' se puntúa como más significativo que encontrar palabras comunes como 'function'. Piensa en ello como un grep con clasificación estadística.
Ejemplo: Buscar 'HandleRequest function' encuentra func HandleRequest(w http.ResponseWriter, r *http.Request) y 'La función HandleRequest procesa solicitudes entrantes', pero no 'procesa
solicitudes HTTP' a pesar de ser semánticamente similar.
El parámetro k1 (por defecto 1.5) controla cuánto importan los términos repetidos: valores más altos
enfatizan más la repetición. El parámetro b (por defecto 0.75) controla la normalización de longitud:
valores más altos penalizan más los documentos más largos.
Esto es rápido, local (sin costos de API) y predecible para encontrar nombres de funciones, nombres de clases, endpoints de API y cualquier identificador que aparezca textualmente. La desventaja es la nula comprensión del significado: 'RetryHandler' y 'retry logic' no coincidirán a pesar de estar relacionados. Es un complemento esencial para la búsqueda semántica.
Búsqueda semántica mejorada por LLM (semantic-embeddings)
Genera resúmenes semánticos con un LLM antes de la incrustación, lo que permite buscar por lo que hace el código en lugar de por cómo se llama:
strategies:
- type: semantic-embeddings
embedding_model: openai/text-embedding-3-small
chat_model: openai/gpt-5-mini
vector_dimensions: 1536
database: ./code.db
ast_context: true
chunking:
size: 1000
code_aware: trueDurante la indexación, el código se divide utilizando la estructura AST (las funciones permanecen
intactas), luego el chat_model genera un resumen semántico de cada fragmento. Se incrusta el
resumen, no el código fuente. Cuando buscas, tu consulta coincide con estos resúmenes, pero se devuelve
el código original.
Esto resuelve un problema de las incrustaciones comunes: las incrustaciones de código fuente están
dominadas por nombres de variables y detalles de implementación. Una función llamada processData que
implementa lógica de reintento no coincidirá semánticamente con 'reintento'. Pero cuando el LLM lo
resume primero, el resumen menciona explícitamente 'lógica de reintento', haciéndolo localizable.
Ejemplo: Considera este código:
func (c *Client) Do(req *Request) (*Response, error) {
for i := 0; i < 3; i++ {
resp, err := c.attempt(req)
if err == nil { return resp, nil }
time.Sleep(time.Duration(1<<i) * time.Second)
}
return nil, errors.New("max retries exceeded")
}El resumen del LLM es: "Implementa lógica de reintento con retroceso exponencial para solicitudes HTTP, intentando hasta 3 veces con retrasos de 1s, 2s, 4s antes de fallar."
Buscar 'lógica de reintento retroceso exponencial' ahora encuentra este código, a pesar de que el
código nunca usa esas palabras. La opción ast_context: true incluye metadatos AST en las
instrucciones para una mejor comprensión. La fragmentación code_aware: true evita dividir funciones
a la mitad de su implementación.
Este enfoque destaca al buscar código por comportamiento en códigos fuente grandes con nombres inconsistentes. La desventaja es una indexación significativamente más lenta (una llamada de LLM por fragmento) y mayores costos de API (tanto para modelos de chat como de incrustación). A menudo es excesivo para código bien documentado o proyectos simples.
Combinar estrategias con recuperación híbrida
Cada estrategia tiene fortalezas y debilidades. Combinarlas captura tanto la comprensión semántica como las coincidencias exactas de términos:
rag:
knowledge:
docs: [./documentation, ./src]
strategies:
- type: chunked-embeddings
embedding_model: openai/text-embedding-3-small
vector_dimensions: 1536
database: ./vector.db
limit: 20
- type: bm25
database: ./bm25.db
limit: 15
results:
fusion:
strategy: rrf
k: 60
deduplicate: true
limit: 5Cómo funciona la fusión
Ambas estrategias se ejecutan en paralelo, cada una devolviendo sus mejores candidatos (20 y 15 en este
ejemplo). La fusión combina los resultados utilizando puntuación basada en rangos, elimina los
duplicados y devuelve los 5 mejores resultados finales. Tu agente obtiene resultados que funcionan
tanto para consultas semánticas ('cómo hago...') como para búsquedas de términos exactos ('busca la
función configure_auth').
Estrategias de fusión
Se recomienda RRF (Reciprocal Rank Fusion - Fusión de Rango Recíproco). Combina resultados basándose en el rango en lugar de las puntuaciones absolutas, lo que funciona de manera confiable cuando las estrategias usan diferentes escalas de puntuación. No requiere ajustes.
Para la fusión ponderada, le das más importancia a una estrategia:
fusion:
strategy: weighted
weights:
chunked-embeddings: 0.7
bm25: 0.3Esto requiere ajustes para tu contenido. Utilízalo cuando sepas que un enfoque funciona mejor para tu caso de uso.
La fusión por puntuación máxima (Max score fusion) toma la puntuación más alta entre las estrategias:
fusion:
strategy: maxEsto solo funciona si las estrategias usan escalas de puntuación comparables. Es simple pero menos sofisticado que RRF.
Mejorar la calidad de la recuperación
Reclasificar resultados (Reranking)
La recuperación inicial se optimiza para la velocidad. La reclasificación vuelve a puntuar los resultados con un modelo más sofisticado para mejorar la relevancia:
results:
reranking:
model: openai/gpt-5-mini
threshold: 0.3
criteria: |
Al puntuar la relevancia, prioriza:
- Documentación oficial sobre el contenido de la comunidad
- Información reciente sobre material desactualizado
- Ejemplos prácticos sobre explicaciones teóricas
- Implementaciones de código sobre discusiones de diseño
limit: 5El campo criteria (criterios) es potente: utilízalo para codificar el conocimiento del dominio sobre
lo que hace que los resultados sean relevantes para tu caso de uso específico. Cuanto más específicos
sean tus criterios, mejor será la reclasificación.
Desventaja: Resultados significativamente mejores pero añade latencia y costos de API (llamada de LLM para puntuar cada resultado).
Configuración de la fragmentación (Chunking)
La forma de dividir los documentos afecta drásticamente a la calidad de la recuperación. Adapta la fragmentación al tipo de contenido. El tamaño del fragmento se mide en caracteres (puntos de código Unicode), no en tokens.
Para documentación y prosa, utiliza fragmentos moderados con superposición (overlap):
chunking:
size: 1000
overlap: 100
respect_word_boundaries: trueLa superposición conserva el contexto en los límites del fragmento. Respetar los límites de las palabras evita cortar palabras a la mitad.
Para código, utiliza fragmentos más grandes con división basada en AST:
chunking:
size: 2000
code_aware: trueEsto mantiene las funciones intactas. El ajuste code_aware utiliza tree-sitter para respetar la
estructura del código.
NoteActualmente solo se admite Go; se planea el soporte para idiomas adicionales.
Para contenido corto y enfocado, como referencias de API:
chunking:
size: 500
overlap: 50Las secciones breves necesitan menos superposición ya que son naturalmente autónomas.
Experimenta con estos valores. Si la recuperación pierde contexto, aumenta el tamaño del fragmento o la superposición. Si los resultados son demasiado amplios, disminuye el tamaño del fragmento.
Tomar decisiones sobre RAG
Cuándo usar RAG
Usa RAG cuando:
- Tu contenido sea demasiado grande para la ventana de contexto.
- Desees una recuperación dirigida, no todo a la vez.
- El contenido cambie y deba mantenerse actualizado.
- El agente necesite buscar en muchos archivos.
No uses RAG cuando:
- El contenido sea lo suficientemente pequeño como para incluirlo en las instrucciones del agente.
- La información rara vez cambie (considera la ingeniería de prompts en su lugar).
- Necesites datos en tiempo real (RAG utiliza capturas preindexadas).
- El contenido ya esté en un formato de búsqueda que el agente pueda consultar directamente.
Elegir estrategias de recuperación
Usa la búsqueda semántica (chunked-embeddings) para documentación de cara al usuario, contenido con
terminología variada y búsquedas conceptuales en las que los usuarios redacten las preguntas de forma
diferente a tus documentos.
Usa la búsqueda por palabras clave (bm25) para identificadores de código, nombres de funciones,
endpoints de API, mensajes de error y cualquier contenido donde las coincidencias de términos exactos
importen. Esencial para jerga técnica y nombres propios.
Usa la búsqueda semántica mejorada por LLM (semantic-embeddings) para la búsqueda de código por
funcionalidad, localización de implementaciones por comportamiento en lugar de por nombre, o contenido
técnico complejo que requiera una comprensión profunda. Elige esta opción cuando la precisión importe
más que la velocidad de indexación.
Usa híbrido (múltiples estrategias) para la búsqueda de propósito general en contenido mixto, cuando no estés seguro de qué enfoque funciona mejor o para sistemas de producción donde la calidad sea lo más importante. Máxima cobertura a costa de la complejidad.
Ajustes para tu proyecto
Comienza con los valores predeterminados y luego ajústalos según los resultados.
Si la recuperación pierde contenido relevante:
- Aumenta el
limiten las estrategias para recuperar más candidatos. - Ajusta el
threshold(umbral) para que sea menos estricto. - Aumenta el
size(tamaño) del fragmento para capturar más contexto. - Añade más estrategias de recuperación.
Si la recuperación devuelve contenido irrelevante:
- Disminuye el
limita menos candidatos. - Aumenta el
thresholdpara ser más estricto. - Añade reclasificación (reranking) con criterios específicos.
- Disminuye el
sizedel fragmento para obtener resultados más enfocados.
Si la indexación es demasiado lenta:
- Aumenta el
batch_sizepara realizar menos llamadas a la API. - Aumenta
max_embedding_concurrencypara paralelismo. - Considera BM25 en lugar de incrustaciones (local, sin API).
- Utiliza modelos de incrustación más pequeños.
Si los resultados carecen de contexto:
- Aumenta el
overlap(superposición) del fragmento. - Aumenta el
sizedel fragmento. - Utiliza
return_full_content: truepara devolver documentos completos. - Añade fragmentos vecinos a los resultados.
Lectura adicional
- Referencia de configuración - Opciones y parámetros de RAG completos
- Ejemplos de RAG - Configuraciones en funcionamiento para diferentes escenarios
- Referencia de herramientas - Cómo funcionan las herramientas de búsqueda de RAG en los flujos de trabajo de los agentes