Открытые метрики качества
Мы публикуем, как детектор работает на нашем тестовом корпусе: насколько полно он находит размеченные данные (recall) и насколько точны его находки (precision). Ни одно число здесь не вписано руками — все они прочитаны из артефакта замера, который собирается прогоном эвала, а тот же прогон стоит гейтом в CI.
Проверить свой текстИтог замера
Счётчики, из которых посчитаны проценты: TP 1394, FP 1, FN 3. Проценты усечены вниз, поэтому читатель пересчитывает их сам: recall = TP / (TP + FN), precision = TP / (TP + FP).
Как считаются эти числа
Каждое размеченное значение корпуса сверяется с находками детектора по пересечению отрезков текста, отдельно по каждой категории:
- TP — находка совпала с размеченным значением той же категории;
- FP — детектор нашёл то, чего в разметке нет;
- FN — размеченное значение детектор не нашёл.
recall = TP / (TP + FN) — доля найденного. precision = TP / (TP + FP) — доля верных находок. Знаменатель виден: в корпусе размечено 1397 значений, детектор нашёл 1394 из них и пропустил 3.
Проценты усечены вниз до двух знаков, а не округлены: округление вверх завышало бы публичное число. Рядом с процентами стоят счётчики TP/FP/FN и пороги гейта, поэтому каждое число можно пересчитать и сверить с порогом. Значение «100 %» в таблице — это результат на десятках размеченных значений одной категории, а не гарантия на любом тексте. Precision вообще нижняя граница: разметка перечисляет не все персональные данные страницы, поэтому неподтверждённая находка не обязательно ложная.
Замер идёт на профиле без NER (enable_ner=false); организации и локации (NER) меряются отдельным профилем python -m eval.run_eval --ner и в этих числах не участвуют. Ни артефакт, ни эта страница на работу детектора не влияют, поэтому числа действительны и для коммита, в который артефакт добавлен.
По категориям
| Категория | Tier | TP | FP | FN | Recall | Precision |
|---|---|---|---|---|---|---|
ADDRESS | 2 | 31 | 0 | 0 | 100,00 % | 100,00 % |
ANTHROPOMETRY | 4 | 34 | 0 | 0 | 100,00 % | 100,00 % |
BIRTH_CERT | 4 | 31 | 0 | 0 | 100,00 % | 100,00 % |
BIRTH_PLACE | 4 | 38 | 0 | 0 | 100,00 % | 100,00 % |
CITIZENSHIP | 4 | 44 | 0 | 0 | 100,00 % | 100,00 % |
CODE | 3 | 30 | 0 | 0 | 100,00 % | 100,00 % |
CONTRACT | 3 | 32 | 1 | 0 | 100,00 % | 96,96 % |
CREDENTIAL | 3 | 30 | 0 | 0 | 100,00 % | 100,00 % |
DENYLIST | 3 | 33 | 0 | 0 | 100,00 % | 100,00 % |
DOB | 2 | 32 | 0 | 0 | 100,00 % | 100,00 % |
DRIVER_LICENSE | 4 | 38 | 0 | 0 | 100,00 % | 100,00 % |
EDUCATION | 4 | 30 | 0 | 0 | 100,00 % | 100,00 % |
EMAIL | 1 | 32 | 0 | 0 | 100,00 % | 100,00 % |
EMPLOYMENT | 4 | 35 | 0 | 0 | 100,00 % | 100,00 % |
FOREIGN_ID | 4 | 32 | 0 | 0 | 100,00 % | 100,00 % |
GENDER | 4 | 31 | 0 | 0 | 100,00 % | 100,00 % |
HEALTH | 3 | 30 | 0 | 0 | 100,00 % | 100,00 % |
INCOME | 4 | 31 | 0 | 0 | 100,00 % | 100,00 % |
IP_ADDRESS | 3 | 30 | 0 | 0 | 100,00 % | 100,00 % |
MARITAL_STATUS | 4 | 32 | 0 | 0 | 100,00 % | 100,00 % |
MILITARY | 4 | 36 | 0 | 0 | 100,00 % | 100,00 % |
MONEY | 3 | 62 | 0 | 0 | 100,00 % | 100,00 % |
PERSON | 1 | 32 | 0 | 0 | 100,00 % | 100,00 % |
PROPERTY_STATUS | 4 | 30 | 0 | 0 | 100,00 % | 100,00 % |
RU_ACCOUNT | 2 | 42 | 0 | 0 | 100,00 % | 100,00 % |
RU_BIK | 2 | 31 | 0 | 0 | 100,00 % | 100,00 % |
RU_CARD | 1 | 50 | 0 | 0 | 100,00 % | 100,00 % |
RU_CARD_EXPIRY | 2 | 30 | 0 | 0 | 100,00 % | 100,00 % |
RU_CVV | 2 | 30 | 0 | 0 | 100,00 % | 100,00 % |
RU_INN | 1 | 50 | 0 | 0 | 100,00 % | 100,00 % |
RU_KPP | 2 | 31 | 0 | 0 | 100,00 % | 100,00 % |
RU_OGRN | 2 | 30 | 0 | 0 | 100,00 % | 100,00 % |
RU_OGRNIP | 2 | 33 | 0 | 0 | 100,00 % | 100,00 % |
RU_PASSPORT | 1 | 34 | 0 | 0 | 100,00 % | 100,00 % |
RU_PHONE | 1 | 44 | 0 | 0 | 100,00 % | 100,00 % |
RU_SNILS | 1 | 46 | 0 | 0 | 100,00 % | 100,00 % |
SECRET_API_KEY | 3 | 33 | 0 | 0 | 100,00 % | 100,00 % |
SECRET_GENERIC | 3 | 32 | 0 | 3 | 91,42 % | 100,00 % |
SOCIAL_STATUS | 4 | 32 | 0 | 0 | 100,00 % | 100,00 % |
VEHICLE_PLATE | 3 | 30 | 0 | 0 | 100,00 % | 100,00 % |
Tier — группа категорий с разными требованиями: Tier 1 — критичные персональные данные и платёжные реквизиты, Tier 2 — реквизиты, адрес и дата рождения, Tier 3 — шумные и контекстные категории, Tier 4 — анкетные поля из перечня видов персональных данных.
Пороги гейта
Эти числа — не приз, а условие сборки: прогон эвала падает, если порог нарушен, поэтому публикуемый результат нельзя тихо опустить. Пороги намеренно ниже измеренного — именно поэтому измеренное значение не подогнано под порог.
| Требование | Порог |
|---|---|
| Общий recall (structured-RU) | 0,85 |
| Tier 1 — критичные Пдн (паспорт, СНИЛС, ИНН, карта, ФИО, телефон, почта): recall | 0,97 |
| Tier 1 — precision | 0,85 |
| Tier 2 — реквизиты, адрес, дата рождения: recall | 0,95 |
| Tier 3 — шумные и контекстные категории: recall (отчётный порог, CI им не блокируется) | 0,75 |
| Precision — обязателен для всех категорий | 0,8 |
NER-профиль (--ner): recall | 0,75 |
NER-профиль (--ner): precision | 0,7 |
Как проверить этот замер
- Команда замера
python -m eval.run_eval— тот же прогон стоит гейтом в CI- Перегенерация артефакта
python scripts/quality_report.py— собирает артефакт из этого прогона- Артефакт замера
api/quality_report.json— из него читают числа и эта страница, и главная; расхождение ловит тест- Проверка свежести артефакта
python scripts/quality_report.py --check-digests— сверит дайджесты корпуса и детектирующих источников (секунды, без прогона эвала);--check— полная сверка со свежим прогоном- Отпечаток замера (сверьте свой)
a560e37b46aecf434ccd5715e2e6e29ebd7cde9d9ab390deaf3ea4ac3db58a8f— sha256 от канонического JSON секции замера (ensure_ascii=False, sort_keys=True). Повторите прогон и сравните: у вас должен получиться этот же отпечаток; два прогона подряд дают побайтово одинаковый вывод. Команда печатает отпечаток:python scripts/quality_report.py --check-digests- Ревизия на момент замера
5e6d5289ed8710a301e3f9e00fbf6a4ae2a5b081— ревизия, на дереве которой выполнен прогон, а не коммит, в который добавлен артефакт: замер идёт до коммита, а коммит не может содержать собственный хеш. Свежесть артефакта определяется не этой строкой, а дайджестами корпуса и детектирующих источников —python scripts/quality_report.py --check-digests- Дата замера (UTC)
- 2026-10-10
- Тестовый корпус
- версия 4.3, 1483 записи, дайджест sha256:873dbb53a885
Чего эти числа не значат
- Корпус синтетический. Записи генерируются кодом (
eval/corpus/build_corpus.py, фиксированный seed), а значения собираются так, чтобы проходить собственные валидаторы детектора. Ничьи реальные данные в корпусе не используются — публиковать метрики на чужих документах мы не станем. - В корпусе есть adversarial-блок — 52 записей с обфускацией и кодированием (гомоглифы, percent-encoding, разбивка разделителями). Он измеряется вместе с остальными: отдельной цифры «на состязательных примерах» на этой странице нет, и читать общий recall как устойчивость к обфускации нельзя.
- Реальные документы клиентов в замер не входят. Пилот на настоящих договорах, реестрах и резюме — отдельная задача (issue #735), и он не сделан. Поэтому замер описывает корпус, а не «любой документ»: на живых сканах, сложных таблицах и нетиповых форматах числа будут другими, и увидеть их можно только этим пилотом.
- OCR и сканы меряются отдельно — мини-корпус сканов и команда
python -m eval.run_ocr_eval. На этой странице их чисел нет: замер воспроизводится только там, где есть движок распознавания (tesseract), а без него прогон честно сообщает, что мерить нечего, и отчёта не пишет. - Латентность не публикуем. Воспроизводимого замера времени ответа в репозитории нет (issue #733), а число, зависящее от железа замеряющего, читатель повторить не может. Вместо такого числа — явный отказ.
- Числа — свойство корпуса и версии детектора на дату замера, а не обещание на будущее. Поэтому артефакт хранит дайджесты корпуса и детектирующих источников: правка детектора без перегенерации артефакта расходится с ними и видна сразу, а полная сверка со свежим прогоном — команда
--check.
Специальные категории персональных данных. В таблице есть категории специальных данных (например, HEALTH): детектор у облачной и self-hosted версий общий, и замер честно показывает его работу. Но облачный сервис специальные категории не обрабатывает — при их обнаружении он отказывает в обработке, запрос отклоняется с сообщением об отказе, а содержимое не сохраняется и не передаётся. Для работы с такими документами предназначена self-hosted версия: /business. Формулировка отказа — в политике конфиденциальности и в оферте.
Что дальше
- Проверить свой текст или документ — детектор покажет категории найденных данных;
- Какие данные находим — полный список категорий на этом инстансе;
- API для разработчиков — если проверку нужно встроить в свой процесс.