Yeda AI Tips · #042

English

Búsqueda híbrida + reranking: corrige el punto ciego de los embeddings con las coincidencias exactas

Busca un número de pedido exacto en un sistema RAG construido puramente sobre embeddings y, a menudo, no obtendrás nada útil de vuelta. No porque el número de pedido no esté en tu corpus — sino porque los embeddings nunca fueron diseñados para acertar coincidencias exactas de tokens.

El problema: los embeddings y las palabras clave fallan de maneras distintas

La búsqueda por embeddings densos es excelente para capturar el significado. Pregunta "cómo obtengo un reembolso" y puede recuperar un fragmento sobre "política de devoluciones y reintegros" aunque las palabras apenas se solapen — ese es todo el sentido de la búsqueda semántica. Pero esa misma fortaleza es una debilidad para las consultas donde importa la cadena exacta: números de pedido, SKUs, códigos de error, números de modelo de producto. Dos números de pedido muy distintos pueden terminar embebidos cerca uno del otro en el espacio vectorial porque el texto circundante es similar, aunque — token por token — no tengan nada en común.

La búsqueda por palabras clave (clásicamente BM25, una función de puntuación construida sobre la frecuencia de términos) tiene el perfil opuesto: está hecha para premiar la coincidencia exacta de términos. Acierta los números de pedido y los códigos de error, pero se pierde las paráfrasis — busca "cómo recupero mi dinero" contra un corpus que solo dice "reembolso" y la búsqueda pura por palabras clave no devuelve nada.

Ninguno de los dos métodos de recuperación cubre el punto ciego del otro. Usar solo uno de ellos significa que estás estructuralmente condenado a perder toda una categoría de consultas.

La solución: ejecuta ambos, fusiona los resultados y luego haz reranking

1. Recuperación híbrida. Ejecuta la búsqueda por palabras clave BM25 y la búsqueda por embeddings densos contra la misma consulta, en paralelo, cada una produciendo su propia lista ordenada de candidatos. Combina las dos listas ordenadas con Reciprocal Rank Fusion (RRF) — un método de fusión que combina los rankings según la posición de cada resultado en cada lista, en lugar de intentar normalizar y comparar directamente dos escalas de puntuación distintas.

2. Reranking. Toma la lista fusionada y combinada — no todo tu índice, solo los mejores candidatos de la fusión (un rango común es el top 50 aproximadamente) — y hazles reranking con un cross-encoder. A diferencia del modelo de embeddings usado para la recuperación inicial, que codifica la consulta y cada documento de forma independiente, un cross-encoder mira la consulta y un documento candidato juntos en una sola pasada. Esa atención conjunta lo hace dramáticamente mejor para juzgar la relevancia real, pero también mucho más costoso por comparación — que es exactamente por lo que solo lo ejecutas sobre una lista corta de candidatos, no sobre todo el corpus.

# 1. retrieve from both indexes
bm25_hits = bm25_index.search(query, k=50)
dense_hits = vector_store.similarity_search(query, k=50)

# 2. fuse rankings (reciprocal rank fusion)
fused = reciprocal_rank_fusion([bm25_hits, dense_hits])

# 3. rerank the fused top candidates with a cross-encoder
top_candidates = fused[:50]
reranked = cross_encoder.rerank(query, top_candidates)

Por qué vale la pena la pieza adicional

Esto no es una mejora teórica — aparece directamente en los benchmarks de calidad de recuperación. En un recorrido documentado, agregar una pasada de reranking sobre la recuperación híbrida empujó el NDCG@10 (una métrica estándar de calidad de ranking — qué tan bien caen los resultados más relevantes cerca del tope de la lista, no solo si están presentes en algún lugar) de aproximadamente 38 a 47. En una traza de tool-call en vivo aparte, se observó que habilitar el reranking elevaba la puntuación de similitud de una consulta a 0.47. Ese es un conjunto de resultados principales significativamente mejor llegando al modelo, desde el mismo corpus subyacente y la misma recuperación inicial — la diferencia está enteramente en la fusión y el reranking.

Mantén el reranking pequeño y preciso

El paso del cross-encoder es el costoso — está haciendo inferencia conjunta real sobre cada par consulta-documento que se le entrega, no una comparación vectorial barata. El patrón que mantiene esto práctico:

Hacer reranking de todo tu índice en cada consulta anula por completo el propósito de tener un recuperador de primera etapa rápido.

Trucos avanzados

Recursos

¿Estás construyendo una función con IA? Yeda AI diseña, audita y lanza sistemas LLM en producción.

Habla con nosotros · Lee el blog