* docs: replace Exported Classes import blocks with summary tables across all 25 modules * docs: add method/parameter tables to parse, ingest, ontology, normalize, triplet_store, change_management, conflicts, export, graph_store, provenance, and semantic_extract modules
17 KiB
title, description, icon
| title | description | icon |
|---|---|---|
| Conflicts Module | Multi-source conflict detection and resolution — value, type, temporal, and logical conflicts with investigation guides. | triangle-exclamation |
semantica.conflicts detects and resolves contradictions when multiple sources disagree on the same fact. It surfaces five conflict types, seven resolution strategies, and generates investigation guides for manual review — so conflicts never silently corrupt your knowledge graph.
Why Detect Conflicts?
When you ingest data from multiple sources, contradictions are inevitable. One annual report says Apple's revenue was $391B; a financial newswire says $383B. Without conflict detection, both values land in your graph and queries silently return inconsistent answers.
Semantica's conflict detection makes disagreements explicit and actionable:
- Value conflicts — SEC says revenue is $391B; Reuters says $383B
- Type conflicts — "Python" is a
ProgrammingLanguagein one source, aSnakespecies in another - Temporal conflicts — a CEO had two different employers during overlapping date ranges
- Logical conflicts — an entity simultaneously holds two mutually exclusive properties
- Relationship conflicts — the same relationship has inconsistent cardinality or properties across sources
Exported Classes
| Class | Role |
|---|---|
ConflictDetector |
Detects value, type, temporal, logical, and relationship conflicts across entity pairs |
ConflictResolver |
Resolves conflicts with configurable strategy: voting, credibility_weighted, most_recent, first_seen, highest_confidence, manual_review |
ConflictType |
Enum: VALUE_CONFLICT, TYPE_CONFLICT, TEMPORAL_CONFLICT, LOGICAL_CONFLICT, RELATIONSHIP_CONFLICT |
ResolutionStrategy |
Enum of available resolution strategies passed to ConflictResolver |
SourceTracker |
Tracks which source contributed each property value on each entity |
ConflictAnalyzer |
Analyzes conflict patterns, severity distribution, and per-source statistics |
InvestigationGuideGenerator |
Generates step-by-step checklists for human review of unresolvable conflicts |
What You Get
Value, type, temporal, logical, and relationship conflict detection across all entity pairs. 7 resolution strategies including voting, credibility-weighted, and temporal preference. Track which source each conflicting fact came from, with per-source credibility scores. Pattern analysis, severity grouping, source-level statistics, and trend identification. Auto-generate step-by-step investigation checklists for human and expert review. `detect_conflicts()` and `resolve_conflicts()` for one-call workflows.Quick Start
```python from semantica.conflicts import SourceTrackertracker = SourceTracker()
tracker.set_source_credibility("sec_filings", 0.95)
tracker.set_source_credibility("pubmed", 0.92)
tracker.set_source_credibility("wikipedia", 0.80)
tracker.set_source_credibility("news_articles", 0.65)
```
detector = ConflictDetector()
conflicts = detector.detect_conflicts(kg)
print(f"Found {len(conflicts)} conflicts")
for conflict in conflicts:
print(f"[{conflict.conflict_type}] entity='{conflict.entity_id}' attr='{conflict.attribute}'")
print(f" Values: {conflict.values} Severity: {conflict.severity:.2f}")
```
analyzer = ConflictAnalyzer()
analysis = analyzer.analyze_conflicts(conflicts)
by_severity = analysis["by_severity"]
print(f"Critical: {len(by_severity.get('critical', []))}")
print(f"High: {len(by_severity.get('high', []))}")
print(f"Low: {len(by_severity.get('low', []))}")
```
resolver = ConflictResolver(source_tracker=tracker)
# Auto-resolve low-severity
auto_resolved = resolver.resolve_conflicts(
by_severity["low"],
strategy=ResolutionStrategy.CREDIBILITY_WEIGHTED,
)
# Generate investigation guides for critical conflicts
generator = InvestigationGuideGenerator()
for conflict in by_severity["critical"]:
guide = generator.generate_guide(conflict)
print(f"\n{guide.title}")
for step in guide.steps:
print(f" [{step.order}] ({step.priority.upper()}) {step.description}")
```
ConflictDetector
from semantica.conflicts import ConflictDetector
detector = ConflictDetector()
conflicts = detector.detect_conflicts(kg)
Detection Types
| Type | What It Detects | Example |
|---|---|---|
VALUE |
Same entity, same attribute, different values across sources | Revenue $391B vs $383B |
TYPE |
Same entity classified as different types | "Python" as Language vs Snake |
TEMPORAL |
Overlapping validity windows with contradictory facts | CEO at two companies simultaneously |
LOGICAL |
Facts that violate ontology axioms or SHACL constraints | is_alive=True but death_date set |
RELATIONSHIP |
Inconsistent relationship properties across sources | Edge weight 0.9 vs 0.3 from two sources |
Run targeted detection by type:
# Detect all types at once (default)
conflicts = detector.detect_conflicts(kg)
# Detect specific types only — faster for targeted checks
value_conflicts = detector.detect_value_conflicts(entities, "revenue")
type_conflicts = detector.detect_type_conflicts(entities)
relation_conflicts = detector.detect_relationship_conflicts(kg)
Key behaviours:
- Severity scores are computed from the magnitude of disagreement — a $8B revenue discrepancy scores higher than a $1M discrepancy
LOGICALconflicts require an ontology or SHACL schema to be loaded; without one, they are not detected- Detection runs in O(n·sources) time — it groups by entity+attribute and checks disagreement within each group
ConflictDetector Methods
| Method | Returns | Description |
|---|---|---|
detect_conflicts(kg) |
List[Conflict] |
Detect all conflict types at once |
detect_value_conflicts(entities, attribute) |
List[Conflict] |
Detect value disagreements on a specific attribute |
detect_type_conflicts(entities) |
List[Conflict] |
Detect type classification conflicts |
detect_temporal_conflicts(entities) |
List[Conflict] |
Detect overlapping validity window conflicts |
detect_logical_conflicts(kg) |
List[Conflict] |
Detect ontology/SHACL constraint violations |
detect_relationship_conflicts(kg) |
List[Conflict] |
Detect relationship property conflicts |
ConflictResolver
from semantica.conflicts import ConflictResolver, ResolutionStrategy
resolver = ConflictResolver()
results = resolver.resolve_conflicts(conflicts, strategy=ResolutionStrategy.VOTING)
for result in results:
print(f"Resolved '{result.attribute}' → {result.resolved_value}")
print(f" Strategy: {result.strategy} Confidence: {result.confidence:.2f}")
Choosing a Resolution Strategy
Weights each source's value by its assigned credibility score — favors authoritative sources automatically:```python
from semantica.conflicts import ConflictResolver, SourceTracker, ResolutionStrategy
tracker = SourceTracker()
tracker.set_source_credibility("sec_filings", 0.92)
tracker.set_source_credibility("wikipedia", 0.80)
tracker.set_source_credibility("news_articles", 0.65)
resolver = ConflictResolver(source_tracker=tracker)
results = resolver.resolve_conflicts(
conflicts,
strategy=ResolutionStrategy.CREDIBILITY_WEIGHTED,
)
```
Best for: sources with known reliability rankings (SEC > blog).
```python
results = resolver.resolve_conflicts(conflicts, strategy=ResolutionStrategy.VOTING)
```
Best for: 3+ sources with roughly equal credibility. When all sources have identical credibility scores, `CREDIBILITY_WEIGHTED` behaves identically to `VOTING`.
# First seen wins — for stable facts (founding date, original name)
results = resolver.resolve_conflicts(conflicts, strategy=ResolutionStrategy.FIRST_SEEN)
```
# Flag for human review — use with InvestigationGuideGenerator
results = resolver.resolve_conflicts(conflicts, strategy=ResolutionStrategy.MANUAL_REVIEW)
generator = InvestigationGuideGenerator()
for conflict in conflicts:
guide = generator.generate_guide(conflict)
print(f"{guide.title}")
for step in guide.steps:
print(f" [{step.order}] {step.description}")
```
Best for: high-stakes decisions (severity > 0.8), regulated data (HIPAA/SOX), and domain-specific ambiguity.
| Strategy | Enum | When to Use |
| -------- | ---- | ----------- |
| Majority vote | `VOTING` | 3+ sources with roughly equal credibility |
| Credibility-weighted | `CREDIBILITY_WEIGHTED` | Sources have different authority levels |
| Most recent | `MOST_RECENT` | Fast-changing facts: stock price, headcount, status |
| First seen | `FIRST_SEEN` | Stable facts: founding date, original name |
| Highest confidence | `HIGHEST_CONFIDENCE` | Extraction pipeline outputs confidence scores |
| Manual review | `MANUAL_REVIEW` | High-stakes decisions, regulated data |
| Expert review | `EXPERT_REVIEW` | Domain-specific ambiguity — escalate to a specialist |
Use the convenience aliases for shorter code:
from semantica.conflicts import voting, credibility_weighted, most_recent, highest_confidence
results = resolver.resolve_conflicts(conflicts, strategy=voting)
SourceTracker
from semantica.conflicts import SourceTracker
from datetime import datetime
tracker = SourceTracker()
tracker.set_source_credibility("sec_10k", 0.92)
tracker.set_source_credibility("wikipedia", 0.80)
tracker.track_property_source(
entity_id="apple_inc",
property_name="revenue",
value="$391B",
source="sec_10k_2023",
timestamp=datetime(2024, 1, 26),
)
sources = tracker.get_property_sources("apple_inc", "revenue")
for s in sources:
print(f"{s.source}: {s.value} (credibility: {s.credibility:.2f})")
chain = tracker.get_traceability_chain("apple_inc")
Key behaviours:
- Credibility scores default to 0.50 for any source not explicitly set
SourceTrackerstores property-level provenance — so you can trace exactly which source contributed each value
ConflictAnalyzer
from semantica.conflicts import ConflictAnalyzer
analyzer = ConflictAnalyzer()
analysis = analyzer.analyze_conflicts(conflicts)
patterns = analysis["patterns"]
by_severity = analysis["by_severity"]
source_stats = analysis["by_source"]
trends = analyzer.analyze_trends(conflicts)
print(f"Trend direction: {trends['direction']}") # "increasing" | "stable" | "decreasing"
print(f"Change: {trends['change_pct']:.1f}%")
Key behaviours:
analyze_conflicts()["patterns"]groups conflicts by attribute name and type — use it to find systemic data quality issuesanalyze_conflicts()["by_source"]flags sources with disproportionate conflict rates — a signal that a source's pipeline needs reviewanalyze_trends()compares conflict counts over time — a rising trend means a data source is degrading
InvestigationGuideGenerator
Auto-generate human-readable investigation checklists for conflicts requiring manual or expert review:
from semantica.conflicts import InvestigationGuideGenerator
generator = InvestigationGuideGenerator()
guide = generator.generate_guide(conflict)
print(f"Title: {guide.title}")
print(f"Context: {guide.context}")
for step in guide.steps:
print(f" [{step.order}] ({step.priority.upper()}) {step.description}")
print(f" → Verify: {step.check}")
Schemas
@dataclass
class Conflict:
id: str
entity_id: str # the entity involved
attribute: str # the conflicting property name
values: List[str] # conflicting values (one per source)
sources: List[str] # source IDs for each value
conflict_type: ConflictType # VALUE | TYPE | TEMPORAL | LOGICAL | RELATIONSHIP
severity: float # 0.0 (minor) to 1.0 (critical)
confidence: float # detection confidence 0–1
detected_at: datetime
metadata: Dict[str, Any]
from semantica.conflicts import ConflictType
ConflictType.VALUE_CONFLICT # revenue is $391B in source A, $383B in source B
ConflictType.TYPE_CONFLICT # "Apple" is ORGANIZATION in one source, PRODUCT in another
ConflictType.TEMPORAL_CONFLICT # overlapping validity windows with contradictory states
ConflictType.LOGICAL_CONFLICT # fact violates an ontology axiom or SHACL constraint
ConflictType.RELATIONSHIP_CONFLICT # inconsistent relationship properties across sources
@dataclass
class InvestigationGuide:
title: str # human-readable title for the conflict
context: str # summary of the disagreement
steps: List[InvestigationStep] # ordered checklist for the reviewer
@dataclass
class InvestigationStep:
order: int
description: str # what to do
check: str # specific fact or document to verify
priority: str # "high" | "medium" | "low"