Pramiti Docs
Packages

Merger Reconciler

Cross-ontology class matching, conflict classification, and resolution for M&A

pramiti-merger-reconciler matches and reconciles data models from different organizations during M&A integration. It identifies overlapping concepts, classifies conflicts, and suggests resolutions — with optional LLM-powered semantic similarity.

Install

pip install pramiti-merger-reconciler

Quick Start

from pramiti_merger_reconciler import ClassSpec, match_classes, classify, suggest
from pramiti_merger_reconciler.models import ClassConflict

# Define classes from two organizations
classes_a = [
    ClassSpec(class_name="Revenue", definition="Net revenue after discounts"),
    ClassSpec(class_name="Customer", definition="Active paying customer"),
]
classes_b = [
    ClassSpec(class_name="Revenue", definition="Gross revenue before discounts"),
    ClassSpec(class_name="Client", definition="Any customer with an account"),
]

# Match classes across ontologies
matches = match_classes(classes_a, classes_b)

# Classify and suggest resolutions
for m in matches:
    conflict_type = classify(m)
    proposal = suggest(ClassConflict(m, conflict_type))
    print(f"{m.class_a.class_name} ↔ {m.class_b.class_name}: {conflict_type}")
    print(f"  Suggestion: {proposal}")

The 4-Step Matching Algorithm

The match_classes() function uses a 4-step algorithm:

  1. Exact name match (score=1.0) — Classes with identical names
  2. Normalized name match (score=0.9) — Case-insensitive with suffix stripping (e.g., "CustomerData" matches "customer")
  3. Semantic LLM similarity (score=0.5-0.85, threshold=0.7) — Optional LLM-powered semantic comparison, capped at max_similarity_pairs
  4. Unmatched residuals — Classes that have no match in the other ontology
# Without LLM (fast, deterministic)
matches = match_classes(classes_a, classes_b)

# With LLM (more accurate for semantic similarity)
from my_adapter import MyLLMAdapter
matches = match_classes(classes_a, classes_b, llm=MyLLMAdapter(), max_similarity_pairs=200)

API Reference

ClassSpec

@dataclass
class ClassSpec:
    class_name: str        # Class name
    definition: str        # Business definition
    properties: list = []  # Optional list of properties

MatchResult

@dataclass
class MatchResult:
    class_a: ClassSpec
    class_b: ClassSpec
    match_type: str        # "exact", "normalized", "semantic", "unmatched"
    score: float           # 0.0 to 1.0

Conflict Classification (classify())

Classifies the nature of a match conflict:

  • identical — Exact/normalized match, same source tables
  • compatible — High-score match, compatible property sets
  • structural_conflict — Same concept, disjoint source tables
  • semantic_conflict — Similar name, incompatible definitions or tables
  • missing — Class exists only in one workspace

Resolution Suggestions (suggest())

Canned text for identical / compatible / missing. LLM-assisted (or "manual review required") for semantic_conflict and structural_conflict.

ILLMAdapter (Interface)

class ILLMAdapter(ABC):
    def compute_similarity(self, text_a: str, text_b: str) -> float: ...

The NoOpLLMAdapter returns 0.0 for all comparisons, effectively disabling semantic matching.

Technical Details

  • Name normalization strips common suffixes: data, record, table, entity, type, class, model, info, detail
  • LLM call count is bounded by max_similarity_pairs to control costs
  • The algorithm is deterministic when no LLM is used — same inputs always produce same outputs
  • The ReportSummary model provides aggregate statistics for the reconciliation: total matches, conflicts by type, resolution suggestions

On this page