Перейти к содержимому
Бизнес-анализ

Автоматическое обезличивание данных перед передачей в AI-модель

Локальный пайплайн находит чувствительные данные и заменяет их на обратимые токены перед отправкой в LLM или в датасет для обучения. Никаких внешних API — весь процессинг внутри локального контура.

95%+

precision по данным

ориентир на синтетической/выдуманной выборке (без реальных ПДн)

< 1 с

на документ ~1000 слов

CPU-inference, без GPU

0

внешних API вызовов

весь процессинг локально

4–7 дней с учетом анализа архитектуры

до развёртывания

Docker + REST API / n8n

Проблема

Ручная вычитка данных перед AI была медленной и ненадёжной. Регулярные выражения покрывали только простые паттерны — ФИО, адреса и названия организаций пропускались. Риск утечки ПДн во внешние LLM.

Решение

Построен локальный пайплайн: ансамбль детекторов (Natasha NER + Presidio), токенизация с маппингом, повторная валидация чистоты выходных данных и опциональная детокенизация ответов модели. Никакого внешнего трафика.

Результат

95%90%

95%+ precision по данным, 90%+ по организациям на синтетической выборке. Встраивается в существующие потоки через REST API или n8n.

Контекст и проблема

Компании, которые хотят использовать LLM для анализа документов, логов, CRM-выгрузок, сталкиваются с одним блокером: данные нельзя отправлять во внешние API. 152-ФЗ, корпоративные ИБ-политики, NDA — всё это делает прямую передачу дата-сетов в AI невозможной без предварительной очистки.

Два типичных сценария, которые встречаются в командах:

  • Ручная вычитка перед отправкой — аналитик перечитывает каждый документ и удаляет ФИО, телефоны, названия компаний. Медленно, зависит от человека, не масштабируется при батчевой обработке.
  • Полный отказ от LLM для чувствительных задач — потеря целого класса AI-сценариев: дообучение на корпоративных данных.

Регулярные выражения — частичное решение: они находят email и номера телефонов, но пропускают составные ФИО, адреса в свободной форме, названия организаций и даты в нестандартных форматах.

Ключевая проблема — не скорость, а системность: единоразовый скрипт под конкретную задачу не решает проблему — он создаёт новый источник риска, который никто не сопровождает.

Решение: шестиэтапный пайплайн

Идея: убрать риск до того, как данные покинут защищённый контур, и сделать это повторяемым, аудируемым процессом — а не разовым скриптом.

  1. Загрузка сырого датасета — TXT, JSON, CSV, логи обращений. Парсинг с учётом структуры: для JSON и таблиц обезличивание по полям, а не подстроками.

  2. Детекция сущностей (ансамбль) — два детектора параллельно:

    • Natasha (Slovnet NER, BERT-based) — ФИО, организации, локации, даты на русском языке.
    • Presidio (Analyzer) — email, телефоны, паспортные данные, ИНН, номера банковских карт, IP-адреса.
  3. Токенизация — каждая найденная сущность заменяется на обратимый токен вида [PERSON_001], [ORG_014], [PHONE_003]. Маппинг сохраняется в защищённый vault-файл.

  4. Валидация — повторный проход детектором по выходному тексту. Если PII осталось — документ помечается как требующий ручной проверки, а не тихо пропускается.

  5. Передача в LLM или обучение — чистый датасет без чувствительных данных. Модель работает с токенами, структура и семантика сохранены.

  6. Детокенизация (опционально) — ответ модели возвращается в защищённый контур, токены заменяются обратно на оригинальные значения по vault-маппингу. Пользователь видит персонализированный ответ; PII никогда не покидал периметр.

Ключевые архитектурные решения

Почему ансамбль детекторов, а не один инструмент?

Стандартные решения на базе spaCy слабо работают с Русским языком. Natasha закрывает базовую NER-задачу, но даёт ложные срабатывания на составных ФИО и коротких названиях организаций. Presidio — сильный на структурированных атрибутах (email, ИНН), но не обучен на русскоязычных именованных сущностях. Ансамбль с пост-фильтром по словарям стоп-слов даёт точность выше, чем каждый детектор по отдельности.

Почему персистентный маппинг, а не одноразовая замена?

«Иванов Иван Иванович» и «Иван Иванов» в одном датасете — это один человек. Если токены разные — семантика для обучения теряется: модель учится, что [PERSON_001] и [PERSON_047] — разные сущности. Персистентный маппинг на уровне сессии решает эту проблему: одна сущность → один токен во всём датасете.

Почему минимум AI, максимум детерминированного кода?

Токенизация, vault, валидация, детокенизация — всё это детерминированный код без LLM. AI-компонент (Natasha NER) используется только там, где задачу нельзя решить правилами: распознавание именованных сущностей в свободном тексте. Такой подход даёт воспроизводимость, аудируемость и отсутствие «галлюцинаций» — критично для задач безопасности данных.

Почему полностью локальная обработка?

Это следует напрямую из задачи. Решение, которое отправляет данные для обезличивания во внешний API, противоречит самой цели. Natasha inference работает на CPU с 4 ГБ RAM — GPU не требуется. Docker-контейнер разворачивается в закрытом контуре заказчика без внешнего трафика.

До и после

ПараметрДоПосле
Метод обезличиванияРучная вычитка или regexАнсамбль NER + правила
Покрытие ФИОНизкое (зависит от внимания)95%+ precision (ориентир)
Покрытие организацийПрактически нет90%+ precision (ориентир)
Время на документ ~1000 словНесколько минут вручную< 1 сек на CPU
АудируемостьНет следаКаждая замена логируется
ОбратимостьНевозможнаVault-маппинг, детокенизация
МасштабЕдиничные документыБатчи 10k+ записей
Внешний трафикНикакого

Что оказалось технически сложным

Русскоязычный NER и ложные срабатывания. Natasha даёт ложные срабатывания на общеупотребительных словах, которые совпадают с именами («Роман», «Вера», «Надежда»), и на аббревиатурах организаций. Решение — пост-фильтр по словарям стоп-слов и контекстная проверка: если слово окружено типичными контекстными маркерами имени, токенизируем; если нет — пропускаем.

Структурированные данные. Для JSON и CSV нельзя просто искать и заменять подстроки в плоском тексте — нужно парсить структуру, определять типы полей и применять обезличивание выборочно. Поле comment обезличиваем; поле product_id — нет.

Консистентность маппинга. Один и тот же человек может быть записан как «Иванов И.И.», «Иван Иванович Иванов», «Иван». Нормализация перед маппингом + нечёткое сопоставление по Левенштейну позволяют присвоить одинаковый токен.

Стек

  • NER (русский): Natasha — Slovnet NER (BERT-based), Navec-эмбеддинги для контекста
  • NER (структурированные атрибуты): Microsoft Presidio — Analyzer + Anonymizer
  • Язык и фреймворки: Python 3.11, Pydantic (валидация схем входных данных), FastAPI (REST API для встраивания)
  • Интерфейсы: CLI для ручных запусков; HTTP-нода для встраивания в n8n
  • Тестирование: pytest — 100+ синтетических примеров (договоры, логи, CRM-выгрузки)
  • Разработка: Кастомная — рефакторинг пайплайна, покрытие тестами
  • Инфраструктура: Docker — воспроизводимое развёртывание; 4 ГБ RAM, CPU-inference без GPU
  • Принципиально: никаких внешних LLM API — весь процессинг локальный

Результат

Точность детекции (ориентир на синтетической/выдуманной выборке из 100 документов, реальные ПДн не применялись):

  • ФИО — precision 95%+
  • Организации — precision 90%+
  • Структурированные атрибуты (email, телефон, ИНН) — >99% (Presidio + regex)

Скорость: < 1 сек на документ ~1000 слов на CPU — батч из 10 000 документов обрабатывается за часы, не дни.

Аудируемость: каждая замена логируется: исходная сущность (в vault), тип, позиция в тексте, уверенность детектора. Vault хранится отдельно от данных.

Разблокированные сценарии: команды, которые откладывали AI-инициативы из-за требований ИБ, получают пред-процессор, который проходит согласование — данные физически не покидают контур.

Готовность к развёртыванию: шаблон разворачивается за 4–7 дней. REST API позволяет встроить в существующий пайплайн без переписывания. Docker-контейнер воспроизводим на любой инфраструктуре заказчика.