Hybrid search: keywords and meaning together
Hybrid search runs keyword and semantic retrieval together and merges their rankings, so a question is served whichever way it is phrased.
from llama_index.core.llms import MockLLM
from llama_index.core.retrievers import QueryFusionRetriever
hybrid = QueryFusionRetriever(
[semantic, keyword],
llm=MockLLM(),
similarity_top_k=2,
num_queries=1,
mode="reciprocal_rerank",
use_async=False,
)QueryFusionRetriever runs several retrievers and fuses their results. num_queries=1 uses the question as given; above 1 it asks a model to write extra versions of the question. It looks a model up when it is created even when it will not call one, and without a key its default is unavailable, so MockLLM from lesson 9 fills that slot. reciprocal_rerank merges by rank position, not raw score, so a BM25 score of 3 and a similarity of 0.4 can be combined fairly.
for question in ["LMP-204", "Is reimbursement possible?", "Is the LMP-204 refundable?"]:
print(question, [(n.metadata["file_name"], round(n.score, 4)) for n in hybrid.retrieve(question)])Both kinds of question now put the right file first. Fused scores are small numbers from the ranks, useful for ordering and not for a cutoff like lesson 11's.
Reciprocal rank fusion gives each result 1 divided by (a constant plus its rank) from each retriever, and adds them up. A chunk ranked high by both wins; a chunk found by only one still scores.
- Swap the order of
[semantic, keyword]. Does the result change? - Set
similarity_top_k=3on the fusion retriever. - Use
hybridinside a query engine withRetrieverQueryEngine.from_args(hybrid, llm=ExtractiveLLM()).
This is what real progress feels like.