Skip to main content

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.yaml is generated by scripts/gen_regex_rules.py and 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:

  1. Regex filter — structurally obvious PII (phone, email, IDs, cards, secrets).
  2. 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

  • Architectureroberta-base encoder → 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.txt for 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 EMAIL figure is depressed by noisy gold boundaries on concatenated tokens (gold ffxkt@… vs. the model's correct uhffxkt@…), not by regex misses. Reproduce with privyscope 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 SECRET for 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

privyscope_en-0.1.5.tar.gz (14.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

privyscope_en-0.1.5-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

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

Hashes for privyscope_en-0.1.5.tar.gz
Algorithm Hash digest
SHA256 9d6d8d34ab3fe44e2f4cab7667b1d000fe7e037744fe5418221f93c8e50f6a34
MD5 2bc7c44b230c1f1902ff1c8529b0e005
BLAKE2b-256 99f48147e3733356ed019d275031a362e91a328a84b1e9e93e5770edea7809b0

See more details on using hashes here.

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

Hashes for privyscope_en-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 3fe505e07160f49cc66a67042c210551ce57fff3333ac1489592b3887f64a83b
MD5 cb9ea3b89f18ce1ecd5251b876e9b776
BLAKE2b-256 1360d4be1a1039d91a2252917ac9d0746b0560aa5f5e89ae1a7ab0bb7c247ae4

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 files

0.1.3

2 files

0.1.2

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page