privacy-filter-ru (v2)

Дообученная openai/privacy-filter для поиска персональных данных в русском тексте. На вход подаётся текст, на выходе — фрагменты с типом и смещениями в символах. Что делать с ними дальше (маскировать, заменять на id, шифровать), решает тот, кто использует модель.

Архитектура не менялась: двунаправленный классификатор токенов, MoE, 1.4B параметров всего и около 50M активных, токенизатор o200k. Изменились классификационная голова (метки) и веса без экспертов.

Метки

Схема BIOES: B-, I-, E-, S-<тип> плюс O, всего 61 класс.

тип что это
private_person имя, фамилия, отчество, инициалы — в любом падеже, без обращений («Уважаемый …»)
private_address адрес проживания или регистрации, в том числе неполный («ул. Мира, д. 7»)
private_phone личный телефон
private_email личный e-mail
private_url личная ссылка (vk, t.me, …)
private_date конкретная дата (рождения, события)
secret пароль, токен, ключ API, код из SMS, PIN, CVV
account_number банковский и лицевой счёт
payment_card номер банковской карты
passport_number серия и номер паспорта (РФ и заграничного)
inn ИНН (10 или 12 цифр)
snils СНИЛС
ogrn ОГРН / ОГРНИП
oms_policy полис ОМС
vehicle_plate госномер автомобиля

Первые 8 типов совпадают с исходной моделью, остальные добавлены. Фрагмент не включает поясняющие слова: в «ИНН 7707083893» размечается только 7707083893.

Не размечаются:

  • публичные персоны, организации, город сам по себе;
  • служебные контакты: горячие линии (8 800…, 900, 112), адреса вида support@/noreply@, сайты компаний;
  • банковские реквизиты, которые не относятся к человеку: КПП, БИК, корреспондентский счёт.

Использование

transformers

pip install "transformers>=5.6" torch
from transformers import pipeline

pii = pipeline(model="Rajey/privacy-filter-ru", trust_remote_code=True)
pii("Иван Петров, СНИЛС 112-233-445 95, карта 4276 3800 1234 5675")
# [{'entity_group': 'private_person', 'score': 0.75, 'word': 'Иван Петров', 'start': 0, 'end': 11},
#  {'entity_group': 'snils', 'score': 0.99, 'word': '112-233-445 95', 'start': 19, 'end': 33},
#  {'entity_group': 'payment_card', 'score': 0.99, 'word': '4276 3800 1234 5675', 'start': 41, 'end': 60}]

start/end — смещения в символах исходной строки. Для пустой строки вернётся пустой список.

Если текстов много, передавайте их списком с batch_size: так в 15–20 раз быстрее, чем по одному.

results = pii(texts, batch_size=64)   # список списков, в том же порядке

trust_remote_code=True подключает pii_pipeline.py из этого репозитория (около 150 строк). Он собирает фрагменты из меток BIOES ограниченным Viterbi, как пакет opf, и декодирует весь батч сразу. Без него получится только разметка по токенам через pipeline("token-classification", model="Rajey/privacy-filter-ru"): стандартная агрегация transformers понимает лишь префиксы B-/I- и рвёт фрагменты. На тестах F1 тогда падает с 0.85 до 0.74.

Скорость

RTX 5080, тексты по ~40 токенов, полный цикл от строки до фрагментов:

мс на текст текстов/с
по одному тексту 31 32
batch_size=64 1.9 525
CPU (12 потоков), batch_size=16 27 38

Длинные тексты

Порт модели в transformers строит полную матрицу внимания T×T, хотя каждый токен видит только 128 соседей с каждой стороны: на тексте в 60 тысяч токенов это ~30 ГБ. Поэтому pipeline режет тексты длиннее 4096 токенов на окна с перекрытием 1024 токена с каждой стороны и декодирует склеенные логиты целиком. У модели 8 слоёв с окном 128, так что токен зависит не более чем от 1024 соседей, и результат окон совпадает с одним полным прогоном побитово (проверено). Память при этом ограничена одним окном: пик ~8 ГБ на GPU, на CPU ~5 ГБ ОЗУ сверх самой модели. Текст в 24 тысячи токенов на RTX 5080 занимает ~3 с, в 60 тысяч токенов на CPU (12 потоков) ~150 с.

Размеры можно менять: pii(text, window=2560, context=1024) уменьшит память ценой лишних вычислений на перекрытиях.

В config.json заданы experts_implementation: grouped_mm и dtype: float32. transformers для этой архитектуры по умолчанию берёт медленную реализацию экспертов eager (~250 мс на текст на той же GPU); grouped_mm в fp32 даёт те же предсказания на всех тестовых документах, поэтому включён сразу. bf16 (pipeline(..., dtype="bfloat16")) ускоряет большие батчи ещё примерно в полтора раза, но меняет предсказания в ~2% документов.

opf

В original/ лежит тот же чекпойнт в формате пакета opf, со встроенным Viterbi:

hf download Rajey/privacy-filter-ru --include "original/*" --local-dir privacy-filter-ru
opf --checkpoint privacy-filter-ru/original "Иван Петров, паспорт 4510 123456"

На Windows без Triton нужно выставить OPF_MOE_TRITON=0.

Логиты двух форматов совпадают: на проверочных текстах расхождение не больше 2.5e-5, предсказанные метки совпадают в 100% случаев.

Качество

Метрики посчитаны по фрагментам: точные границы и верный тип. Колонка «скрыто» — доля фрагментов, полностью покрытых какой-либо предсказанной меткой; она показывает, сколько данных не утекло бы при маскировании. Базовой модели засчитывается account_number там, где у неё нет более узкой метки.

Два тестовых набора. Ни один их шаблон не участвовал в обучении:

  • test v1 — 132 документа, 336 фрагментов: 17 шаблонов, отложенных ещё в v1, и 36 ручных текстов (чаты, OCR, логи, смешанный русский с английским, ловушки с публичными персонами). Набор заморожен.
  • test_new — 78 документов, 107 фрагментов: 9 отложенных шаблонов, добавленных в v2, и 24 ручных текста на слабые метки и негативы.
test v1: P R F1 скрыто test_new: P R F1 скрыто
openai/privacy-filter 0.56 0.55 0.56 0.84 0.49 0.48 0.48 0.74
privacy-filter-ru v1 0.74 0.79 0.77 0.93 0.39 0.50 0.44 0.85
privacy-filter-ru v2 0.83 0.86 0.85 0.95 0.55 0.67 0.61 0.97

На шаблонах, которые были в обучении (но с новыми значениями), F1 = 0.96.

По меткам, test v1:

метка gold F1 база F1 v1 F1 v2 скрыто база скрыто v1 скрыто v2
private_person 131 0.67 0.82 0.88 0.79 0.95 0.95
private_date 62 0.55 0.84 0.80 0.81 0.95 0.97
private_address 27 0.13 0.68 0.69 0.89 0.93 0.93
private_phone 25 0.80 0.81 0.94 0.96 0.96 0.96
private_email 20 0.87 0.87 1.00 1.00 1.00 1.00
secret 16 0.19 0.29 0.67 0.81 0.62 0.75
passport_number 9 0.80 0.86 0.71 1.00 1.00 0.89
inn 8 0.00 0.57 0.73 0.88 1.00 1.00
snils 8 0.00 0.86 1.00 0.88 1.00 1.00
ogrn 7 0.00 0.00 0.88 0.86 1.00 1.00
vehicle_plate 7 0.25 0.25 0.88 0.29 0.14 1.00
private_url 5 0.91 0.91 1.00 1.00 1.00 1.00
account_number 4 0.19 0.67 0.67 1.00 0.75 0.75
payment_card 4 0.67 0.57 0.80 1.00 1.00 1.00
oms_policy 3 0.50 0.00 0.67 1.00 1.00 1.00

По меткам, test_new:

метка gold F1 база F1 v1 F1 v2 скрыто v2
private_person 43 0.56 0.71 0.69 0.95
secret 19 0.52 0.23 0.49 0.95
vehicle_plate 16 0.12 0.40 0.88 1.00
ogrn 9 0.80 0.00 0.36 1.00
oms_policy 8 0.86 0.00 0.22 1.00
private_date 6 0.73 0.71 0.83 1.00
Downloads last month
-
Safetensors
Model size
1B params
Tensor type
F32
·
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for Rajey/privacy-filter-ru

Finetuned
(54)
this model