from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
@dataclass
[docs]
class Document:
"""
Represents a single reliability text document (condition report, work order, etc.).
Offsets are always defined on `text` (the original authoritative string).
Normalization can be added later using `normalized_text` + `offset_map`.
"""
[docs]
normalized_text: Optional[str] = None
@dataclass
[docs]
class SourceHit:
"""
Provenance record for how a candidate span was generated.
Examples:
- source_type="regex", source_id="REGEX_FAIL_START"
- source_type="gazetteer_exact", source_id="deg_mech_list"
- source_type="noun_chunk", source_id="spacy_np"
"""
[docs]
score: Optional[float] = None
[docs]
details: Dict[str, Any] = field(default_factory=dict)
@dataclass
[docs]
class LabelHypothesis:
"""
A proposed label for a candidate span before final resolution.
`group` is typically filled by schema lookup (label->group).
`score` can be used as a prior confidence or later overwritten by an ML classifier.
"""
[docs]
group: Optional[str] = None
[docs]
score: Optional[float] = None
[docs]
rationale: Optional[str] = None
@dataclass
[docs]
class CandidateSpan:
"""
A proposed entity mention span before final decision.
Fields:
- start/end: character offsets into Document.text
- text: cached substring for convenience
- sources: provenance (where did this candidate come from)
- proposed_labels: potentially multiple, potentially conflicting
"""
[docs]
sources: List[SourceHit] = field(default_factory=list)
[docs]
proposed_labels: List[LabelHypothesis] = field(default_factory=list)
[docs]
attributes: Dict[str, Any] = field(default_factory=dict)
[docs]
is_nested_allowed: bool = True
@dataclass
[docs]
class ResolvedSpan:
"""
A finalized span after conflict resolution / compatibility enforcement.
`labels` may contain multiple labels only if allowed by schema/rules (e.g., G5+G6).
"""
[docs]
provenance: Dict[str, Any] = field(default_factory=dict)
@dataclass
[docs]
class Decision:
"""
Records how one or more CandidateSpan(s) are resolved into final output spans.
action:
- "accept": accept as-is (possibly with refined label list)
- "reject": discard
- "split": output_spans contains >1 span
- "nest": output contains nested spans
- "defer": unresolved; keep for ML or human review
"""
[docs]
output_spans: List[ResolvedSpan]
[docs]
triggered_rule_ids: List[str] = field(default_factory=list)
[docs]
notes: List[str] = field(default_factory=list)
[docs]
confidence: Optional[float] = None
@dataclass
[docs]
class RelationProposal:
"""
Optional suggested relation between resolved spans. This is not required for v0.1,
but the compatibility schema can recommend link types like:
- "causes", "affects", "made_of", "has_outcome"
"""
[docs]
confidence: Optional[float] = None
[docs]
evidence: Dict[str, Any] = field(default_factory=dict)
[docs]
triggered_rule_ids: List[str] = field(default_factory=list)
@dataclass
[docs]
class PipelineResult:
"""
Final result for a document.
- decisions: full traceability of how spans were resolved
- entities: flattened accepted spans (for typical downstream use)
- relations: optional relation proposals
- diagnostics: counters/timings/debug info
"""
[docs]
decisions: List[Decision]
[docs]
entities: List[ResolvedSpan]
[docs]
relations: List[RelationProposal]
[docs]
diagnostics: Dict[str, Any] = field(default_factory=dict)