src.dackar.RCA.storage.chroma_store¶
Attributes¶
Classes¶
Stage-6 store for canonical processed_text_record objects. |
Functions¶
|
|
|
|
|
|
|
Normalize high-level retrieval filters into the scalar metadata keys that |
|
Return True if doc is associated with at least one of the wanted component IDs. |
|
Apply the dense-path Chroma filter semantics to a BM25 hit's metadata. |
|
|
|
|
|
Flatten a canonical |
|
Convert a processed_text_record into the |
|
Return the Chroma collection name for a document type, e.g. |
Module Contents¶
- src.dackar.RCA.storage.chroma_store._iter_jsonl(jsonl_path)[source]¶
- Parameters:
jsonl_path (str)
- Return type:
Iterable[Dict[str, Any]]
- src.dackar.RCA.storage.chroma_store._collapse_ws(s)[source]¶
- Parameters:
s (Optional[str])
- Return type:
str
- src.dackar.RCA.storage.chroma_store._looks_like_processed_text_record(obj)[source]¶
- Parameters:
obj (Dict[str, Any])
- Return type:
bool
- src.dackar.RCA.storage.chroma_store.extract_processed_text_record(obj)[source]¶
- Parameters:
obj (Dict[str, Any])
- Return type:
Optional[Dict[str, Any]]
- src.dackar.RCA.storage.chroma_store._stable_record_id_from_doc(doc)[source]¶
- Parameters:
doc (langchain_core.documents.Document)
- Return type:
Optional[str]
- src.dackar.RCA.storage.chroma_store._sanitize_meta_value(value)[source]¶
- Parameters:
value (Any)
- Return type:
Optional[Any]
- src.dackar.RCA.storage.chroma_store._normalize_filter_meta(filter_meta)[source]¶
Normalize high-level retrieval filters into the scalar metadata keys that are actually stored in Chroma.
Examples
doc_ids -> doc_id
doc_types -> doc_type
component_ids is translated in query_doc_type() into primary_component_id
- Parameters:
filter_meta (Optional[Dict[str, Any]])
- Return type:
Dict[str, Any]
- src.dackar.RCA.storage.chroma_store._doc_matches_component_ids(doc, wanted)[source]¶
Return True if doc is associated with at least one of the wanted component IDs.
- Checks:
The scalar
primary_component_idmetadata field (index-friendly path).The scalar
component_idmetadata field (legacy single-component path).The
component_idsfield. In practice this is a JSON-encoded string on every path, because metadata is passed through_sanitize_meta()(which stringifies lists) before it reaches either Chroma or the in-memory BM25 corpus. The plain-list branch is kept only as a defensive fallback for externally constructed documents.
- Parameters:
doc (langchain_core.documents.Document)
wanted (set)
- Return type:
bool
- src.dackar.RCA.storage.chroma_store._doc_matches_filter_sane(doc, filter_sane)[source]¶
Apply the dense-path Chroma filter semantics to a BM25 hit’s metadata.
The dense path builds
{k: {"$in": vals}}for list-valued filters and{k: {"$eq": v}}for scalars. This mirrors that membership-vs-equality logic for the in-memory BM25 post-filter so the two retrieval views agree. Previously BM25 used==even for list-valued filters, which never matched a scalar metadata value and silently dropped every BM25 hit — collapsing hybrid retrieval to dense-only whenever a list filter was set.- Parameters:
doc (langchain_core.documents.Document)
filter_sane (Dict[str, Any])
- Return type:
bool
- src.dackar.RCA.storage.chroma_store._sanitize_meta(meta)[source]¶
- Parameters:
meta (Dict[str, Any])
- Return type:
Dict[str, Any]
- src.dackar.RCA.storage.chroma_store._record_component_ids(metadata)[source]¶
- Parameters:
metadata (Dict[str, Any])
- Return type:
List[str]
- src.dackar.RCA.storage.chroma_store.build_chroma_metadata(record)[source]¶
Flatten a canonical
processed_text_recordinto Chroma-storable metadata.Chroma metadata values must be primitives (str / int / float / bool). This function projects the nested record structure onto a flat scalar dict that supports both index-level filtering and BM25 text search:
Copies identity/traceability keys (
record_id,doc_id,doc_type,chunk_index,chunk_id, page span, authority level, section role).Derives
primary_component_id(first component) for index-level component filtering.Flattens
condition_assessment,eca,oe_metadata, NER entities, and Stage-5 causal statements intoca_*/eca_*/oe_*/*_textscalar keys.Sets
finding_statusfrom the document type (ECA=confirmed, CR=preliminary, OE=fleet_experience, else observational).
List-valued keys are preserved but JSON-stringified by
_sanitize_meta()on return, and companion*_textkeys are added for the fields inLIST_FIELDS.- Returns:
A sanitized, primitive-only metadata dict ready to hand to Chroma.
- Parameters:
record (Dict[str, Any])
- Return type:
Dict[str, Any]
- src.dackar.RCA.storage.chroma_store.to_chroma_payload(record)[source]¶
Convert a processed_text_record into the
(id, document, metadata)triple upserted into Chroma.The vector id is the record’s
record_id, the embedded/indexed document text is the whitespace-collapsedembedding_text, and metadata comes frombuild_chroma_metadata().- Parameters:
record (Dict[str, Any])
- Return type:
Dict[str, Any]
- src.dackar.RCA.storage.chroma_store.collection_name_for_doc_type(doc_type, prefix='processed')[source]¶
Return the Chroma collection name for a document type, e.g.
processed_CR.The doc type is upper-cased and sanitized (
/and spaces become_) so it is a valid, stable collection identifier; a falsy doc type maps toOTHER.- Parameters:
doc_type (str)
prefix (str)
- Return type:
str
- class src.dackar.RCA.storage.chroma_store.ChromaRecordStore(persist_directory, *, embed_model=None, ollama_base_url=None, collection_prefix='processed', bm25_k=20)[source]¶
Stage-6 store for canonical processed_text_record objects.
One Chroma collection is used per document class (CR, MR, SOP, ECA, …). Every indexed vector corresponds to one validated processed_text_record.
- Parameters:
persist_directory (str)
embed_model (Optional[str])
ollama_base_url (Optional[str])
collection_prefix (str)
bm25_k (int)
- _states: Dict[str, _CollectionState][source]¶
- get_or_create_collection(doc_type, collection_name=None)[source]¶
- Parameters:
doc_type (str)
collection_name (Optional[str])
- Return type:
- load_collection(doc_type, collection_name=None)[source]¶
Open a persisted collection for querying and return its
_CollectionState.The dense (vector) side is fully backed by Chroma’s on-disk index, so it works regardless of which process performed the original ingest.
BM25, however, is an in-memory corpus built only from documents upserted during the current process (see
upsert_records()). When a collection is loaded fresh from disk without a matching in-process ingest,state.bm25_docsis empty and hybrid retrieval degrades to dense-only —hybrid_weightthen has no effect. This is a deliberate limitation of the current design (the BM25 corpus is not persisted); callers needing hybrid retrieval in a query-only process must re-ingest the source JSONL first. A warning is emitted here to make the degraded mode explicit.- Parameters:
doc_type (str)
collection_name (Optional[str])
- Return type:
- _get_or_build_bm25(state)[source]¶
- Parameters:
state (_CollectionState)
- Return type:
Optional[langchain_community.retrievers.BM25Retriever]
- upsert_records(records, *, doc_type=None, collection_name=None)[source]¶
Upsert a batch of processed_text_records into the collection for their doc type.
All records in a call must share one doc type (a mixed-type batch raises
ValueError); the type is taken fromdoc_typeor inferred from the first record. Malformed records and records with empty embedding text are skipped. Each surviving record is upserted into Chroma byrecord_id(dense side) and added to the collection’s in-memory BM25 corpus (sparse side), so a subsequent query in the same process gets true hybrid retrieval.- Returns:
The number of records actually upserted.
- Parameters:
records (Iterable[Dict[str, Any]])
doc_type (Optional[str])
collection_name (Optional[str])
- Return type:
int
- upsert_jsonl(jsonl_path, *, doc_type_override=None)[source]¶
Ingest a JSONL file of processed_text_records, one Chroma collection per doc type.
Records are read from
jsonl_path(each line may be a bare record or wrapped under aprocessed_text_recordkey), grouped by doc type (or forced todoc_type_override), and upserted viaupsert_records().- Returns:
Mapping of
doc_type -> number of records upserted.- Parameters:
jsonl_path (str)
doc_type_override (Optional[str])
- Return type:
Dict[str, int]
- query_doc_type(doc_type, query_text, *, top_k=8, filter_meta=None, collection_name=None, hybrid_weight=0.5)[source]¶
Hybrid (dense + BM25) retrieval over a single doc-type collection.
Runs a dense vector search and a BM25 search, then fuses the two ranked lists with Reciprocal Rank Fusion weighted by
hybrid_weight(dense) /1 - hybrid_weight(BM25). The fused_scoreis written back onto each returned document’s metadata.- Filtering:
filter_metais normalized (see_normalize_filter_meta()) into scalar Chroma$eq/$inclauses.component_idsis handled specially: it becomes an index-levelprimary_component_id$infilter, with a legacy post-filter fallback for older records that predateprimary_component_id(see_doc_matches_component_ids()).- BM25 availability:
BM25 only contributes when this collection was ingested in the current process; on a disk-loaded collection retrieval is dense-only (see
load_collection())._bm25_availableis recorded on each returned document’s metadata.
- Parameters:
doc_type (str) – Document type selecting the collection.
query_text (str) – Natural-language query.
top_k (int) – Maximum number of fused results to return.
filter_meta (Optional[Dict[str, Any]]) – Optional high-level metadata filters.
collection_name (Optional[str]) – Explicit collection override (else derived from
doc_type).hybrid_weight (float) – Dense-vs-BM25 blend in [0, 1]; 1.0 is dense-only, 0.0 is BM25-only.
- Returns:
Up to
top_kLangChainDocumentobjects ordered by fused score.- Raises:
ValueError – If the target collection has not been initialised via
upsert_jsonl()/upsert_records()/load_collection().- Return type:
List[langchain_core.documents.Document]