v0.9.0 — Hybrid & Advanced Retrieval
Hybrid & Advanced Retrieval — BM25+Vector fusion, temporal decay, MMR, domain routing
This release introduces a fully configurable, multi-strategy retrieval pipeline for fabri's memory system. All changes are backward-compatible — existing configs and databases work without modification.
Retrieval strategies
Controlled by memory.retrieval_strategy:
| Strategy | Description |
|---|---|
dense |
Original cosine vector similarity (default, unchanged) |
sparse |
BM25-only via SQLite FTS5 (built-in) or rank_bm25 for Qdrant |
hybrid |
RRF fusion of dense + sparse |
hybrid+mmr |
Hybrid + Maximal Marginal Relevance diversification |
Reciprocal Rank Fusion (RRF) — entries appearing in both dense and sparse results get double credit. MMR — diversifies the final pool by balancing relevance vs redundancy (memory.mmr_lambda, default 0.7).
Scoring pipeline (all opt-in)
- Temporal decay (
memory.temporal_decay: true) —score *= exp(-ln(2) * age_days / half_life_days). Default half-life: 30 days. - Importance boost (
memory.importance_weight: 0.2) —min(1, hit_count/10 + 0.3 if strategic). - Domain routing (
memory.domain_routing: true) — zero-latency keyword heuristic; matching entries get a 1.15× boost, never hard-filters.
SQLite FTS5 index (zero extra install)
FTS5 is Python built-in. Porter tokenizer. Synced on every upsert/delete. Auto-migration: existing DBs are bulk-populated from guidelines on first upgrade — no manual step needed.
Memory schema enrichment
MemoryEntry gains four new optional fields (all default-safe for old payloads): domain, outcome, agent_id, task_embedding_hash. Deterministic ID hash unchanged — no DB migration needed.
New config keys (all default to pre-v0.9.0 behavior)
memory:
retrieval_strategy: dense # dense | sparse | hybrid | hybrid+mmr
temporal_decay: false
temporal_half_life_days: 30.0
mmr_lambda: 0.7
domain_routing: false
importance_weight: 0.2
query_expansion: false # reservedOptional dependency
pip install 'fabri[bm25]' # client-side BM25 for Qdrant hybrid retrieval
SQLite users get full hybrid retrieval with zero extra installs.
Bug fix
agent_runner_tool.py hardcoded QdrantMemoryStore; now uses build_memory_store(mem_cfg) so SQLite users get hybrid retrieval in sub-agent runs too.
Quick start
# agent.yaml
memory:
backend: sqlite
retrieval_strategy: hybrid+mmr
temporal_decay: true
domain_routing: true