PII Bench (piibench)

What it measures. Detection of personal data that has no fixed format — PERSON ORGANIZATION LOCATION ADDRESS DATE_TIME — in text shaped the way outbound traffic to AI assistants is shaped: JSON request bodies, XML, SQL, CSV, key=value pairs, log lines, Markdown tables and OCR output, as well as prose. Public PII benchmarks score prose; a model that is accurate on prose can still miss the same name when it sits in a JSON string value, and a prose-only benchmark cannot show it.

What it does not measure. Identifiers with a fixed format — email addresses, payment-card, IBAN and passport numbers — are excluded from scoring, because a regular expression resolves them exactly. A prediction that lands on such an identifier is not counted as a false positive. Touch rate reports how often a model marks those characters anyway; it is reported, never ranked. A touch rate of — means the dataset contains no excluded identifiers, so it was not measured — it is not zero, and the average skips it.

Protocol. 3,500 rows: 500 from each of seven third-party datasets (TAB, GermEval 2014, FactRuEval-2016, MEDDOCAN, IAHLT, Gretel, Nemotron), serialised into twelve carrier formats with every gold offset re-mapped so each span still covers the same substring. Precision, recall and F1 are computed over characters and are label-agnostic: a character counts as correctly detected when it is predicted as PII and lies inside a gold span of any scored type, so no entrant's label names are re-interpreted. Scores are micro-averaged within each dataset and then averaged across the seven, so no single dataset dominates. 95 % confidence intervals are percentile bootstrap intervals over rows, resampled within each dataset. Entrants are ranked by average F1 only, each at a pinned model revision, with the host and numeric precision of every run recorded beside its result.

Data and code. The rows, gold spans, per-dataset licences, the scoring code and every entrant's raw predictions are published as ScienceSoft/piibench. This page computes no metric of its own; it renders those result files. How to run the benchmark, below, reproduces any row or scores a new model.

Conflict of interest. piibench is built and published by ScienceSoft, which also develops one of the models scored here; rows prefixed scnsoft- are ScienceSoft's. On this board scnsoft-pii-encoder ranks first: its average F1 is +0.0233 above that of the strongest independent entrant, nvidia-gliner-pii (paired bootstrap over rows, 2,000 resamples, 95 % CI [+0.0147, +0.0322]). Weigh that knowing who published the board.

What that result is evidence of. It concerns one artefact — the published weights, revision 1c1e5be8cbe359c0, trained with one random seed — not the training recipe. The recipe was trained with three seeds, and each run was scored through the same production inference engine (the -engine-raw path). Against the same reference, only one of the three clears it: seed 1234, the released model, +0.0192 [+0.0105, +0.0278]; seed 4321, +0.0057 [−0.0028, +0.0145]; seed 7777, +0.0011 [−0.0080, +0.0103]. The released model is therefore the upper end of the recipe's observed spread, and another training run of the same recipe would not be expected to be separably ahead of the reference. The two other seeds are listed under Seed variance, reported and never ranked, and their weights are published on the seed-4321 and seed-7777 branches of the model repository. The margin is also specific to this corpus of 3,500 rows.

Rows that are one model. scnsoft-pii-encoder, scnsoft-pii-encoder-engine-raw and scnsoft-pii-encoder-engine-shipped are one artefact, the same weights, scored three ways: through the Hugging Face ONNX path used for every other entrant; through the product's Rust engine before its post-filters (-engine-raw); and after them (-engine-shipped). The post-filters trade recall for precision on the product's own traffic, so -engine-shipped scores lower here. The engine rows describe the product's pipeline around the model, not a model on their own; otherwise this benchmark scores one model at a time, never a full product.

Steering. A dataset is steered for a model if that model's training was shaped by examining it — the difference between a measurement and a rehearsal. Four of the seven datasets steered ScienceSoft's model: TAB, FactRuEval, MEDDOCAN and IAHLT each motivated a change to its training corpus (TAB's mark is kept although the change it motivated was later switched off — DESIGN.md §4). GermEval, Gretel and Nemotron are unsteered. Steering for other entrants is not known and not claimed either way. Read ScienceSoft's placement with this in mind.

Overall ranking

Ranked by average F1 over the seven datasets. Licence, model revision and notes are shown under each entrant's name.

#modelweightsF195 % CIPRtouchmedian ms/row
1scnsoft-pii-encoderProprietary (evaluation use) · revision 1c1e5be8cbe359c0ScienceSoft's released model (revision 1c1e5be8cbe359c0, int8 ONNX), scored through the same Hugging Face ONNX path as the other ONNX entrants. The rows scnsoft-pii-encoder-engine-raw and scnsoft-pii-encoder-engine-shipped are the same weights decoded by the product's Rust engine.int80.777[0.769, 0.784]0.7100.8780.02120.31R
2scnsoft-pii-encoder-engine-rawProprietary (evaluation use) · revision 1c1e5be8cbe359c0The released model's weights (scnsoft-pii-encoder, 1c1e5be8cbe359c0) decoded by the product's Rust inference engine instead of the Hugging Face ONNX path: the product's pipeline around the model, not a separate model. The scnsoft-pii-encoder-engine-shipped row additionally applies the product's post-filters.int80.772[0.765, 0.780]0.6850.9080.020—
3nvidia-gliner-piiNVIDIA Open Model License (commercial use permitted per card) · revision bd23e8ef4425Ranked third on the PII Masking Benchmark (PIIMB) when it was added here.fp320.753[0.746, 0.761]0.7440.7830.288140.61
4scnsoft-pii-encoder-engine-shippedProprietary (evaluation use) · revision 1c1e5be8cbe359c0The released model's weights (scnsoft-pii-encoder, 1c1e5be8cbe359c0) decoded by the product's Rust inference engine instead of the Hugging Face ONNX path: the product's pipeline around the model, not a separate model. The scnsoft-pii-encoder-engine-shipped row additionally applies the product's post-filters.int80.718[0.709, 0.726]0.7120.7420.017—
5xlmr-ner-hrlAFL-3.0 · revision 253f557bd824A general multilingual named-entity model (person, organisation, location; including Arabic, German, Spanish and Russian), not tuned for PII. It shows what off-the-shelf NER achieves.fp320.711[0.702, 0.719]0.7940.6530.01727.05
6bardsai-eu-multiApache-2.0 · revision 0e72e19f030efp320.706[0.696, 0.716]0.6580.7720.88927.55
7openmed-smallApache-2.0 · revision a2360d3f4252Ranked second on the PII Masking Benchmark (PIIMB) when it was added here.fp320.689[0.681, 0.696]0.7090.7010.67426.27
8openmed-largeApache-2.0 · revision df7af994d39dRanked first on the PII Masking Benchmark (PIIMB) when it was added here.fp320.660[0.652, 0.667]0.7170.6580.630131.79
9gravitee-bert-smallApache-2.0 · revision f8c27a85c51cfp320.604[0.596, 0.611]0.6290.6350.5407.95
10presidio-spacy-smMIT (Presidio) + MIT (spaCy models)Microsoft Presidio with spaCy's small models (de_core_news_sm, en_core_web_sm, es_core_news_sm, ru_core_news_sm); the larger models were not available on the scoring host. spaCy has no Arabic model, so Arabic rows receive no predictions. The model used for each language is recorded in the result's meta.json.fp320.568[0.559, 0.576]0.5260.6320.4818.47
11catalog-multilang-pii-ner-fp32MIT · revision 730c579658f8The same weights as catalog-multilang-pii-ner-int8 at fp32, to measure the accuracy cost of int8 quantisation.fp320.552[0.543, 0.560]0.7810.4550.58325.18
12catalog-multilang-pii-ner-int8MIT · revision 730c579658f8onnx-community/multilang-pii-ner-ONNX, the multilingual PII model in the model catalog of ScienceSoft's data-loss-prevention agent, at the int8 export the agent deploys.int80.548[0.539, 0.556]0.7770.4510.58720.14
13piiranha (non-commercial licence)CC-BY-NC-ND-4.0 · revision 255acde67a2fLicensed CC BY-NC-ND 4.0 (non-commercial, no derivatives). Scored for reference because it is the most-downloaded model for this task; its licence is shown beside its score.fp320.481[0.470, 0.492]0.8120.3590.36749.82
14catalog-bert-small-pii-int8Apache-2.0 · revision 6cb4e77c2b2cThe int8 ONNX export of gravitee-io/bert-small-pii-detection (the gravitee-bert-small row) held in the same agent catalog.int80.473[0.466, 0.479]0.5820.5920.3884.74
15deberta-finetuned-piiMIT · revision a038061af920h2oai/deberta_finetuned_pii (revision 68089cd67db0) publishes byte-identical weights under another account, so both are represented by this one row.fp320.419[0.410, 0.427]0.3280.7850.79347.18
16tabularisai-euApache-2.0 · revision c928cd51d4f2fp320.412[0.403, 0.422]0.8270.3200.58570.92

95 % CI: percentile bootstrap over rows, 1000 resamples.

By carrier — the axis this benchmark exists for

modelF1 (avg)csv
n=168
csv_row
n=148
json
n=147
json_fields
n=173
keyvalue
n=154
log
n=159
markdown_table
n=162
ocr
n=167
prose
n=1719
sql
n=172
sql_values
n=153
xml
n=178
scnsoft-pii-encoder0.7770.7620.9290.7660.9050.7470.7590.7740.7310.7590.7290.9570.745
scnsoft-pii-encoder-engine-raw0.7720.7490.9500.7440.9150.7390.7450.7540.7280.7550.7250.9680.732
nvidia-gliner-pii0.7530.7480.9410.7020.8960.7470.5850.7520.7230.7390.7070.9400.739
scnsoft-pii-encoder-engine-shipped0.7180.7260.8520.7080.8150.6860.7390.6970.6720.7180.6970.8660.679
xlmr-ner-hrl0.7110.7280.7300.6980.7150.6820.7420.7120.6940.7250.7020.7280.712
bardsai-eu-multi0.7060.7030.8500.7020.8240.6430.7310.7040.6370.7040.6650.7860.695
openmed-small0.6890.7210.8120.6640.7790.6990.5520.7000.6650.7100.6740.7690.719
openmed-large0.6600.6910.7780.6240.7790.6670.5430.7030.6500.6910.6530.7640.696
gravitee-bert-small0.6040.5840.7950.5640.7450.6060.4820.6160.5870.5740.5650.8470.600
presidio-spacy-sm0.5680.6320.5640.6090.6880.6190.5220.6360.6120.6430.6200.6760.621
catalog-multilang-pii-ner-fp320.5520.6100.6120.5670.6180.5340.5200.5940.5260.5900.5510.5860.568
catalog-multilang-pii-ner-int80.5480.6030.6290.5620.6300.5240.5220.5860.5130.5840.5470.5920.561
piiranha0.4810.5220.4780.5030.4730.4810.5720.4930.4220.5060.4790.3710.515
catalog-bert-small-pii-int80.4730.4520.7560.4670.7340.4660.4180.4340.4240.4310.4490.7260.445
deberta-finetuned-pii0.4190.2820.6160.3140.5500.2910.2820.2910.3040.3250.3040.6930.304
tabularisai-eu0.4120.4680.3070.4590.5280.4320.4710.4310.3900.4580.4120.3880.461

By dataset

modelF1 (avg)factrueval†germeval†greteliahltmeddocannemotrontab
scnsoft-pii-encoder0.7770.7510.6580.8890.6920.8540.8180.774
scnsoft-pii-encoder-engine-raw0.7720.7540.6570.8930.6810.8440.8200.758
nvidia-gliner-pii0.7530.6960.7220.8620.5910.7960.8710.735
scnsoft-pii-encoder-engine-shipped0.7180.7970.7340.8200.6660.8210.7360.450
xlmr-ner-hrl0.7110.7750.8600.6660.7550.8050.7030.414
bardsai-eu-multi0.7060.7300.7490.7960.7090.8080.7280.424
openmed-small0.6890.4890.6290.8400.4550.8460.8400.724
openmed-large0.6600.3930.5870.8470.3730.8440.8470.729
gravitee-bert-small0.6040.0840.5180.9600.3210.7370.8250.783
presidio-spacy-sm0.5680.7380.6820.6620.0000.5950.6280.669
catalog-multilang-pii-ner-fp320.5520.3880.5280.7810.2050.7470.6820.535
catalog-multilang-pii-ner-int80.5480.3930.5350.7750.1790.7390.6810.533
piiranha0.4810.2510.4880.6860.4540.6990.4880.301
catalog-bert-small-pii-int80.4730.0230.3300.8910.0570.4300.8440.735
deberta-finetuned-pii0.4190.2710.1680.7410.2510.4650.5030.533
tabularisai-eu0.4120.0980.3100.8480.1450.6720.5850.230

† GermEval and FactRuEval annotate no dates; any date a model finds there counts against it, for every model.

By language

modelF1 (avg)ardeenesru
scnsoft-pii-encoder0.7770.6920.6580.8110.8540.751
scnsoft-pii-encoder-engine-raw0.7720.6810.6570.8040.8440.754
nvidia-gliner-pii0.7530.5910.7220.7960.7960.696
scnsoft-pii-encoder-engine-shipped0.7180.6660.7340.6150.8210.797
xlmr-ner-hrl0.7110.7550.8600.5430.8050.775
bardsai-eu-multi0.7060.7090.7490.5930.8080.730
openmed-small0.6890.4550.6290.7860.8460.489
openmed-large0.6600.3730.5870.7930.8440.393
gravitee-bert-small0.6040.3210.5180.8400.7370.084
presidio-spacy-sm0.5680.0000.6820.6580.5950.738
catalog-multilang-pii-ner-fp320.5520.2050.5280.6460.7470.388
catalog-multilang-pii-ner-int80.5480.1790.5350.6420.7390.393
piiranha0.4810.4540.4880.4680.6990.251
catalog-bert-small-pii-int80.4730.0570.3300.8030.4300.023
deberta-finetuned-pii0.4190.2510.1680.5850.4650.271
tabularisai-eu0.4120.1450.3100.5320.6720.098

Seed variance — reported, never ranked

Further training runs of the released model's recipe that differ from it only in the random seed. They are not entrants: they are listed so that the released model's result can be read against the spread of its recipe, and they appear in no ranked table on this page. The released model on the same path, scnsoft-pii-encoder-engine-raw, scores 0.7725.

modelF195 % CIPR
scnsoft-pii-encoder-seed-4321-engine-rawProprietary (evaluation use) · revision adb000952c6ae80cSeed-variance disclosure, not a ranked entrant. The released model's training recipe, retrained with random seed 4321 instead of 1234; corpus, hyperparameters, export and quantisation are identical. Scored through the same production Rust engine as the released model (raw side, before product post-filters). Weights: the seed-4321 branch of ScienceSoft/scnsoft-pii-encoder, revision adb000952c6ae80c. Reported so that the released model's result can be read against the recipe's spread across seeds.0.7590[0.751, 0.766]0.6780.897
scnsoft-pii-encoder-seed-7777-engine-rawProprietary (evaluation use) · revision b076938f9ea83266Seed-variance disclosure, not a ranked entrant. The released model's training recipe, retrained with random seed 7777 instead of 1234; corpus, hyperparameters, export and quantisation are identical. Scored through the same production Rust engine as the released model (raw side, before product post-filters). Weights: the seed-7777 branch of ScienceSoft/scnsoft-pii-encoder, revision b076938f9ea83266. Reported so that the released model's result can be read against the recipe's spread across seeds.0.7543[0.746, 0.762]0.6580.913

Speed — inference latency, batch size 1

Median and p95 milliseconds per row, timed one request at a time after a discarded warmup — the shape this product actually runs in (an agent inline in a request path), not batch throughput. Reported and separately sortable; it never reorders the F1 ranking above, and a model this benchmark cannot yet time shows an em dash, never a zero.

modelmedian ms/rowp95 ms/rowrows/sechost
catalog-bert-small-pii-int84.7413.17170.0Apple M4 Max / accelerator mps
gravitee-bert-small7.9514.00118.9Apple M4 Max / accelerator mps
presidio-spacy-sm8.4718.27113.9Apple M4 Max / accelerator mps
catalog-multilang-pii-ner-int820.1436.1850.7Apple M4 Max / accelerator mps
scnsoft-pii-encoder (timed at model revision e98225e07225; the accuracy on this board is for revision 1c1e5be8cbe359c0)20.3133.4651.7Apple M4 Max / accelerator mps
catalog-multilang-pii-ner-fp3225.1843.9740.2Apple M4 Max / accelerator mps
openmed-small26.2736.4837.8Apple M4 Max / accelerator mps
xlmr-ner-hrl27.0532.6338.5Apple M4 Max / accelerator mps
bardsai-eu-multi27.5534.2838.0Apple M4 Max / accelerator mps
deberta-finetuned-pii47.18134.6316.6Apple M4 Max / accelerator mps
piiranha49.8266.1120.8Apple M4 Max / accelerator mps
tabularisai-eu70.92116.9813.3Apple M4 Max / accelerator mps
openmed-large131.79182.877.4Apple M4 Max / accelerator mps
nvidia-gliner-pii140.61199.676.9Apple M4 Max / accelerator mps
scnsoft-pii-encoder-engine-rawtiming failed or excluded: not timed: this row is scored from predictions the Rust engine saved to a file, so there is no Python model for this timer to call. Timing the Rust engine needs its own measurement.—
scnsoft-pii-encoder-engine-shippedtiming failed or excluded: not timed: this row is scored from predictions the Rust engine saved to a file, so there is no Python model for this timer to call. Timing the Rust engine needs its own measurement.—

Entity-level — SemEval-2013 exact / partial (supplementary, not ranked)

modelexact F1partial F1
scnsoft-pii-encoder0.5390.638
scnsoft-pii-encoder-engine-raw0.5420.635
nvidia-gliner-pii0.5890.651
scnsoft-pii-encoder-engine-shipped0.5190.601
xlmr-ner-hrl0.0620.366
bardsai-eu-multi0.3690.445
openmed-small0.0380.253
openmed-large0.0350.256
gravitee-bert-small0.3530.428
presidio-spacy-sm0.3600.425
catalog-multilang-pii-ner-fp320.0700.212
catalog-multilang-pii-ner-int80.0700.211
piiranha0.0350.245
catalog-bert-small-pii-int80.2350.312
deberta-finetuned-pii0.0140.160
tabularisai-eu0.1660.243

Not run, and why

The benchmark names failures rather than omitting them. A model absent with no explanation is indistinguishable from one quietly dropped for scoring badly.

slugidlicencereason
catalog-neurobert-neronnx-community/NeuroBERT-NER-ONNXunstatedNot scored: the model card declares no licence; it will be scored once a licence is stated at the source.
hikmaai-distilbertHikmaAI/hikmaai-distilbert-piiApache-2.0Not scored: the standard token-classification pipeline passes token_type_ids to this DistilBERT model, which does not accept them, and no ONNX export exists to work around it.
gliner-pii-baseknowledgator/gliner-pii-base-v1.0Apache-2.0no result published yet; it is scored when one is.
wikineural-multilingualBabelscape/wikineural-multilingual-nerCC-BY-NC-SA-4.0Not scored: licensed CC BY-NC-SA 4.0 (non-commercial), excluded under the same rule that excludes non-commercial datasets.

Hardware and software

Inference ran on CPU (accelerators present but unused).

How to run the benchmark

Everything needed is in the dataset repository: the rows, the scoring harness and every published result. Python 3.9 or later, and the Hugging Face command-line tool (pip install -U huggingface_hub) for step 1.

  1. Download the benchmark and install the harness.
    hf download ScienceSoft/piibench --repo-type dataset --local-dir piibench
    cd piibench
    pip install -e ".[predict]"
  2. Run a model over the published rows. The default pipeline is Hugging Face token-classification with aggregation_strategy="simple"; --pipeline onnx, gliner and presidio are also available and additionally need onnxruntime, gliner or presidio-analyzer respectively. Steps 3 and 4 need only the base install.
    piibench predict --rows data/rows.jsonl --model <hf-model-id> --revision <commit> --out preds.jsonl
  3. Score the predictions. Writes result.json, a copy of the predictions and meta.json (host, precision, library versions).
    piibench score --rows data/rows.jsonl --preds preds.jsonl --model <name> --out-dir results/<name>
  4. Compare with any published entrant on the same rows — a paired bootstrap on the difference in average F1:
    piibench compare --rows data/rows.jsonl --a preds.jsonl --b results/nvidia-gliner-pii/preds.jsonl --iterations 2000 --seed 0

Reproducing a published row. Run step 2 with that row's model id and the revision recorded in results/<slug>/result.json (_provenance.model_revision), or re-score its published preds.jsonl directly with step 3. Scores are deterministic for a given rows file; each result records that file's SHA-256 as _provenance.rows_sha256 — cite it with any number you report. Rows produced by ScienceSoft's Rust engine (-engine-*) cannot be regenerated with this harness; their predictions are published so that they can be re-scored.

Submitting a model. Open a pull request on the dataset repository that adds results/<name>/ as written by step 3, with the model id and pinned revision.

Generated from result files; this page computes no metric of its own. Framework, datasets, licences and the honesty rules are in the dataset repository.