Проверка ответов модели: правила, LLM и regex для PII
Проверка ответов модели помогает поймать PII, рискованные советы и спорные формулировки. Разберем, где хватает regex, а где нужен второй LLM.

Где ответ модели создает риск
Самый неприятный ответ модели часто выглядит спокойно и "разумно". В нем нет ругани, явной угрозы или странных символов. Он похож на обычное письмо в поддержку, сводку по клиенту или краткую юридическую справку. Поэтому риск замечают поздно: человек читает текст, кивает и отправляет его дальше.
С PII это происходит постоянно. Модель может вставить в ответ телефон, почту, номер паспорта, адрес или кусок договора, потому что увидела эти данные в истории диалога, в RAG-контексте или в системной подсказке. Для пользователя это выглядит как "удобная персонализация", а для компании это уже инцидент. Один лишний номер телефона в чате легко пропустить. Сто таких ответов за день - и это уже утечка, с которой потом разбираются ИБ, юристы и владелец продукта.
Проблема шире, чем прямой слив данных. Модель может дать совет, который звучит уверенно, но ведет команду в юридически опасную зону. Например, предложить отправить клиенту чужие реквизиты "для ускорения", скрыть обязательное уведомление или сформулировать отказ так, что он нарушит внутренние правила банка, страховой или маркетплейса. Текст остается гладким. Риск сидит в смысле.
Фраза вроде "это не юридическая консультация" почти ничего не меняет. Если ассистент уже выдал вредный совет, приписка внизу не убирает вред. Сотрудник копирует ответ в письмо, оператор озвучивает его клиенту, бот делает следующий шаг автоматически. Последствия создает действие, а не оговорка.
Ручная модерация быстро упирается в потолок. На малом потоке редактор или оператор еще может просматривать ответы. В продакшене счет идет на тысячи и десятки тысяч сообщений. Люди устают, пропускают однотипные ошибки, спорят о серых случаях и тормозят сценарий. Если ответ нужен за 2 секунды, проверка человеком уже ломает опыт. Если ставить людей на каждый исходящий текст, стоимость растет быстрее пользы.
Проверка ответов модели нужна не только для редких катастроф. Она нужна для обычных, внешне нормальных сообщений. Самые дорогие ошибки редко выглядят как авария. Чаще это вежливый, складный текст, который нельзя было показывать пользователю.
Что ловить перед показом ответа
Перед отправкой ответа смотрят не только на грубые ошибки. Самые частые проблемы - утечка персональных данных, слишком уверенные юридические формулировки и обещания, которые модель не имеет права давать. Именно здесь и нужна проверка ответов модели: спокойный на вид текст может создать реальный риск для компании.
В ответ чаще всего попадают не редкие данные, а обычные куски из переписки, CRM или прошлых запросов. Модель может вернуть телефон, email, адрес, номер договора, дату рождения, паспортные данные, ИНН, СНИЛС, последние цифры карты или полный номер счета. Иногда она не цитирует их целиком, а собирает профиль из нескольких фрагментов: "Иван Петров, 12.04.1987, живет по адресу..." Для 152-ФЗ и внутренних правил этого уже достаточно, чтобы создать проблему.
Рядом с PII стоит ловить и секреты. В ответах всплывают API-ключи, токены, внутренние ID, номера заявок и служебные ссылки. Пользователь их не просил, но модель могла подтянуть их из контекста и вставить "для удобства". Так и происходят тихие утечки.
Обычно перед показом ответа ищут четыре типа сигналов:
- прямые идентификаторы: паспорт, СНИЛС, ИНН, номер счета, карта, телефон
- связки данных: ФИО вместе с датой рождения, адресом или местом работы
- учетные данные и секреты: токены, ключи, номера сессий
- ссылки на внутренние документы, тикеты и переписку
С цифрами все проще. Опаснее формулировки, которые звучат как юридический совет. Если модель пишет "вы можете передавать эти данные без согласия", "это точно соответствует 152-ФЗ" или "штрафа не будет", такой ответ лучше не показывать автоматически. Даже фраза вроде "закон разрешает" без условий уже рискованна, потому что право почти всегда зависит от цели обработки, роли оператора, договора и согласия.
Еще одна ловушка - обещания результата. Модель любит говорить "банк обязан вернуть деньги", "суд примет вашу сторону", "жалобу точно удовлетворят". Для клиента это выглядит как позиция компании, а не как черновик машины.
Спорные случаи не стоит резать автоматически. Их лучше отправлять на ручную проверку. Сюда попадают замаскированные данные вроде "****1234", цитаты из договора, пересказ нормы закона своими словами, данные публичных лиц, а также ответы, где модель смешала совет по продукту с трактовкой права.
Пограничный пример: "Можно хранить логи в другой стране, если убрать имена?" Здесь мало найти PII в LLM. Нужно понять, о каких логах идет речь, кто оператор, что именно уже маскируют и какие правила действуют в компании.
Хороший фильтр перед показом ответа не пытается понять весь смысл текста сразу. Он сначала ловит то, что видно без сложного анализа, а затем отправляет неоднозначные ответы человеку или в отдельную модель для проверки. Иначе regex для PII даст слишком много пропусков, а одна только LLM начнет пропускать то, что ей показалось безобидным.
Где правила и regex работают лучше всего
Правила и regex полезны там, где риск можно описать явно. Если у фрагмента есть понятный шаблон, машина ловит его быстро, дешево и почти без споров. Для первой линии защиты это часто лучший вариант.
Они особенно хороши для форматов, которые легко узнать по символам и длине:
- email с типичной структурой
- номера телефонов в ожидаемых масках
- номера карт с проверкой длины и, при желании, контрольной суммы
- серии и номера паспорта в заданном формате
Такой фильтр удобно ставить прямо перед показом ответа пользователю. Если найдено совпадение, лучше не показывать строку как есть. Проще сразу замаскировать часть значения: оставить 2-4 символа, а остальное скрыть. Это снижает риск даже тогда, когда модель случайно вставила чужие данные в обычный текст.
Правила полезны не только для PII. Они хорошо работают на простых ограничениях ответа: слишком длинный текст, неожиданный язык, запрещенная структура, например JSON там, где нужен короткий абзац для клиента. В поддержке банка это частый случай: оператор просит короткий ответ без внутренних пометок, а модель вдруг выдает длинное объяснение с кусками служебного текста. Простое правило отсекает такой ответ быстрее, чем отдельная модель.
Для узких сценариев хорошо работают списки запрещенных фраз. Если в юридически чувствительном потоке нельзя писать "гарантируем доход", "это не требует согласия" или "передайте полный номер карты", такие фразы лучше ловить отдельным словарем. Его плюс в прозрачности: команда видит, что именно блокируется, и может быстро обновить список.
Но regex не понимает смысл. Он найдет "1234 5678 9012 3456", но не поймет, что фраза "можно игнорировать согласие клиента" опаснее любой цифры. Он видит форму, а не контекст. Поэтому правила хороши как быстрый и предсказуемый слой, но не как единственная защита.
Даже если в стеке уже есть маскирование PII на уровне запроса, проверка финального ответа все равно нужна. Пользователь видит именно ответ, и проверять нужно именно его. В системах вроде RU LLM это особенно удобно учитывать сразу: маскирование PII встроено в запросы, но финальный текст перед показом все равно лучше прогонять через отдельные правила.
Когда нужна отдельная модель
Отдельная модель для проверки нужна там, где правила и regex видят форму, но не понимают смысл ответа. Это обычно происходит с "мягкими" рисками: модель не выводит номер паспорта напрямую, но просит прислать его целиком, обещает юридический результат или дает совет, после которого компания получит жалобу.
Проверяющей модели мало одного текста ответа. Ей стоит отдавать сам ответ, исходный запрос пользователя и короткий контекст: что это за сценарий, кто пользователь, что ассистенту разрешено делать. Один и тот же ответ в чате банка и во внутреннем тестовом стенде читается по-разному.
Лучше просить такую модель ставить метки риска, а не переписывать ответ заново. Иначе смешиваются две задачи: контроль и генерация. Потом трудно понять, почему блок сработал, что именно модель сочла опасным и можно ли это правило проверить на других примерах.
Обычно хватает четырех классов риска:
- PII и лишний сбор персональных данных
- юридический совет вместо общей справки
- обещание результата, гарантии, вводящие в заблуждение формулировки
- вредный совет, который подталкивает к обходу правил или небезопасным действиям
Для каждого класса нужен свой порог. В банковском сценарии пропуск ответа с запросом полного номера карты или с прямым юридическим выводом стоит дорого. Ложный блок тоже неприятен, но обычно дешевле, чем пропуск. В FAQ для низкорисковых тем баланс может быть другим: там лишняя блокировка бьет по качеству сервиса сильнее.
Небольшой пример. Пользователь спрашивает, можно ли "безопасно" отправить фото паспорта для ускорения проверки. Ассистент отвечает: "Да, отправьте разворот целиком, так мы точно одобрим заявку". Regex заметит не все. Отдельная модель увидит сразу две проблемы: сбор лишних PII и обещание результата.
Такой слой проверки редко получается точным с первой попытки. Сохраняйте промахи: что заблокировали зря, что пропустили, какой был запрос и какой ответ ушел на экран. По этим примерам правят промпт проверки, пороги и набор меток. Если у вас уже есть аудит-трейлы на каждый запрос, как в RU LLM, разбор таких случаев идет заметно быстрее.
Как собрать каскад проверки
Один фильтр почти всегда дает перекос. Только regex пропустит смысловой риск, а только вторая модель окажется дорогой и медленной. Для проверки ответов модели лучше работает каскад, где каждый слой решает свою простую задачу.
Сначала ставят самые дешевые проверки. Regex и простые правила хорошо ловят то, что похоже на PII в LLM: номер телефона, почту, паспортные шаблоны, ИНН, карты, явные просьбы составить опасный юридический совет от имени компании. На этом этапе не нужно угадывать смысл текста. Нужно быстро снять очевидные случаи за миллисекунды.
Потом добавляют контекстные правила. Один и тот же ответ может быть приемлем в закрытом кабинете сотрудника и недопустим в публичном чате. Поэтому проверка должна учитывать роль пользователя, канал, тип запроса и режим продукта. Ответ для внутреннего аналитика, ответ для клиента банка и ответ для оператора поддержки проходят разный набор правил.
Если первые два слоя не дали ясного решения, спорный ответ уходит во вторую модель. Ей не стоит отдавать весь поток. Лучше отправлять только сомнительные случаи: regex что-то нашел, но не уверен; правила конфликтуют; в тексте есть намек на персональные данные или правовую трактовку без прямого шаблона. Тогда отдельная модель для проверки действительно окупается: она разбирает контекст там, где правила слепы.
У каскада должно быть всего четыре действия:
- показать ответ без изменений
- замаскировать найденные фрагменты
- переписать ответ в безопасной форме
- остановить выдачу и вернуть отказ
Чем меньше действий, тем проще отладка. Если система умеет двадцать статусов, команда перестает понимать, почему ответ дошел до пользователя.
Что писать в журнал
Каждое решение нужно записывать вместе с причиной. Храните не только итог, но и сработавшие проверки, короткий фрагмент сигнала, уровень риска и версию политики. Тогда через месяц можно понять, почему один ответ замаскировали, а другой остановили.
Если вы уже гоняете трафик через RU LLM, полезно передавать в этот журнал policy_version и метки канала в каждый запрос. Такой след потом экономит много времени при разборе инцидентов и спорных блокировок.
Пример на сценарии банка
Клиент пишет в чат банка: "Почему мне начислили штраф по кредиту? Мой паспорт 45 08 123456, проверьте договор и скажите, могу ли я не платить". Такой запрос опасен сразу по двум причинам. В нем есть PII, и он толкает модель к ответу, который может выглядеть как юридическая консультация.
Первый фильтр здесь совсем простой, и это плюс. Regex находит шаблон российского паспорта, скрывает номер и не пускает его дальше в логи, аналитику и подсказки для модели. В рабочем тексте остается вариант вроде: "Мой паспорт [СКРЫТО]". Это не решает всю задачу, но убирает лишний риск почти без задержки.
Потом срабатывают правила. Если черновик ответа содержит фразы вроде "для вас нет юридических рисков", "штраф точно незаконен" или "можете не платить", система останавливает отправку. Для банка это плохой ответ даже в том случае, если остальной текст звучит спокойно и убедительно. Жесткие правила хорошо режут такие обещания. Здесь не нужна тонкая оценка. Здесь нужен прямой запрет.
Но правила не всегда ловят более мягкие формулировки. Модель может написать: "Судя по описанию, штраф можно оспорить без последствий". Формально прямого обещания тут нет, но смысл почти тот же. На этом шаге помогает отдельная модель для проверки. Она смотрит на ответ целиком и помечает его как похожий на юридический совет.
После такого флага система не должна молча переписать ответ и сделать вид, что все в порядке. Лучше попросить безопасную переформулировку и позвать сотрудника. Новый ответ может звучать так: "Я не могу оценить ваш правовой риск или советовать, платить штраф или нет. Я могу объяснить, как банк обычно считает штрафы, и передать вопрос специалисту с доступом к вашему договору".
На одном этом примере видно, зачем нужен каскад. Regex убирает паспортные данные. Правила режут явные опасные обещания. Вторая модель ловит смысл, который не помещается в шаблон. А сотрудник берет на себя тот момент, где банку уже нельзя полагаться только на автоматическую проверку.
Ошибки, которые дают ложную безопасность
Многие команды тщательно фильтруют входной запрос, а ответу модели доверяют почти вслепую. Это частая ошибка. Пользователь может не прислать PII, но модель все равно вернет номер телефона, кусок договора, ФИО из контекста чата или слишком смелую юридическую формулировку.
Для систем с российскими данными это особенно неприятно. Если вы строите проверку под 152-ФЗ, смотреть нужно на весь путь ответа, а не только на промпт. Иначе защита выглядит аккуратно на схеме, но не ловит реальный риск в проде.
Вторая ловушка - искать "любой набор цифр" и считать это защитой. Такой regex быстро ломает обычные сообщения: суммы, даты, номера заказов, последние 4 цифры карты, коды заявок. В итоге команда видит много шума, устает от алертов и начинает пропускать уже настоящие срабатывания.
Лучше проверять классы отдельно. У паспорта один формат, у телефона другой, у ИНН и СНИЛС свои признаки. Там, где можно, добавляйте контекст, длину, контрольные суммы и соседние слова. Простое правило часто полезнее слишком широкого шаблона.
Отдельная модель тоже легко дает ложную уверенность, если дать ей слишком мало контекста. Если проверяющая модель видит только финальный ответ без исходного вопроса, без системных правил и без источника цитаты, она начинает угадывать. В одном случае она блокирует безопасное резюме, в другом пропускает рискованный совет, потому что не понимает, что текст относится к юридическому спору.
Еще одна ошибка - смешивать блокировку, маскирование и переписывание в одном шаге. Тогда команда не понимает, что именно произошло: система нашла PII, скрыла его или просто смягчила ответ. Для аудита это плохая схема.
Обычно процесс лучше разделять на три шага:
- сначала найти риск
- потом выбрать действие
- потом изменить текст или остановить ответ
Последняя проблема тише, но дороже всего. Команды часто складывают все ложные срабатывания в одну папку "ошибки фильтра". Так вы не увидите, что телефон ловится хорошо, а юридические риски почти не размечены, или что email режется точно, а ИНН дает море шума.
Разбирайте метрики по классам. Для каждого класса задайте свой порог, свою логику и свой тестовый набор. Через пару недель обычно становится видно, какие 1-2 категории создают почти весь шум. Их и нужно чинить первыми.
Быстрая проверка перед запуском
Перед релизом нужен не идеальный контур, а проверка, которая быстро покажет слабые места. Если ответ уходит пользователю без ручного просмотра, у команды должна быть простая таблица: какой риск вы ловите и что система делает в каждом случае.
Обычно хватает таких классов:
- явные персональные данные: система маскирует фрагмент или не показывает ответ
- скрытые PII в свободном тексте: ответ уходит на более строгую проверку второй линией
- юридически рискованные формулировки: система блокирует ответ и просит модель переформулировать его в нейтральном виде
- неуверенные случаи: ответ не блокируют молча, а отправляют в ручной разбор или в отдельную очередь
Синтетических примеров мало. Нужен тестовый набор из реальных диалогов, очищенных и размеченных вашей командой. Возьмите не только плохие ответы, но и нормальные, чтобы фильтр не начал резать безопасный текст. Хорошая практика - добавить к каждому примеру ожидаемое действие: пропустить, замаскировать, переписать, заблокировать.
Если фильтр сработал, это должно быть видно сразу. Разработчик и оператор должны понимать, что именно произошло: какое правило или regex совпали, какой фрагмент текста вызвал тревогу, какую оценку дала отдельная модель и почему ответ ушел в блок. Иначе получится черный ящик, который сложно чинить и еще сложнее объяснять бизнесу.
Задержку тоже лучше измерять по слоям, а не одним числом. Regex может занимать миллисекунды, правила - чуть больше, а отдельная модель проверки легко добавит сотни миллисекунд. Смотрите хотя бы p50 и p95 для каждого шага. Если тяжелая проверка замедляет ответ слишком сильно, запускайте ее только после срабатывания простых фильтров.
Логи и разбор инцидентов должны учитывать 152-ФЗ с самого начала. Не храните в логах сырой ответ, если в нем могут остаться паспортные данные, телефон или адрес. Храните маскированный текст, идентификатор политики, время, решение фильтра и аудит-трейл по запросу. Если контур работает через RU LLM, встроенные метки AI-Law, маскирование PII и аудит-трейлы упрощают эту часть, но правила хранения и доступа все равно утверждает ваша команда.
Такой прогон перед запуском часто находит неприятную правду: проблема не в модели, а в том, что никто заранее не решил, что делать с каждым типом риска.
Что делать дальше
Не пытайтесь закрыть все случаи сразу. Начните с 20-30 частых сценариев. Возьмите реальные диалоги из пилота или поддержки: модель повторяет паспортные данные клиента, пересказывает текст договора, отвечает на претензию, советует, что писать в жалобе. Такой набор быстро показывает, где проверка ответов модели действительно снижает риск, а где она просто режет полезные ответы.
Не сводите все к одной цифре. Иначе команда видит общий процент и не понимает, что именно сломано.
Считайте отдельно утечки PII, отдельно ответы с юридическим риском и отдельно ложные блоки, когда система режет нормальный ответ. Для каждого сценария храните причину срабатывания и итоговое решение.
После этого задайте порог для каждого класса риска. Например, пропуск телефона или номера карты почти всегда требует жесткой блокировки или маскирования. А спорная юридическая формулировка чаще требует не блокировки, а перевыпуска ответа по более строгому шаблону. Ложные блоки тоже стоят денег: сотрудник ждет, клиент раздражается, команда перестает доверять фильтру.
Без аудита такая схема быстро разваливается. Сохраняйте исходный запрос, ответ модели, сработавшие правила, версию промпта, решение проверяющего слоя и финальный текст, который ушел пользователю. Тогда спорные случаи можно разбирать по фактам, а не по памяти в чате через неделю.
Маскирование тоже лучше включить сразу. Оно не заменяет проверку, но заметно уменьшает вред в логах, тестовых выгрузках и ручных разборах. Если у вас несколько команд, это особенно полезно: аналитики и разработчики видят кейс, но не получают лишние персональные данные.
Если вы работаете через RU LLM, такую схему проще собрать в одном контуре. Можно опереться на единый OpenAI-совместимый эндпоинт, встроенные метки AI-Law, аудит-трейлы и маскирование PII, а разбор инцидентов вести по журналу запросов. Для команд с российскими требованиями это часто практичнее, чем собирать эти части по разным сервисам и потом вручную сводить картину.
Дальше все просто: раз в неделю добавляйте 5-10 новых кейсов из продакшена и убирайте правила, которые дают шум. Так каскад растет на живых данных, а не на догадках.