- hank-safe-harbor β HIPAA Safe Harbor PHI De-identifier + Consistent Faker (small Β· local Β· CPU or β€24 GB GPU)
- TL;DR
- What "leak" means here (the honest metric)
- Headline benchmark (synthetic beds, one scorer for every system)
- Independent public benchmark β ASQ-PHI
- Coref + faking fidelity (LFF β the differentiator)
- How it works (the shipped pipeline)
- Deployment
- Usage
- Limitations & out-of-scope (read this)
- Evaluation scope & roadmap
- Provenance & licensing
- TL;DR
hank-safe-harbor β HIPAA Safe Harbor PHI De-identifier + Consistent Faker (small Β· local Β· CPU or β€24 GB GPU)
A small, fully-local, open clinical PHI tool that doesn't just blank out
[REDACTED]β it rewrites every identifier into a consistent, type-faithful fake so the note stays readable, and it reports an honest end-to-end leak metric (the real value's verbatim survival in the final faked text, measured against ground truth β never a recall-path proxy). Detects competitively with the best open clinical encoders, runs on one β€24 GB consumer GPU with zero PHI egress, and is the smallest open neural detect-and-consistently-fake pipeline we know of with a ground-truth leak metric.
β οΈ Read the scope honestly: all numbers below are measured on synthetic clinical notes (we have no licensed real-clinical corpus yet β see Evaluation scope). Recognized public-benchmark numbers (i2b2/n2c2) and a real-clinical result (PhysioNet) are in progress, not yet claimed.
TL;DR
- One system: an ensemble of two encoder NERs β
roberta-large(English/Latin + diacritics) βͺxlm-roberta-large(multilingual; non-Latin scripts) β feeding a deterministic coref + consistent-faker apply layer. (A generative path existed in development; it is not shipped in v1 β it scored below this ensemble and wasn't portable off Apple Silicon.) - Recall β₯ 0.97 and per-value true-leak β€ 0.03 on every (synthetic) bed, flat, no per-bed spike (all systems scored by one committed scorer on one denominator β non-Latin values included).
- Runs on one β€ 24 GB consumer GPU (encoders ~1.8 GB at fp16; CPU-capable). Zero PHI egress.
- We do NOT claim raw-detection-F1 SOTA. A strong clinical encoder (Stanford) edges us on one bed; we own it. The contribution is the combination: local, open, detect and consistent faking, with an honest ground-truth leak metric.
- Evaluated on synthetic data only (so far). Public-benchmark (i2b2/n2c2) and real-clinical (PhysioNet) results are planned; see Evaluation scope & roadmap.
What "leak" means here (the honest metric)
Leak = a real ground-truth PHI value surviving verbatim in the final faked text, scored against
the ground-truth values (not against the model's own detections β that would be tautological), and
counted per distinct (type, value). This is what a downstream reader of the de-identified note would
actually be exposed to. No non-shipping crutch (fail-closed gate, occurrence-propagation bridge, or a
post-hoc recall-union outside the published pipeline) is added to flatter it; the structural recall-union
described under How it works ships and is counted as part of the pipeline. The numbers are the raw
shipped pipeline's output.
Headline benchmark (synthetic beds, one scorer for every system)
Every system below is scored by one committed, reproducible scorer
(scripts/rebench_apples.py β benchmark/results/rebench_head_to_head.json) on one GT denominator
per bed β normalize-only dedup with non-Latin (CJK/Greek/Thai) values included (an earlier
internal harness used a gate that silently dropped them; this does not). Beds (note counts):
in-dist 120 Β· fresh-OOD 36 Β· holdout-2 (intl) 30 Β· Nemotron 180. Small β treat single-bed deltas as
indicative, not statistically significant (bootstrap CIs planned). All four are synthetic, including
Nemotron (NVIDIA-generated synthetic PII), not real de-identified clinical records.
Our ensemble β recall + true end-to-end leak (verbatim GT-value survival in the faked text):
| bed | recall | true-leak |
|---|---|---|
| in-dist | 0.9947 | 0.0080 |
| fresh-OOD | 0.9746 | 0.0254 |
| holdout-2 (intl) | 0.9904 | 0.0096 |
| Nemotron | 0.9864 | 0.0123 |
Detection recall vs open clinical encoders (same beds/scorer; obi & Stanford are detect-only, so their "leak" is the redact-all floor = 1 β recall, not a faked-text leak):
| bed | ours | obi | Stanford |
|---|---|---|---|
| in-dist | 0.9947 | 0.9754 | 0.9697 |
| fresh-OOD | 0.9746 | 0.9329 | 0.9389 |
| holdout-2 | 0.9904 | 0.8798 | 0.8713 |
| Nemotron | 0.9864 | 0.9632 | 0.9905 |
Stanford wins Nemotron β disclosed. We lead on the other three, and the largest gap is on holdout-2, the international bed: 0.990 vs 0.88/0.87 β and this is now an honest win: every system is scored on the same gt=940 denominator that includes the 65 non-Latin (CJK/Greek/Thai) values the English encoders miss and our XLM-R member catches. (n=30 β indicative, not significant.)
Fair-fight vs the real open clinical peer (riggsmed/deid-LONGFORMER-NemPII). Run through the
same scorer/denominator as us (detect β consistent faker): we beat it 12β30Γ on end-to-end leak
on the three beds outside its training distribution β and, critically, even on Nemotron, riggsmed's
own training distribution, detection is a tie (ours 0.986 vs 0.988) and we still leak less (0.012 vs
0.015). Off its distribution riggsmed behaves like a general-PII detector (recall 0.70β0.79). Per-bed
leak: ours 0.008/0.025/0.010/0.012 vs riggsmed 0.224/0.317/0.286/0.015. (benchmark/results/rebench_head_to_head.json.)
Context β vs a general-PII baseline (Microsoft Presidio + Faker). Not a clinical tool (clinical recall 0.72β0.93 here), so a weak-baseline reference rather than a peer (measured on the earlier scorer, not re-run on the unified denominator): end-to-end faked-text leak roughly 0.09β0.29 vs our 0.008β0.025 β an order of magnitude, but the riggsmed fair-fight above is the meaningful comparison.
Reproducible from scripts/rebench_apples.py β benchmark/results/rebench_head_to_head.json. (The earlier
writeup docs/results/2026-06-18-phi-detection-benchmark-h2h.html predates this unified re-measure.)
Independent public benchmark β ASQ-PHI
ASQ-PHI (MIT) is a third-party benchmark of 1,051 synthetic clinical search queries (832 PHI-positive + 219 hard negatives) β a different distribution from our training notes, and it shares our policy that age < 90 is not PHI. We had never seen it.
| system | recall (832 pos) | over-redaction (219 hard negatives) |
|---|---|---|
| ours (ensemble) | 0.966 | 2.3 % (5/219) |
| obi/deid_roberta_i2b2 | 0.997 | 89.5 % (196/219) |
| StanfordAIMI | 0.996 | 26.9 % (59/219) |
| AWS Comprehend Medical* | 0.968 | ~89.5 % |
*Comprehend = ASQ-PHI authors' own published baseline (validation_results/, threshold 0.3; cite-only,
no API keys). obi / Stanford / ours re-run by us on the same beds. (ASQ is English-only β 0 of its 2,973
GT values are non-Latin β so its scorer and the unified scorer above share the same denominator.)
Honest read: obi and Stanford detect ~3 points more PHI than us on these short queries β but they do
it by over-redacting 27β90 % of the zero-PHI hard negatives (flagging age/diagnoses), which destroys
query utility β the exact "Safe Handoff" failure ASQ-PHI was built to expose. We sit at a far better
point on that recall-utility tradeoff: recall on par with Comprehend (0.966 vs 0.968) while
over-redacting 2.3 % vs ~90 %. Our raw detection recall is not SOTA on this set β we own that; our
utility is. (benchmark/results/asq_phi_head_to_head.json.)
Coref + faking fidelity (LFF β the differentiator)
Measured on the actual faked output (in-dist, n=40): type-fidelity 0.985 (n=904 aligned spans); NAME/FACILITY consistency 0.955 (HOSPITAL 1.0 β one real facility β one fake across OCR/case variants; names 0.947); distinctness 0.884. Format-realism 1.0 but mostly tautological β only ~10 % of spans (EMAIL/IP/URL/ADDRESS) use independent validators; the rest are by-construction or weak (name = alpha-token only). Disclosed per-type in the JSON.
Over-redaction (false-positive faking) = 0.177 β about 1 in 6 faked spans is non-PHI text the recall-first design rewrote rather than risk a leak. This is a deliberate recall-over-precision tradeoff; it can rewrite some non-PHI content. Measured and reported; a tags-only (no-rewrite) mode and a utility-loss metric are planned.
How it works (the shipped pipeline)
- Detect β union of two encoder NERs:
roberta-large(English/Latin + diacritic-hardened) βͺxlm-roberta-large(multilingual; closes non-Latin scripts). The union beats either encoder alone on every bed. - Structural recall-union β a set of high-precision syntactic detectors (EMAIL/URL/IP/SSN/ PHONE/FAX/DATE/MRN/ID-token formats) is unioned in to catch well-formed identifiers the model missed. This ships and is part of the reported recall; it is a syntactic recall-union, not a semantic crutch. A model-only vs model+structural ablation (to quantify each component's recall contribution) is planned.
- Coref + apply layer β group mentions of one entity (deterministic, shared-significant-token)
and replace each with a consistent, type-faithful, format-preserving fake (facility/name/date/
ID handlers). No
[REDACTED]holes.
Deployment
- Footprint: two encoders (
roberta-large355 M +xlm-roberta-large550 M) β 1.8 GB at fp16 (~3.6 GB fp32 on disk). Comfortably within a single β€ 24 GB consumer GPU; CPU-capable. - Throughput (Apple-MLX dev box; a discrete GPU is faster): ~2,200β3,400 notes/hr; ~1.0β1.8 s/note.
- Cost anchor β $35 / 1 M notes on a 4090 (re-derivable), vs cited cloud list prices (AWS β $14.5k, Azure β $13.1k / 1 M). Zero PHI egress.
Usage
Install the hank-safe-harbor engine plus a
device-appropriate inference backend (so CPU users never pull CUDA):
pip install "hank-safe-harbor[onnx]" # CPU, lightest (~40 MB rt) β Linux/Railway
pip install "hank-safe-harbor[onnx-gpu]" # NVIDIA CUDA
pip install "hank-safe-harbor[torch]" # Mac/MPS, or CUDA via torch
# (until on PyPI: pip install "hank-safe-harbor[onnx] @ git+https://github.com/hank-ai/hank-safe-harbor")
from hank_safe_harbor import SafeHarbor
deid = SafeHarbor.from_pretrained() # default model, downloaded on first use
# or an explicit repo id: SafeHarbor.from_pretrained("hank-ai/hank-safe-harbor")
out = deid.deidentify(note_text) # -> {"deid_text", "spans", "mapping", ...}
# point at a local clone, force a backend, or list registered variants:
# deid = SafeHarbor.from_pretrained("./hank-safe-harbor", backend="onnx")
# from hank_safe_harbor import list_models; list_models()
The bundle ships each encoder as both model.safetensors (torch) and model.onnx
(onnxruntime); from_pretrained auto-selects whichever backend you installed.
Limitations & out-of-scope (read this)
- Evaluated on synthetic data only (so far). Every number above is on synthetic notes (incl. Nemotron, which is NVIDIA-generated synthetic PII β not real de-identified records). For a clinical tool the audience cares most about real-note performance; we are pursuing PhysioNet (real-clinical) and i2b2/n2c2 (the recognized public benchmark) β see roadmap. Until those land, read the numbers as "strong on synthetic clinical text," not a real-world or SOTA claim.
- Not raw-detection-F1 SOTA. Strong English clinical encoders beat us on some beds; cloud systems may too. Our claim is the local + open + detect+fake + honest-leak combination.
- Prior art exists for detect+fake. Consistent-surrogate de-identification is not new (CliniDeID, PhysioNet De-ID, Stanford's hide-in-plain-sight). Our specific contribution is the smallest open neural pipeline doing it locally with a ground-truth leak metric β not "the only" tool that fakes.
- Over-redaction ~0.18 (false-positive faking) is the cost of recall-first; it rewrites some non-PHI. Measured and reported above.
- Leak is not zero. ~1β3 % per-value survival on these beds sits inside the cited Carrell HIPS 1β6 % band (context, not a superiority claim). Consistent faking is also vulnerable in principle to a Carrell-style "parrot" re-identification attack (attenuates, does not eliminate); an explicit parrot-attack audit is planned.
- Ages are NOT treated as PHI (including 90+) β a deliberate, documented deviation from HIPAA Safe Harbor for clinical utility; dates ARE redacted/faked. Disclosed up front.
- Small beds (tens to ~180 notes) are high-variance; bootstrap CIs are being added. Cloud competitors are cite-only (no API keys).
Evaluation scope & roadmap
- Now (v1): synthetic beds (above) + an apples-to-apples open-encoder head-to-head, all re-run through one scorer.
- Done: apples-to-apples fair-fight vs the
riggsmedclinical detect+fake peer + the independent ASQ-PHI public benchmark (both above), all re-run through one scorer. - In progress: TAB (recognized anonymization benchmark, off-domain cross-check); bootstrap CIs on every row.
- Planned (real-clinical): PhysioNet de-id gold corpus (real clinical text).
- v1.1: i2b2/n2c2 2014 strict-entity micro-F1 (official scorer), vs obi/Stanford, when the data portal reopens. We will report the full entity/token Γ full/HIPAA grid, not a single inflated number.
Provenance & licensing
Trained on synthetic clinical notes (teacher-distilled, schema-validated, decontaminated against
all evaluation beds); no real patient data was used in training or evaluation. Base models
(roberta-large, xlm-roberta-large) and their licenses are listed in NOTICE. Released under
Apache-2.0 (see LICENSE). Eval harness + per-bed/per-type result JSONs in benchmark/results/;
every metric here is an observed value from those files β none fabricated.