anonymizer-cpu-v0.1
Finds private values in text (names, usernames, hosts, emails, phones, addresses, IPs, IDs, secrets and more; 18 types). Runs on a CPU.
- Size: 32M parameters, fp32 ONNX (128 MB)
- Base: Ettin encoder 32M, distilled from a larger teacher
- Window: 8,192 tokens per call
- Runtime: onnxruntime,
tokenizers,numpy - License: MIT
Download
pip install pirateface
pf download pirateface/anonymizer-cpu-v0.1
Use it
pip install onnxruntime tokenizers numpy
python scrub.py "Ping Elara Quinby at elara@kitelabs.io or ssh deploy@cedar-01 (10.0.4.17)"
from scrub import Scrubber
Scrubber().spans(text) # [(start, end, TYPE), ...]
How it compares
Against openai/privacy-filter, same scorer for both.
Coding-agent traffic
892 held-out traces; only types both models look for (names, emails, phones, addresses, IBANs, secrets).
Public PII benchmarks
Character-level F1 (Horizon-Labs' method). privacy-filter is ahead on average: 0.81 vs 0.77.
Speed and size
One CPU core; privacy-filter as its fastest official build (q4 ONNX).
Memory 285 MB vs 1,448 MB. Parameters 32M vs 1.4B.
How it works
An LLM scrubber rewrites the text, one pass per token. This model reads it once and labels every word: keep, or a private type. That's why it runs on one CPU core.
flowchart TB
subgraph LLM["LLM scrubber: rewrites the text, one pass per token"]
direction LR
L0["Ping Elara at elara@kitelabs.io"] --> L1["pass 1: Ping"] --> L2["pass 2: [NAME]"] --> L3["pass 3: at"] --> L4["pass 4: [EMAIL]"]
end
subgraph PF["anonymizer-cpu-v0.1: labels every word in one pass"]
direction LR
P0["Ping Elara at elara@kitelabs.io"] --> P1["one pass"] --> TAGS
subgraph TAGS["labels"]
direction TB
T1["Ping: keep"] ~~~ T2["Elara: NAME"] ~~~ T3["at: keep"] ~~~ T4["elara@kitelabs.io: EMAIL"]
end
end
LLM ~~~ PFTypes
NAME, USER, HOST, EMAIL, PHONE, ADDRESS, GEO, ORG, PROJECT, ID, DATE, IP, MAC, IBAN, WALLET, SECRET, PLACE, CHANNEL
