Обезличивание данных перед отправкой в нейросеть: практический подход

Персональные данные не нужно отправлять модели, чтобы она обработала документ. Показываем, как заменять их метками, возвращать в ответ и проверять, что ничего не просочилось.

6 мин · · автоматизация · бизнес

Чтобы модель написала ответ клиенту или пересказала договор, ей не нужно знать, как зовут клиента и какой у него телефон. Нужен смысл документа. Поэтому разумная схема для нейросети в обработке документов такая: сначала заменить персональные данные метками, потом отправить текст, а в полученном ответе вернуть реальные значения на место. Ниже разбираем, что именно искать, как устроена замена и обратная подстановка, какой код для этого нужен, где метод ломается и как проверить результат до запуска в работу.

Обезличивание данных перед отправкой в нейросеть: зачем это нужно

Всё, что вы передаёте в запросе, уходит на сторону поставщика модели. Если в тексте есть ФИО, паспорта, телефоны, почты, номера карт, это персональные данные, и правила работы с ними лежат на вас. Обезличивание решает практическую часть: уменьшает объём чувствительного, что покидает ваш контур, и снижает ущерб при любой утечке (логи, ошибка в доступах, переписка).

Важно трезво понимать границы метода. Замена прямых идентификаторов метками не делает данные анонимными по определению: человека иногда можно узнать по контексту, например по редкой должности, уникальным обстоятельствам или сочетанию деталей. Юридические вопросы (что считается обезличиванием, на каком основании можно передавать данные, где их можно хранить) мы не решаем, обсудите их с юристом компании. Эта статья о технической стороне.

Какие данные искать

Что искатьКак находитьНадёжность
Emailрегулярное выражениевысокая
Телефонрегулярное выражение с учётом +7 и 8высокая, но проверьте свои форматы
Номер банковской картыцепочка цифр плюс проверка по алгоритму Лунавысокая
СНИЛСшаблон 123-456-789 01высокая
ИННцифры рядом со словом «ИНН»средняя: без контекста 10–12 цифр легко спутать с другими числами
Серия и номер паспорташаблон из 4 и 6 цифрсредняя: возможны ложные срабатывания
ФИО, названия организаций, адресасловарь из вашей CRM или распознавание именованных сущностейзависит от данных и языка
Номера договоров, заказовшаблон вашей нумерациивысокая, если шаблон известен

Для имён и организаций в русском тексте есть библиотеки распознавания именованных сущностей (например, Natasha), но их качество проверяйте на своих документах. Самый надёжный источник имён — ваши же справочники: клиенты, сотрудники, контрагенты. Они известны заранее, и искать их проще, чем угадывать.

Схема: заменить, отправить, вернуть

  1. Заменить. Каждое найденное значение получает метку вида [PHONE_1], [EMAIL_1], [PERSON_1]. Одинаковые значения получают одинаковые метки, чтобы модель понимала, что «Иванов» в начале и в конце документа — один человек.
  2. Отправить. В запрос уходит текст только с метками. В системном промпте скажите: «метки в квадратных скобках не изменяй, не пытайся раскрыть и сохраняй в ответе».
  3. Вернуть. В полученном ответе метки заменяются реальными значениями. Таблица соответствия хранится только у вас и в модель не уходит.

Код на Python

bash
import re
from collections import defaultdict


def luhn_ok(digits: str) -> bool:
    total = 0
    for i, ch in enumerate(reversed(digits)):
        d = int(ch)
        if i % 2 == 1:
            d *= 2
            if d > 9:
                d -= 9
        total += d
    return total % 10 == 0

Как это работает на примере:

bash
m = Masker()
m.add_known("PERSON", ["Иванов Пётр Сергеевич"])
src = ("Клиент Иванов Пётр Сергеевич (ivanov@example.com, +7 916 123-45-67) "
       "просит расторгнуть договор. Позвоните Иванову Петру Сергеевичу: +7 916 123-45-67.")
print(m.mask(src))

Результат:

bash
Клиент [PERSON_1] ([EMAIL_1], [PHONE_1]) просит расторгнуть договор. Позвоните Иванову Петру Сергеевичу: [PHONE_1].

Телефон и почта заменены, повторный телефон получил ту же метку. А вот «Иванову Петру Сергеевичу» осталось: словарь знал только именительный падеж. Это главная слабость метода для русского языка, и о ней следующий раздел.

Отправка запроса и возврат значений:

bash
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://api.zukko.pro/v1",
    api_key=os.environ["ZUKKO_API_KEY"],
)

SYSTEM = (
    "Ты помощник юриста. Кратко перескажи документ. Метки в квадратных скобках "
    "вроде [PERSON_1] или [PHONE_1] не изменяй, не раскрывай и сохраняй в ответе как есть."
)

Где метод ломается

  • Падежи и формы имён. «Иванов», «Иванову», «Ивановым» — разные строки. Добавляйте в словарь основные формы или основы слов; основа ловит больше, но может задеть однокоренные слова.
  • Контекст, который выдаёт человека. «Директор единственного в городе завода» остаётся в тексте. Прямых идентификаторов нет, а человека видно. Просматривайте типичные документы глазами и добавляйте правила.
  • Данные на картинках и в сканах. Если вы отправляете в модель изображение документа, текст на нём регулярными выражениями не замаскировать. Сначала распознайте текст, замаскируйте, потом отправляйте. Эта схема описана в статье как распознать PDF нейросетью.
  • Метки пропадают или меняются. Модель может переформулировать «[PERSON_1]» как «клиент» или исказить номер метки. Функция leftovers ловит лишние метки, а потерянные видны по сравнению числа меток до и после.
  • Таблица соответствия. Это самое чувствительное, что у вас есть: не пишите её в логи и не отправляйте в модель. Подробнее о логах: логирование LLM без утечки данных.

Как проверять

  1. Тестовый набор. Соберите 30–50 типичных документов, прогоните через mask и просмотрите результат. Особенно ищите пропущенные имена и адреса.
  2. Повторный поиск на выходе маски. Прогоните обезличенный текст через те же шаблоны ещё раз: остаться ничего не должно.
  3. Канарейки. Вставьте в тестовый документ заведомо вымышленные данные (почту, телефон, имя) и убедитесь, что они заменены. После каждого изменения правил запускайте этот тест.
  4. Выборочная ручная проверка того, что реально уходит в запрос, на первых сотнях документов.
  5. Метрики. Считайте число замен по типам и следите за аномалиями: резкое падение числа телефонов в потоке означает, что формат поменялся и регулярное выражение его не видит.

Для дополнительной страховки заведите для такой задачи отдельный ключ с дневным лимитом и списком разрешённых моделей (об этом подробнее).

Сколько это стоит

Маскирование выполняется у вас локально и ничего не стоит, метки добавляют к тексту лишь несколько токенов. Цены модели, на 18 октября 2026, за 1M токенов. Допустим (условный пример), 500 договоров по 6 000 токенов, ответ по 500 токенов. Вход 3 000 000, выход 250 000.

  • claude-sonnet-5-5 (вход $0.4, выход $2): 3 000 000 × 0.4 / 1 000 000 + 250 000 × 2 / 1 000 000 = 1.20 + 0.50 = $1.70.
  • deepseek-v4.1-flash ($0.013 / $0.038): 3 000 000 × 0.013 / 1 000 000 + 250 000 × 0.038 / 1 000 000 = 0.039 + 0.0095 ≈ $0.05.

Свежие цены всегда в ответе GET https://api.zukko.pro/v1/models.

Частые вопросы

Достаточно ли регулярных выражений?

Для формальных данных (почты, телефоны, карты, СНИЛС) обычно да, если шаблоны проверены на ваших форматах. Для имён, организаций и адресов нужны словари из ваших справочников или распознавание сущностей, а выборочная проверка обязательна.

Можно ли просить модель саму найти персональные данные?

Можно как вторую линию проверки, но не как единственную: для этого текст придётся отправить модели в исходном виде, а это то, чего вы хотели избежать. Запускать такую проверку имеет смысл локально, на модели в вашем контуре.

Что делать, если метки в ответе изменились?

Не подставляйте значения вслепую. Повторите запрос, усилив инструкцию, или отправьте документ на ручную обработку. Функция leftovers из примера отлавливает такие случаи.

Как подключиться из России?

Из России баланс можно пополнить через СБП, картой MasterCard или в криптовалюте. Ключ создаётся в кабинете Zukko.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.

Обезличивание данных перед отправкой в нейросеть · Zukko