
Обратная функция фильтра конфиденциальности OpenAI. Та же модель 1.5b, возвращает PII в виде структурированных спанов вместо маскирования
Находит все фрагменты PII в массиве текста и возвращает их в виде структурированных спанов.
Построен на основе OpenAI Privacy Filter: та же модель 1.5B, те же метки, те же веса.
Privacy Filter маскирует. Privacy Parser извлекает.
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
Вместо <REDACTED> вы получаете что было найдено, где оно находится (start, end) и какого оно типа.
Privacy Filter отвечает на вопрос «сделать этот текст безопасным». Иногда нужен другой ответ: «что именно здесь находится?»
| Бэкенд | Нужны веса | Скорость | F1 * | Когда использовать |
|---|---|---|---|---|
PIIParser | нет | µs | 1.000 | без зависимостей, структурированные шаблоны |
ModelPIIParser | 1.5B | ~500 ms CPU | 0.733 | сырой вывод модели |
HybridPIIParser | 1.5B | ~600 ms CPU | 0.929 | выбор по умолчанию |
* точное совпадение спанов на пяти образцовых фикстурах opf. Небольшой набор: рассматривайте его как smoke-тест, а не как бенчмарк.
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
Первый запуск модели загружает контрольную точку opf (~3 ГБ) в ~/.opf/privacy_filter/.
Задайте OPF_CHECKPOINT или передайте model=, чтобы использовать другое расположение.
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}
Бэкенд на регулярных выражениях, без модели:
$ 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>
| Флаг | Значения | По умолчанию |
|---|---|---|
TEXT | текст, или -f FILE, или stdin | |
--mode | json · spans · redacted | json |
--placeholder | любая строка | <REDACTED> |
--indent | int, 0 для компактного JSON | 2 |
Бэкенд модели:
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, 8 категорий:
| Метка | Пример |
|---|---|
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 … |
При пересечении диапазонов побеждает более длинный, затем метка с более высоким приоритетом: 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[]
Каждый этап можно отключить:
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" }
]
}
Регулярное выражение PIIParser повторяет структуру opf.RedactionResult (schema_version, summary, detected_spans, redacted_text), поэтому вы можете менять бэкенды, не затрагивая потребителей.
Тесты ожидают, что privacy-filter клонирован рядом с этим репозиторием (они читают его примеры фикстур).
python tests/test_hybrid.py
Fixture F1: 0.929
Scenarios: 8/8 passed
Latency: ~600 ms CPU
Это инструмент двойного назначения. Запускайте его только на данных, которыми вы владеете или которые уполномочены обрабатывать. Извлечение персональных данных из утёкших или украденных источников незаконно в большинстве юрисдикций.