feat(retrieval): BM25 lexical retriever and dense hybrid fusion with RRF (#233) - #264
Merged
codeforstartups merged 2 commits intoSep 28, 2026
Conversation
codeforstartups
approved these changes
Sep 28, 2026
codeforstartups
left a comment
Owner
There was a problem hiding this comment.
Excellent — this is the sparse/BM25 hybrid from the roadmap. A pure-Python Okapi BM25 index (zero deps, Lucene-style IDF + TF saturation) plus BM25Retriever and BM25HybridRetriever that fuses lexical + dense results via RRF. Big quality win for keyword-heavy queries where pure vector search underperforms. Verified: ruff clean, 18 tests pass, CI green incl. typecheck. Merging — thanks @shivamm-gupta! 🙌
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #233.
This PR introduces an in-memory Okapi BM25 lexical retriever and a hybrid fusion retriever combining dense ANN vector search (S3 Vectors) with sparse BM25 lexical search using Reciprocal Rank Fusion (RRF).
Key Additions & Features
Pure-Python BM25 Index (
dynavec.bm25):default_tokenize: Preserves exact compound identifiers (e.g.SKU-892-XZ,XPS-13-9310,ConnectionResetError,10.0.0.1) both as whole tokens and sub-tokens for maximal recall on both exact codes and partial queries, with configurable stopword filtering.$in,$nin,$gt,$gte,$lt,$lte,$ne).BM25Retriever(dynavec.retrievers):Dynavecclient orNamespaceView.search(), asyncasearch(),index_documents(), andpopulate_from_store().BM25HybridRetriever(dynavec.retrievers):reciprocal_rank_fusionwith configurable weights (dense_weightandsparse_weight).RRFWeightFitterlearned weights orFitResultinstances.search()and asyncasearch().Client & Namespace Ergonomics:
Dynavec.as_bm25_retriever()Dynavec.as_hybrid_retriever()Dynavec.hybrid_search()NamespaceView.as_bm25_retriever()NamespaceView.as_hybrid_retriever()NamespaceView.hybrid_search()Exports:
BM25Index,BM25Retriever, andBM25HybridRetrieverexported in top-leveldynavec.Verification
tests/test_bm25_retriever.py(18 unit tests):RRFWeightFitter/FitResultweight passing and overrideDynavecandNamespaceViewergonomicsruff check(0 errors).