VectorGroundTruthStore¶
Semantic vector store for RAG-based factual grounding. Ingest documents, then pass to CoherenceScorer for fact-checked scoring. Supports pluggable backends via a registry pattern.
Usage¶
from director_ai.core.retrieval.vector_store import VectorGroundTruthStore
store = VectorGroundTruthStore()
store.ingest([
"Refunds are available within 30 days of purchase.",
"Standard shipping takes 5-7 business days.",
"Pro plan costs $49/month.",
])
# Use with scorer
from director_ai import CoherenceScorer
scorer = CoherenceScorer(
threshold=0.6,
ground_truth_store=store,
use_nli=True,
)
VectorGroundTruthStore Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
backend |
VectorBackend \| None |
None |
Backend instance (default: InMemoryBackend) |
tenant_id |
str |
"" |
Default tenant ID for multi-tenant stores |
Methods¶
add()¶
store.add(
key="refund-policy",
value="Refunds are available within 30 days.",
metadata={"kb_version_bump": "patch"}, # patch, minor, or major
)
Facts start at 1.0.0. Replacing a fact with different content bumps the patch
version by default. Pass kb_version_bump="minor" or "major" in metadata when
the source change is a larger schema or policy change. The vector metadata is
stamped with:
kb_versionkb_chunk_versionkb_content_hashkb_previous_hashkb_record_kindkb_source_keykb_chunk_index
Use fact_version(key), fact_version_record(key), or version_manifest() to
inspect the in-process version ledger.
retract_fact()¶
Retraction records mark a fact or derived chunk source as unusable for retrieval
without deleting backend rows. retrieve_context() and
retrieve_context_with_chunks() filter matching vector results and keyword
fallback facts after retraction. Use retraction_records() to inspect the
event log.
replace_fact()¶
store.replace_fact(
"refund-policy",
"Refunds are available within 45 days.",
reason="policy update",
)
Replacement records preserve the superseded version and content hash while the
new value is indexed under the same key. Use replacement_records() to inspect
the event log.
kb_snapshot_root()¶
root = store.kb_snapshot_root(tenant_id="acme")
audit_payload = store.kb_snapshot_audit_record(tenant_id="acme")
kb_snapshot_root() returns a deterministic SHA-256 Merkle root over the
tenant-visible KB version ledger. Leaves are sorted by tenant, key, record
kind, and chunk index, so the same KB state produces the same root regardless
of ingestion order. Retractions and replacements update the root because the
snapshot includes status, current content hash, previous hash, and semantic
version fields.
kb_snapshot_audit_record() returns a compact payload with:
eventtenant_idrevisionrecord_countretraction_countreplacement_countconflict_countmerkle_root
Pass this payload to AuditLogger.log_review(kb_snapshot=audit_payload) when a
review decision must carry the KB state it was grounded against.
The local R9 evidence packet exercises this contract together with protected claim conflicts and provenance-chain verification:
The generated JSON records only tenant-safe hashes, roots, counts, conflict metadata, and pass/fail status. It does not serialise raw fact values.
conflict_reports()¶
store.add_fact(
"signed-dose",
"Dose is 5 mg.",
metadata={
"claim_id": "dose-claim",
"signed_fact_id": "signed-1",
"claim_source": "signed_fact",
},
)
store.add_fact(
"incoming-dose",
"Dose is 10 mg.",
metadata={"claim_id": "dose-claim"},
)
reports = store.conflict_reports()
conflict_reports() returns tenant-scoped records created during fact writes
when a new fact overlaps a retracted ledger entry, differs from a protected
signed fact, differs from a passport claim, or declares an explicit
contradicts relation. Reports are advisory: ingestion continues, retrieval
still uses the active version ledger, and callers can route reports to review
queues or audit sinks.
freshness_status_signals()¶
store.add_fact(
"trial-paper",
"Trial X reported a 12 percent response rate.",
metadata={
"external_id": "doi:10.example/trial-paper",
"source_timestamp": "1710000000",
"citation_status": "active",
"status_source": "publisher-feed",
},
)
signals = store.freshness_status_signals()
Use freshness_status_signals() to pass KB source age and external citation
status metadata into score_temporal_freshness(citation_statuses=signals).
The method emits tenant-scoped dictionaries with source_id, status,
status_source, and any available timestamp fields.
ingest()¶
Add documents to the store. Each document is embedded and indexed as a derived
vector chunk with kb_record_kind="derived_chunk" and a semantic chunk version.
retrieve_context()¶
Retrieve concatenated context string for a query (matching parent GroundTruthStore interface). Use retrieve_context_with_chunks() for structured EvidenceChunk results.
VectorBackend¶
Abstract protocol for vector storage backends. Implement add() and query() to create a custom backend.
from director_ai.core.retrieval.vector_store import VectorBackend
class MyBackend(VectorBackend):
def add(self, texts: list[str], ids: list[str] | None = None) -> None:
...
def query(self, text: str, top_k: int = 3) -> list[tuple[str, float]]:
# Returns list of (text, distance) pairs
...
Built-in Backends¶
| Backend | Install | Description |
|---|---|---|
InMemoryBackend |
included | TF-IDF cosine similarity. No deps, good for testing. |
SentenceTransformerBackend |
pip install director-ai[embeddings] |
Dense embeddings via sentence-transformers. Production-quality. |
ChromaBackend |
pip install director-ai[vector] |
ChromaDB persistent store. Scales to millions of documents. |
FAISSBackend |
pip install director-ai[faiss] |
In-process FAISS index (flat exact or IVF); the default dense engine behind grounded() when the extra is installed. |
QdrantBackend |
pip install director-ai[qdrant] |
Qdrant vector database; document ids map to deterministic UUID points so re-adds upsert. |
WeaviateBackend |
pip install director-ai[weaviate] |
Weaviate database via the v4 collections API (HTTP + gRPC). |
ElasticsearchBackend |
pip install director-ai[elasticsearch] |
Elasticsearch 8.x with hybrid BM25 + kNN retrieval. |
PineconeBackend |
pip install director-ai[pinecone] |
Pinecone managed vector database. |
ChromaBackend¶
from director_ai.core.retrieval.vector_store import ChromaBackend
backend = ChromaBackend(
collection_name="legal_contracts",
persist_directory="/data/chroma",
embedding_model="BAAI/bge-large-en-v1.5",
)
store = VectorGroundTruthStore(backend=backend)
SentenceTransformerBackend¶
from director_ai.core.retrieval.vector_store import SentenceTransformerBackend
backend = SentenceTransformerBackend(
model_name="BAAI/bge-large-en-v1.5",
)
store = VectorGroundTruthStore(backend=backend)
Backend Registry¶
Register custom backends for use with DirectorConfig.vector_backend:
from director_ai.core.retrieval.vector_store import register_vector_backend, get_vector_backend
register_vector_backend("qdrant", MyQdrantBackend)
BackendClass = get_vector_backend("qdrant") # returns the class, not an instance
backend = BackendClass(**kwargs)
| Function | Purpose |
|---|---|
register_vector_backend(name, cls) |
Register a backend class |
get_vector_backend(name) |
Look up a registered backend class |
list_vector_backends() |
List registered backend names |
Retrieval Decorators¶
Each decorator wraps any VectorBackend and changes how queries are
formed or how results are assembled:
| Decorator | Description |
|---|---|
HybridBackend |
BM25 + dense fusion — weighted RRF by default, with convex, combmnz and zscore score-fusion strategies selectable via fusion_method; with_fusion() derives strategy views over one shared index. |
RerankedBackend |
Cross-encoder reranking over an over-fetched candidate set. |
TenantScopedBackend |
Binds any backend to one tenant: stamps the tenant on add, forces the tenant filter on every query, and verifies each returned row (drop + metric, or raise with strict=True). |
HyDEBackend |
Generates a pseudo-document for the query before dense retrieval (HyDE). |
MultiVectorBackend |
Indexes multiple representations per document and queries across all of them. |
ParentChildBackend |
Indexes small child chunks for precision, returns the enclosing parent chunks for context. |
ContextualCompressionBackend |
Compresses retrieved passages down to the query-relevant sentences. |
QueryDecompositionBackend |
Splits compound queries, retrieves per sub-query, and merges results. |
AdaptiveRouter sits in front of retrieval and classifies each query
into a retrieve-or-skip decision, so trivial prompts bypass the store
entirely.
Knowledge-Base Health¶
KBHealthCheck runs diagnostics over a store (document count,
queryability, probe-query latency) and returns a KBHealthReport
with healthy, per-check counts, and any issues or warnings:
Reranking¶
Enable cross-encoder reranking for improved retrieval precision:
scorer = CoherenceScorer(
ground_truth_store=store,
reranker_enabled=True,
reranker_model="cross-encoder/ms-marco-MiniLM-L-6-v2",
reranker_top_k_multiplier=3, # Retrieve 3x, rerank to top_k
)
Full API¶
director_ai.core.retrieval.vector_store.VectorGroundTruthStore
¶
VectorGroundTruthStore(backend: VectorBackend | None = None, tenant_id: str = '', evidence_firewall: EvidenceFirewall | None = None)
Bases: VersionLedgerMixin, ConflictLedgerMixin, SnapshotAuditMixin, GroundTruthStore
Ground truth store with vector-based semantic retrieval.
Extends the keyword-based GroundTruthStore with embedding-based
similarity search. Falls back to keyword matching when the vector
backend returns no results. Version bookkeeping, conflict detection,
and the snapshot audit come from the composed mixins.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
VectorBackend — vector DB backend (default: InMemoryBackend).
|
|
None
|
add_fact
¶
Alias for add() — also populates parent keyword store.
ingest
¶
Bulk-add plain text documents into the vector backend.
add
¶
Add one fact to the vector backend with version metadata.
retrieve_context
¶
Retrieve context as a string (matching parent interface).
Falls back to keyword-based parent if vector search returns nothing.
grounded
classmethod
¶
grounded(embedding_model: str = RECOMMENDED_EMBEDDING_MODEL, use_hybrid: bool = True, rrf_k: int = 60, tenant_id: str = '', use_ann: bool = True, use_reranker: bool = True, reranker_model: str = RECOMMENDED_RERANKER_MODEL, fusion_method: str = 'rrf', sparse_weight: float = 1.0, dense_weight: float = 1.0, enforce_tenant_isolation: bool = False) -> VectorGroundTruthStore
Build the recommended grounded retrieval recipe.
Sets up hybrid retrieval (BM25 + FAISS-indexed dense) with a sentence-transformer embedding model and cross-encoder reranking. This is the intended production path for domain profiles (medical, finance, legal) where NLI-only scoring has 100% FPR without KB grounding.
Every optional layer degrades gracefully: without faiss the
dense path is the sentence-transformer linear scan, without
sentence-transformers it is the keyword InMemoryBackend,
and a missing reranker stack leaves retrieval un-reranked — each
with a logged warning, never an exception.
Usage::
store = VectorGroundTruthStore.grounded()
store.ingest(["Your product documentation...", ...])
scorer = CoherenceScorer(ground_truth_store=store, use_nli=True)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
embedding_model
|
str
|
HuggingFace model ID for dense embeddings.
Default: |
RECOMMENDED_EMBEDDING_MODEL
|
use_hybrid
|
bool
|
Wrap dense backend with BM25 + rank/score fusion (default True). |
True
|
rrf_k
|
int
|
Reciprocal Rank Fusion parameter (default 60). |
60
|
tenant_id
|
str
|
Default tenant scope for multi-tenant deployments. |
''
|
use_ann
|
bool
|
Index dense embeddings with FAISS instead of the Python
linear scan when |
True
|
use_reranker
|
bool
|
Rerank fused candidates with a cross-encoder when the reranker stack is installed (default True). |
True
|
reranker_model
|
str
|
HuggingFace model ID for the cross-encoder reranker.
Default: |
RECOMMENDED_RERANKER_MODEL
|
fusion_method
|
str
|
Hybrid fusion strategy — |
'rrf'
|
sparse_weight
|
float
|
BM25 run weight in the fusion (default 1.0). |
1.0
|
dense_weight
|
float
|
Dense run weight in the fusion (default 1.0). |
1.0
|
enforce_tenant_isolation
|
bool
|
Bind the whole retrieval stack to |
False
|
retrieve_context_with_chunks
¶
retrieve_context_with_chunks(query: str, top_k: int = 3, tenant_id: str = '') -> list[EvidenceChunk]
Retrieve context as EvidenceChunk objects.
director_ai.core.retrieval.vector_store.VectorBackend
¶
Bases: ABC
Protocol for vector database backends.
add
abstractmethod
¶
Index text under doc_id with optional metadata.
query
abstractmethod
¶
Return the n_results closest matches to text for the tenant.
aadd
async
¶
Async add — delegates to sync add via executor by default.
aquery
async
¶
Async query — delegates to sync query via executor by default.
director_ai.core.retrieval.vector_store.InMemoryBackend
¶
Bases: VectorBackend
Simple in-memory cosine-similarity backend (no external deps).
Uses TF-IDF-like word overlap for embedding approximation. Suitable for testing and small fact stores.
director_ai.core.retrieval.vector_store.ChromaBackend
¶
ChromaBackend(collection_name: str = 'director_ai_facts', persist_directory: str | None = None, embedding_model: str | None = None, embedding_function: _ChromaEmbeddingFunction | None = None)
Bases: VectorBackend
ChromaDB backend for production vector search.
Director uses Chroma in embedded mode only. The backend constructs either
chromadb.PersistentClient(path=...) for local persistence or
chromadb.Client() for ephemeral in-process storage; it never constructs
an HTTP client or forwards remote-code execution flags. That boundary keeps
server-only Chroma advisories outside Director's execution path while the
optional dependency remains open to operator-managed upgrades.
Operators may inject a local Chroma embedding function for offline, deterministic, or pre-warmed deployments. That path avoids the Chroma default embedder and sentence-transformer model downloads while preserving real Chroma storage and query semantics.
Requires pip install chromadb sentence-transformers.
Create or open a Chroma collection with optional persistence.
director_ai.core.retrieval.vector_store.SentenceTransformerBackend
¶
SentenceTransformerBackend(model_name: str = 'BAAI/bge-large-en-v1.5', model: _EmbeddingModel | None = None)
Bases: VectorBackend
Embedding-based backend using sentence-transformers directly.
Recommended model: BAAI/bge-large-en-v1.5 (best quality/speed tradeoff). Alternative: Snowflake/snowflake-arctic-embed-l for multilingual.
Operators may inject a preloaded embedding object that implements
encode(text, normalize_embeddings=True). This keeps embedded, offline,
or model-managed deployments on the same retrieval path without requiring
the backend to own model loading.
Requires pip install sentence-transformers unless model is given.
Load the embedding model and initialise the in-memory index.