--- title: "Conflicts Module" description: "Multi-source conflict detection and resolution — value, type, temporal, and logical conflicts with investigation guides." icon: "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 `ProgrammingLanguage` in one source, a `Snake` species 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 SourceTracker tracker = 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) ``` ```python from semantica.conflicts import ConflictDetector 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}") ``` ```python from semantica.conflicts import ConflictAnalyzer 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', []))}") ``` ```python from semantica.conflicts import ConflictResolver, InvestigationGuideGenerator, ResolutionStrategy 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 ```python 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: ```python # 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 - `LOGICAL` conflicts 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 ```python 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). Majority vote — most common value across sources wins: ```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`. ```python # Most recent source wins — for fast-changing facts results = resolver.resolve_conflicts(conflicts, strategy=ResolutionStrategy.MOST_RECENT) # First seen wins — for stable facts (founding date, original name) results = resolver.resolve_conflicts(conflicts, strategy=ResolutionStrategy.FIRST_SEEN) ``` ```python from semantica.conflicts import InvestigationGuideGenerator # 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: ```python from semantica.conflicts import voting, credibility_weighted, most_recent, highest_confidence results = resolver.resolve_conflicts(conflicts, strategy=voting) ``` ## SourceTracker ```python 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 - `SourceTracker` stores property-level provenance — so you can trace exactly which source contributed each value ## ConflictAnalyzer ```python 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 issues - `analyze_conflicts()["by_source"]` flags sources with disproportionate conflict rates — a signal that a source's pipeline needs review - `analyze_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: ```python 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 ```python @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] ``` ```python 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 ``` ```python @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" ``` ## Tips and Common Pitfalls **Detect before you merge, not after.** Run conflict detection on raw entity data before deduplication and graph construction. Detecting conflicts in a live graph that already contains merged entities is harder — you lose the original source attribution. **Always set credibility scores.** The default credibility is 0.50 for all sources. Without explicit scores, `CREDIBILITY_WEIGHTED` behaves identically to `VOTING`. The power of this strategy is in the differentiation. **Don't auto-resolve everything.** Use `MANUAL_REVIEW` for conflicts with severity > 0.8 — high severity means the disagreement is large and the stakes of getting it wrong are high. **LOGICAL conflicts need a schema.** `detect_type_conflicts()` and `LOGICAL` detection only work if an OWL ontology or SHACL schema is loaded. Without one, `detect_conflicts()` will skip those types silently. **Use `analyze_sources()` to identify bad data feeds.** A single source causing 80% of your conflicts is a data quality problem upstream, not a conflict to resolve record by record. Flag it and investigate the source pipeline. **Severity is relative, not absolute.** A 0.5 severity score on a $1B revenue discrepancy and on a minor label difference both score 0.5 — the number reflects the disagreement structure, not the business impact. Domain context determines what to prioritize. **Combine with provenance.** The `SourceTracker` feeds directly into the [Provenance](provenance) module's audit trail. If you need to explain how a resolved value was chosen, provenance records give you the full chain. Resolve duplicate entities before conflict detection. Logical conflicts use SHACL shapes and ontology axioms. Track which source each conflicting fact came from. The graph being checked for conflicts.