Blogs / Por Qué Tu RAG Recupera los Chunks Equivocados

Por Qué Tu RAG Recupera los Chunks Equivocados

Publicado
28 de septiembre de 2026
Autor
Faizan Nadeem
Etiquetas
RAG AI Engineering Backend Development LLM
Una señal de tránsito amarilla de calle sin salida
Photo by Victória Kubiaki on Unsplash

“El modelo está alucinando” es el diagnóstico por defecto cuando un sistema RAG da una respuesta incorrecta, y generalmente es el equivocado. La alucinación —el modelo inventando algo con total confianza— es un fallo de generación. Pero el fallo mucho más común en un pipeline RAG en producción ocurre un paso antes: el retrieval le entrega al modelo el contexto equivocado o incompleto, y el modelo hace exactamente lo que debe hacer con lo que se le dio. No está mintiendo; está respondiendo fielmente a partir de material fuente deficiente.

Esta distinción importa porque los dos fallos tienen soluciones completamente diferentes, y los equipos habitualmente pasan semanas ajustando prompts o cambiando modelos de generación para arreglar un problema que nunca estuvo en la generación. Este artículo es un recorrido diagnóstico por las cuatro razones más comunes por las que el retrieval devuelve los chunks incorrectos —desajuste de embeddings, límites de chunks que dividen la respuesta, asimetría consulta-documento y metadatos faltantes— con formas concretas de identificar cuál es el problema real, qué hacer al respecto, y un caso de estudio completo que rastrea una respuesta incorrecta a través de todo el proceso.

Aprenderás:

  • Cómo determinar si una respuesta incorrecta es un fallo de retrieval o de generación antes de tocar el prompt
  • Por qué el modelo de embedding puede ser sistemáticamente inadecuado para tu dominio, no simplemente “no ideal”
  • Cómo los límites de chunks dividen silenciosamente la frase exacta que una consulta necesita del contexto del que depende
  • Qué es la asimetría consulta-documento y por qué las preguntas y las respuestas no se embedden naturalmente cerca entre sí
  • Por qué los metadatos faltantes o incorrectos hacen que el retrieval devuelva contenido del documento, versión o alcance equivocados
  • Una lista de verificación estructurada para trabajar cuando la calidad del retrieval regresa

Tabla de contenidos

  1. Primero: ¿Es esto realmente un fallo de retrieval?
  2. Desajuste de embeddings
  3. Límites de chunks que dividen la respuesta
  4. Asimetría consulta-documento
  5. Metadatos faltantes o incorrectos
  6. Un caso de estudio completo: Rastreando una respuesta incorrecta
  7. Cuando las causas se combinan
  8. Una lista de verificación diagnóstica
  9. Conclusión

Primero: ¿Es esto realmente un fallo de retrieval?

Antes de diagnosticar cualquiera de las cuatro causas a continuación, confirma que el fallo está realmente antes de la generación. La forma más rápida: toma la consulta que produjo una respuesta incorrecta, ejecuta el retrieval de forma aislada y verifica manualmente si el chunk con la respuesta correcta aparece en algún lugar de lo que se recuperó —no necesariamente en el rango 1, simplemente presente en el conjunto de candidatos que se pasó al LLM.

  • Si el chunk correcto está completamente ausente, es un fallo de retrieval —una de las cuatro causas a continuación. Ningún cambio de prompt arregla una respuesta que nunca estuvo en la ventana de contexto.
  • Si el chunk correcto está presente pero la respuesta sigue siendo incorrecta, es un fallo de generación —el modelo tenía el material correcto y no lo usó correctamente. Ese es un problema de fidelidad, cubierto con sus propias métricas en evaluación de un pipeline RAG.

Ejecutar esta verificación en incluso diez o quince respuestas incorrectas recientes, a mano, antes de asumir cualquier cosa sobre la causa raíz, ahorra mucho esfuerzo desperdiciado —es común encontrar que la mayoría de los reportes de “el modelo alucinó” son en realidad “el modelo nunca vio la respuesta”.

Desajuste de embeddings

El síntoma: el retrieval devuelve chunks que están temáticamente relacionados pero nunca contienen la respuesta específica, de manera consistente, a través de muchas consultas diferentes —no un error ocasional, un patrón.

El mecanismo: cada modelo de embedding tiene un dominio implícito para el que fue entrenado a representar bien, y el texto fuera de ese dominio se embeddea en una región menos significativa del espacio vectorial. Un modelo de embedding de propósito general entrenado principalmente en texto web y prosa estilo Wikipedia representará notablemente peor la densa estructura de cláusulas de un contrato legal, la superficie API de una base de código o las notas abreviadas de un registro médico que la prosa ordinaria —no porque el modelo esté roto, sino porque nunca aprendió una estructura confiable para ese tipo de texto.

Cómo confirmarlo: selecciona cinco o seis consultas que estén fallando e inspecciona directamente la similitud de coseno entre el embedding de la consulta y el embedding del chunk gold versus el embedding de la consulta y algunos chunks no relacionados. Si la puntuación de similitud del chunk gold no es significativamente mayor que la de los chunks no relacionados, el espacio de embedding en sí no está separando bien el contenido relevante del irrelevante para este tipo de texto —esa es la firma de un desajuste, no un problema de chunking o metadatos.

def diagnose_embedding_gap(query_emb, gold_chunk_emb, sample_chunk_embs) -> dict:
    gold_sim = cosine_sim(query_emb, gold_chunk_emb)
    sample_sims = [cosine_sim(query_emb, e) for e in sample_chunk_embs]
    return {
        "gold_similarity": gold_sim,
        "sample_mean": sum(sample_sims) / len(sample_sims),
        "gap": gold_sim - (sum(sample_sims) / len(sample_sims)),
    }

Una brecha pequeña o negativa a través de muchas consultas, no solo una, es la señal para actuar.

La solución: para un corpus genuinamente específico de dominio (legal, médico, código, documentación técnica interna profunda), un modelo de embedding ajustado al dominio o fine-tuneado generalmente cierra esta brecha de manera más confiable que cambiar entre modelos de propósito general. A falta de fine-tuning, combinar búsqueda vectorial con BM25 le da al matching de términos exactos un camino alrededor de un espacio de embedding débil, lo que a menudo es la solución más rápida de desplegar mientras se evalúa una solución de embedding a largo plazo.

Límites de chunks que dividen la respuesta

El síntoma: el documento correcto se está recuperando, a veces incluso el área general correcta de él, pero el hecho específico necesario para responder la pregunta falta del chunk real que llegó a los resultados principales.

El mecanismo: esta es una consecuencia directa de cómo se dividió el corpus en chunks, no de cómo se buscó. Un chunker de tamaño fijo o dividido ingenuamente no sabe que el significado de una tabla depende del párrafo que la introduce, o que una definición y la frase que la usa pertenecen juntas —se divide por conteo de tokens, y si la división cae entre el setup y el payoff, el embedding del chunk que contiene solo la mitad del payoff no representa completamente el concepto sobre el que realmente pregunta la consulta.

Cómo confirmarlo: abre el documento fuente directamente y mira exactamente dónde caen los límites de los chunks en relación con la oración o tabla que contiene la respuesta gold. Si la respuesta está dividida en dos chunks adyacentes, o si está precedida de contexto esencial (una definición de variable, una condición calificadora) que cayó en el chunk anterior, este es un problema de límites, no de embedding.

La solución: este es el tema completo del post principal de esta serie —ver estrategias de chunking para RAG, evaluadas con documentos reales para una comparación completa de enfoques fijos, recursivos, semánticos y jerárquicos, y para los mecanismos específicos de overlap y chunking jerárquico parent-child, ambos de los cuales existen específicamente para reducir este modo de fallo.

Asimetría consulta-documento

El síntoma: las preguntas formuladas como preguntas ("¿cómo reseteo una contraseña olvidada?") recuperan peor que la misma necesidad subyacente formulada como declaración (“proceso de reseteo de contraseña”), aunque un humano consideraría ambas formas igualmente válidas de preguntar lo mismo.

El mecanismo: una pregunta y su respuesta no están naturalmente cerca en el espacio de embedding, aunque estén semánticamente vinculadas —"¿Cuánto tiempo tardará en procesarse mi reembolso?" y “Los reembolsos se emiten en 5-7 días hábiles” comparten casi ningún vocabulario superficial, y un bi-encoder entrenado principalmente en similitud simétrica (dos declaraciones similares, en lugar de una pregunta emparejada con una respuesta declarativa) no aprende automáticamente que una pregunta y su respuesta deberían embeddarse cerca. Esta es una propiedad estructural de la tarea de embedding, no un bug en ningún modelo específico.

Cómo confirmarlo: reescribe algunas consultas fallidas como declaraciones que se parezcan a cómo probablemente está redactada la respuesta en el documento fuente, y vuelve a ejecutar el retrieval. Si la versión declarativa recupera el chunk gold de manera confiable y la forma de pregunta no, esta es asimetría consulta-documento, no desajuste de embedding —el espacio de embedding está bien para el matching prosa-a-prosa; es específicamente la dirección pregunta-a-respuesta la que es débil.

La solución: tres enfoques, aproximadamente en orden de esfuerzo:

  • Modelos de embedding entrenados con prefijos específicos de instrucción o consulta (muchos modelos de embedding modernos soportan modos de codificación separados query: y passage: específicamente para abordar esta asimetría) —verifica si tu modelo actual soporta esto antes de asumir que no.
  • Reescritura o expansión de consultas antes del retrieval: haz que un LLM reformule una pregunta en una forma declarativa plausible, o genera una respuesta hipotética a la pregunta (la técnica HyDE) y embedea esa respuesta hipotética en lugar de la pregunta literal, ya que una respuesta plausible se embeddea mucho más cerca de la respuesta real que la pregunta.
HYDE_PROMPT = "Write a short, plausible passage that would answer this question: {query}"

def hyde_retrieve(query: str, llm_fn, embed_fn, vector_search_fn, k: int = 5):
    hypothetical_answer = llm_fn(HYDE_PROMPT.format(query=query))
    hyde_embedding = embed_fn(hypothetical_answer)
    return vector_search_fn(hyde_embedding, k=k)

Esto cuesta una llamada LLM adicional por consulta, así que vale la pena medirlo contra tu conjunto de evaluación en lugar de asumir que siempre ayuda —para corpora donde las preguntas y respuestas ya comparten vocabulario, la ganancia puede ser pequeña en relación con la latencia añadida.

  • La búsqueda híbrida también ayuda aquí de una manera diferente que para el desajuste de embedding —si la pregunta y el documento comparten aunque sea algunos términos exactos, BM25 puede encontrar el chunk correcto incluso cuando el camino de retrieval denso se ve afectado por la asimetría de formulación.

Metadatos faltantes o incorrectos

El síntoma: el retrieval devuelve contenido que es temáticamente correcto pero pertenece a la versión incorrecta del documento, al nivel de producto incorrecto, a la región incorrecta, o —en un sistema multi-tenant— a los datos del cliente incorrecto.

El mecanismo: la similitud vectorial no tiene un concepto inherente de “actual”, “aplica a este cliente” o “versión correcta”. Si tu corpus contiene tanto la página de precios actual como la versión archivada del año pasado, y ambas fueron indexadas sin un campo de metadatos que las distinga, una consulta sobre precios puede recuperar cualquiera de ellas sin señal para preferir la actual —los embeddings de ambas son legítimamente similares, porque el contenido genuinamente lo es. El fallo no está en la búsqueda de similitud; está en que una pieza de información de la que la consulta realmente depende (actualidad, alcance, tenant) nunca se adjuntó al chunk como metadatos filtrables en primer lugar.

Cómo confirmarlo: cuando se recupera un chunk incorrecto pero plausible, verifica si difiere del correcto en una dimensión que debería haber sido un filtro —una document_version diferente, un product_tier diferente, un tenant_id diferente— en lugar de ser contenido genuinamente irrelevante. Si el chunk recuperado es “correcto excepto por el alcance”, es un problema de metadatos, no semántico.

La solución: adjunta los campos de alcance relevantes (versión, tenant, región, nivel de acceso) a cada chunk en el momento de la ingesta, y aplícalos como un pre-filtro estricto antes de que se ejecute la búsqueda de similitud, no como una verificación posterior a los resultados:

SELECT id, body, embedding <=> :query_embedding AS distance
FROM documents
WHERE tenant_id = :tenant_id
  AND document_version = 'current'
ORDER BY embedding <=> :query_embedding
LIMIT 5;

Filtrar en la cláusula WHERE antes de que se ejecute el ordenamiento por similitud significa que un chunk archivado o fuera de alcance nunca es un candidato, en lugar de depender del ranking de similitud para bajarlo lo suficiente como para que no importe —lo que a menudo no ocurrirá, ya que un documento desactualizado puede ser genuinamente similar al actual. Esto importa aún más en sistemas que sirven a múltiples clientes o tenants desde un índice compartido —ver RAG multi-tenant: filtrado de metadatos sin filtrar datos para los mecanismos específicos de pre-filtrado versus post-filtrado y por qué la elección entre ellos tiene consecuencias reales de corrección y rendimiento.

Un caso de estudio completo: Rastreando una respuesta incorrecta

Para hacer la lista de verificación concreta, aquí hay un rastreo hipotético pero representativo de una respuesta incorrecta a través de los pasos de diagnóstico.

El reporte: un usuario pregunta “¿El plan anual soporta downgrades de asientos a mitad de ciclo?” y el sistema responde “No, el número de asientos no puede cambiarse después de comprar el plan anual” —lo cual es incorrecto; los downgrades están permitidos, con prorrateo, en el siguiente ciclo de facturación.

Paso 1 — ¿Es retrieval o generación? Extraer el conjunto de candidatos crudo para esta consulta muestra que los 5 chunks principales son todos sobre actualizar asientos, de una sección “Escalando Tu Plan”. El chunk que realmente cubre los downgrades —en una sección separada “Ajustes de Ciclo de Facturación”— nunca aparece en los primeros 10. Esto descarta la generación: el modelo nunca vio el contenido correcto, así que respondió desde lo más cercano que vio, que resultó ser sobre la operación opuesta.

Paso 2 — Verificar la brecha de similitud. Embeddear la consulta contra el chunk gold faltante versus los chunks relacionados con upgrades recuperados muestra que la puntuación de similitud del chunk gold es solo marginalmente menor que los principales falsos positivos —no una brecha grande, lo que argumenta contra un desajuste de embedding severo.

Paso 3 — Inspeccionar límites de chunks. El chunk gold en sí está intacto —la política de downgrade está completamente contenida dentro de un chunk, no dividida. Esto descarta un problema de límites.

Paso 4 — Reescribir como declaración. Volver a ejecutar el retrieval con “política de downgrade de asientos a mitad de ciclo para planes anuales” en lugar de la pregunta original trae el chunk correcto al rango 2. Esa es la señal: esto fue asimetría consulta-documento —"¿X soporta Y?" como formulación de pregunta se embeddea más cerca de otro contenido en forma de pregunta y relacionado con upgrades que del texto de política declarativo que realmente lo responde.

La solución aplicada: agregar reescritura de consultas estilo HyDE antes del retrieval para este corpus (documentación de soporte y facturación, que se inclina fuertemente hacia declaraciones de política declarativas en lugar de contenido formateado como Q&A) movió el chunk gold de esta consulta específica de sin rango al rango 1, y elevó el recall@5 en una muestra de preguntas formuladas de manera similar en el conjunto de evaluación por un margen significativo —el tipo de corrección dirigida y medida que el proceso de diagnóstico anterior está diseñado para producir, en lugar de un cambio de prompt genérico aplicado sin saber cuál de las cuatro causas estaba realmente en juego.

Cuando las causas se combinan

Estas cuatro causas no son mutuamente excluyentes, y en un corpus del mundo real desordenado es común que dos se superpongan en la misma consulta. Una pregunta formulada asimétricamente a su respuesta y dividida en un límite de chunk produce una brecha de similitud que parece un desajuste de embedding directo hasta que se verifican los límites y la formulación por separado —la lista de verificación a continuación está ordenada específicamente para que descartar cada causa reduzca lo que queda, en lugar de intentar diagnosticar las cuatro a la vez desde un solo síntoma.

Un hábito práctico: cuando una corrección para una causa no resuelve completamente una consulta fallida, no concluyas que el diagnóstico fue incorrecto —vuelve a ejecutar la lista de verificación contra el fallo residual. Es común que una corrección de alcance de metadatos revele un problema de asimetría subyacente que estaba previamente enmascarado por resultados de tenants irrelevantes que copaban completamente los rangos superiores.

Una lista de verificación diagnóstica

Cuando la calidad del retrieval regresa o una consulta específica sigue fallando, trabaja en este orden —cada uno descarta o confirma una de las causas anteriores antes de pasar a la siguiente:

  1. Confirma que es retrieval, no generación. Verifica si el chunk gold estaba en el conjunto de candidatos en absoluto.
  2. Verifica la brecha de similitud. ¿La puntuación de similitud del chunk gold es significativamente mayor que la de chunks no relacionados, o el espacio de embedding no los está separando bien?
  3. Inspecciona los límites de chunks alrededor de la respuesta gold. ¿Está el hecho necesario dividido entre chunks, o falta contexto anterior esencial?
  4. Reescribe la consulta como declaración y vuelve a probar. ¿Solo eso lo arregla? Si es así, es asimetría, no calidad de embedding.
  5. Verifica si el resultado incorrecto difiere en una dimensión de alcance (versión, tenant, región) en lugar de por tema. Si es así, es un filtro de metadatos faltante.
  6. Solo después de descartar las cuatro, mira la generación. Si el chunk correcto estaba presente y rankeado razonablemente y la respuesta sigue siendo incorrecta, ese es un problema de fidelidad —mídelo explícitamente en lugar de ajustar el prompt por intuición.

Conclusión

“El modelo alucinó” raramente es la historia completa, y saltar directo al ajuste de prompts omite el paso de diagnóstico que habría mostrado la causa real en minutos. El desajuste de embeddings, los límites de chunks divididos, la asimetría consulta-documento y los metadatos faltantes son cuatro problemas estructuralmente diferentes que resultan producir el mismo síntoma —una respuesta incorrecta— y conflactuarlos desperdicia exactamente el tiempo de ingeniería que una verificación manual de quince minutos de los candidatos recuperados habría ahorrado. Trabaja la lista de verificación antes de tocar el prompt; casi siempre es más rápido encontrar la causa real que adivinarla.

Faizan Nadeem
Autor
Faizan Nadeem

AI/GenAI engineer specialising in agentic RAG, LangGraph, and production LLM systems with Python and FastAPI. 2 years building AI agents, RAG pipelines, and the backends behind them.

Más artículos