store_nodes() for BM25 hybrid
CompletionIn this exercise, you will implement a hybrid retriever that combines dense embeddings with BM25 sparse retrieval using Reciprocal Rank Fusion (RRF). The key challenge is that when using Qdrant as the vector store, index.docstore.docs is empty—nodes must be scrolled back from the vector store via the store_nodes() utility provided in the codebase. Your task is to complete the build_fusion_retriever function that:
- Calls
store_nodes(index)to hydrate the full corpus as a list ofBaseNodeobjects. - If the node list is empty, falls back to returning the
dense_retrieverunchanged. - Builds a
BM25Retrieverfrom those nodes usingfrom_defaults()withsimilarity_top_kset tosparse_top_k(computed asmin(top_k, len(node_list))to avoid corpus-size issues). - Creates a
QueryFusionRetrieverwithmode="reciprocal_rerank"andnum_queries=1(no LLM expansion) that fusesdense_retrieverand the sparse retriever. - Wraps the construction in a try/except so that any failure (e.g., missing dependencies) returns the dense retriever unchanged.
The starter code has three # TODO: gaps. Fill them in with the correct code.
Relevant identifiers from the source code:
store_nodes(index) -> listBM25Retriever.from_defaults(nodes=..., similarity_top_k=...)QueryFusionRetriever(retrievers, similarity_top_k=..., num_queries=..., mode="reciprocal_rerank", ...)
Your code
Sources
- roadmap-kg/kg/rerank.py:188-225
- roadmap-kg/kg/rerank.py:151-186
- roadmap-kg/kg/memory_common.py:975-990