Módulo 6: Evaluar la calidad de la recuperación
El camino hacia mejor recall
Descripción
La Lección 06 dejó un diagnóstico preciso, con evidencia: BM25 falla contra las queries ancla de tres formas distintas —el imán léxico (referencias cruzadas que ganan por vocabulario compartido, sin ser la respuesta), el falso amigo temático (un chunk relacionado pero incorrecto que comparte vocabulario genuino), y el límite estructural (una palabra que simplemente no existe en el vocabulario del índice). Esta lección responde la pregunta que un diagnóstico honesto siempre deja pendiente: ¿qué se construye para arreglar esto en producción?
No vas a implementar nada de lo que sigue — eso rompería la frontera de esta guía, fijada desde el diseño. Vas a salir de esta lección sabiendo, con precisión, qué técnica corrige cada modo de falla específico que mediste en la Lección 06, en qué etapa del pipeline actúa, y en qué guía de AI Engineering se construye de verdad.
Conexión con el módulo
Esta es la lección de cierre conceptual del módulo: toma el diagnóstico de la Lección 06 y lo convierte en un mapa de "qué aprender después". La Lección 08 (mini-proyecto) no construye ninguna de estas técnicas — reúne el harness completo de evaluación, tal como quedó definido en las Lecciones 03-05, como el entregable final del módulo.
El mapa: tres técnicas, tres etapas del pipeline
Antes de los detalles, la vista de conjunto. Hay tres formas de mejorar la recuperación sobre lo que esta guía ya construyó, y no son intercambiables — cada una interviene en un punto distinto del pipeline:
┌─────────────────────────────────────────────────┐
│ query │
└───────────────────────┬─────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ ETAPA 1: RECUPERACIÓN (candidatos) │
│ BM25 (esta guía) ─── o ─── embeddings semánticos ─── o ─── híbrido │
│ → produce una lista de candidatos, potencialmente grande (top-50) │
└───────────────────────┬────────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ ETAPA 2: RE-RANKING (opcional, sobre los candidatos de la etapa 1) │
│ Un cross-encoder relee cada (query, chunk) candidato con más │
│ precisión, y reordena — nunca agrega candidatos que no estaban │
└───────────────────────┬────────────────────────────────────────────┘
▼
top-k final, el que ve el agente
La distinción entre las dos etapas es la pieza más importante de esta lección: el re-ranking solo puede reordenar lo que la recuperación ya trajo como candidato. Si la Etapa 1 nunca considera un chunk —como pasó con "reimbursement", que ni siquiera generó un candidato porque el término no existe en el índice invertido—, ningún re-ranker, por sofisticado que sea, puede rescatarlo después. Esto no es un detalle técnico menor: determina qué técnica resuelve qué falla, como vas a ver a continuación.
Técnica 1: re-ranking con cross-encoders
Qué hace: BM25 calcula el score de cada chunk de forma independiente — nunca compara el texto completo de la query contra el texto completo del chunk al mismo tiempo, solo cuenta coincidencias de términos. Un cross-encoder es un modelo que sí hace eso: recibe la query y un chunk candidato juntos, en la misma pasada, y produce un score de relevancia que sí puede distinguir "este chunk menciona el tema" de "este chunk responde la pregunta" — porque lee ambos con el contexto completo del otro.
Dónde actúa: después de la recuperación, sobre una lista corta de candidatos (típicamente el top-20 o top-50 de BM25) — nunca sobre el corpus completo, porque un cross-encoder es mucho más caro de correr por candidato que BM25.
Qué fallas de la Lección 06 resolvería:
- El imán léxico. Un cross-encoder que lee "See
refund-policyfor what happens..." junto con la query "Can I get a refund if I didn't show up?" tiene la capacidad de reconocer que esa oración es una referencia cruzada —un "ver también"—, no una respuesta, algo que BM25 estructuralmente no puede hacer porque nunca lee los dos textos en conjunto. - El falso amigo del descuento. De forma parecida, un cross-encoder puede distinguir que
cancellation-policy-001habla del descuento solo de pasada (como un beneficio adicional de la ventana de cancelación pro), mientras quemembership-tiers-faq-001es la sección dedicada por completo a responder "¿cuánto descuento?" — una distinción de énfasis que el conteo de términos de BM25 no captura.
Qué NO resolvería: el límite estructural. Si BM25 nunca generó un candidato para "reimbursement" —porque el término no existe en su índice invertido—, no hay ninguna lista de candidatos sobre la que el cross-encoder pueda actuar. El re-ranking mejora el orden de lo recuperado; no amplía qué se recupera.
Dónde se construye: advanced-rag-techniques-guide (AI Engineering) — la implementación completa de un cross-encoder de re-ranking, con un modelo real, sobre un corpus real.
Técnica 2: embeddings semánticos y hybrid search
Qué hace: un embedding convierte un texto (query o chunk) en un vector numérico, entrenado de forma que textos con significado similar terminen con vectores cercanos en ese espacio — aunque no compartan ni una sola palabra. A diferencia de BM25, que compara cadenas de texto exactas, un embedding compara significado. Hybrid search combina las dos señales —el score léxico de BM25 y la similitud semántica del embedding— en un solo ranking, típicamente con una suma ponderada o con reciprocal rank fusion.
Dónde actúa: en la Etapa 1 (recuperación), como reemplazo o complemento de BM25 — no como un paso posterior, sino como una segunda fuente de candidatos que se fusiona con los de BM25 antes de devolver cualquier resultado.
Qué fallas de la Lección 06 resolvería:
- El límite estructural — esta es la única técnica de las tres que lo resuelve. Un embedding entrenado sobre suficiente texto en inglés coloca "reimbursement" y "refund" cerca en el espacio vectorial, porque son sinónimos en el uso real del idioma, sin importar que compartan cero letras en común. La búsqueda semántica encontraría
refund-policypara esa query aunque la palabra exacta nunca aparezca en el corpus — algo que ningún ajuste de BM25 puede lograr, porque el problema no es de ranking, es de que el término ni siquiera está en el vocabulario indexado. - La trampa reembolso/no-show, parcialmente. "No-show" y "refund" no son sinónimos —son conceptos relacionados pero distintos—, así que un embedding no garantiza automáticamente que
no-show-policygane; pero un embedding de la query completa ("no me presenté, ¿me devuelven el dinero?") sí puede capturar la relación conceptual entre "no show up" y "no-show" de una forma que la coincidencia literal de "refund"/"show"/"up" decancellation-policy-003no logra imitar tan bien.
Qué NO resolvería tan bien como el re-ranking: el imán léxico. Un embedding puro también puede confundirse con una oración de referencia cruzada corta si esa oración menciona genuinamente los temas correctos —"refund-policy", "no-show-policy"— aunque sea de pasada; la ventaja real de un cross-encoder es que lee la relación completa entre query y chunk, no solo la cercanía general de temas.
Dónde se construye: embeddings-deep-dive-guide (AI Engineering) cubre la teoría del embedding —arquitectura, entrenamiento, cómo un modelo aprende que "reimbursement" y "refund" son cercanos—; vector-databases-fundamentals-guide (AI Engineering) cubre cómo se indexa y consulta un vector index real por dentro (HNSW, IVF, PQ) y cómo se opera un vector database de producción (ChromaDB, Pinecone, Weaviate, Qdrant); advanced-rag-techniques-guide cubre la fusión híbrida BM25+embeddings en sí.
Técnica 3: query expansion y HyDE
Qué hace: en vez de cambiar cómo se compara la query contra el corpus, esta familia de técnicas cambia la query misma antes de buscar. Query expansion agrega sinónimos o reformulaciones a la query original (por ejemplo, agregar "reimbursement" automáticamente cuando el usuario escribió "refund"). HyDE (Hypothetical Document Embeddings) le pide a un modelo que genere una respuesta hipotética a la pregunta, y busca con el embedding de esa respuesta hipotética en vez de con el embedding de la pregunta original — la intuición es que una respuesta hipotética se parece más, en el espacio de embeddings, a una respuesta real que la pregunta misma.
Dónde actúa: antes de la Etapa 1 — transforma la query, y después se la pasa a BM25, a un embedding, o a ambos.
Qué fallas de la Lección 06 resolvería: en principio, tanto el imán léxico (si la expansión agrega términos que favorecen al chunk correcto) como el límite estructural (si la expansión agrega el sinónimo que faltaba) — pero con menos garantías que las dos técnicas anteriores, porque depende de la calidad de la expansión o de la respuesta hipotética generada, que puede introducir su propio ruido.
Dónde se construye: advanced-rag-techniques-guide (AI Engineering).
Tabla resumen: qué arregla cada cosa
| Falla medida en L06 | Re-ranking (cross-encoder) | Hybrid search (BM25 + embeddings) | Guía de AI Engineering |
|---|---|---|---|
Imán léxico (cancellation-policy-002/-003) | ✅ Fuerte | ⚠️ Parcial | advanced-rag-techniques-guide |
Falso amigo (cancellation-policy-001, discount) | ✅ Fuerte | ⚠️ Parcial | advanced-rag-techniques-guide |
| Trampa reembolso/no-show | ⚠️ Parcial | ✅ Fuerte | advanced-rag-techniques-guide + embeddings-deep-dive-guide |
| Límite estructural ("reimbursement", 0 resultados) | ❌ No alcanza | ✅ Fuerte | embeddings-deep-dive-guide + vector-databases-fundamentals-guide |
Ninguna fila dice "una sola técnica arregla todo" — y esa es la conclusión real de la tabla. Un sistema de producción serio no elige entre BM25 y embeddings: los combina (hybrid search) y agrega re-ranking encima para el tramo final del ranking, precisamente porque cada técnica cubre un punto ciego distinto de las otras.
Cómo se vería, en forma (sin ejecutarlo)
Solo para que la forma quede clara —esto es concepto, no código ejecutado en esta guía, porque sentence-transformers y los modelos de cross-encoder/embedding no están preinstalados y requieren red para descargar pesos—, así es como se vería integrar un re-ranker sobre el search de esta guía:
# CONCEPTO -- no ejecutado en esta guia (requiere sentence-transformers + red,
# fuera del entorno $0/sin-red de production-rag-and-document-ingestion-guide).
# Desarrollado de verdad en advanced-rag-techniques-guide (AI Engineering).
def search_with_reranking(query: str, k: int, index: Index, rerank_top_n: int = 20):
candidates = search(query, k=rerank_top_n, index=index) # BM25, Etapa 1
reranked = cross_encoder.rerank(query, [c.text for c in candidates]) # Etapa 2
return reranked[:k]
La forma importa más que el código: la recuperación léxica de esta guía sigue siendo la Etapa 1 — no se descarta, se usa como el filtro barato que reduce 57 chunks a un puñado de candidatos razonables — y el cross-encoder, mucho más caro por candidato, solo corre sobre esos pocos, nunca sobre el corpus completo. Es exactamente el mismo principio de "presupuesto" que ya viste con k en el Módulo 2: nunca le pides a la pieza más cara del pipeline que procese más de lo necesario.
Por qué esta guía se detiene aquí
No es que estas técnicas sean menos importantes que lo que sí se construyó — es una decisión de frontera, la misma que quedó fijada desde el diseño de esta guía. sentence-transformers, chromadb y modelos de cross-encoder no están preinstalados en este entorno y requieren red para instalarse o descargar pesos, violando la regla $0/sin-red que esta guía sostiene desde el Módulo 1. Más allá de esa razón práctica, hay una razón pedagógica: entender por qué BM25 falla, con números reales como los de la Lección 06, es el prerequisito real para usar bien estas técnicas más caras — sin ese diagnóstico, "agregar embeddings" se vuelve una superstición de producción ("dicen que ayuda") en vez de una decisión informada sobre qué falla específica se está resolviendo.
Errores comunes
-
Pensar que hybrid search o re-ranking son "opcionales, solo para mejorar un poco más". Como muestra la tabla, hay fallas —el límite estructural en particular— que BM25 solo, por más bien afinado que esté (
k1,b, o cualquierkde búsqueda), estructuralmente no puede resolver. No es una mejora incremental; es una clase de falla distinta que necesita una pieza distinta. -
Confundir re-ranking con "un BM25 mejor". El re-ranking no reemplaza a BM25 — opera después, sobre lo que BM25 ya trajo. Si BM25 nunca puso el chunk correcto en la lista de candidatos, no hay re-ranking posible.
-
Asumir que hybrid search "arregla todo automáticamente". Como se vio en la fila del imán léxico, un embedding puro también puede confundirse con una referencia cruzada temáticamente relacionada — hybrid search mejora el panorama, no lo resuelve con garantía total. La tabla de esta lección marca "parcial" a propósito, no "resuelto".
-
Saltar directo a implementar estas técnicas sin el diagnóstico de la Lección 06. Elegir entre re-ranking, hybrid search o query expansion sin saber cuál de los tres modos de falla domina tu caso real es elegir a ciegas — el valor de haber medido recall@k/precision@k y diseccionado las fallas no es solo académico, es lo que informa qué construir después.
Ejercicios
Ejercicio 1: Clasifica tres fallas nuevas (Fácil)
Para cada una de estas tres situaciones hipotéticas sobre el corpus de Reservo, decide cuál de las tres técnicas de esta lección (re-ranking, hybrid search, query expansion) sería la primera opción razonable:
(a) Una query usa la palabra "gratis" en vez de "free" y no encuentra nada, porque el corpus está en inglés. (b) Un chunk que solo menciona "Boardroom" en una lista de salas con puerta física gana, por accidente, el top-1 de una query sobre el equipamiento específico de Boardroom. (c) Una query usa "termination fee" en vez de "cancellation" y "no-show" — un concepto relacionado pero con vocabulario completamente distinto al del corpus.
Ver solución
(a) Query expansion (o, si la política del producto lo permite, forzar el idioma de la query) — es un problema de vocabulario completamente ausente por idioma, no por sinónimo dentro del mismo idioma; ni el re-ranking ni un embedding entrenado solo en inglés resolverían esto de forma confiable sin una traducción previa.
(b) Re-ranking con cross-encoder — es el mismo patrón del imán léxico/falso amigo de la Lección 06: un chunk que menciona el tema de pasada le gana a uno que lo desarrolla, y un cross-encoder que lee query y chunk juntos es la herramienta más directa para esa distinción.
(c) Hybrid search con embeddings semánticos — "termination fee" y "cancellation"/"no-show" son conceptualmente cercanos pero léxicamente distintos, el mismo patrón que "reimbursement"/"refund" de la Lección 06 — el límite estructural que solo un embedding semántico resuelve.
Ejercicio 2: Explica por qué el orden de las etapas importa (Medio)
Explica, en dos o tres frases, por qué correr un cross-encoder de re-ranking antes de BM25 (en vez de después) sería una mala idea de diseño, incluso si técnicamente fuera posible.
Ver solución
Un cross-encoder es mucho más caro de correr por candidato que BM25 —evalúa la query y el chunk juntos, con un modelo completo, en vez de solo contar coincidencias de términos con aritmética simple—. Correrlo sobre los 57 chunks completos del corpus (o, peor, sobre un corpus real de producción con millones de chunks) en vez de sobre un puñado de candidatos ya sería computacionalmente costoso a una escala que no se justifica. El orden correcto —BM25 primero, como filtro barato que reduce el corpus a un top-20/50 razonable, y el cross-encoder después, solo sobre esos pocos candidatos— es exactamente el mismo principio de "presupuesto" que esta guía ya usó con el parámetro k de search: nunca gastar la pieza más cara del pipeline en más trabajo del necesario.
Ejercicio 3: Diseña el EVAL_SET que usarías para comparar BM25 solo contra hybrid search (Difícil)
Sin implementar nada, describe cómo extenderías el harness de este módulo (recall_at_k, precision_at_k, evaluate) para comparar, con números, si un hipotético sistema hybrid search mejora sobre el BM25 de esta guía. ¿Qué cambiaría, y qué se mantendría exactamente igual?
Ver solución
Lo que se mantiene exactamente igual: el EVAL_SET (las mismas seis queries con el mismo doc_id esperado — el ground truth no cambia porque el sistema que se evalúa cambió) y las funciones recall_at_k/precision_at_k (miden lo mismo, sin importar de dónde vinieron los results). Lo que cambiaría: en vez de un solo index BM25, tendrías dos sistemas de recuperación —search_bm25(query, k, index) (el de esta guía) y un search_hybrid(query, k, index_hibrido) hipotético—, y correrías evaluate(EVAL_SET, index, k) una vez contra cada uno, para el mismo rango de k, reportando ambos resultados lado a lado (como la tabla de recall@k/precision@k de las Lecciones 04-05, pero con una columna extra por sistema). La comparación honesta exige correr exactamente el mismo EVAL_SET, con el mismo ground truth, contra ambos sistemas — si el EVAL_SET cambiara entre una corrida y la otra, ya no estarías comparando dos sistemas, sino dos evaluaciones distintas, y el número dejaría de significar nada. Esta es, en esencia, la forma en que advanced-rag-techniques-guide evaluaría si una técnica nueva realmente mejora sobre la línea base — el mismo harness de este módulo, reutilizado como vara de medir.
Resumen y siguiente paso
- El re-ranking con cross-encoders opera después de la recuperación, sobre una lista corta de candidatos, y resuelve bien el imán léxico y el falso amigo temático —pero nunca puede rescatar un chunk que la recuperación nunca consideró candidato.
- Hybrid search (BM25 + embeddings) opera en la recuperación, y es la única de las tres técnicas de esta lección que resuelve el límite estructural (un término, como "reimbursement", ausente del vocabulario indexado).
- Query expansion/HyDE transforma la query antes de buscar — útil para ambos tipos de falla, con menos garantías que las otras dos.
- Ninguna técnica resuelve todo por sí sola — un sistema de producción serio combina recuperación híbrida con re-ranking, precisamente porque cubren puntos ciegos distintos. Esta guía se detiene en el diagnóstico ($0, sin red);
advanced-rag-techniques-guide,embeddings-deep-dive-guideyvector-databases-fundamentals-guide(AI Engineering) construyen las tres técnicas de verdad.
Siguiente lección: 08 — Mini-proyecto: un harness de evaluación de recuperación. El cierre del módulo: recall_at_k, precision_at_k y evaluate juntas, en un guion de punta a punta, con un reporte final sobre el índice completo.
Recursos adicionales
advanced-rag-techniques-guide(AI Engineering) — Re-ranking con cross-encoders, hybrid search BM25+embeddings, query expansion/HyDE, RAGAS. La implementación completa de las tres técnicas nombradas en esta lección.embeddings-deep-dive-guide(AI Engineering) — Teoría del embedding semántico: arquitectura, entrenamiento, por qué "reimbursement" y "refund" terminan cerca en el espacio vectorial.vector-databases-fundamentals-guide(AI Engineering) — Cómo se indexa y consulta un vector index real por dentro (HNSW, IVF, PQ) y cómo se opera ChromaDB/Pinecone/Weaviate/Qdrant en producción.- Nogueira & Cho — "Passage Re-ranking with BERT" — El paper que originó el patrón de re-ranking con cross-encoders sobre candidatos de un recuperador léxico, exactamente el patrón nombrado en esta lección.
- Gao et al. — "Precise Zero-Shot Dense Retrieval without Relevance Labels" (HyDE) — El paper original de HyDE, la técnica de query expansion nombrada en esta lección.