Files
semantica/docs/reference/conflicts.md
T
Mohd Kaif 5d70d0c10d docs: replace Exported Classes import blocks with summary tables (all 25 modules) (#567)
* 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
2026-05-24 15:49:58 +05:30

17 KiB
Raw Blame History

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 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

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
  • 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

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:

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
  • SourceTracker stores 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 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:

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 01
    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"

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.