Open-source Python library

Are these the same thing?

Two records, or two documents, spelled differently, sharing an id. arche reads the fields out of the text, says whether they are one thing, shows the evidence, says review when it should, and keeps a receipt you can replay next year.

Get startedRead how it works

Fellegi-Sunter computes the probability. arche reads the documents, gates the merge and keeps the receipt.

terminal
$ pip install arche-core
$ arche compare --text --json - \
    "Adesola Okonkwo, NIN 12345678901, adesola@example.com" \
    "Adesola E. Okonkwo, NIN 12345678901, 124 Maple Street"

{
  "identity": "same_entity",
  "action": "merge",
  "basis": "corroborated",
  "explanation": "national ID match; name similarity 80%",
  "factors": {"name": 0.8, "national_id": 1.0, "name_tf": 0.7233},
  "decision_id": "dec:sha256:8912e7da95835995ea26b78045221e…"
}

It reads the documents

A bank statement, an invoice and a payslip in; one record per document out, with the fields arche read and where it read them; each resolved against the others. Plain text, PDF, DOCX and scans, on your machine.

It refuses to guess

review is a real answer. Two identical strings that are ordinary words are held apart, and the page says why. No jurisdiction it can infer, no statute that covers the country, no distinctive agreement: each comes back as its own answer, never as a verdict dressed up.

Every decision has an id

decision_id is a content hash over the evidence and the pinned versions. Same inputs, same id, byte for byte. Look it up, explain it, replay it, sign it, hand it to someone who does not trust you.

The law is attached

detect_pii returns every span with the statute section it falls under. deidentify returns the copy the statute permits. A redaction under the wrong law looks finished and is not, so arche refuses when the evidence for the jurisdiction is thin.

Built for

Supplier onboarding

A vendor form, a bank statement and a registry extract that spell one company three ways. Resolve them to one record with the evidence, and keep the receipt for the audit.

Delivery addresses

The blue gate behind Elim Pharmacy, 124 Elim Streat. A verified endpoint when the evidence is strong, one short question when it is close, an honest refusal when it is weak.

Public registers

Schools, clinics and companies across two lists that disagree on spelling, coordinates and ids. Batch resolution with Splink underneath when the batch is large enough to train it.

Data handed to a model

What is in this text, under which law, and what may leave the machine. A fail-closed guard in front of any provider, and an MCP server so an agent asks before it sends.

The same, from Python

Three fragments of text mention someone. They share a national id and a name, once with a middle initial, disagree on an email, and none of the addresses match. Same person?
import arche

text1 = "Adesola Okonkwo, NIN 12345678901, address: 123 Maple Street, adesola@example.com"
text2 = "Adesola Okonkwo, NIN 12345678901, adesola@gmail.com, address: 124 Maple Street"
text3 = "Adesola E. Okonkwo, NIN 12345678901, adesola@gmail.com, address: 231 Elim Street"

ledger = arche.attach("duckdb:///:memory:")            # a file path keeps it
person = dict(entity="person", jurisdiction="NG", backend="basic", store=ledger)

r12 = arche.compare(text1, text2, **person)
r13 = arche.compare(text1, text3, **person)
r23 = arche.compare(text2, text3, **person)
print(r12.identity, r12.action, "|", r23.identity, r23.action)

(entity,) = ledger.entities()                          # three texts, one person
print(entity.shared, entity.conflicts)
print(ledger.replay(r12.decision_id).reproduced)       # the same decision, again

safe = arche.deidentify(text1, jurisdiction="NG", backend="basic")
print(safe.text)                                       # the statute chose each rendering
same_entity merge | same_entity merge
{'national_id': '12345678901'} {'email': ['adesola@example.com', 'adesola@gmail.com'], 'full_name': ['Adesola Okonkwo', 'Adesola E. Okonkwo']}
True
NAME_f71c6342 NAME_925a28e1, NIN [NIN], address: [ADDRESS], EMAIL_3f6caee6

identity is what arche believes: the same person, because a shared national id is distinctive. action is what it recommends: merge, because the name corroborates the id; on a national id alone it would say hold. The email the records disagree on is not averaged away, it sits in conflicts for whoever acts on the entity. The ledger noticed that three pairwise answers describe one person, kept the receipts, and can make any of them again. The last line is the copy the statute permits, from the same detectors.

Documentation

Every example on these pages is run against the installed package before it is published.

Splink is the better matcher and arche uses it: on Febrl 4, on Splink's own 50k historical set and on a Nigerian school register, Splink wins, and backend="auto" hands it the scoring above a thousand records. arche is what sits around the score: the evidence, the gate, the id, the receipt. The benchmarks include the runs where arche loses. arche is pre-1.0; do not make production decisions about personal data with it without your own privacy, security, legal and accuracy review.