Retrievers
TL;DR: Use
@retrieverto define semantic search functions. Fabra handles embedding, vector search, and caching automatically.
At a Glance
| Decorator | @retriever(index="docs", top_k=5) |
| Vector DB | pgvector (Postgres extension) |
| Embedding | OpenAI, Cohere, Anthropic |
| Caching | cache_ttl=timedelta(seconds=300) stores in Redis |
| Magic Wiring | Empty function body auto-searches the index |
| DAG Integration | Use {retriever_name} in feature templates |
What is a Retriever?
A Retriever is a function that searches an index and returns relevant documents. The @retriever decorator transforms a simple function into a full vector search pipeline.
from fabra.retrieval import retriever
@retriever(index="knowledge_base", top_k=5)
async def search_docs(query: str):
# Magic Wiring: Automatically searches `knowledge_base` index.
passBasic Usage
Define a Retriever
from fabra.core import FeatureStore
from fabra.retrieval import retriever
store = FeatureStore()
@retriever(index="knowledge_base", top_k=5)
async def search_knowledge(query: str):
# Pass 'query' argument automatically to vector search
passCall the Retriever
# In async context
results = await search_knowledge("How do I configure Redis?")
# Returns: ["Redis is configured via FABRA_REDIS_URL...", ...]Parameters
| Parameter | Type | Description | Default |
|---|---|---|---|
name |
str |
Name of the retriever (defaults to function name) | Optional |
index |
str |
Name of vector index to search (activates Magic Wiring) | Optional |
top_k |
int |
Number of results to return (used with index) |
5 |
backend |
str |
Backend type ("custom" or "postgres") | "custom" |
cache_ttl |
int |
Seconds to cache results in Redis | 0 (no cache) |
Caching
Enable caching to reduce vector search latency for repeated queries:
@retriever(index="docs", top_k=5, cache_ttl=timedelta(seconds=300))
async def cached_search(query: str) -> list[str]:
passHow it works:
- Query is hashed to create cache key.
- If cached, return immediately from Redis.
- If not cached, perform vector search and cache results.
Cache key format: retriever:{index}:{query_hash}
Similarity Threshold
Filter out low-relevance results:
@retriever(index="docs", top_k=10)
async def high_quality_search(query: str) -> list[str]:
# Returns top 10 most relevant documents
passDAG Wiring
Retrievers can be wired into feature DAGs using template syntax:
@feature(entity=User)
def user_context(user_id: str) -> str:
return "Query: {search_docs}" # Will call search_docs retrieverThe DependencyResolver automatically:
- Parses
{retriever_name}templates. - Resolves retriever dependencies.
- Injects results into the feature computation.
Custom Embedding
Override the default embedding provider:
@retriever(index="docs", top_k=5)
async def cohere_search(query: str) -> list[str]:
# Embedding provider is configured globally via FABRA_EMBEDDING_PROVIDER
# or COHERE_API_KEY environment variable
passMultiple Indexes
Search across different document collections:
@retriever(index="product_docs", top_k=3)
async def search_products(query: str) -> list[str]:
pass
@retriever(index="support_tickets", top_k=3)
async def search_tickets(query: str) -> list[str]:
pass
# Combine in context assembly
@context(store, max_tokens=4000)
async def support_context(query: str) -> list[ContextItem]:
products = await search_products(query)
tickets = await search_tickets(query)
return [
ContextItem(content=str(products), priority=1),
ContextItem(content=str(tickets), priority=2),
]Metadata Filtering
Filter results by document metadata:
@retriever(index="docs", top_k=5)
async def search_docs(query: str, version: str = None) -> list[str]:
# Metadata filter applied automatically if version provided
pass
# Usage
results = await search_docs("How to configure?", version="1.2.0")Error Handling
Retrievers handle errors gracefully:
@retriever(index="docs", top_k=5)
async def safe_search(query: str) -> list[str]:
pass
# If index doesn't exist or search fails:
# - Returns empty list []
# - Logs warning with details
# - Does not raise exceptionPerformance Tips
- Use caching for repeated queries:
cache_ttl=300 - Set threshold to filter low-quality results:
threshold=0.7 - Limit top_k to what you need: smaller is faster
- Pre-warm cache for common queries at startup
Under the Hood
When you call a retriever:
sequenceDiagram
participant App
participant Retriever
participant Cache as Redis Cache
participant Embed as Embedding Provider
participant Vector as pgvector
App->>Retriever: search_docs("query")
Retriever->>Cache: Check cache
alt Cache Hit
Cache-->>Retriever: Cached results
else Cache Miss
Retriever->>Embed: Embed query
Embed-->>Retriever: Query vector
Retriever->>Vector: Similarity search
Vector-->>Retriever: Top-K docs
Retriever->>Cache: Store in cache
end
Retriever-->>App: ResultsFAQ
Q: How do I implement semantic search in Python?
A: Use Fabra's @retriever decorator: @retriever(index="docs", top_k=5). Define an async function with a query parameter. Fabra handles embedding and pgvector search automatically.
Q: What vector database does Fabra use? A: Fabra uses pgvector (Postgres extension) for vector search. No separate vector database required—your vectors live alongside your relational data.
Q: How do I cache retriever results?
A: Add cache_ttl to the decorator: @retriever(index="docs", top_k=5, cache_ttl=timedelta(seconds=300)). Results are cached in Redis using a hash of the query.
Q: Can I use multiple vector indexes?
A: Yes. Define separate retrievers for each index: @retriever(index="product_docs") and @retriever(index="support_tickets"). Combine results in context assembly.
Q: What embedding providers are supported?
A: OpenAI (default), Cohere, and Anthropic. Configure via FABRA_EMBEDDING_PROVIDER environment variable or API key detection.
Q: How do I filter retriever results by metadata?
A: Add filter parameters to your retriever function: async def search(query: str, version: str = None). Filters are applied automatically during vector search.
Next Steps
- Context Assembly: Combine retrievers with token budgets
- Event-Driven Features: Update retrievers on events
- Context Store Overview: Full context infrastructure