rag
- class RAG(embed='mistral/mistral-embed', store=None, chunker='recursive', chunk_size=1000, chunk_overlap=200, bm25_alpha=None, bm25_autorebuild=True, reranker=None, query_expander=None, generate_fn=None)[source]
Bases:
objectEnd-to-end retrieval-augmented generation pipeline.
Combines embedding, chunking, vector/BM25 search, reranking, query expansion, and LLM generation into a single interface.
- Parameters:
embed (Embeddings | str) – Embedding model instance or model name string (e.g.
"mistral/mistral-embed").store (VectorStore | None) – Vector store for persistent embeddings. If
None, only BM25 search is available (whenbm25_alphais set).chunker (str) – Name of the chunking strategy (
"recursive","character","markdown","code","hierarchical").chunk_size (int) – Target chunk size in characters.
chunk_overlap (int) – Overlap between consecutive chunks in characters.
bm25_alpha (float | None) – If set, enables BM25 alongside vector search with this weight for the vector component (0–1).
Nonedisables BM25.reranker (str | None) – Reranker strategy name (
"cross_encoder","diversity","noop").Nonedisables reranking.query_expander (Callable[[str], list[str]] | None) – Callable that takes a query string and returns a list of expanded query strings.
generate_fn (Callable[[str], str | GenerationResult] | None) – Default generation function for
query()andaquery(). Takes a prompt string, returns an answer string orGenerationResult.bm25_autorebuild (bool)
Example
Using litellm for generation:
from ffai.rag import RAG, litellm_generate_fn rag = RAG(embed="mistral/mistral-embed") fn = litellm_generate_fn( model="mistral/mistral-small-latest", api_key=key, ) result = rag.query("What is Python?", generate_fn=fn) print(result.usage.input_tokens) print(result.cost_usd)
- classmethod from_config(*, bm25_only=False, api_key=None, **overrides)[source]
Create a RAG instance from the project configuration file.
Reads all settings from
config/main.yamlunder therag:key. The embedding model’s API key is resolved in order: theapi_keyparameter, the provider-specific environment variable (e.g.MISTRAL_API_KEY), and finallyNone(which will raise at embed time if no key is found).- Parameters:
bm25_only (bool) – If True, skip vector store creation and use BM25 search only.
api_key (str | None) – API key for the embedding model provider. When None, the key is read from a provider-specific environment variable (e.g.
MISTRAL_API_KEY).**overrides (Any) – Override any constructor parameter from config.
- Returns:
Configured RAG instance.
- Return type:
- set_generate_fn(generate_fn)[source]
Set or replace the default generation function.
Also re-wires the query expander if one is configured.
- Parameters:
generate_fn (Callable[[str], str | GenerationResult]) – Sync callable that takes a prompt and returns an answer string or
GenerationResult.- Return type:
None
- index(text, source=None, checksum=None, **metadata)[source]
Index a document (sync wrapper).
Safe to call from within a running event loop (e.g. Jupyter).
- Parameters:
text (str) – Document text to index.
source (str | None) – Source identifier for deduplication and filtering.
checksum (str | None) – If provided with
source, skip indexing when the checksum matches the previously stored value.**metadata (str) – Additional metadata key-value pairs attached to every chunk.
- Returns:
Number of chunks created.
- Return type:
- async aindex(text, source=None, checksum=None, **metadata)[source]
Index a document into the vector store and/or BM25 index.
Chunks the text, computes embeddings, and stores them. Skips indexing if
checksummatches the previously stored value.- Parameters:
text (str) – Document text to index.
source (str | None) – Source identifier for deduplication and filtering.
checksum (str | None) – If provided with
source, skip indexing when the checksum matches the previously stored value.**metadata (str) – Additional metadata key-value pairs attached to every chunk.
- Returns:
Number of chunks created (0 if text is empty or checksum matches).
- Return type:
- search(query, top_k=5, **filters)[source]
Search for relevant chunks (sync wrapper).
Safe to call from within a running event loop (e.g. Jupyter).
- async asearch(query, top_k=5, **filters)[source]
Search for relevant chunks using vector, BM25, or hybrid search.
Applies query expansion and reranking if configured.
- query(question, generate_fn=None, top_k=5, prompt_template=None, max_context_chars=None, allow_llm_on_empty=True, generate_timeout=None, **filters)[source]
Retrieve context and generate an answer (sync wrapper).
Safe to call from within a running event loop (e.g. Jupyter).
- async aquery(question, generate_fn=None, top_k=5, prompt_template=None, max_context_chars=None, allow_llm_on_empty=True, generate_timeout=None, **filters)[source]
Retrieve context and generate an answer.
Searches for relevant chunks via
asearch.Formats hits into a context string (
format_hits).Fills the prompt template with
{context}and{question}.Calls
generate_fnin a thread (asyncio.to_thread).
- Parameters:
question (str) – The user question.
generate_fn (Callable[[str], str | GenerationResult] | None) – A sync callable that takes the formatted prompt and returns an answer string or
GenerationResult. WhenNone, uses the default set on the RAG instance.top_k (int) – Number of search results to retrieve.
prompt_template (str | None) – Must contain
{context}and{question}placeholders. Unknown placeholders resolve to empty string. Defaults toDEFAULT_RAG_PROMPT.max_context_chars (int | None) – Truncates the formatted context to this many characters. Note that each hit includes a header line (source, relevance) that counts toward the budget, so small values may exclude all content.
Nonemeans no limit.allow_llm_on_empty (bool) – When
Falseand no search hits are found, skip the LLM call and return an emptyQueryResult. Defaults toTrue(backward compat).generate_timeout (float | None) – Maximum seconds to wait for
generate_fnto complete. RaisesTimeoutErrorif exceeded. The underlying LLM request continues running in its thread (cannot be cancelled), so the API cost may still be incurred. Defaults toNone(no timeout).**filters (str) – Passed through to the vector store
whereclause.
- Returns:
A
QueryResultwith the answer, search hits, deduplicated sources, the full prompt sent togenerate_fn, and generation metadata (usage, cost, duration).- Return type:
- delete(source)[source]
Delete all chunks associated with a source from the store and BM25 index.
- Parameters:
source (str) – Source identifier to delete.
- Return type:
None
- count()[source]
Return the total number of indexed chunks.
Checks the vector store first, then falls back to BM25.
- Returns:
Chunk count, or 0 if neither store is configured.
- Return type:
- rebuild_bm25_from_store()[source]
Rebuild the BM25 index from the persistent vector store.
Clears the current BM25 index and re-adds every chunk the store exposes via
get_all(). Chunks whosechunking_strategymetadata is set and differs from the current chunker are skipped (legacy chunks with no strategy tag are included for backward compatibility).- Returns:
Number of documents added to the BM25 index.
- Raises:
RuntimeError – if BM25 or the store is not configured.
- Return type:
- class BM25Index(k1=1.5, b=0.75, epsilon=0.25)[source]
Bases:
objectBM25 sparse index for keyword-based retrieval.
Implements the Okapi BM25 algorithm for text relevance scoring. Used alongside vector search for hybrid retrieval.
- Parameters:
- add_documents(documents, id_key='id', content_key='content')[source]
Add multiple documents to the index.
- class CharacterChunker(chunk_size=1000, chunk_overlap=200, metadata=None, respect_word_boundaries=True)[source]
Bases:
ChunkerBaseCharacter-based chunking with word-boundary awareness.
- Parameters:
- class ChunkDeduplicator(mode='exact', similarity_threshold=0.95)[source]
Bases:
objectDetect and filter duplicate/near-duplicate chunks.
Supports multiple deduplication modes: - exact: Hash-based exact content matching - similarity: Embedding cosine similarity threshold
- Parameters:
Example
>>> dedup = ChunkDeduplicator(mode="exact") >>> chunks, embeddings = dedup.filter_duplicates(chunks, embeddings)
- is_duplicate(content, embedding=None)[source]
Check if chunk is a duplicate of previously seen content.
- class ChunkerBase(chunk_size=1000, chunk_overlap=200, metadata=None)[source]
Bases:
ABCAbstract base class for text chunking strategies.
- Parameters:
- class ClientAdapter(client, **kwargs)[source]
Bases:
objectWrap an FFAI client into a callable that returns a GenerationResult.
Handles both synchronous and asynchronous
generate_responsemethods, automatically awaiting coroutines when necessary.- Parameters:
client (Any) – An FFAI client instance with a
generate_responsemethod.**kwargs (Any) – Extra keyword arguments forwarded to
generate_responseon every call.
- class CodeChunker(chunk_size=1000, chunk_overlap=200, metadata=None, language='python', split_by='function')[source]
Bases:
ChunkerBaseCode-aware chunking that splits by functions/classes.
- Parameters:
- LANGUAGE_PATTERNS: dict[str, dict[str, str]] = {'generic': {'class': '^(class|struct|interface)\\s+\\w+', 'comment': '^(#|//|/\\*)', 'function': '^(function|func|def|fn)\\s+\\w+', 'import': '^(import|use|require)'}, 'go': {'class': '^type\\s+\\w+\\s+struct', 'comment': '^(//|/\\*)', 'function': '^func\\s+(\\(\\w+\\s+\\*?\\w+\\)\\s+)?\\w+\\s*\\(', 'import': '^import\\s+'}, 'java': {'class': '^\\s*(public\\s+)?(abstract\\s+)?class\\s+\\w+|interface\\s+\\w+', 'comment': '^(//|/\\*)', 'function': '^\\s*(public|private|protected|static)?\\s*\\w+\\s+\\w+\\s*\\(', 'import': '^import\\s+'}, 'javascript': {'class': '^(export\\s+)?class\\s+\\w+', 'comment': '^(//|/\\*|\\*)', 'function': '^(async\\s+)?function\\s+\\w+|const\\s+\\w+\\s*=\\s*(async\\s+)?\\([^)]*\\)\\s*=>|export\\s+(async\\s+)?function', 'import': '^(import\\s+|export\\s+|require\\s*\\()'}, 'python': {'class': '^class\\s+\\w+[\\(:]', 'comment': '^(#|\'\'\'|\\"\\"\\")', 'decorator': '^@\\w+', 'function': '^(async\\s+)?def\\s+\\w+\\s*\\(', 'import': '^(import\\s+|from\\s+\\S+\\s+import)'}, 'rust': {'class': '^(pub\\s+)?struct\\s+\\w+|impl\\s+\\w+', 'comment': '^(//|/\\*|\\*)', 'function': '^(pub\\s+)?(async\\s+)?fn\\s+\\w+', 'import': '^use\\s+'}, 'typescript': {'class': '^(export\\s+)?(abstract\\s+)?class\\s+\\w+|interface\\s+\\w+|type\\s+\\w+', 'comment': '^(//|/\\*|\\*)', 'function': '^(async\\s+)?(function\\s+\\w+|const\\s+\\w+\\s*=\\s*(async\\s+)?\\([^)]*\\)\\s*(:\\s*\\w+)?\\s*=>|export\\s+(async\\s+)?function)', 'import': '^(import\\s+|export\\s+|require\\s*\\()'}}
- class ContextualEmbeddings(context_template=None, max_context_length=200)[source]
Bases:
objectGenerate embeddings with document context prepended.
Prepends document context (title, summary, or preceding content) to each chunk before embedding, improving semantic understanding.
- Parameters:
- DEFAULT_CONTEXT_TEMPLATE = 'Document: {title}\n\nSection: {section}\n\n{chunk}'
- prepare_chunk_for_embedding(chunk_content, document_title=None, section_header=None, document_summary=None, preceding_context=None)[source]
Prepare a chunk with context for embedding.
- Parameters:
- Returns:
Context-enhanced text for embedding.
- Return type:
- class CrossEncoderReranker(model_name='cross-encoder/ms-marco-MiniLM-L-6-v2', max_length=512, fastembed_model_name=None)[source]
Bases:
RerankerBaseRe-ranker using cross-encoder models.
Tries sentence-transformers first, then falls back to fastembed (ONNX-based). Requires at least one of:
pip install sentence-transformers pip install fastembed
- Parameters:
- class DiversityReranker(lambda_param=0.7)[source]
Bases:
RerankerBaseRe-ranker that promotes result diversity.
Re-orders results to maximize diversity based on content similarity. Uses MMR (Maximal Marginal Relevance) style selection.
- Parameters:
lambda_param (float) – Balance between relevance and diversity (0-1). Higher = more relevance, lower = more diversity.
- class Embeddings(model='mistral/mistral-embed', api_key=None, api_base=None, cache_enabled=True, cache_size=256, device='cpu', **kwargs)[source]
Bases:
objectCompute text embeddings using local or remote models.
Supports local sentence-transformer models (prefix
local/) and remote providers via LiteLLM (e.g.mistral/mistral-embed,openai/text-embedding-3-small). Results are optionally cached in an LRU-style in-memory cache.- Parameters:
model (str) – Model identifier. Use
local/<name>for local sentence-transformer models, or<provider>/<model>for remote APIs.api_key (str | None) – API key for the remote provider. If None, the key is read from a provider-specific environment variable.
api_base (str | None) – Optional custom API base URL.
cache_enabled (bool) – Whether to cache embedding results in memory.
cache_size (int) – Maximum number of entries in the embedding cache.
device (str) – Torch device for local models (e.g.
"cpu","cuda").**kwargs (Any) – Extra keyword arguments forwarded to the LiteLLM embedding call.
- clear_cache()[source]
Clear the embedding cache.
- Returns:
Number of entries that were in the cache before clearing.
- Return type:
- class GenerationResult(text, usage=None, cost_usd=0.0, duration_ms=None)[source]
Bases:
objectResult of a RAG generation call.
Return this from
generate_fnto preserve token usage, cost, and timing metadata. Returning a plain string silently discards these metrics and emits a warning.- usage
Provider-specific token usage object (e.g.
TokenUsage).- Type:
Any | None
- class HierarchicalChunker(chunk_size=400, chunk_overlap=100, metadata=None, parent_chunk_size=1500, max_levels=2)[source]
Bases:
ChunkerBaseHierarchical chunking with parent-child relationships.
- Parameters:
- chunk(text, metadata=None)[source]
Split text into hierarchical chunks with parent-child relationships.
- get_parent_chunks(chunks)[source]
Filter to return only parent chunks.
- Parameters:
chunks (list[HierarchicalTextChunk])
- Return type:
- get_child_chunks(chunks)[source]
Filter to return only child chunks.
- Parameters:
chunks (list[HierarchicalTextChunk])
- Return type:
- get_chunks_with_parent_context(child_chunks, all_chunks)[source]
Get child chunks with their parent context for retrieval.
- Parameters:
child_chunks (list[HierarchicalTextChunk]) – Child chunks retrieved from search.
all_chunks (list[HierarchicalTextChunk]) – All chunks (to look up parents).
- Returns:
List of dicts with child content and parent context.
- Return type:
- class HierarchicalIndex(include_parent_context=True)[source]
Bases:
objectIndex for hierarchical chunk storage and retrieval.
Stores both parent and child chunks, enabling: - Fine-grained search on child chunks - Parent context retrieval for matched children
- Parameters:
include_parent_context (bool) – Whether to include parent content in results.
- add_chunk(chunk_id, content, embedding=None, parent_id=None, hierarchy_level=0, metadata=None)[source]
Add a chunk to the hierarchical index.
- Parameters:
chunk_id (str) – Unique chunk identifier.
content (str) – Chunk text content.
embedding (list[float] | None) – Chunk embedding vector (optional).
parent_id (str | None) – Parent chunk ID (None for root/parent chunks).
hierarchy_level (int) – Level in hierarchy (0=parent, 1+=children).
metadata (dict[str, Any] | None) – Optional metadata dictionary.
- Return type:
None
- enhance_results_with_context(results, include_parent=None)[source]
Enhance search results with parent context.
- class HierarchicalTextChunk(content, chunk_index, start_char, end_char, metadata=None, id='', parent_id=None, child_ids=None, hierarchy_level=0)[source]
Bases:
TextChunkA text chunk that participates in a parent-child hierarchy.
Used by hierarchical chunking strategies that maintain relationships between larger parent chunks and smaller child chunks.
- Parameters:
- class HybridSearch(vector_search_fn=None, bm25_search_fn=None, alpha=0.6, rrf_k=60)[source]
Bases:
objectHybrid search combining vector similarity and BM25 keyword matching.
Uses reciprocal rank fusion (RRF) to combine results from multiple retrieval methods.
- Parameters:
vector_search_fn (Callable[[str, int], list[dict[str, Any]]] | None) – Function that takes (query, n_results) and returns vector results.
bm25_search_fn (Callable[[str, int], list[dict[str, Any]]] | None) – Function that takes (query, n_results) and returns BM25 results.
alpha (float) – Weight for vector search (1-alpha for BM25). Default 0.6.
rrf_k (int) – RRF constant for rank fusion. Default 60.
- set_alpha(alpha)[source]
Set the alpha parameter (vector weight).
- Parameters:
alpha (float) – Weight for vector search (0.0 to 1.0).
- Return type:
None
- class MarkdownChunker(chunk_size=1000, chunk_overlap=200, metadata=None, split_headers=None, preserve_structure=True, max_chunk_fallback=True)[source]
Bases:
ChunkerBaseMarkdown-aware chunking that splits by headers.
- Parameters:
chunk_size (int) – Maximum characters per chunk.
chunk_overlap (int) – Overlap between consecutive chunks.
metadata (dict[str, Any] | None) – Default metadata for all chunks.
split_headers (list[str] | None) – List of header levels to split on (e.g., [“h1”, “h2”]).
preserve_structure (bool) – Whether to include header in chunk content.
max_chunk_fallback (bool) – Whether to further split large sections.
- HEADER_PATTERNS = {'h1': '^# .+', 'h2': '^## .+', 'h3': '^### .+', 'h4': '^#### .+', 'h5': '^##### .+', 'h6': '^###### .+'}
- class NoopReranker[source]
Bases:
RerankerBasePass-through re-ranker that does nothing.
Used when re-ranking is disabled but a reranker interface is expected.
- class QueryExpander(llm_generate_fn=None, n_variations=3, include_original=True)[source]
Bases:
objectExpand queries using LLM for multi-query retrieval.
Generates multiple reformulations of a search query to improve recall by catching different phrasings and aspects of the topic.
- Parameters:
Example
>>> def mock_llm(prompt): return "1. What is auth?\n2. How to authenticate?" >>> expander = QueryExpander(llm_generate_fn=mock_llm, n_variations=2) >>> queries = expander.expand("authentication methods") >>> # Returns: ["authentication methods", "What is auth?", "How to authenticate?"]
- class QueryResult(answer, hits, sources, prompt, usage=None, cost_usd=0.0, duration_ms=None)[source]
Bases:
objectResult of a RAG query combining search and generation.
- Parameters:
- hits
Search hits used as context.
- Type:
- usage
Provider-specific token usage object.
- Type:
Any | None
- class RecursiveChunker(chunk_size=1000, chunk_overlap=200, metadata=None, separators=None, keep_separator=True)[source]
Bases:
ChunkerBaseRecursive chunking that splits hierarchically by separators.
- Parameters:
chunk_size (int) – Maximum characters per chunk.
chunk_overlap (int) – Overlap between consecutive chunks.
metadata (dict[str, Any] | None) – Default metadata for all chunks.
separators (list[str] | None) – List of separators in order of preference.
keep_separator (bool) – Whether to keep the separator with chunks.
- DEFAULT_SEPARATORS = ['\n\n\n', '\n\n', '\n', '. ', '! ', '? ', '; ', ', ', ' ', '']
- class RerankerBase[source]
Bases:
objectBase class for re-rankers.
- class SearchHit(content, score, source='', metadata=<factory>, parent_content=None, id='')[source]
Bases:
objectSingle search result from a RAG query.
- Parameters:
- class TextChunk(content, chunk_index, start_char, end_char, metadata=None)[source]
Bases:
objectA single chunk of text produced by a chunker.
- Parameters:
- VectorStore
alias of
ChromaVectorStore
- class VectorStoreBase[source]
Bases:
ABCAbstract base class for vector store backends.
All backends must implement the core CRUD + search methods. The
whereparameter inasearchaccepts a backend-neutral filter dict with string keys and values. Each backend translates this to its native filter format internally.Example backend-neutral filters:
{"source": "doc1"} {"chunking_strategy": "recursive", "source": "doc1"}
For compound filters, backends should support an
$andkey:{"$and": [{"source": "doc1"}, {"chunking_strategy": "recursive"}]}
- abstractmethod async aadd(ids, texts, embeddings, metadatas)[source]
Add documents with pre-computed embeddings to the store.
- Parameters:
- Returns:
Number of documents added.
- Return type:
- abstractmethod async asearch(query_embedding, top_k=5, where=None)[source]
Search for documents by vector similarity.
- abstractmethod delete_by_source(source)[source]
Delete all chunks matching
source.- Parameters:
source (str)
- Return type:
None
- abstractmethod delete_by_source_and_strategy(source, strategy)[source]
Delete chunks matching both
sourceandchunking_strategy.
- abstractmethod clear()[source]
Delete all stored data and recreate the collection.
- Return type:
None
- abstractmethod get_all()[source]
Return all stored documents as dicts with
id,content,metadatakeys.
- chunk_text(text, strategy='recursive', chunk_size=1000, chunk_overlap=200, metadata=None, **kwargs)[source]
Convenience function to chunk text with a single call.
- Parameters:
- Returns:
List of TextChunk objects.
- Return type:
- format_hits(hits, max_chars=None, include_parent=True)[source]
Format search hits into a numbered, human-readable text string.
Each hit is rendered with its index, source, relevance score, content, and optionally a snippet of its parent context.
- Parameters:
- Returns:
A formatted string, or an empty string if hits is empty.
- Return type:
- fuse_search_results(result_lists, n_results=5, dedupe_by='id')[source]
Fuse results from multiple searches with deduplication.
Combines results from multiple query variations, removing duplicates while preserving relevance ordering.
- Parameters:
- Returns:
Fused and deduplicated list of results.
- Return type:
- get_chunker(strategy='recursive', chunk_size=1000, chunk_overlap=200, metadata=None, **kwargs)[source]
Get a chunker instance based on strategy name.
- Parameters:
strategy (str) – Chunking strategy name (character, recursive, markdown, code, hierarchical).
chunk_size (int) – Maximum chunk size.
chunk_overlap (int) – Overlap between chunks.
metadata (dict[str, Any] | None) – Default metadata for chunks.
**kwargs (Any) – Additional strategy-specific parameters.
- Returns:
Configured chunker instance.
- Raises:
ValueError – If strategy name is not recognized.
- Return type:
- get_reranker(reranker_type='none', **kwargs)[source]
Get a reranker by type name.
- Parameters:
- Returns:
Configured reranker instance.
- Return type:
- get_store(backend='chroma', **kwargs)[source]
Get a vector store instance by backend name.
- Parameters:
- Returns:
Configured vector store instance.
- Raises:
ValueError – If backend name is not recognized.
ImportError – If the backend’s dependency is not installed.
- Return type:
- reciprocal_rank_fusion(result_lists, k=60, weights=None)[source]
Combine multiple result lists using reciprocal rank fusion.
Classes
- class BM25Index(k1=1.5, b=0.75, epsilon=0.25)[source]
Bases:
objectBM25 sparse index for keyword-based retrieval.
Implements the Okapi BM25 algorithm for text relevance scoring. Used alongside vector search for hybrid retrieval.
- Parameters:
- add_documents(documents, id_key='id', content_key='content')[source]
Add multiple documents to the index.
- class CharacterChunker(chunk_size=1000, chunk_overlap=200, metadata=None, respect_word_boundaries=True)[source]
Bases:
ChunkerBaseCharacter-based chunking with word-boundary awareness.
- Parameters:
- class ChunkDeduplicator(mode='exact', similarity_threshold=0.95)[source]
Bases:
objectDetect and filter duplicate/near-duplicate chunks.
Supports multiple deduplication modes: - exact: Hash-based exact content matching - similarity: Embedding cosine similarity threshold
- Parameters:
Example
>>> dedup = ChunkDeduplicator(mode="exact") >>> chunks, embeddings = dedup.filter_duplicates(chunks, embeddings)
- is_duplicate(content, embedding=None)[source]
Check if chunk is a duplicate of previously seen content.
- class ChunkerBase(chunk_size=1000, chunk_overlap=200, metadata=None)[source]
Bases:
ABCAbstract base class for text chunking strategies.
- Parameters:
- class ClientAdapter(client, **kwargs)[source]
Bases:
objectWrap an FFAI client into a callable that returns a GenerationResult.
Handles both synchronous and asynchronous
generate_responsemethods, automatically awaiting coroutines when necessary.- Parameters:
client (Any) – An FFAI client instance with a
generate_responsemethod.**kwargs (Any) – Extra keyword arguments forwarded to
generate_responseon every call.
- class CodeChunker(chunk_size=1000, chunk_overlap=200, metadata=None, language='python', split_by='function')[source]
Bases:
ChunkerBaseCode-aware chunking that splits by functions/classes.
- Parameters:
- LANGUAGE_PATTERNS: dict[str, dict[str, str]] = {'generic': {'class': '^(class|struct|interface)\\s+\\w+', 'comment': '^(#|//|/\\*)', 'function': '^(function|func|def|fn)\\s+\\w+', 'import': '^(import|use|require)'}, 'go': {'class': '^type\\s+\\w+\\s+struct', 'comment': '^(//|/\\*)', 'function': '^func\\s+(\\(\\w+\\s+\\*?\\w+\\)\\s+)?\\w+\\s*\\(', 'import': '^import\\s+'}, 'java': {'class': '^\\s*(public\\s+)?(abstract\\s+)?class\\s+\\w+|interface\\s+\\w+', 'comment': '^(//|/\\*)', 'function': '^\\s*(public|private|protected|static)?\\s*\\w+\\s+\\w+\\s*\\(', 'import': '^import\\s+'}, 'javascript': {'class': '^(export\\s+)?class\\s+\\w+', 'comment': '^(//|/\\*|\\*)', 'function': '^(async\\s+)?function\\s+\\w+|const\\s+\\w+\\s*=\\s*(async\\s+)?\\([^)]*\\)\\s*=>|export\\s+(async\\s+)?function', 'import': '^(import\\s+|export\\s+|require\\s*\\()'}, 'python': {'class': '^class\\s+\\w+[\\(:]', 'comment': '^(#|\'\'\'|\\"\\"\\")', 'decorator': '^@\\w+', 'function': '^(async\\s+)?def\\s+\\w+\\s*\\(', 'import': '^(import\\s+|from\\s+\\S+\\s+import)'}, 'rust': {'class': '^(pub\\s+)?struct\\s+\\w+|impl\\s+\\w+', 'comment': '^(//|/\\*|\\*)', 'function': '^(pub\\s+)?(async\\s+)?fn\\s+\\w+', 'import': '^use\\s+'}, 'typescript': {'class': '^(export\\s+)?(abstract\\s+)?class\\s+\\w+|interface\\s+\\w+|type\\s+\\w+', 'comment': '^(//|/\\*|\\*)', 'function': '^(async\\s+)?(function\\s+\\w+|const\\s+\\w+\\s*=\\s*(async\\s+)?\\([^)]*\\)\\s*(:\\s*\\w+)?\\s*=>|export\\s+(async\\s+)?function)', 'import': '^(import\\s+|export\\s+|require\\s*\\()'}}
- class ContextualEmbeddings(context_template=None, max_context_length=200)[source]
Bases:
objectGenerate embeddings with document context prepended.
Prepends document context (title, summary, or preceding content) to each chunk before embedding, improving semantic understanding.
- Parameters:
- DEFAULT_CONTEXT_TEMPLATE = 'Document: {title}\n\nSection: {section}\n\n{chunk}'
- prepare_chunk_for_embedding(chunk_content, document_title=None, section_header=None, document_summary=None, preceding_context=None)[source]
Prepare a chunk with context for embedding.
- Parameters:
- Returns:
Context-enhanced text for embedding.
- Return type:
- class CrossEncoderReranker(model_name='cross-encoder/ms-marco-MiniLM-L-6-v2', max_length=512, fastembed_model_name=None)[source]
Bases:
RerankerBaseRe-ranker using cross-encoder models.
Tries sentence-transformers first, then falls back to fastembed (ONNX-based). Requires at least one of:
pip install sentence-transformers pip install fastembed
- Parameters:
- class DiversityReranker(lambda_param=0.7)[source]
Bases:
RerankerBaseRe-ranker that promotes result diversity.
Re-orders results to maximize diversity based on content similarity. Uses MMR (Maximal Marginal Relevance) style selection.
- Parameters:
lambda_param (float) – Balance between relevance and diversity (0-1). Higher = more relevance, lower = more diversity.
- class GenerationResult(text, usage=None, cost_usd=0.0, duration_ms=None)[source]
Bases:
objectResult of a RAG generation call.
Return this from
generate_fnto preserve token usage, cost, and timing metadata. Returning a plain string silently discards these metrics and emits a warning.- usage
Provider-specific token usage object (e.g.
TokenUsage).- Type:
Any | None
- class HierarchicalChunker(chunk_size=400, chunk_overlap=100, metadata=None, parent_chunk_size=1500, max_levels=2)[source]
Bases:
ChunkerBaseHierarchical chunking with parent-child relationships.
- Parameters:
- chunk(text, metadata=None)[source]
Split text into hierarchical chunks with parent-child relationships.
- get_parent_chunks(chunks)[source]
Filter to return only parent chunks.
- Parameters:
chunks (list[HierarchicalTextChunk])
- Return type:
- get_child_chunks(chunks)[source]
Filter to return only child chunks.
- Parameters:
chunks (list[HierarchicalTextChunk])
- Return type:
- get_chunks_with_parent_context(child_chunks, all_chunks)[source]
Get child chunks with their parent context for retrieval.
- Parameters:
child_chunks (list[HierarchicalTextChunk]) – Child chunks retrieved from search.
all_chunks (list[HierarchicalTextChunk]) – All chunks (to look up parents).
- Returns:
List of dicts with child content and parent context.
- Return type:
- class HierarchicalIndex(include_parent_context=True)[source]
Bases:
objectIndex for hierarchical chunk storage and retrieval.
Stores both parent and child chunks, enabling: - Fine-grained search on child chunks - Parent context retrieval for matched children
- Parameters:
include_parent_context (bool) – Whether to include parent content in results.
- add_chunk(chunk_id, content, embedding=None, parent_id=None, hierarchy_level=0, metadata=None)[source]
Add a chunk to the hierarchical index.
- Parameters:
chunk_id (str) – Unique chunk identifier.
content (str) – Chunk text content.
embedding (list[float] | None) – Chunk embedding vector (optional).
parent_id (str | None) – Parent chunk ID (None for root/parent chunks).
hierarchy_level (int) – Level in hierarchy (0=parent, 1+=children).
metadata (dict[str, Any] | None) – Optional metadata dictionary.
- Return type:
None
- enhance_results_with_context(results, include_parent=None)[source]
Enhance search results with parent context.
- class HierarchicalTextChunk(content, chunk_index, start_char, end_char, metadata=None, id='', parent_id=None, child_ids=None, hierarchy_level=0)[source]
Bases:
TextChunkA text chunk that participates in a parent-child hierarchy.
Used by hierarchical chunking strategies that maintain relationships between larger parent chunks and smaller child chunks.
- Parameters:
- class HybridSearch(vector_search_fn=None, bm25_search_fn=None, alpha=0.6, rrf_k=60)[source]
Bases:
objectHybrid search combining vector similarity and BM25 keyword matching.
Uses reciprocal rank fusion (RRF) to combine results from multiple retrieval methods.
- Parameters:
vector_search_fn (Callable[[str, int], list[dict[str, Any]]] | None) – Function that takes (query, n_results) and returns vector results.
bm25_search_fn (Callable[[str, int], list[dict[str, Any]]] | None) – Function that takes (query, n_results) and returns BM25 results.
alpha (float) – Weight for vector search (1-alpha for BM25). Default 0.6.
rrf_k (int) – RRF constant for rank fusion. Default 60.
- set_alpha(alpha)[source]
Set the alpha parameter (vector weight).
- Parameters:
alpha (float) – Weight for vector search (0.0 to 1.0).
- Return type:
None
- class MarkdownChunker(chunk_size=1000, chunk_overlap=200, metadata=None, split_headers=None, preserve_structure=True, max_chunk_fallback=True)[source]
Bases:
ChunkerBaseMarkdown-aware chunking that splits by headers.
- Parameters:
chunk_size (int) – Maximum characters per chunk.
chunk_overlap (int) – Overlap between consecutive chunks.
metadata (dict[str, Any] | None) – Default metadata for all chunks.
split_headers (list[str] | None) – List of header levels to split on (e.g., [“h1”, “h2”]).
preserve_structure (bool) – Whether to include header in chunk content.
max_chunk_fallback (bool) – Whether to further split large sections.
- HEADER_PATTERNS = {'h1': '^# .+', 'h2': '^## .+', 'h3': '^### .+', 'h4': '^#### .+', 'h5': '^##### .+', 'h6': '^###### .+'}
- class NoopReranker[source]
Bases:
RerankerBasePass-through re-ranker that does nothing.
Used when re-ranking is disabled but a reranker interface is expected.
- class QueryExpander(llm_generate_fn=None, n_variations=3, include_original=True)[source]
Bases:
objectExpand queries using LLM for multi-query retrieval.
Generates multiple reformulations of a search query to improve recall by catching different phrasings and aspects of the topic.
- Parameters:
Example
>>> def mock_llm(prompt): return "1. What is auth?\n2. How to authenticate?" >>> expander = QueryExpander(llm_generate_fn=mock_llm, n_variations=2) >>> queries = expander.expand("authentication methods") >>> # Returns: ["authentication methods", "What is auth?", "How to authenticate?"]
- class QueryResult(answer, hits, sources, prompt, usage=None, cost_usd=0.0, duration_ms=None)[source]
Bases:
objectResult of a RAG query combining search and generation.
- Parameters:
- hits
Search hits used as context.
- Type:
- usage
Provider-specific token usage object.
- Type:
Any | None
- class RAG(embed='mistral/mistral-embed', store=None, chunker='recursive', chunk_size=1000, chunk_overlap=200, bm25_alpha=None, bm25_autorebuild=True, reranker=None, query_expander=None, generate_fn=None)[source]
Bases:
objectEnd-to-end retrieval-augmented generation pipeline.
Combines embedding, chunking, vector/BM25 search, reranking, query expansion, and LLM generation into a single interface.
- Parameters:
embed (Embeddings | str) – Embedding model instance or model name string (e.g.
"mistral/mistral-embed").store (VectorStore | None) – Vector store for persistent embeddings. If
None, only BM25 search is available (whenbm25_alphais set).chunker (str) – Name of the chunking strategy (
"recursive","character","markdown","code","hierarchical").chunk_size (int) – Target chunk size in characters.
chunk_overlap (int) – Overlap between consecutive chunks in characters.
bm25_alpha (float | None) – If set, enables BM25 alongside vector search with this weight for the vector component (0–1).
Nonedisables BM25.reranker (str | None) – Reranker strategy name (
"cross_encoder","diversity","noop").Nonedisables reranking.query_expander (Callable[[str], list[str]] | None) – Callable that takes a query string and returns a list of expanded query strings.
generate_fn (Callable[[str], str | GenerationResult] | None) – Default generation function for
query()andaquery(). Takes a prompt string, returns an answer string orGenerationResult.bm25_autorebuild (bool)
Example
Using litellm for generation:
from ffai.rag import RAG, litellm_generate_fn rag = RAG(embed="mistral/mistral-embed") fn = litellm_generate_fn( model="mistral/mistral-small-latest", api_key=key, ) result = rag.query("What is Python?", generate_fn=fn) print(result.usage.input_tokens) print(result.cost_usd)
- classmethod from_config(*, bm25_only=False, api_key=None, **overrides)[source]
Create a RAG instance from the project configuration file.
Reads all settings from
config/main.yamlunder therag:key. The embedding model’s API key is resolved in order: theapi_keyparameter, the provider-specific environment variable (e.g.MISTRAL_API_KEY), and finallyNone(which will raise at embed time if no key is found).- Parameters:
bm25_only (bool) – If True, skip vector store creation and use BM25 search only.
api_key (str | None) – API key for the embedding model provider. When None, the key is read from a provider-specific environment variable (e.g.
MISTRAL_API_KEY).**overrides (Any) – Override any constructor parameter from config.
- Returns:
Configured RAG instance.
- Return type:
- set_generate_fn(generate_fn)[source]
Set or replace the default generation function.
Also re-wires the query expander if one is configured.
- Parameters:
generate_fn (Callable[[str], str | GenerationResult]) – Sync callable that takes a prompt and returns an answer string or
GenerationResult.- Return type:
None
- index(text, source=None, checksum=None, **metadata)[source]
Index a document (sync wrapper).
Safe to call from within a running event loop (e.g. Jupyter).
- Parameters:
text (str) – Document text to index.
source (str | None) – Source identifier for deduplication and filtering.
checksum (str | None) – If provided with
source, skip indexing when the checksum matches the previously stored value.**metadata (str) – Additional metadata key-value pairs attached to every chunk.
- Returns:
Number of chunks created.
- Return type:
- async aindex(text, source=None, checksum=None, **metadata)[source]
Index a document into the vector store and/or BM25 index.
Chunks the text, computes embeddings, and stores them. Skips indexing if
checksummatches the previously stored value.- Parameters:
text (str) – Document text to index.
source (str | None) – Source identifier for deduplication and filtering.
checksum (str | None) – If provided with
source, skip indexing when the checksum matches the previously stored value.**metadata (str) – Additional metadata key-value pairs attached to every chunk.
- Returns:
Number of chunks created (0 if text is empty or checksum matches).
- Return type:
- search(query, top_k=5, **filters)[source]
Search for relevant chunks (sync wrapper).
Safe to call from within a running event loop (e.g. Jupyter).
- async asearch(query, top_k=5, **filters)[source]
Search for relevant chunks using vector, BM25, or hybrid search.
Applies query expansion and reranking if configured.
- query(question, generate_fn=None, top_k=5, prompt_template=None, max_context_chars=None, allow_llm_on_empty=True, generate_timeout=None, **filters)[source]
Retrieve context and generate an answer (sync wrapper).
Safe to call from within a running event loop (e.g. Jupyter).
- async aquery(question, generate_fn=None, top_k=5, prompt_template=None, max_context_chars=None, allow_llm_on_empty=True, generate_timeout=None, **filters)[source]
Retrieve context and generate an answer.
Searches for relevant chunks via
asearch.Formats hits into a context string (
format_hits).Fills the prompt template with
{context}and{question}.Calls
generate_fnin a thread (asyncio.to_thread).
- Parameters:
question (str) – The user question.
generate_fn (Callable[[str], str | GenerationResult] | None) – A sync callable that takes the formatted prompt and returns an answer string or
GenerationResult. WhenNone, uses the default set on the RAG instance.top_k (int) – Number of search results to retrieve.
prompt_template (str | None) – Must contain
{context}and{question}placeholders. Unknown placeholders resolve to empty string. Defaults toDEFAULT_RAG_PROMPT.max_context_chars (int | None) – Truncates the formatted context to this many characters. Note that each hit includes a header line (source, relevance) that counts toward the budget, so small values may exclude all content.
Nonemeans no limit.allow_llm_on_empty (bool) – When
Falseand no search hits are found, skip the LLM call and return an emptyQueryResult. Defaults toTrue(backward compat).generate_timeout (float | None) – Maximum seconds to wait for
generate_fnto complete. RaisesTimeoutErrorif exceeded. The underlying LLM request continues running in its thread (cannot be cancelled), so the API cost may still be incurred. Defaults toNone(no timeout).**filters (str) – Passed through to the vector store
whereclause.
- Returns:
A
QueryResultwith the answer, search hits, deduplicated sources, the full prompt sent togenerate_fn, and generation metadata (usage, cost, duration).- Return type:
- delete(source)[source]
Delete all chunks associated with a source from the store and BM25 index.
- Parameters:
source (str) – Source identifier to delete.
- Return type:
None
- count()[source]
Return the total number of indexed chunks.
Checks the vector store first, then falls back to BM25.
- Returns:
Chunk count, or 0 if neither store is configured.
- Return type:
- rebuild_bm25_from_store()[source]
Rebuild the BM25 index from the persistent vector store.
Clears the current BM25 index and re-adds every chunk the store exposes via
get_all(). Chunks whosechunking_strategymetadata is set and differs from the current chunker are skipped (legacy chunks with no strategy tag are included for backward compatibility).- Returns:
Number of documents added to the BM25 index.
- Raises:
RuntimeError – if BM25 or the store is not configured.
- Return type:
- class RecursiveChunker(chunk_size=1000, chunk_overlap=200, metadata=None, separators=None, keep_separator=True)[source]
Bases:
ChunkerBaseRecursive chunking that splits hierarchically by separators.
- Parameters:
chunk_size (int) – Maximum characters per chunk.
chunk_overlap (int) – Overlap between consecutive chunks.
metadata (dict[str, Any] | None) – Default metadata for all chunks.
separators (list[str] | None) – List of separators in order of preference.
keep_separator (bool) – Whether to keep the separator with chunks.
- DEFAULT_SEPARATORS = ['\n\n\n', '\n\n', '\n', '. ', '! ', '? ', '; ', ', ', ' ', '']
- class RerankerBase[source]
Bases:
objectBase class for re-rankers.
- class SearchHit(content, score, source='', metadata=<factory>, parent_content=None, id='')[source]
Bases:
objectSingle search result from a RAG query.
- Parameters:
- class TextChunk(content, chunk_index, start_char, end_char, metadata=None)[source]
Bases:
objectA single chunk of text produced by a chunker.
- Parameters:
- VectorStore
alias of
ChromaVectorStore
- class VectorStoreBase[source]
Bases:
ABCAbstract base class for vector store backends.
All backends must implement the core CRUD + search methods. The
whereparameter inasearchaccepts a backend-neutral filter dict with string keys and values. Each backend translates this to its native filter format internally.Example backend-neutral filters:
{"source": "doc1"} {"chunking_strategy": "recursive", "source": "doc1"}
For compound filters, backends should support an
$andkey:{"$and": [{"source": "doc1"}, {"chunking_strategy": "recursive"}]}
- abstractmethod async aadd(ids, texts, embeddings, metadatas)[source]
Add documents with pre-computed embeddings to the store.
- Parameters:
- Returns:
Number of documents added.
- Return type:
- abstractmethod async asearch(query_embedding, top_k=5, where=None)[source]
Search for documents by vector similarity.
- abstractmethod delete_by_source(source)[source]
Delete all chunks matching
source.- Parameters:
source (str)
- Return type:
None
- abstractmethod delete_by_source_and_strategy(source, strategy)[source]
Delete chunks matching both
sourceandchunking_strategy.
- abstractmethod clear()[source]
Delete all stored data and recreate the collection.
- Return type:
None
- abstractmethod get_all()[source]
Return all stored documents as dicts with
id,content,metadatakeys.
Functions
- chunk_text(text, strategy='recursive', chunk_size=1000, chunk_overlap=200, metadata=None, **kwargs)[source]
Convenience function to chunk text with a single call.
- Parameters:
- Returns:
List of TextChunk objects.
- Return type:
- format_hits(hits, max_chars=None, include_parent=True)[source]
Format search hits into a numbered, human-readable text string.
Each hit is rendered with its index, source, relevance score, content, and optionally a snippet of its parent context.
- Parameters:
- Returns:
A formatted string, or an empty string if hits is empty.
- Return type:
- fuse_search_results(result_lists, n_results=5, dedupe_by='id')[source]
Fuse results from multiple searches with deduplication.
Combines results from multiple query variations, removing duplicates while preserving relevance ordering.
- Parameters:
- Returns:
Fused and deduplicated list of results.
- Return type:
- get_chunker(strategy='recursive', chunk_size=1000, chunk_overlap=200, metadata=None, **kwargs)[source]
Get a chunker instance based on strategy name.
- Parameters:
strategy (str) – Chunking strategy name (character, recursive, markdown, code, hierarchical).
chunk_size (int) – Maximum chunk size.
chunk_overlap (int) – Overlap between chunks.
metadata (dict[str, Any] | None) – Default metadata for chunks.
**kwargs (Any) – Additional strategy-specific parameters.
- Returns:
Configured chunker instance.
- Raises:
ValueError – If strategy name is not recognized.
- Return type:
- get_reranker(reranker_type='none', **kwargs)[source]
Get a reranker by type name.
- Parameters:
- Returns:
Configured reranker instance.
- Return type:
- get_store(backend='chroma', **kwargs)[source]
Get a vector store instance by backend name.
- Parameters:
- Returns:
Configured vector store instance.
- Raises:
ValueError – If backend name is not recognized.
ImportError – If the backend’s dependency is not installed.
- Return type: