Hybrid Search
RadarOS supports three search modes inKnowledgeBase:
| Mode | How it works | Best for |
|---|---|---|
vector | Embedding similarity (cosine distance) | Semantic meaning, paraphrased queries |
keyword | BM25 scoring on an in-memory inverted index | Exact terms, acronyms, codes, IDs |
hybrid | Combines both via Reciprocal Rank Fusion (RRF) | Best of both — the recommended default for production |
Hybrid search is built into
KnowledgeBase and works with all vector store backends (InMemory, PgVector, Qdrant, MongoDB). No additional dependencies needed.Why Hybrid?
Pure vector search understands meaning but can miss exact terms. Pure keyword search matches terms exactly but misses semantics. Hybrid combines both:Vector Search
Query: “time off vacation days”
Finds: PTO policy doc (no doc says “vacation” but meaning matches)
Keyword Search
Query: “401k matching”
Finds: 401(k) plan doc (exact term match scores high)
Quick Start
KnowledgeBase Config
Default search mode for all
search() and asTool() calls. Can be overridden per call.Fine-tune hybrid search behavior. Only used when
searchMode is "hybrid".HybridSearchConfig
Weight for vector (semantic) results. Increase to favor semantic matches.
Weight for keyword (BM25) results. Increase to favor exact term matches.
RRF smoothing constant. Higher values dampen the effect of rank differences across the two result lists. Lower values make top-ranked results more dominant.
Per-Query Override
You can override the search mode on individualsearch() calls, regardless of the default:
With asTool()
PasssearchMode to asTool() to control how the agent searches:
searchMode is not passed to asTool(), it inherits the KB’s default.
How It Works Under the Hood
Parallel retrieval
search() runs vector search (via the vector store) and keyword search (via the built-in BM25 index) in parallel. Each fetches topK × 2 candidates for better fusion quality.BM25 scoring
The in-memory
BM25Index tokenizes the query, computes term frequency / inverse document frequency scores, and ranks documents. Stop words are filtered, and scores are length-normalized.Reciprocal Rank Fusion
Both ranked lists are merged using RRF. For each document, its fused score is:
score = Σ weight_i / (k + rank_i)Documents appearing in both lists get scores from both, naturally ranking higher.BM25 Index
TheBM25Index is built-in and maintained automatically:
- Auto-populated: When you call
add()oraddDocuments(), documents are indexed in both the vector store and the BM25 index. - Auto-cleaned: When you call
delete()orclear(), documents are removed from both. - In-memory: The BM25 index lives in process memory. It’s rebuilt from the vector store’s documents on startup if needed.
- Configurable: BM25 uses standard Okapi BM25 parameters (
k1 = 1.5,b = 0.75) which work well for most use cases.
Tuning Tips
| Goal | Adjustment |
|---|---|
| Favor semantic matches | Set vectorWeight: 2.0, keywordWeight: 1.0 |
| Favor exact term matches | Set vectorWeight: 1.0, keywordWeight: 2.0 |
| Less sensitive to rank position | Increase rrfK (e.g., 100) |
| More sensitive to top results | Decrease rrfK (e.g., 20) |
| Technical docs with many acronyms | Higher keywordWeight |
| Natural language Q&A | Higher vectorWeight |
Full Example
Seeexamples/knowledge/28-hybrid-search.ts for a complete comparison of all three search modes: