Gold corpus and eval¶
This page is how we measure leftover risk. Unit tests prove that functions return the right shape. They do not prove that a real document still hides emails, cards, and names.
A gold-corpus is a set of documents with labeled personal spans. We run the package on those documents and compare what it hid with what the labels say should be hidden.
The product command run does not change. These scripts and tests sit beside it. Words used below are defined on Terminology.
This is not a legal privacy proof and not a HIPAA or GDPR certificate.
Goals¶
| Goal | Why |
|---|---|
| Measure completeness on public anonymization tests | Competitors publish recall and leak rate. We cannot claim quality on OCR, native PDF, or a later NER stage if leftovers on a gold set never fail a test. |
| Keep PR CI cheap and deterministic | Cloud API keys are forbidden in PR CI. Regex-only is the gate. A live language model is opt-in. |
| Fail the build when structured leftovers remain | The product already writes *.residual_pii.json. A report that nobody reads is not a gate. |
| Cover the sectors in Why Anonymize? | Healthcare, legal, government, research, finance, and enterprise are the jobs users bring. |
| Keep the large public files out of git | TAB, Presidio, and Gretel are downloadable. The installer writes them under data/gold-corpus/, which git ignores. |
What we measure¶
Scores follow the TAB split (mention vs entity, direct vs quasi). Definitions: leftover, gold-corpus, how we measure.
Honesty. The committed regex-only baseline is one run of this package’s regex stage. It is not a cross-tool ranking. Names and most legal quasi-identifiers stay in the clear until a language model or a later NER stage exists. Do not copy these numbers onto the README as marketing.
Regex-only on the full downloaded set (6,761 documents), stored in tests/eval/baselines/gold_corpus_regex_only.json:
| Profile | Mention F1 | Leftover | Structured leftover |
|---|---|---|---|
| regex-only | 0.262 | 0.576 | 0.039 |
| ner | — | — | not shipped (item 20) |
| detailed LLM | — | — | opt-in; not required in PR CI |
What is in the corpus¶
The catalog is tests/eval/sources.json.
| Source | Domain | In git? | Role |
|---|---|---|---|
Mini-tab (tests/eval/fixture.json) |
general | Yes | Tiny TAB-style fixture from item 13. Always in PR CI. |
Domain pack (tests/eval/domain_pack.json) |
healthcare, legal, government, research, finance, enterprise | Yes | Short labeled pages for the user sectors. Always in PR CI. |
| TAB | legal | No. Download. | Official GoldCorpus: English ECHR court cases. MIT. |
| Presidio synth_dataset_v2 | general | No. Download. | Public Presidio-class PII eval set. MIT. |
| Gretel PII Masking EN v1 (test) | many industries | No. Download. | 5,000 synthetic documents. Apache-2.0. |
| i2b2/n2c2, MIMIC, Kaggle PII, MAPA | healthcare, research, government | No | Need a login or a data-use agreement. Listed only. Not fetched. |
Downloaded files land in data/gold-corpus/raw/ and a normalized JSONL view in data/gold-corpus/normalized/. Git ignores /data/.
Workflows¶
1. Install the public tests¶
Default fetch: TAB test + dev, Presidio synth, Gretel test. Add --full for TAB train (about 48 MB extra).
2. Score the package (regex-only baseline)¶
This runs extract_entities_via_regex and anonymize_text_content(..., use_llm=False). It writes tests/eval/baselines/gold_corpus_regex_only.json. No API key is required.
3. Print the public eval table¶
The table is tests/eval/baselines/public_eval_table.md. NER is a placeholder until item 20. Live detailed scoring is --llm --model-name … and is not part of PR CI.
4. PR CI completeness gate¶
.github/workflows/ci.yml runs make test-cov. That job includes:
| Gate | What fails the build |
|---|---|
| System test | Structured mention recall below 1.0, or structured leftover above 0, on mini-tab + domain pack. |
| Red-team | *.residual_pii.json still contains a structured identifier. |
| Coverage | Line coverage below 70% (first measured run was 77%; the floor is not “90%”). |
| Fuzz | tests/test_fuzz.py: regex NER, mapping envelopes, PDF bytes, CSV bytes. A zero-page PDF must not look like a successful empty extract. |
The large downloaded sets are not required in PR CI. If they are present locally, an extra test checks that structured leftover on a sample stays at or under 10%.
5. Tiny fixture only¶
This scores tests/eval/fixture.json the same way as item 13. Use it when you only need the scorer, not the public corpus.
Layout¶
scripts/download_gold_corpus.py # install (gitignored data)
scripts/run_gold_benchmark.py # score + leftover
scripts/eval_public_table.py # regex vs NER vs LLM table
scripts/eval_tab.py # mini fixture only
tests/eval/gold.py # converters, leftover, gates
tests/eval/sources.json # catalog
tests/eval/domain_pack.json # committed use-case pages
tests/eval/fixture.json # mini-tab
tests/eval/baselines/ # committed scores, not the documents
tests/eval/test_completeness.py # CI leftover / recall / residual JSON
tests/test_fuzz.py # Hypothesis
data/gold-corpus/ # downloaded files (not in git)
See also¶
- Terminology — leftover, mention, quasi-identifier, TAB
- Recipes — the same commands in the recipe list
- Why Anonymize? — sectors the domain pack covers
- Improvement-plan item 19 (maintainers only, not on this site)