
Umkehrung des OpenAI Privacy Filters. Dasselbe 1,5B-Modell, gibt PII als strukturierte Spans zurück, anstatt sie zu maskieren
Finde jedes personenbezogene Datenelement (PII) in einem Textstapel und erhalte es als strukturierte Spans zurück.
Basiert auf OpenAI Privacy Filter: gleiches 1,5B-Modell, gleiche Labels, gleiche Gewichte.
Privacy Filter maskiert. Privacy Parser extrahiert.
Hi Quindle Testwick ([email protected] / +1-415-555-0102),
account 40702810500001234567, 14 Beautiful Ct, Anytown USA,
password Priv4cy-Filt3r-2026.
private_person Quindle Testwick
private_email [email protected]
private_phone +1-415-555-0102
account_number 40702810500001234567
private_address 14 Beautiful Ct, Anytown USA
secret Priv4cy-Filt3r-2026
Statt <REDACTED> erhältst du was gefunden wurde, wo es sich befindet (start, end) und welchen Typ es hat.
Privacy Filter beantwortet die Frage „mache diesen Text sicher“. Manchmal brauchst du eine andere Antwort: „Was genau steht hier drin?“
| Backend | Benötigt Gewichte | Geschwindigkeit | F1 * | Verwenden, wenn |
|---|---|---|---|---|
PIIParser | nein | µs | 1.000 | keine Abhängigkeiten, strukturierte Muster |
ModelPIIParser | 1.5B | ~500 ms CPU | 0.733 | rohe Modellausgabe |
HybridPIIParser | 1.5B | ~600 ms CPU | 0.929 | Standardwahl |
* exakte Span-Übereinstimmung auf den fünf opf-Beispiel-Fixtures. Eine kleine Menge: Betrachte es als Smoke-Test, nicht als Benchmark.
git clone https://github.com/openai/privacy-filter
git clone https://github.com/chiefautism/privacy-parser
uv venv
uv pip install -e ./privacy-filter # only for the model backends
uv pip install -e ./privacy-parser
Der erste Modelllauf lädt den opf-Checkpoint (~3 GB) nach ~/.opf/privacy_filter/ herunter.
Setze OPF_CHECKPOINT oder übergib model=, um einen anderen Speicherort zu verwenden.
from pii_parser.hybrid import HybridPIIParser
parser = HybridPIIParser(device="cpu") # or "cuda"
result = parser.parse("Hi Quindle Testwick, call me at +1-415-555-0102")
for s in result.spans:
print(s.label, s.start, s.end, s.text)
print(result.to_json())
from pii_parser import parse
result = parse("mail [email protected], token ghp_abcdefghijklmnopqrstuvwxyz0123456789")
result.detected_spans # (DetectedSpan(label='private_email', ...), ...)
result.redacted_text # 'mail <REDACTED>, token <REDACTED>'
result.summary # {'span_counts': {...}, 'total_spans': 2}
Regex-Backend, kein Modell:
$ echo "Alice paid 40702810500001234567 on 2026-05-17." | pii-parser --mode spans
account_number 11 31 40702810500001234567
private_date 35 45 2026-05-17
$ pii-parser "mail [email protected]" --mode redacted
mail <REDACTED>
| Flag | Werte | Standard |
|---|---|---|
TEXT | Text, oder -f FILE, oder stdin | |
--mode | json · spans · redacted | json |
--placeholder | beliebige Zeichenkette | <REDACTED> |
--indent | int, 0 für kompaktes JSON | 2 |
Modell-Backend:
python -m pii_parser.cli_model "Alice paid 40702810500001234567 on 2026-05-17."
python -m pii_parser.cli_model -f dump.txt --device cuda --mode spans
opf v2-Taxonomie, 8 Kategorien:
| Label | Beispiel |
|---|---|
private_person | Quindle Testwick |
private_email | [email protected] |
private_phone | +1-415-555-0102 |
private_address | 14 Beautiful Ct, Anytown USA |
private_url | https://example.com/u/quindle |
private_date | 2026-05-17 |
account_number | 40702810500001234567 |
secret | sk-…, ghp_…, AKIA…, Bearer … |
Wenn sich Spans überschneiden, gewinnt der längere, dann das Label mit höherer Priorität: email > url > secret > account > phone > date > address > person.
text
│
▼
opf 1.5B ──► BIOES logits ──► Viterbi (tuned biases) ──► char spans
│
▼
span merge glues "Quindle" + "Testwick" into one person
│
▼
regex backstop adds url / secret / account where the model missed them
│
▼
spans[]
Jede Stufe kann deaktiviert werden:
HybridPIIParser(
enable_merge=True,
enable_regex_backstop=True,
enable_viterbi_tuning=True,
decode_mode="viterbi", # or "argmax"
)
{
"text": "Hi Quindle Testwick ...",
"spans": [
{ "label": "private_person", "start": 3, "end": 19, "text": "Quindle Testwick" }
]
}
Der Regex PIIParser spiegelt opf.RedactionResult wider (schema_version, summary, detected_spans, redacted_text), sodass du Backends austauschen kannst, ohne Konsumenten anzupassen.
Die Tests erwarten, dass privacy-filter neben diesem Repo geklont ist (sie lesen dessen Beispiel-Fixtures).
python tests/test_hybrid.py
Fixture F1: 0.929
Scenarios: 8/8 passed
Latency: ~600 ms CPU
Dies ist ein Dual-Use-Tool. Führen Sie es nur auf Daten aus, die Ihnen gehören oder deren Verarbeitung Sie autorisiert sind. Das Extrahieren personenbezogener Daten aus geleakten oder gestohlenen Quellen ist in den meisten Rechtsordnungen illegal.