
Busca híbrida: BM25 vs. vetorial (e por que você precisa das duas)
Um agente de suporte digita "SKU-4471" no seu chatbot RAG. Voltam quatro resultados. Todos errados, com absoluta confiança. Um modelo de embedding de propósito geral não tem motivo nenhum para colocar essa string exata perto de si mesma no espaço vetorial. É exatamente esse modo de falha que justifica a existência da busca híbrida, e é por isso que as equipes vivem fazendo a mesma pergunta: como combinar de verdade o BM25 e a busca vetorial sem ficar vigiando um parâmetro de ajuste para sempre?
Se você está avaliando o ferramental RAG de forma mais ampla, nosso ranking das melhores ferramentas RAG cobre o stack ao redor.
Principais conclusões
- O BM25 encontra correspondências exatas de palavras-chave (SKUs, códigos de erro); a busca vetorial encontra texto conceitualmente semelhante, não strings idênticas.
- A busca híbrida combina as duas, geralmente via Reciprocal Rank Fusion (RRF), e supera qualquer uma delas isoladamente em cargas de consulta mistas.
- No benchmark WANDS, o RRF simples marca 0,7068 de NDCG (contra 0,6983 do BM25); com ajuste fino, chega a 0,7497, um ganho de 7,4%.
- Postgres/pgvector roda busca híbrida nativamente com
ts_rank+ pgvector, sem precisar de um banco de dados vetorial dedicado.
O que é busca híbrida? (BM25 + vetorial, combinados)
A busca híbrida executa o BM25 e a busca vetorial como duas passagens de recuperação separadas sobre a mesma consulta e depois mescla as duas listas de resultados ranqueados em uma única saída, usando um algoritmo de fusão, quase sempre a Reciprocal Rank Fusion. Ela não é um terceiro método de recuperação; é uma camada de orquestração sobre dois métodos que já existem.
Essa distinção importa porque uma boa parte do tráfego de busca em torno desse tema trata o BM25 e a busca vetorial como se fossem a mesma coisa. Não são. O BM25 é uma função de pontuação esparsa, baseada em palavras-chave, com raízes na recuperação de informação dos anos 1970. A busca vetorial é uma busca de similaridade densa, baseada em embeddings, que só se tornou prática em escala na última década. A busca híbrida trata os dois como entradas complementares, não como técnicas concorrentes, e funde as saídas em vez de escolher um vencedor de antemão.
BM25 vs. vetorial vs. híbrida: comparação rápida
| Dimensão | BM25 (esparso/lexical) | Busca vetorial (densa/semântica) | Híbrida |
|---|---|---|---|
| Melhor em | Termos exatos, tokens raros, IDs | Paráfrase, sinônimos, conceitos | Os dois tipos de consulta |
| Falha em | Perguntas parafraseadas, sinonímia | SKUs, códigos de erro, siglas | Corpus sem nenhum dos dois padrões |
| Lida com correspondência exata (SKUs, IDs, códigos de erro) | Sim | Não | Sim |
| Lida com paráfrase e sinônimos | Não | Sim | Sim |
| Exige modelo de embedding | Não | Sim | Sim |
| Exige ajuste | Parâmetros k1, b | Fragmentação, escolha do modelo | Método de fusão (RRF/alfa) |
| Perfil típico de latência | Sub-milissegundo a poucos ms | Poucos a médios ms (depende do ANN) | Soma dos dois, mais o custo da fusão |
| Exemplos de suporte nativo | Elasticsearch, ts_rank do Postgres | Qdrant, Pinecone, pgvector | Weaviate, Qdrant, Elasticsearch |
No benchmark WANDS de e-commerce, o BM25 sozinho marcou 0,6983 de NDCG e a busca vetorial sozinha marcou 0,6953 (quase empatados). A fusão RRF simples, sem ajuste por corpus, chegou a 0,7068, um ganho modesto de 1,2% sobre o BM25 isolado. O benchmark do Doug Turnbull também testou uma variante ajustada que adiciona um boost no nome do produto por cima do RRF, e essa versão atingiu 0,7497, um ganho de 7,4%. Vale ser honesto sobre qual número você está citando: o RRF sozinho dá uma vantagem pequena, mas real, já de cara; o número maior, de 7,4%, exigiu um ajuste extra específico do domínio que a maioria das equipes pula no primeiro dia. Nem o BM25 nem a busca vetorial dominam sozinhos; eles cobrem modos de falha diferentes, e fundir os dois fecha as duas lacunas de uma vez.
Mecânica do BM25: como a busca por palavras-chave pontua relevância
O BM25 pontua documentos pela frequência do termo, ponderada pela raridade desse termo em todo o corpus, e depois normalizada pelo comprimento do documento. Robertson e Zaragoza formalizaram isso no artigo de 2009 "The Probabilistic Relevance Framework: BM25 and Beyond". É um refinamento do TF-IDF, não um substituto.
Dois parâmetros controlam a maior parte do comportamento do BM25. O k1 (tipicamente 1,2 a 2,0) controla a saturação da frequência do termo: ele limita o quanto a repetição de uma palavra aumenta a pontuação, de modo que um documento que diz "invoice" 40 vezes não supera automaticamente outro que a menciona 4 vezes em uma passagem mais enxuta e mais relevante. O b (padrão 0,75) controla a normalização por comprimento do documento: ele decide com que rigor o BM25 penaliza documentos longos por conterem naturalmente mais ocorrências do termo.
Errar o b é um erro de ajuste real e comum. Documentos técnicos curtos (logs de erro, títulos de produto) pedem um b mais baixo, já que a variação de comprimento é pequena; conteúdo longo (páginas de documentação, artigos) geralmente pede um b mais próximo do padrão. A fraqueza central do BM25 é o descasamento de vocabulário: se o usuário pergunta "como faço para receber meu dinheiro de volta" e o documento só diz "política de reembolso", o BM25 não encontra nenhum token em comum e não retorna nada útil.
Mecânica da busca vetorial densa (e onde ela quebra)
A busca vetorial mapeia texto em embeddings de dimensão fixa usando um modelo e depois encontra vetores próximos por similaridade de cosseno ou produto escalar, geralmente acelerada por um índice aproximado de vizinho mais próximo. O HNSW é o algoritmo dominante em Weaviate, Qdrant e Milvus, trocando uma pequena quantidade de recall por grandes ganhos de velocidade em escala.
É isso que resolve o problema de descasamento de vocabulário do BM25: "receber meu dinheiro de volta" e "política de reembolso" caem perto um do outro no espaço de embeddings mesmo sem nenhum token em comum, porque o modelo captura significado, não forma superficial. Escolher o modelo certo importa muito aqui. Veja nosso guia sobre como escolher o modelo de embedding certo e nosso comparativo de como avaliamos os embeddings da Voyage, OpenAI e Cohere se você está pesando as opções.
Mas a recuperação densa tem seu próprio ponto cego, e ele é a imagem espelhada do ponto cego do BM25. Quando construímos sistemas RAG para clientes, a falha de correspondência exata que encontramos com mais frequência não é nada exótica. É um agente de suporte pedindo um número de pedido ou SKU específico, e o índice vetorial retornando com toda a confiança algo semanticamente parecido, mas errado. Um modelo de embedding de propósito geral não tem motivo para colocar "SKU-4471" ou "ERR_CONN_RST" perto de si mesmo no espaço vetorial em vez de um token relacionado, porém errado, porque strings assim raramente aparecem como conceitos distintos e isolados nos dados de treino. A BigData Boutique documenta exatamente esse padrão de falha com seus próprios exemplos de SKU e código de erro. É um fenômeno bem estabelecido e confirmado de forma independente em várias implantações de RAG, não uma esquisitice pontual.
Como combinar BM25 e busca vetorial: RRF vs. fusão ponderada por alfa
Existem duas formas reais de fundir resultados do BM25 e da busca vetorial, e quase ninguém que escreve sobre busca híbrida contrasta as duas com clareza. A Reciprocal Rank Fusion (RRF), do artigo de 2009 da SIGIR de Cormack, Clarke e Buettcher, opera sobre posições: score = sum(1 / (k + rank_i)) em cada lista de resultados, com k tipicamente igual a 60. Como ela só se importa com a posição, não com o score bruto, a RRF lida sem reclamar com a diferença de escala entre os scores ilimitados do BM25 e o intervalo de 0 a 1 da similaridade de cosseno, e não precisa de ajuste por corpus.
A fusão ponderada por alfa (convexa) funciona de outro jeito: final = alpha * dense_score + (1 - alpha) * sparse_score, operando sobre scores normalizados em vez de posições. Ela consegue refletir melhor a magnitude da confiança (um resultado vetorial com 0,95 de similaridade de fato parece mais forte que um com 0,61), mas exige ajustar o alpha para cada corpus, e esse ajuste quebra em silêncio quando a distribuição dos seus scores muda (modelo de embedding novo, corpus reindexado, mix de consultas diferente).
Na prática, a escolha se resume a quanto você confia na calibração dos seus scores. Rodando um BM25 padrão contra um único modelo de embedding estável, a ponderação por alfa pode arrancar um ranking um pouco melhor porque usa o vão real entre os scores, não só a posição. Mas essa calibração deriva mais do que as pessoas esperam. Troque a versão do modelo de embedding, refaça a fragmentação dos documentos ou adicione uma passada de reranking antes, e a distribuição dos seus scores densos muda. Ninguém é acordado de madrugada quando alpha=0.6 deixa de ser o valor certo; o ranking simplesmente fica um pouco pior em silêncio, e é fácil não perceber a menos que você rode avaliações de recuperação com regularidade. A RRF escapa disso por completo porque nunca olha para os scores brutos, só para a posição no ranking, então uma reindexação ou troca de modelo não consegue quebrá-la em silêncio do jeito que consegue quebrar a ponderação por alfa.
A RRF não precisa de ajuste por corpus; a ponderação por alfa precisa de vigilância constante conforme seus dados mudam.
Os motores se dividem nos padrões. O Weaviate expõe tanto a RRF quanto um parâmetro alpha que você define explicitamente. O Elasticsearch traz RRF nativa pela sua API retriever (confirme o gating exato de versão na sua instalação; isso chegou na linha 8.x). O Qdrant suporta RRF nativamente pela sua Query API. O recurso híbrido do Pinecone geralmente se apoia na combinação convexa ponderada por alfa em vez de expor a RRF diretamente. Se você não tem certeza de qual escolher, comece pela RRF. É o padrão que dá menos manutenção.
RRF do zero: um exemplo em Python neutro quanto a fornecedor
Todo exemplo de código de RRF que encontramos em guias concorrentes está preso ao SDK de um fornecedor: o cliente do Weaviate, o cliente do Qdrant, o cliente do Pinecone. Aqui está uma versão sem framework que você pode soltar em qualquer stack, com k=60 como padrão:
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}")É o algoritmo inteiro. Sem SDK, sem lock-in de fornecedor, e funciona quer suas duas listas ranqueadas venham do Elasticsearch e de um índice Faiss, quer do ts_rank do Postgres e do pgvector. Se você mesmo roda os modelos em vez de chamar uma API, veja como rodar modelos de embedding localmente com o Ollama.
Postgres + pgvector: busca híbrida sem um banco de dados vetorial dedicado
Você não precisa de um banco de dados vetorial dedicado para rodar busca híbrida. Segundo um benchmark de pg_textsearch/pgvector do desenvolvedor Pedro Alonso (Postgres 17, pg_textsearch 1.3.0, pgvector 0.8.2, embeddings nomic-embed-text, dataset BEIR SciFact), uma única instância de Postgres rodando o ts_rank nativo marcou apenas 0,07 de NDCG@10, muito atrás dos 0,69 do BM25, dos 0,66 do pgvector e dos 0,70 da híbrida, tudo em uma instância só, com o RRF híbrido em torno de 11,5 ms de mediana.
O 0,07 é a pista reveladora: o ts_rank embutido do Postgres é um ranqueador por densidade de cobertura, não um BM25 de verdade. Se você quer pontuação BM25 real no Postgres, precisa de uma extensão. pg_textsearch, VectorChord e ParadeDB adicionam um ranking de estilo BM25 apropriado que o ts_rank nativo não oferece. Combine uma delas com o pgvector para a similaridade densa, funda as duas listas ranqueadas com a função RRF acima, e você tem busca híbrida em uma única instância de Postgres, sem nenhuma infraestrutura separada para operar.
Em linhas gerais, esse pareamento fica assim em uma única consulta, combinando um rank lexical de uma extensão capaz de BM25 com uma distância vetorial do 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);Passe os dois conjuntos de resultados para a função RRF acima e você tem busca híbrida em uma instância de Postgres. O limite honesto: isso se sustenta bem até a casa dos milhões de linhas, mas o Postgres não foi construído como um motor de recuperação dedicado. Você cuida do ajuste dos índices por conta própria, o ts_rank_cd puro continua não sendo um BM25 de verdade sem uma extensão, e você não recebe o reranking embutido nem o suporte a múltiplos vetores que Weaviate ou Milvus trazem nativamente. Se o seu corpus é de pequeno a médio porte e você já roda Postgres, isso economiza uma segunda peça inteira de infraestrutura. Acima de dezenas de milhões de documentos, ou se você precisa de reranking avançado, um motor dedicado vale o investimento.
Se você está pesando Qdrant, Chroma ou pgvector para o seu stack de forma mais ampla, essa é uma decisão separada do método de fusão em si. Veja nosso comparativo de Qdrant, Chroma e pgvector para os tradeoffs.
Quais bancos de dados vetoriais suportam busca híbrida nativa?
A maioria dos bancos de dados vetoriais modernos já traz busca híbrida pronta para uso, mas o método de fusão padrão deles difere de forma relevante.
| Motor | Suporte híbrido nativo | Método de fusão | Observações |
|---|---|---|---|
| Weaviate | Sim | RRF ou ponderada por alfa | Expõe os dois, você escolhe por consulta |
| Qdrant | Sim | RRF | Via Query API |
| Elasticsearch | Sim | RRF | Via API retriever |
| OpenSearch | Sim | Normalização + soma ponderada | Usa "processadores de normalização" |
| Vespa | Sim | Fusão nativa | Um dos primeiros motores a suportar isso |
| Milvus | Sim | Multivetor + BM25 esparso | Híbrida via API de busca combinada |
| pgvector + Postgres | Sim (com extensão) | RRF manual (veja acima) | Precisa de extensão ts_rank/BM25 para pontuação lexical real |
Confirme o gating exato de versão antes de se comprometer. Os recursos híbridos chegaram rápido a esses motores ao longo de 2026, e o formato das APIs muda de release para release. Para uma decisão de compra mais ampla, além da mecânica de fusão, veja nosso ranking completo dos melhores bancos de dados vetoriais.
A busca híbrida vale a complexidade?
A busca híbrida é arquiteturalmente correta quando o seu corpus tem tanto padrões de correspondência exata (SKUs, IDs, termos raros) quanto consultas conceituais e parafraseadas. Se o seu corpus não tem nenhum dos dois (conteúdo puramente narrativo, sem identificadores que alguém busque pela string literal), você pode estar adicionando complexidade de fusão por um ganho que mal vai notar.
Pense no que "somente narrativo" realmente significa: o arquivo de blog de uma empresa, uma wiki interna de engenharia cheia de runbooks em prosa, um site de documentação que ninguém busca por ID de produto ou número de ticket. Nesses corpus, a busca vetorial sozinha geralmente entrega a maior parte do valor, e a etapa de fusão só adiciona uma segunda passagem de recuperação e um parâmetro que alguém agora precisa cuidar, por um ganho que arredonda para ruído. Compare isso com um sistema de tickets de suporte ou um catálogo de e-commerce, onde SKUs, números de pedido e códigos de modelo aparecem o tempo todo nas consultas reais dos usuários. Esse é o teste de verdade: puxe dez consultas reais dos seus próprios logs e conte quantas contêm um identificador exato que um modelo de embedding baseado em paráfrase nunca posicionaria corretamente. Zero, pule a híbrida. Mais que uma ou duas, construa.
A busca híbrida não é um upgrade universal: se o seu corpus não tem SKUs, IDs nem consultas de termos raros, você pode estar adicionando complexidade de fusão por um ganho que nunca vai notar.
O custo é real, mas limitado: uma segunda passagem de recuperação, uma etapa de fusão e um parâmetro de ponderação que alguém agora precisa cuidar. Estamos deliberadamente não citando um número de latência aqui, porque os números que circulam por aí vêm de setups sem nome em hardwares sem nome, e o seu vai diferir. Meça no seu próprio corpus antes de decidir. Dois tópicos do Hacker News capturam a tensão real dos praticantes aqui: "Hybrid Search Is Just the Beginning: Optimizing the R in RAG" e "Better RAG Results with Reciprocal Rank Fusion and Hybrid Search". Os dois tópicos questionam a adoção da híbrida como melhor prática de cargo cult sem antes verificar se o seu corpus sequer tem os padrões de consulta que ela se propõe a resolver. Antes de construí-la, vale entender como medir de verdade a qualidade da recuperação: números de NDCG e recall@k só significam algo contra o seu próprio corpus, não contra um dataset de benchmark.
Nossa posição: use a híbrida por padrão em qualquer sistema RAG que atende consultas de suporte ao usuário, e-commerce ou tickets. Essas cargas quase sempre misturam identificadores com linguagem natural. Pule-a para corpus somente narrativos (documentos longos, wikis narrativas) até você ter medido uma lacuna real que a recuperação de método único deixa aberta.
Sobre o autor
Mert Batur é cofundador da Techsy.io, onde a equipe entrega agentes de IA, sistemas de automação e pipelines de voz/SDR para clientes B2B. Ele escreve sobre o stack de ferramentas LLM que a equipe da Techsy usa de verdade em produção. Conecte-se no LinkedIn.
Perguntas frequentes
O que é busca híbrida em RAG?
A busca híbrida executa a recuperação BM25 (palavra-chave) e vetorial (semântica) como passagens separadas sobre a mesma consulta e depois mescla as duas listas ranqueadas com um algoritmo de fusão, geralmente a Reciprocal Rank Fusion. Ela pega tanto as consultas de correspondência exata quanto as conceituais e parafraseadas, que nenhum dos dois métodos resolve sozinho.
O BM25 é a mesma coisa que busca vetorial?
Não. O BM25 é uma busca lexical esparsa que pontua a sobreposição exata e a raridade dos termos. A busca vetorial é uma busca semântica densa que usa embeddings e matemática de similaridade. São dois métodos de recuperação com forças opostas, e a busca híbrida combina os dois em vez de substituir qualquer um deles.
Como combinar BM25 e busca vetorial?
Rode os dois métodos de recuperação de forma independente sobre a mesma consulta e depois funda as duas listas de resultados ranqueadas, quase sempre com a Reciprocal Rank Fusion, que soma 1 / (k + rank) em cada lista. A combinação de scores ponderada por alfa é a alternativa, mas precisa de ajuste por corpus que a RRF não precisa.
O que é Reciprocal Rank Fusion (RRF)?
A RRF é um algoritmo de fusão do artigo da SIGIR de 2009 de Cormack, Clarke e Buettcher que combina várias listas ranqueadas somando 1 / (k + rank) para cada documento, com k tipicamente igual a 60. Ela opera sobre a posição no ranking, não sobre os scores brutos, então se mantém estável mesmo com diferenças de escala entre os métodos de recuperação.
Qual é a diferença entre RRF e fusão ponderada por alfa?
A RRF combina posições e não precisa de ajuste por corpus. A fusão ponderada por alfa combina scores normalizados usando um parâmetro alpha ajustável, o que pode refletir melhor a magnitude da confiança, mas exige reajuste contínuo sempre que a distribuição dos scores muda, como depois de uma reindexação ou troca de modelo.
Quando devo usar busca híbrida em vez de só busca vetorial?
Use busca híbrida quando suas consultas misturam identificadores exatos (SKUs, números de pedido, códigos de erro) com perguntas conceituais em linguagem natural; sistemas de suporte, e-commerce e tickets geralmente misturam. Pule-a para conteúdo somente narrativo, sem identificadores, onde a complexidade extra da fusão provavelmente não vai mostrar um ganho mensurável.
Por que a busca vetorial erra correspondências exatas como SKUs ou códigos de erro?
Os modelos de embedding aprendem com padrões gerais de linguagem, e strings como "SKU-4471" ou "ERR_CONN_RST" raramente aparecem como conceitos distintos e isolados nos dados de treino. O modelo não tem um motivo forte para colocar essa string exata mais perto de si mesmo do que de um token semanticamente relacionado, porém errado.
Quais bancos de dados vetoriais suportam busca híbrida nativamente?
Weaviate, Qdrant, Elasticsearch, OpenSearch, Vespa e Milvus trazem busca híbrida nativa em 2026, embora os métodos de fusão padrão deles difiram (RRF vs. ponderada por alfa vs. normalização). O Postgres com pgvector também consegue rodar busca híbrida, mas precisa de uma extensão BM25, já que o ts_rank nativo não é um BM25 de verdade.
A busca híbrida vale a complexidade adicional?
Para corpus que misturam consultas de correspondência exata e conceituais, sim. O RRF simples já supera qualquer um dos métodos isolados no benchmark WANDS (0,7068 contra 0,6983 do BM25), e uma variante ajustada chega a um ganho de 7,4% (0,7497). Para corpus somente narrativos, sem identificadores, a segunda passagem de recuperação e o ajuste de fusão que ela exige podem pesar mais que um ganho que você não vai notar. Meça antes de se comprometer.
O Postgres/pgvector consegue fazer busca híbrida sem um banco de dados vetorial dedicado?
Sim. Combine o pgvector para a similaridade densa com uma extensão BM25 de verdade, como pg_textsearch, VectorChord ou ParadeDB (o ts_rank nativo sozinho marcou apenas 0,07 de NDCG@10 no benchmark de pg_textsearch/pgvector do Pedro Alonso, contra 0,70 da híbrida) e depois funda as duas listas ranqueadas com RRF, tudo dentro de uma única instância de Postgres.
Os dois métodos de recuperação deixam lacunas reais quando rodados sozinhos: o BM25 erra a paráfrase, a busca vetorial erra os identificadores exatos, e fundir os dois com RRF é o caminho de menor manutenção para fechar as duas. Se você está pesando se constrói isso por conta própria ou chama uma equipe que já entregou recuperação RAG antes, nosso guia completo para construir uma aplicação RAG cobre o próximo passo, ou fale com a gente se você prefere que a Techsy construa junto com você.