
Búsqueda híbrida: BM25 vs vector (y por qué necesitas ambos)
Un agente de soporte escribe "SKU-4471" en tu chatbot RAG. Llegan cuatro resultados. Todos equivocados, pero con total seguridad. Un modelo de embeddings de propósito general no tiene ninguna razón para colocar esa cadena exacta cerca de sí misma en el espacio vectorial. Ese único modo de fallo es la razón de ser de la búsqueda híbrida, y es el motivo por el que los equipos repiten siempre la misma pregunta: ¿cómo se combinan de verdad BM25 y la búsqueda vectorial sin pasar la vida vigilando un knob de ajuste?
Si estás evaluando herramientas RAG en un sentido más amplio, nuestro ranking de las mejores herramientas RAG cubre todo el stack que las rodea.
Conclusiones clave
- BM25 encuentra coincidencias exactas de palabras clave (SKUs, códigos de error); la búsqueda vectorial encuentra texto conceptualmente similar, no cadenas idénticas.
- La búsqueda híbrida combina ambos métodos, normalmente mediante Reciprocal Rank Fusion (RRF), y supera a cualquiera de los dos por separado en cargas de consultas mixtas.
- En el benchmark WANDS, RRF sin ajustes logra 0,7068 de NDCG (frente al 0,6983 de BM25); con ajuste fino llega a 0,7497, una mejora del 7,4 %.
- Postgres/pgvector puede ejecutar búsqueda híbrida de forma nativa con
ts_rank+ pgvector, sin necesidad de una base de datos vectorial dedicada.
¿Qué es la búsqueda híbrida? (BM25 + vector, combinados)
La búsqueda híbrida ejecuta BM25 y la búsqueda vectorial como dos pasadas de recuperación separadas sobre la misma consulta, y luego fusiona las dos listas de resultados ordenadas en una sola salida mediante un algoritmo de fusión, casi siempre Reciprocal Rank Fusion. No es un tercer método de recuperación; es una capa de orquestación sobre dos métodos que ya existen.
Esa distinción importa porque una buena parte del tráfico de búsqueda sobre este tema trata BM25 y la búsqueda vectorial como si fueran lo mismo. No lo son. BM25 es una función de puntuación dispersa, basada en palabras clave, con raíces en la recuperación de información de los años 70. La búsqueda vectorial es una búsqueda de similitud densa, basada en embeddings, que solo se volvió práctica a gran escala en la última década. La búsqueda híbrida los trata como entradas complementarias, no como técnicas rivales, y fusiona sus salidas en lugar de elegir un ganador por adelantado.
BM25 vs vector vs híbrida: comparación rápida
| Dimensión | BM25 (disperso/léxico) | Búsqueda vectorial (densa/semántica) | Híbrida |
|---|---|---|---|
| Mejor en | Términos exactos, tokens raros, IDs | Paráfrasis, sinónimos, conceptos | Ambos tipos de consulta |
| Falla en | Preguntas parafraseadas, sinonimia | SKUs, códigos de error, siglas | Corpus sin ninguno de los dos patrones |
| Maneja coincidencias exactas (SKUs, IDs, códigos de error) | Sí | No | Sí |
| Maneja paráfrasis y sinónimos | No | Sí | Sí |
| Requiere modelo de embeddings | No | Sí | Sí |
| Requiere ajuste | Parámetros k1, b | Chunking, elección de modelo | Método de fusión (RRF/alpha) |
| Perfil de latencia típico | Submilisegundo a pocos ms | Pocos a decenas de ms (según ANN) | Suma de ambos, más el coste de fusión |
| Ejemplos de soporte nativo | Elasticsearch, Postgres ts_rank | Qdrant, Pinecone, pgvector | Weaviate, Qdrant, Elasticsearch |
En el benchmark WANDS de comercio electrónico, BM25 por sí solo logró 0,6983 de NDCG y la búsqueda vectorial por sí sola logró 0,6953 (casi empatados). La fusión RRF simple, sin ajuste por corpus, alcanzó 0,7068, una mejora modesta del 1,2 % sobre BM25 solo. El benchmark de Doug Turnbull también probó una variante ajustada que añade un boost al nombre de producto sobre RRF, y esa versión llegó a 0,7497, una mejora del 7,4 %. Vale la pena ser honesto sobre qué número estás citando: RRF por sí solo te da una ventaja pequeña pero real desde el primer momento; la cifra mayor del 7,4 % necesitó un ajuste adicional específico del dominio que la mayoría de los equipos se salta el primer día. Ni BM25 ni la búsqueda vectorial dominan por sí solos; cubren modos de fallo distintos, y fusionarlos cierra las dos brechas a la vez.
Cómo funciona BM25: así puntúa la relevancia la búsqueda por palabras clave
BM25 puntúa los documentos según la frecuencia de término, ponderada por lo raro que es ese término en todo el corpus, y luego normalizada por la longitud del documento. Robertson y Zaragoza formalizaron esto en su artículo de 2009 "The Probabilistic Relevance Framework: BM25 and Beyond". Es un refinamiento de TF-IDF, no un reemplazo.
Dos parámetros controlan la mayor parte del comportamiento de BM25. k1 (normalmente 1,2-2,0) controla la saturación de frecuencia de término: limita cuánto impulsa la puntuación repetir una palabra, para que un documento que dice "invoice" 40 veces no supere automáticamente a uno que lo dice 4 veces en un pasaje más breve y relevante. b (0,75 por defecto) controla la normalización por longitud de documento: decide con qué dureza BM25 penaliza a los documentos largos por contener de forma natural más coincidencias.
Equivocarse con b es un error de ajuste real y frecuente. Los documentos técnicos cortos (logs de error, títulos de producto) piden un b más bajo, porque la varianza de longitud es pequeña; el contenido extenso (páginas de documentación, artículos) suele pedir un b cercano al valor por defecto. La debilidad central de BM25 es el desajuste de vocabulario: si un usuario pregunta "cómo recupero mi dinero" y el documento solo dice "política de reembolsos", BM25 no encuentra ningún token en común y no devuelve nada útil.
Cómo funciona la búsqueda vectorial densa (y dónde falla)
La búsqueda vectorial mapea texto a embeddings de dimensión fija mediante un modelo, y luego encuentra vectores cercanos por similitud del coseno o producto punto, normalmente acelerada por un índice de vecino más próximo aproximado. HNSW es el algoritmo dominante en Weaviate, Qdrant y Milvus: sacrifica un poco de recall a cambio de grandes ganancias de velocidad a escala.
Esto es lo que resuelve el problema de desajuste de vocabulario de BM25: "recuperar mi dinero" y "política de reembolsos" caen cerca en el espacio de embeddings aunque no compartan ningún token, porque el modelo captura el significado, no la forma superficial. Elegir el modelo correcto importa mucho aquí. Consulta nuestra guía sobre cómo elegir el modelo de embeddings adecuado, y nuestro análisis de cómo comparamos los embeddings de Voyage, OpenAI y Cohere si estás sopesando opciones.
Pero la recuperación densa tiene su propio punto ciego, y es la imagen especular del de BM25. Cuando construimos sistemas RAG para clientes, el fallo de coincidencia exacta que vemos con más frecuencia no es nada exótico. Es un agente de soporte que pregunta por un número de pedido o un SKU concreto, y el índice vectorial que devuelve con total seguridad algo semánticamente parecido pero equivocado. Un modelo de embeddings de propósito general no tiene ninguna razón para colocar "SKU-4471" o "ERR_CONN_RST" cerca de sí mismo en el espacio vectorial frente a un token relacionado pero incorrecto, porque cadenas así casi nunca aparecen como conceptos aislados y distintos en los datos de entrenamiento. BigData Boutique documenta exactamente este patrón de fallo con sus propios ejemplos de SKUs y códigos de error. Es un fenómeno bien establecido y corroborado de forma independiente en despliegues RAG, no una rareza puntual.
Cómo combinar BM25 y búsqueda vectorial: RRF vs fusión ponderada por alpha
Hay dos formas reales de fusionar los resultados de BM25 y de vector, y casi nadie que escribe sobre búsqueda híbrida las contrasta con claridad. Reciprocal Rank Fusion (RRF), del artículo SIGIR de 2009 de Cormack, Clarke y Buettcher, opera sobre posiciones: score = sum(1 / (k + rank_i)) sobre cada lista de resultados, con k normalmente fijado en 60. Como solo le importa la posición, no la puntuación bruta, RRF maneja sin quejarse los desajustes de escala entre las puntuaciones no acotadas de BM25 y el rango de 0 a 1 de la similitud del coseno, y no necesita ajuste por corpus.
La fusión ponderada por alpha (convexa) funciona de otra manera: final = alpha * dense_score + (1 - alpha) * sparse_score, operando sobre puntuaciones normalizadas en lugar de posiciones. Puede reflejar mejor la magnitud de la confianza (un acierto vectorial con similitud 0,95 de verdad parece más fuerte que uno con 0,61), pero requiere ajustar alpha por corpus, y ese ajuste se rompe en silencio cuando cambian tus distribuciones de puntuación (nuevo modelo de embeddings, corpus reindexado, mezcla de consultas distinta).
En la práctica, la elección se reduce a cuánta confianza tienes en la calibración de tus puntuaciones. Con BM25 estándar frente a un único modelo de embeddings estable, la ponderación por alpha puede arañar un ranking algo mejor porque usa la diferencia real de puntuación, no solo la posición. Pero esa calibración deriva más de lo que la gente espera. Cambia la versión del modelo de embeddings, vuelve a hacer el chunking de tus documentos o añade una pasada de reranking antes, y tu distribución de puntuaciones densas cambia. Nadie recibe una alerta cuando alpha=0,6 deja de ser el valor correcto; el ranking simplemente empeora un poco en silencio, y es fácil no darse cuenta a menos que ejecutes evaluaciones de recuperación con regularidad. RRF esquiva todo esto porque nunca mira las puntuaciones brutas, solo la posición en el ranking, así que una reindexación o un cambio de modelo no puede romperlo en silencio como sí puede romper la ponderación por alpha.
RRF no necesita ajuste por corpus; la ponderación por alpha necesita vigilancia constante a medida que tus datos cambian.
Los motores se dividen en sus valores por defecto. Weaviate expone tanto RRF como un parámetro alpha que tú configuras explícitamente. Elasticsearch incluye RRF nativo mediante su API retriever (confirma el versionado exacto en tu despliegue; llegó en la línea 8.x). Qdrant soporta RRF de forma nativa mediante su Query API. La función híbrida de Pinecone suele apoyarse en la combinación convexa ponderada por alpha en lugar de exponer RRF directamente. Si no tienes claro con cuál quedarte, empieza por RRF. Es el valor por defecto que menos mantenimiento exige.
RRF desde cero: un ejemplo en Python sin depender de ningún proveedor
Todos los ejemplos de código RRF que encontramos en guías de la competencia están atados al SDK de un proveedor: el cliente de Weaviate, el de Qdrant, el de Pinecone. Aquí tienes una versión sin framework que puedes soltar en cualquier stack, con k=60 como valor estándar:
def reciprocal_rank_fusion(result_lists, k=60):
"""
result_lists: list of ranked lists, each a list of document IDs
ordered from most to least relevant.
k: RRF constant (60 is the standard default from Cormack et al., 2009).
Returns: list of (doc_id, fused_score) sorted descending by score.
"""
scores = {}
for result_list in result_lists:
for rank, doc_id in enumerate(result_list, start=1):
scores[doc_id] = scores.get(doc_id, 0.0) + 1.0 / (k + rank)
return sorted(scores.items(), key=lambda item: item[1], reverse=True)
# Example usage:
bm25_hits = ["doc_9", "doc_2", "doc_14", "doc_1"]
vector_hits = ["doc_2", "doc_1", "doc_9", "doc_30"]
fused = reciprocal_rank_fusion([bm25_hits, vector_hits])
for doc_id, score in fused:
print(f"{doc_id}: {score:.4f}")Ese es todo el algoritmo. Sin SDK, sin dependencia de proveedor, y funciona igual si tus dos listas ordenadas vinieron de Elasticsearch y un índice Faiss, o de Postgres ts_rank y pgvector. Si ejecutas los modelos tú mismo en lugar de llamar a una API, consulta ejecutar modelos de embeddings en local con Ollama.
Postgres + pgvector: búsqueda híbrida sin una base de datos vectorial dedicada
No necesitas una base de datos vectorial dedicada para ejecutar búsqueda híbrida. Según un benchmark de pg_textsearch/pgvector del desarrollador Pedro Alonso (Postgres 17, pg_textsearch 1.3.0, pgvector 0.8.2, embeddings nomic-embed-text, dataset BEIR SciFact), una única instancia de Postgres con ts_rank nativo logró apenas 0,07 de NDCG@10, muy por detrás del 0,69 de BM25, el 0,66 de pgvector y el 0,70 de la híbrida, todo en una sola instancia, con una mediana de unos 11,5 ms para RRF híbrido.
Ese 0,07 es la pista definitiva: el ts_rank integrado de Postgres es un ranker de densidad de cobertura, no BM25 de verdad. Si quieres puntuación BM25 real en Postgres, necesitas una extensión. pg_textsearch, VectorChord y ParadeDB añaden un ranking de estilo BM25 propio que el ts_rank nativo no ofrece. Combina una de esas con pgvector para la similitud densa, fusiona las dos listas ordenadas con la función RRF de arriba, y tienes búsqueda híbrida en una única instancia de Postgres sin ninguna infraestructura adicional que operar.
Así es más o menos esa combinación en una sola consulta, uniendo un ranking léxico de una extensión con soporte BM25 y una distancia vectorial de pgvector:
WITH lexical AS (
SELECT id, ts_rank_cd(body_tsv, query) AS rank
FROM documents, plainto_tsquery('english', 'refund policy') query
WHERE body_tsv @@ query
ORDER BY rank DESC LIMIT 50
),
semantic AS (
SELECT id, embedding <=> '[0.012, -0.045, ...]' AS distance
FROM documents
ORDER BY distance LIMIT 50
)
SELECT * FROM lexical
FULL OUTER JOIN semantic USING (id);Pasa ambos conjuntos de resultados a la función RRF de arriba y tienes búsqueda híbrida en una instancia de Postgres. El límite honesto: esto aguanta bien hasta unos pocos millones de filas, pero Postgres no se construyó como un motor de recuperación dedicado. El ajuste de índices corre de tu cuenta, el ts_rank_cd plano sigue sin ser BM25 de verdad sin una extensión, y no obtienes el reranking integrado ni el soporte multi-vector que Weaviate o Milvus traen de serie. Si tu corpus es de tamaño pequeño a mediano y ya ejecutas Postgres, esto te ahorra una segunda pieza de infraestructura entera. Más allá de decenas de millones de documentos, o si necesitas reranking avanzado, un motor dedicado se gana el sueldo.
Si estás sopesando Qdrant, Chroma o pgvector para tu stack en un sentido más amplio, esa es una decisión distinta a la del método de fusión en sí. Consulta nuestra comparativa de Qdrant, Chroma y pgvector para ver las contrapartidas.
¿Qué bases de datos vectoriales soportan búsqueda híbrida nativa?
La mayoría de las bases de datos vectoriales modernas ya incluyen búsqueda híbrida de serie, pero el método de fusión que usan por defecto difiere de forma significativa.
| Motor | Soporte híbrido nativo | Método de fusión | Notas |
|---|---|---|---|
| Weaviate | Sí | RRF o ponderada por alpha | Expone ambos, tú eliges por consulta |
| Qdrant | Sí | RRF | Mediante Query API |
| Elasticsearch | Sí | RRF | Mediante API retriever |
| OpenSearch | Sí | Normalización + suma ponderada | Usa "procesadores de normalización" |
| Vespa | Sí | Fusión nativa | Uno de los primeros motores en soportarlo |
| Milvus | Sí | Multi-vector + BM25 disperso | Híbrida mediante API de búsqueda combinada |
| pgvector + Postgres | Sí (con extensión) | RRF manual (ver arriba) | Necesita extensión ts_rank/BM25 para puntuación léxica real |
Verifica el versionado exacto antes de comprometerte. Las funciones híbridas han ido llegando rápido a estos motores a lo largo de 2026, y las formas de las API cambian de una versión a otra. Para una decisión de compra más amplia, más allá de la mecánica de fusión, consulta nuestro ranking completo de las mejores bases de datos vectoriales.
¿Vale la pena la complejidad de la búsqueda híbrida?
La búsqueda híbrida es arquitectónicamente correcta cuando tu corpus tiene tanto patrones de coincidencia exacta (SKUs, IDs, términos raros) como consultas conceptuales y parafraseadas. Si tu corpus no tiene ninguno de los dos (contenido puramente narrativo, sin identificadores que nadie busque por cadena literal), puede que estés añadiendo complejidad de fusión a cambio de una mejora que apenas notarás.
Piensa en cómo es en realidad un corpus "solo narrativo": el archivo de un blog de empresa, una wiki interna de ingeniería llena de runbooks con mucho texto, un sitio de documentación que nadie busca por ID de producto o número de ticket. En esos corpus, la búsqueda vectorial por sí sola suele darte la mayor parte del valor, y el paso de fusión solo añade una segunda pasada de recuperación y un parámetro del que ahora alguien es dueño, a cambio de una mejora que se redondea a ruido. Compara eso con un sistema de tickets de soporte o un catálogo de comercio electrónico, donde los SKUs, números de pedido y códigos de modelo aparecen constantemente en consultas de usuarios reales. Esa es la prueba real: saca diez consultas reales de tus propios logs y cuenta cuántas contienen un identificador exacto que un modelo de embeddings basado en paráfrasis nunca colocaría bien. Cero: sáltate la híbrida. Más de una o dos: constrúyela.
La búsqueda híbrida no es una mejora universal: si tu corpus no tiene SKUs, IDs ni búsquedas de términos raros, puede que estés añadiendo complejidad de fusión a cambio de una mejora que nunca notarás.
El coste es real pero acotado: una segunda pasada de recuperación, un paso de fusión y un parámetro de ponderación del que ahora alguien es dueño. Deliberadamente no citamos aquí una cifra de latencia, porque los números que circulan vienen de configuraciones sin nombre en hardware sin nombre, y la tuya será distinta. Mídelo en tu propio corpus antes de decidir. Dos hilos de Hacker News capturan bien la tensión real entre profesionales: "Hybrid Search Is Just the Beginning: Optimizing the R in RAG" y "Better RAG Results with Reciprocal Rank Fusion and Hybrid Search". Ambos hilos empujan contra adoptar la híbrida como mejor práctica por imitación, sin comprobar antes si tu corpus siquiera tiene los patrones de consulta que ella pretende resolver. Antes de construirla, vale la pena entender cómo medir de verdad la calidad de la recuperación: los números de NDCG y recall@k solo significan algo contra tu propio corpus, no contra un dataset de benchmark.
Nuestra postura: usa híbrida por defecto en cualquier sistema RAG que atienda consultas de soporte, comercio electrónico o ticketing de cara al usuario. Esas cargas de trabajo casi siempre mezclan identificadores con lenguaje natural. Sáltatela en corpus solo narrativos (documentación extensa, wikis narrativas) hasta que hayas medido una brecha real que la recuperación de un solo método deja abierta.
Sobre el autor
Mert Batur es cofundador de Techsy.io, donde el equipo lanza agentes de IA, sistemas de automatización y pipelines de voz/SDR para clientes B2B. Escribe sobre el stack de herramientas LLM que el equipo de Techsy usa de verdad en producción. Conecta en LinkedIn.
Preguntas frecuentes
¿Qué es la búsqueda híbrida en RAG?
La búsqueda híbrida ejecuta la recuperación BM25 (palabras clave) y vectorial (semántica) como pasadas separadas sobre la misma consulta, y luego fusiona las dos listas ordenadas con un algoritmo de fusión, normalmente Reciprocal Rank Fusion. Atrapa tanto las consultas de coincidencia exacta como las conceptuales parafraseadas, que ninguno de los dos métodos maneja por sí solo.
¿BM25 es lo mismo que la búsqueda vectorial?
No. BM25 es búsqueda léxica dispersa que puntúa la superposición y rareza exactas de términos. La búsqueda vectorial es búsqueda semántica densa que usa embeddings y matemáticas de similitud. Son dos métodos de recuperación distintos con fortalezas opuestas; la búsqueda híbrida los combina, no reemplaza a ninguno.
¿Cómo se combinan BM25 y la búsqueda vectorial?
Ejecuta ambos métodos de recuperación de forma independiente sobre la misma consulta y luego fusiona las dos listas de resultados ordenadas, casi siempre con Reciprocal Rank Fusion, que suma 1 / (k + rank) sobre cada lista. La combinación de puntuaciones ponderada por alpha es la alternativa, pero necesita un ajuste por corpus que RRF no.
¿Qué es Reciprocal Rank Fusion (RRF)?
RRF es un algoritmo de fusión del artículo SIGIR de 2009 de Cormack, Clarke y Buettcher que combina varias listas ordenadas sumando 1 / (k + rank) para cada documento, con k normalmente fijado en 60. Trabaja con la posición en el ranking, no con puntuaciones brutas, así que se mantiene estable ante desajustes de escala entre métodos de recuperación.
¿Cuál es la diferencia entre RRF y la fusión ponderada por alpha?
RRF combina posiciones y no necesita ajuste por corpus. La fusión ponderada por alpha combina puntuaciones normalizadas usando un parámetro alpha ajustable, que puede reflejar mejor la magnitud de la confianza pero requiere re-ajustes constantes cada vez que cambian las distribuciones de puntuación, por ejemplo tras una reindexación o un cambio de modelo.
¿Cuándo debería usar búsqueda híbrida en lugar de solo búsqueda vectorial?
Usa búsqueda híbrida cuando tus consultas mezclen identificadores exactos (SKUs, números de pedido, códigos de error) con preguntas conceptuales en lenguaje natural; los sistemas de soporte, comercio electrónico y ticketing suelen hacerlo. Sáltatela en contenido solo narrativo sin identificadores, donde la complejidad de fusión añadida probablemente no mostrará una mejora medible.
¿Por qué la búsqueda vectorial falla en coincidencias exactas como SKUs o códigos de error?
Los modelos de embeddings aprenden de patrones generales del lenguaje, y cadenas como "SKU-4471" o "ERR_CONN_RST" casi nunca aparecen como conceptos aislados y distintos en los datos de entrenamiento. El modelo no tiene una razón fuerte para colocar esa cadena exacta más cerca de sí misma que de un token semánticamente relacionado pero equivocado.
¿Qué bases de datos vectoriales soportan búsqueda híbrida de forma nativa?
Weaviate, Qdrant, Elasticsearch, OpenSearch, Vespa y Milvus incluyen búsqueda híbrida nativa a fecha de 2026, aunque sus métodos de fusión por defecto difieren (RRF vs ponderada por alpha vs normalización). Postgres con pgvector también puede ejecutar búsqueda híbrida, pero necesita una extensión BM25, porque el ts_rank nativo no es BM25 de verdad.
¿Vale la pena la búsqueda híbrida por la complejidad añadida?
Para corpus que mezclan consultas de coincidencia exacta y conceptuales, sí. RRF simple ya supera a cualquiera de los dos métodos en el benchmark WANDS (0,7068 frente al 0,6983 de BM25), y una variante ajustada alcanza una mejora del 7,4 % (0,7497). Para corpus solo narrativos sin identificadores, la segunda pasada de recuperación y el ajuste de fusión que necesita pueden pesar más que una mejora que no notarás. Mide antes de comprometerte.
¿Pueden Postgres/pgvector hacer búsqueda híbrida sin una base de datos vectorial dedicada?
Sí. Combina pgvector para la similitud densa con una extensión BM25 de verdad como pg_textsearch, VectorChord o ParadeDB (el ts_rank nativo por sí solo logró apenas 0,07 de NDCG@10 en el benchmark de pg_textsearch/pgvector de Pedro Alonso, frente al 0,70 de la híbrida), y luego fusiona las dos listas ordenadas con RRF, todo dentro de una única instancia de Postgres.
Ambos métodos de recuperación dejan brechas reales cuando se ejecutan por separado: BM25 falla en la paráfrasis, la búsqueda vectorial falla en los identificadores exactos, y fusionarlos con RRF es la forma de cerrar ambas con menos mantenimiento. Si estás sopesando construirlo tú mismo o traer a un equipo que ya ha lanzado recuperación RAG antes, nuestra guía completa para construir una aplicación RAG cubre el siguiente paso, o ponte en contacto si prefieres que Techsy lo construya contigo.