privyscope-en
English PII detection & masking engine — part of the privyscope series. Detects and masks person names, phone numbers, national IDs, emails, addresses, financial info, private dates, and credentials in English text.
⚠️ privyscope is a redaction aid, not an anonymization or compliance guarantee. See Limitations.
Install
pip install privyscope-en
60-second quickstart
Python
from privyscope_en import Privyscope
engine = Privyscope.from_pretrained() # downloads ONNX weights on first run
result = engine.redact("John Smith's number is 555-123-4567")
result.masked_text # "<PER>'s number is <PHONE>"
result.detected_spans # [DetectedSpan(label="PER", start=0, end=10, ...), ...]
result.summary # {"span_count": 2, "by_label": {"PER": 1, "PHONE": 1}, ...}
CLI
privyscope redact "John Smith's number is 555-123-4567"
cat notes.txt | privyscope redact --operating-point high_recall
Documentation
Full guides live in docs/ — organised by what you want to do:
| I want to… | Guide |
|---|---|
| Run it from the terminal | CLI Reference |
| Call it from Python | Python API Reference |
| Understand the JSON output | Output Schemas |
| Score it on my labelled data | Evaluation & Output Modes |
| Trade precision vs recall | Operating Points |
| Run it offline / air-gapped | Offline Usage |
| Fine-tune on my own data | Fine-tuning |
Entities
Base (regex + NER):
PER · PHONE · ID_NUM · EMAIL · LOC · BANK · DATE · SECRET.
Regex-only extended entities:
EIN · PASSPORT · DRIVER_LICENSE · MEDICAL · CRYPTO · IP · DEVICE · URL
— see privyscope_en/entity_config.yaml.
Stage-1 patterns come from the
pii-pattern-engine ruleset. Most carry a
verification function — a checksum or dictionary validator (luhn, us_ssn_valid,
iban_mod97) that a match must pass before it is redacted, so a number that merely looks
like a card or SSN is left alone.
privyscope_en/regex_rules.yamlis generated byscripts/gen_regex_rules.pyand is overwritten on every build — edit the mapping in that script, not the YAML. See CONTRIBUTING.
How it works
A two-stage hybrid pipeline (SRS §3.4), results merged via Union:
- Regex filter — structurally obvious PII (phone, email, IDs, cards, secrets).
- ONNX NER — a BIOES token classifier with a constrained Viterbi decoder for contextual PII (names, addresses, private dates).
Inference is ONNX Runtime only — no PyTorch at runtime. Recall-first, with runtime operating-point tuning (no retraining). PyTorch is needed only to fine-tune.
Model & performance
-
Architecture —
roberta-baseencoder → BIOES token-classification head → constrained Viterbi decoder. -
Runtime artifact — INT8-quantized ONNX, ~120 MB (under the ≤ 150 MB budget), max sequence length 256. Weights download from Hugging Face Hub on first use, with a SHA-256
checksum.txtfor integrity verification. -
Accuracy — entity-level strict micro-F1 = 0.839 on a held-out validation set (1,000 sentences, disjoint from training;
typed/strict scoring over the full regex + NER pipeline). Per-entity strict F1:PER LOC DATE EMAIL BANK PHONE SECRET 0.83 0.83 0.98 0.81 0.92 0.95 0.79 This validation set is a deliberately hard stress test — multi-locale names plus spoken / typo / space-collapsed registers — scored on strict offset match, so the numbers are a conservative lower bound; clean text scores higher. In particular the
EMAILfigure is depressed by noisy gold boundaries on concatenated tokens (goldffxkt@…vs. the model's correctuhffxkt@…), not by regex misses. Reproduce withprivyscope eval --lang en your_val.jsonl; see Evaluation & Output Modes.
Example: an online-shopping inquiry
A real customer message sent to an online store (~490 chars, with a name, email,
phone, address, and card number) passed straight through engine.redact().
Input
Hello, my name is Michael Anderson. I ordered a pair of running shoes, but the package has still not arrived. My registered email is michael.anderson92@gmail.com and my mobile number is 415-555-0198. The delivery address is 1420 Sunset Boulevard, Los Angeles, CA 90026. I already paid with my credit card 4539-1488-0343-6467. Could you please check the shipment status, and if the parcel is lost, refund the amount to my card? I would really appreciate a quick reply. Thank you very much.
Masked output (result.masked_text)
Hello, my name is <PER>. I ordered a pair of running shoes, but the package has still not arrived. My registered email is <EMAIL> and my mobile number is <PHONE>. The delivery address is <LOC>. I already paid with my credit card <BANK>. Could you please check the shipment status, and if the parcel is lost, refund the amount to my card? I would really appreciate a quick reply. Thank you very much.
The 5 detected spans
| Label | Detected text |
|---|---|
PER |
Michael Anderson |
EMAIL |
michael.anderson92@gmail.com |
PHONE |
415-555-0198 |
LOC |
1420 Sunset Boulevard, Los Angeles, CA 90026 |
BANK |
4539-1488-0343-6467 |
Limitations
- Not an anonymization/compliance guarantee; use as one layer of privacy-by-design.
- Known failure modes: under-detection of uncommon/regional names; over-redaction
of public entities in ambiguous contexts; fragmented spans in heavily
mixed-format text; missed
SECRETfor novel credential formats. - Extra human review recommended for medical/legal/financial/government workflows.
License
Apache-2.0. Weights are distributed on Hugging Face Hub under Apache-2.0 with a
checksum.txt (SHA-256) for integrity verification. Contributions welcome — see
CONTRIBUTING.md.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file privyscope_en-0.1.5.tar.gz.
File metadata
- Download URL: privyscope_en-0.1.5.tar.gz
- Upload date:
- Size: 14.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d6d8d34ab3fe44e2f4cab7667b1d000fe7e037744fe5418221f93c8e50f6a34
|
|
| MD5 |
2bc7c44b230c1f1902ff1c8529b0e005
|
|
| BLAKE2b-256 |
99f48147e3733356ed019d275031a362e91a328a84b1e9e93e5770edea7809b0
|
File details
Details for the file privyscope_en-0.1.5-py3-none-any.whl.
File metadata
- Download URL: privyscope_en-0.1.5-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fe505e07160f49cc66a67042c210551ce57fff3333ac1489592b3887f64a83b
|
|
| MD5 |
cb9ea3b89f18ce1ecd5251b876e9b776
|
|
| BLAKE2b-256 |
1360d4be1a1039d91a2252917ac9d0746b0560aa5f5e89ae1a7ab0bb7c247ae4
|