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 exact→field/fuzzy score→embedding candidates→*link · reject · review
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)