src.dackar.RCA.doc_extraction

Submodules

Attributes

EXTRACTABLE_DOC_TYPES

Exceptions

DocExtractionStoreError

Base error for DocExtractionStore backend failures (Chroma / embedding backend).

EmbeddingModelVersionError

Raised when the query-time embedding model does not match the collection's stored model.

Classes

ConfidenceLevel

str(object='') -> str

DocExtractionRecord

One extraction record per identified causal chain within a source document.

DocExtractionAdapter

Wraps HybridNERPipeline + causal_condition_adapter to produce DocExtractionRecords.

DocExtractionStore

Chroma-backed store for DocExtractionRecord objects.

SemanticMatch

One deduplicated result from a DocExtractionStore.query() call.

EpistemicClassifier

Applies the four-way epistemic classification to a document record.

EpistemicsRoutingConfig

Versioned configuration artifact for the epistemic routing table.

Functions

build_epistemics_manifest_summary(...)

Build the epistemics section of run_manifest.artifacts (Phase A).

Package Contents

class src.dackar.RCA.doc_extraction.ConfidenceLevel[source]

Bases: str, enum.Enum

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to ‘utf-8’. errors defaults to ‘strict’.

HIGH = 'high'
MEDIUM = 'medium'
LOW = 'low'
class src.dackar.RCA.doc_extraction.DocExtractionRecord[source]

One extraction record per identified causal chain within a source document.

A single CR/WO may produce multiple records (one per causal chain). Records with all semantic fields null are stored but flagged for human review. fm_id_candidate is null at ingestion time; resolved via batch KG lookup at RCA run time (§3.3 Step C). embedding_model_version is null until the record is embedded in Stage 2.

doc_id: str
chain_index: int
identified_effect: str | None
assessed_cause: str | None
inferred_fm_label: str | None
fm_id_candidate: str | None
fm_id_candidate_alt: str | None
confidence: ConfidenceLevel
cause_is_symptom: bool
as_found: str | None
as_left: str | None
procedural_deviation_score: float
extraction_version: str
embedding_model_version: str | None
needs_human_review: bool = False
ruled_out_mechanisms: List[str] = []
event_time_start: datetime.datetime | None = None
event_time_end: datetime.datetime | None = None
event_time_confidence: str | None = None
source_cr_id: str | None = None
source_wo_id: str | None = None
source_event_id: str | None = None
fm_resolution_status: str | None = None
fm_resolution_score: float | None = None
doc_type: str = ''
finding_status: str | None = None
authority_level: str | None = None
epistemic_class: str | None = None
classification_resolution_level: str | None = None
degraded_classification: bool = False
embed_text()[source]

Concatenation of semantic fields used for embedding (null-safe).

Return type:

str

is_null_record()[source]

Return True when no semantic content was extracted (all three core fields empty).

Null records are the sentinel produced for a document with no extractable causal language; they are stored and retrievable by metadata but never surface in similarity queries (their embed_text is a single space).

Return type:

bool

is_recurrence_eligible()[source]

Return True when this record may contribute to recurrence counting.

Records with fm_resolution_status == “ambiguous” require analyst promotion before being eligible; all others (auto_resolved, unresolved, or not yet resolved) are treated as eligible by default.

Phase C will add an additional gate: records whose epistemic_class is not “analyzes_past_degradation” will be ineligible regardless of fm_resolution_status. That gate is intentionally off here to avoid a scoring change before calibration.

Return type:

bool

as_chroma_metadata()[source]

Flat metadata dict for Chroma upsert (all values must be str/int/float/bool).

Return type:

dict

class src.dackar.RCA.doc_extraction.DocExtractionAdapter(ner_pipeline, nlp=None, llm_cfg=None, extraction_version='ner-v1.0_gaz-v1_llm-none', _causal_extractor=None)[source]

Wraps HybridNERPipeline + causal_condition_adapter to produce DocExtractionRecords.

Produces one record per identified causal chain in the document. A document with no extractable causal language produces one null record (confidence=low, needs_human_review=True).

fm_id_candidate is always None at extraction time; resolved via batch KG lookup at RCA run time (see DocExtractionStore.resolve_fm_candidates).

Parameters:
  • ner_pipeline (Any)

  • nlp (Any)

  • llm_cfg (Optional[Dict[str, Any]])

  • extraction_version (str)

  • _causal_extractor (Optional[Any])

_ner
_nlp = None
_llm_cfg = None
extraction_version = 'ner-v1.0_gaz-v1_llm-none'
__causal_extractor = None
_get_causal_extractor()[source]
Return type:

Any

extract(doc_id, text, doc_type, section_role='body')[source]

Extract all causal chains from a single document text.

Parameters:
  • doc_id (str) – Source document identifier (e.g. “CR-2026-00123”).

  • text (str) – Full document text (single chunk; multi-chunk handling is a future extension).

  • doc_type (str) – Must be one of EXTRACTABLE_DOC_TYPES.

  • section_role (str) – Hint for condition-state extraction (“body”, “as_found”, “as_left”, etc.).

Returns:

List of DocExtractionRecord, one per causal chain. Never empty — a document with no causal language returns a single null record.

Raises:

ValueError – if doc_type is not in EXTRACTABLE_DOC_TYPES.

Return type:

List[src.dackar.RCA.doc_extraction.schema.DocExtractionRecord]

_null_record(doc_id, as_found, as_left, proc_score)[source]
Parameters:
  • doc_id (str)

  • as_found (Optional[str])

  • as_left (Optional[str])

  • proc_score (float)

Return type:

src.dackar.RCA.doc_extraction.schema.DocExtractionRecord

src.dackar.RCA.doc_extraction.EXTRACTABLE_DOC_TYPES[source]
class src.dackar.RCA.doc_extraction.DocExtractionStore(persist_directory, embed_model='nomic-embed-text-v1.5', ollama_base_url=None, fm_resolution_threshold=0.88, epistemics_classifier=None)[source]

Chroma-backed store for DocExtractionRecord objects.

One collection ("doc_extractions") stores all extraction records across all document types. Each record’s embed_text (§4.1) is computed and stored at upsert time; similarity queries run against these pre-computed vectors.

Key guarantees: - Embedding model version is written into every record’s metadata.

A mismatch between query-time model and stored model raises EmbeddingModelVersionError.

  • fm_id_candidate is always null at ingestion; resolve_fm_candidates() writes it back in batch at the start of an RCA run (§3.3 Step C).

  • query() deduplicates by doc_id, returning only the best-scoring chain per document.

Parameters:
  • persist_directory (str)

  • embed_model (str)

  • ollama_base_url (Optional[str])

  • fm_resolution_threshold (float)

  • epistemics_classifier (Optional[Any])

COLLECTION_NAME = 'doc_extractions'
_HNSW_SPACE = 'cosine'
persist_directory
embed_model = 'nomic-embed-text-v1.5'
ollama_base_url
fm_resolution_threshold = 0.88
epistemics_classifier = None
_collection = None
_embedder = None
_degraded_operations: List[Dict[str, Any]] = []
property embedding_model_version: str
Return type:

str

_get_embedder()[source]
_get_collection()[source]
_embed_texts(texts)[source]
Parameters:

texts (List[str])

Return type:

List[List[float]]

_embed_query(text)[source]
Parameters:

text (str)

Return type:

List[float]

_chroma_collection()[source]
upsert(record)[source]

Embed and store one extraction record. Returns the Chroma record_id.

Records with no embed_text are stored with a single-space document to avoid Chroma rejecting empty strings; they are retrievable by metadata but will not surface in similarity queries.

Parameters:

record (src.dackar.RCA.doc_extraction.schema.DocExtractionRecord)

Return type:

str

upsert_batch(records)[source]

Embed and store multiple extraction records in one batch call.

Parameters:

records (List[src.dackar.RCA.doc_extraction.schema.DocExtractionRecord])

Return type:

int

query(query_text, *, top_k=5, similarity_threshold=0.75, near_match_window=0.1, filter_meta=None, exact_doc_ids=None)[source]

Query for semantically similar extraction records.

The embedding model used at query time must match the collection’s stored embedding_model_version. A mismatch raises EmbeddingModelVersionError.

Deduplication: only the highest-scoring chain per doc_id is returned.

Parameters:
  • query_text (str) – The query string (e.g. fm.name | fm.expected_symptoms | event.symptom_description).

  • top_k (int) – Maximum number of doc_id-deduplicated results to return.

  • similarity_threshold (float) – Minimum cosine similarity for inclusion in the main result set.

  • near_match_window (float) – Width of the soft zone below threshold that populates near_matches.

  • filter_meta (Optional[Dict[str, Any]]) – Optional Chroma metadata pre-filter (e.g. {"doc_type": "CR"}).

  • exact_doc_ids (Optional[set]) – Set of doc_ids already counted via exact-match recurrence (kg_context.past_events). Matching records are excluded from both matches and near_matches to prevent double-counting. None or empty set disables the guard.

Returns:

  • matches: similarity >= similarity_threshold, deduplicated, top_k max, exact_doc_ids excluded

  • near_matches: similarity in [similarity_threshold - near_match_window, similarity_threshold)

Return type:

(matches, near_matches) where

_assert_model_version()[source]

Raise EmbeddingModelVersionError if stored records use a different model.

Return type:

None

resolve_fm_candidates(fm_list, *, resolution_threshold=None)[source]

Resolve fm_id_candidate for unresolved extraction records.

Called once per RCA run before Step 3 / Step 2d. For each record with fm_id_candidate == “” (unresolved), embeds the stored inferred_fm_label and compares against the KG FM list for the current asset neighborhood. Writes fm_id_candidate (and fm_id_candidate_alt) back to the collection if cosine similarity >= resolution_threshold.

Parameters:
  • fm_list (List[Tuple[str, str]]) – List of (fm_id, fm_label) tuples from the KG.

  • resolution_threshold (Optional[float]) – Override default; defaults to self.fm_resolution_threshold.

Returns:

Number of records updated.

Return type:

int

count()[source]

Return total number of extraction records in the collection.

Return type:

int

delete_by_doc_id(doc_id)[source]

Delete all extraction records for a given source document (re-ingestion path).

Parameters:

doc_id (str)

Return type:

None

_record_degradation(operation, exc)[source]

Record a degraded (error-swallowed) operation for run-manifest surfacing.

query() and resolve_fm_candidates() degrade to empty/zero results on backend failure rather than crashing a batch run; each such event is captured here so store_health_summary() can report it and the failure is not misread downstream as a legitimate “no semantic recurrence”.

Parameters:
  • operation (str)

  • exc (Exception)

Return type:

None

property degraded: bool

True when any query/resolve operation swallowed a backend error this run.

Return type:

bool

store_health_summary()[source]

Degradation summary for run_manifest (store_health section).

Returns {"degraded": bool, "degraded_operation_count": int, "events": [...]}. The orchestrator stamps this onto the run manifest so a swallowed Chroma/embedding error surfaces as an explicit degraded-run signal instead of a silent under-count.

Return type:

Dict[str, Any]

class src.dackar.RCA.doc_extraction.SemanticMatch[source]

One deduplicated result from a DocExtractionStore.query() call.

record_id: str
doc_id: str
chain_index: int
identified_effect: str | None
assessed_cause: str | None
inferred_fm_label: str | None
fm_id_candidate: str | None
confidence: src.dackar.RCA.doc_extraction.schema.ConfidenceLevel
cause_is_symptom: bool
similarity_score: float
fm_resolution_status: str | None = None
doc_type: str = ''
finding_status: str | None = None
authority_level: str | None = None
epistemic_class: str | None = None
classification_resolution_level: str | None = None
degraded_classification: bool = False
property confidence_weight: float

Numeric weight for this match’s confidence level (HIGH=1.0, MEDIUM=0.7, LOW=0.3).

Used as a multiplier in semantic_contribution (§4.3) so lower-confidence extractions contribute proportionally less to effective_recurrence_count.

Return type:

float

property cause_is_symptom_factor: float

Down-weight factor when the assessed cause is itself a symptom (0.5) vs. a mechanism (1.0).

A symptom-as-cause is a weaker recurrence signal than a true failure mechanism, so it halves this match’s semantic_contribution.

Return type:

float

property semantic_contribution: float

Fractional recurrence contribution for effective_recurrence_count (§4.3).

Return type:

float

exception src.dackar.RCA.doc_extraction.DocExtractionStoreError[source]

Bases: RuntimeError

Base error for DocExtractionStore backend failures (Chroma / embedding backend).

query() and resolve_fm_candidates() deliberately degrade to empty/zero results on backend failure rather than raising, recording each event via _record_degradation() so it surfaces in the run manifest (see store_health_summary()). Callers that prefer fail-loud semantics can inspect store_health_summary()[“degraded”] and escalate.

exception src.dackar.RCA.doc_extraction.EmbeddingModelVersionError[source]

Bases: DocExtractionStoreError

Raised when the query-time embedding model does not match the collection’s stored model.

class src.dackar.RCA.doc_extraction.EpistemicClassifier(config=None)[source]

Applies the four-way epistemic classification to a document record.

Usage

config = EpistemicsRoutingConfig(policy_version=”epistemics-v1.0”) classifier = EpistemicClassifier(config) annotation = classifier.classify(meta)

meta may be a dict (Chroma metadata), a DocExtractionRecord, or a SemanticMatch — any object that exposes the relevant fields via attribute or dict access.

Priority chain (§3.3)

  1. finding_status — semantic; not degraded

  2. authority_level — semantic; not degraded

  3. doc_type — syntactic proxy; degraded_classification = True

  4. default — no metadata; degraded_classification = True

config
_doc_type_table
classify(record)[source]

Classify one record and return an EpistemicAnnotation.

record may be: - a dict (Chroma metadata dict) - a DocExtractionRecord - a SemanticMatch - any object with attribute access for the relevant fields

Parameters:

record (Any)

Return type:

EpistemicAnnotation

annotate_record(record)[source]

Classify record in-place, writing annotation fields back to it.

Supports DocExtractionRecord and SemanticMatch (both have the three annotation fields as attributes). No-ops silently on other types.

Parameters:

record (Any)

Return type:

None

_resolve_finding_status(finding_status, doc_type)[source]

Look up (finding_status, doc_type) in the routing table.

Tries exact (finding_status, doc_type) first, then (finding_status, “”) as the doc_type-agnostic fallback. Returns None if not found.

Parameters:
  • finding_status (str)

  • doc_type (str)

Return type:

Optional[str]

Parameters:

config (Optional[EpistemicsRoutingConfig])

class src.dackar.RCA.doc_extraction.EpistemicsRoutingConfig[source]

Versioned configuration artifact for the epistemic routing table.

policy_version is stamped on run_manifest.pipeline_config and on every EpistemicAnnotation so that routing decisions are reproducible.

The routing tables are embedded in epistemics.py and versioned via policy_version; changing any table entry requires a version bump.

policy_version: str = 'epistemics-v1.0'
doc_type_overrides: Dict[str, str]
src.dackar.RCA.doc_extraction.build_epistemics_manifest_summary(cross_pattern_evidence, policy_version)[source]

Build the epistemics section of run_manifest.artifacts (Phase A).

Counts epistemic_class distribution, degraded_classification counts by doc_type, and classification_resolution_level distribution across all doc extractions visible to the pipeline. Sourced from cross_pattern_evidence all_links provenance when available; otherwise returns a minimal stub.

This function is called by the orchestrator’s _stage_g_finalize_manifest(). It is defined here (not in the orchestrator) so that it can be unit-tested independently without the orchestrator’s heavy kg dependencies.

Parameters:
  • cross_pattern_evidence (Optional[Dict[str, Any]])

  • policy_version (Optional[str])

Return type:

Dict[str, Any]