Current

Entity resolution with explicit uncertainty

Benchmark first

Corpora: DocRED · WDC Products · KILT · QASC

Protocol: Measure blocking pairs completeness and reduction ratio, entity pair/cluster F1, relation micro-F1, provenance precision/recall, and multi-hop answer accuracy. Then run graph-off and graph-on retrieval with identical seeds to attribute recall gains. Every projected passage must retain its source node and path.

The cascade spends expensive work only after cheap deterministic checks. It never converts an ambiguous candidate into a merge without a configured threshold or review decision.

How it works

Block candidates by tenant, scope, and entity type; compare normalized exact aliases; calculate field-agreement and fuzzy scores; retrieve a small embedding neighborhood only for unresolved candidates; then apply separate link and review thresholds. Scores above link become a proposed canonical ID, scores in the review band retain all candidates and their feature trace, and lower scores remain distinct entities.

scope + type block*→normalized exactfield/fuzzy scoreembedding candidates→*link · reject · review

resolution.py
from mari_components.graph import FieldAgreement, ResolutionDecision, resolve_entity

resolution = resolve_entity([
    FieldAgreement(field="email", agrees=True,
        match_probability=0.99, nonmatch_probability=0.01),
    FieldAgreement(field="name", agrees=False,
        match_probability=0.90, nonmatch_probability=0.20),
], link_threshold=4.0, review_threshold=1.0)

if resolution.decision is ResolutionDecision.REVIEW:
    review_queue.put(candidate, resolution.contributions)