Instructions to use divergentlabs/masker with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use divergentlabs/masker with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="divergentlabs/masker")# Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("divergentlabs/masker") model = AutoModelForTokenClassification.from_pretrained("divergentlabs/masker", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Masker (v2)
masker is a multilingual token classifier for personally identifiable information (PII) in 23 European languages. It is the neural half of a two-part redaction system. This model tags contextual PII: names, addresses, ages and dates.
A separate, dependency-free rules layer handles structured PII (IBANs, cards, national IDs) with real checksum validation. Where both fire on the same span, the checksum-validated rule wins. Everywhere else, the model decides. This repository is the neural half and the full-accuracy reference model of the family.
📱 Need something small enough to run on a phone or in a web browser? See masker-mini, a 6-layer distillation shipped as ONNX and 4-bit Core ML, down to ~18 MB.
What's new in v2
v2 is about person names in real-world text. v1 was trained only on synthetic data. It scored 0.98 strict F1 on that data but missed nearly half of the name characters in real English court judgments.
| out-of-distribution names | v1 | v2 |
|---|---|---|
| names F1 (mean of both) | 0.767 | 0.938 |
| TAB (EN legal) leak recall | 0.552 | 0.912 |
| TAB strict F1 | 0.377 | 0.866 |
| CoNLL-2002 NL leak recall | 0.796 | 0.963 |
| CoNLL-2002 NL strict F1 | 0.718 | 0.915 |
Two changes in the training data made the difference:
- Name-form augmentation. openpii writes every person as "Given Surname". Real text mostly doesn't: 41% of v1's misses were bare surnames ("Price said…") and 37% were initials ("R. Ryssdal", "A.B. Baka"). v2 rewrites openpii name pairs into initials, title + surname ("mevrouw De Vries"), and bare-surname forms in all 23 languages, following each language's conventions (for example, Dutch tussenvoegsel capitalisation).
- Real annotated text. v2 adds 293K sentences of human-annotated NER in 14 languages (listed under Credits). Person annotations are used as gold. The other entities (companies, places, works) teach the model which capitalised words are not people.
Dutch improved as much as English even though no real Dutch text was in the mix. The gain transferred from augmentation and the other languages.
Also changed:
- v2 keeps mDeBERTa's full 250K vocabulary. v1 pruned it to the tokens in its synthetic training corpus. On real text, rare pieces matter: a 64K prune of v2 cost 3 points of out-of-distribution names F1. The weights are bfloat16 (~557 MB).
- Same 12 entity types and label map as v1, so it's a drop-in replacement. v1 is
kept under the
v1tag.
Model type & training
Masker is a DeBERTa-v3 token classifier (278M parameters) fine-tuned from
microsoft/mdeberta-v3-base
with boundary-first BIOES supervision. It was trained for 1 epoch on 1.44M
rows: name-form-augmented
ai4privacy/pii-masking-openpii-1m
plus the real-text corpora. In the real text, person spans come from the gold
annotations (split into given name and surname by masker v1, or by rule), and the other
PII types are pseudo-labelled by masker v1.
The head predicts 12 entity types (48 BIOES labels + O):
GIVEN_NAME, SURNAME, CITY, STREET_NAME, BUILDING_NUMBER, ZIP_CODE,
PHONE, EMAIL, CREDIT_CARD, DATE, AGE, GOVERNMENT_ID.
GOVERNMENT_ID covers passport, national-ID, SSN, tax and driver-license
numbers; the rules layer tells them apart by checksum and format. Other
structured types (IBAN, IP, URL, etc.) are owned entirely by the rules layer and
are not part of this head.
Usage
from transformers import AutoTokenizer, AutoModelForTokenClassification
import torch
tok = AutoTokenizer.from_pretrained("divergentlabs/masker")
model = AutoModelForTokenClassification.from_pretrained("divergentlabs/masker").eval()
text = "Kundin Beatrix Möller, geb. 04.07.1979, Rosenweg 8, 50667 Köln."
enc = tok(text, return_tensors="pt", return_offsets_mapping=True)
offsets = enc.pop("offset_mapping")[0]
with torch.no_grad():
labels = model(**enc).logits.argmax(-1)[0]
for (a, b), lab in zip(offsets.tolist(), labels.tolist()):
if b > a and model.config.id2label[lab] != "O":
print(text[a:b].strip(), "->", model.config.id2label[lab])
The raw output is per-token BIOES labels. The companion mask package turns
them into character spans and merges them with the rules layer. The tokenizer's
offsets include the leading space of word-initial pieces, so trim whitespace
from span edges.
Evaluation
Out-of-distribution: person names on real text
These scores come from real documents that neither masker nor redact trained on. Metrics are person-level (given name + surname merged into one span) and character-exact.
- TAB: the Text Anonymization Benchmark, 127 English ECHR court judgments.
- CoNLL-2002 NL: Dutch news, test split. Used for evaluation only.
| model | names F1 (mean) | TAB overlap F1 | TAB leak recall | CoNLL NL overlap F1 | CoNLL NL leak recall | CoNLL NL false-person rate |
|---|---|---|---|---|---|---|
| masker v2 | 0.938 | 0.949 | 0.912 | 0.928 | 0.963 | 2.1% |
| masker v1 | 0.767 | 0.707 | 0.552 | 0.827 | 0.796 | 4.5% |
| masker-mini v2 | 0.774 | 0.833 | 0.840 | 0.716 | 0.897 | 16.4% |
| nationaldesignstudio/rampart | 0.690 | 0.769 | 0.757 | 0.611 | 0.743 | 11.0% |
| desert-ant-labs/redact | 0.626 | 0.498 | 0.361 | 0.755 | 0.794 | 7.3% |
redact v0.4.0 was run through its own SDK pipeline (min confidence 0.6 plus its rules).
rampart v0.1.3 was run through its own SDK (createGuard().detect() with its
default policy, the spans protect() redacts). On long documents it returns some
paragraph-sized spans, so its TAB strict F1 is only 0.04 and the overlap figures
above flatter it.
- Leak recall is the fraction of gold name characters that get redacted.
- False-person rate is the share of other named entities (companies, places) wrongly tagged as a person.
In-distribution: openpii-1m validation
These are span-level, boundary-exact scores on 8,000 synthetic openpii validation documents.
| metric | v2 | v1 |
|---|---|---|
| Strict span F1 | 0.980 | 0.982 |
| Typed F1 | 0.994 | 0.995 |
| Typed precision | 0.994 | 0.994 |
| Typed recall | 0.995 | 0.996 |
| Leak-safe recall | 0.9995 | 0.9996 |
Per-type strict F1
| entity | F1 | entity | F1 |
|---|---|---|---|
| 1.000 | CITY | 0.995 | |
| DATE | 0.999 | STREET_NAME | 0.993 |
| PHONE | 0.999 | BUILDING_NUMBER | 0.992 |
| GOVERNMENT_ID | 0.999 | AGE | 0.985 |
| CREDIT_CARD | 0.998 | GIVEN_NAME | 0.932 |
| ZIP_CODE | 0.997 | SURNAME | 0.923 |
v2 gives up 0.2 points of strict F1 on synthetic text, all of it on name boundaries, in exchange for +17 points of names F1 on real text. Synthetic openpii and real corpora don't always agree on where a name span starts and ends.
Limitations & biases
- The out-of-distribution sets cover English legal text and Dutch news only. Other languages were trained on real text but have not been measured out-of-distribution. Validate on your own data before relying on the model.
- The remaining TAB misses are mostly partial spans: overlap F1 is 0.949 but strict F1 is 0.866.
- Not a substitute for review in high-stakes settings. No detector is perfect, so design for residual leakage.
Credits & attribution
This model is a derivative work and would not exist without:
- Backbone:
microsoft/mdeberta-v3-baseby Microsoft, MIT License. DeBERTaV3: He, Gao & Chen, 2021 (arXiv:2111.09543). - Synthetic training data:
ai4privacy/pii-masking-openpii-1mby Ai4Privacy, CC-BY-4.0. - Real-text training data:
- Universal NER: en_ewt, da_ddt, pt_bosque, sk_snk, sr_set, sv_talbanken. Mayhew et al., 2024. CC-BY-SA-4.0
- GermEval 2014 (de) and AnCora (es), via the OpenNER standardized collection. CC-BY-4.0
- SUC-X 3.0 (sv), CC-BY-4.0
- KPWr (pl), CC-BY-3.0
- EstNER (et), CC-BY-4.0
- RONEC (ro), MIT
- hr500k (hr), CC-BY-SA-4.0
- Turku NER corpus (fi), CC-BY-SA-4.0
- WikiNER-fr-gold (fr), CC-BY-4.0
- Evaluation only: TAB (MIT) and CoNLL-2002 Dutch (Tjong Kim Sang, 2002).
Please retain these credits in downstream use.
License
Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
The underlying components keep their own terms, listed in Credits above.
Versions before v2 (the v1 tag)
were released under the Offchain Studio Source License, Version 1.0, and remain
under those terms.
Citation
@software{masker,
title = {masker: multilingual PII detection for 23 European languages},
year = {2026},
version = {2},
note = {DeBERTa-v3 token classifier, boundary-first BIOES supervision},
url = {https://huggingface.co/divergentlabs/masker}
}
- Downloads last month
- 38
Model tree for divergentlabs/masker
Datasets used to train divergentlabs/masker
ai4privacy/pii-masking-openpii-1m
bltlab/open-ner-standardized
Collection including divergentlabs/masker
Paper for divergentlabs/masker
Evaluation results
- Strict span F1 on pii-masking-openpii-1m (validation)self-reported0.980
- Typed F1 on pii-masking-openpii-1m (validation)self-reported0.994
- Leak-safe recall on pii-masking-openpii-1m (validation)self-reported1.000
- Person overlap F1 on TAB (ECHR court judgments, EN, test)self-reported0.949
- Person leak recall on TAB (ECHR court judgments, EN, test)self-reported0.912