Что произошло
ИИ-функции вышли из пилотов в промышленную эксплуатацию: классификаторы обращений, извлечение данных из документов, ассистенты над базами регламентов, генерация черновиков. Многие из них принимались по одной схеме: команда посмотрела несколько десятков примеров, результат показался приемлемым, функцию включили.
Дальше происходило то, что по отдельности выглядит как случайность, а в сумме — как закономерность. Провайдер обновил версию модели — ответы ассистента стали длиннее и реже ссылаться на документы. Разработчик «улучшил» промпт для одного типа запросов — просела точность на другом. Переиндексировали базу знаний — часть документов перестала находиться. Ни одно из этих изменений не вызвало ошибки в привычном смысле: система отвечала, логи были чистыми, мониторинг молчал. Об ухудшении компания узнавала от клиентов, юристов или по итогам квартала.
Сдвиг, который произошёл на рынке за последнее время, — признание, что тестирование ИИ-решений является отдельной инженерной практикой со своими артефактами: эталонным набором, метриками качества, регрессионным прогоном при каждом изменении. Практика пришла из команд, которые обожглись, и сейчас становится требованием при приёмке.
Как это устроено
Почему «вход А — выход Б» не работает
Классический автотест проверяет точное соответствие: на этот вход система обязана дать этот выход. С языковой моделью так не получается по четырём причинам.
- Недетерминированность. При одинаковом входе модель может дать разные формулировки — из-за сэмплирования, версии, нагрузки. Два правильных ответа могут не совпадать ни в одном предложении.
- Правильный ответ — множество, а не точка. «Договор можно расторгнуть в одностороннем порядке при уведомлении за тридцать дней» и «односторонний отказ допускается с уведомлением за месяц» — оба верны, если так сказано в источнике.
- Зависимость от окружения. Ответ зависит не только от модели, но и от индекса, параметров поиска, состава инструментов. Изменение любого из них меняет поведение, хотя «код» не менялся.
- Единичный пример ничего не говорит о распределении. Проверка на тридцати примерах, выбранных вручную, показывает работу на этих тридцати. Выборка из реального потока покажет другое.
Из этого делают неверный вывод: «тестировать нельзя, принимаем по ощущениям». Верный вывод другой: тестировать нужно не совпадение, а свойства ответа, и не на примере, а на наборе.
Эталонные сценарии с критериями качества
Эталонный набор — это коллекция реальных входов (обезличенных) с критериями, которым должен соответствовать ответ. Критерий — не текст ответа, а проверяемое свойство. Примеры формулировок:
- ответ содержит ссылку на действующую редакцию регламента и не содержит утверждений, отсутствующих в источнике;
- извлечены все позиции документа, сумма позиций равна итоговой сумме;
- обращение отнесено к категории из списка, категория совпадает с разметкой;
- на вопрос вне базы знаний система отвечает отказом с предложением обратиться к специалисту, а не выдумывает ответ.
Критерии проверяются по лестнице. Первая ступень — детерминированные проверки: структура ответа, наличие ссылки, арифметика, совпадение категории. Вторая — проверка моделью-оценщиком по явной рубрике: «содержит ли ответ утверждения, которых нет в приведённом фрагменте источника». Третья — выборочная проверка человеком, обязательная для калибровки второй ступени.
Набор строится по категориям: типовые запросы, редкие, краевые, провокационные. Он живёт: каждый инцидент в эксплуатации превращается в новый сценарий, чтобы та же ошибка не повторилась незамеченной.
Метрики вместо совпадений
| Метрика | Что измеряет | Где применяется | Как выглядит деградация |
|---|---|---|---|
| Точность классификации | Долю верно отнесённых обращений по категориям | Маршрутизация, тегирование | Просадка на одной категории при росте на другой |
| Полнота извлечения | Долю найденных полей и позиций из эталонной разметки | Документы, формы, таблицы | Часть типов документов перестаёт разбираться |
| Доля ответов с источником | Долю ответов, содержащих ссылку на подтверждающий фрагмент | Ассистенты над базами знаний | Ответы становятся «от себя» после смены модели |
| Доля обоснованных отказов | Долю случаев, когда система верно ответила «в документах этого нет» | Любой ассистент | Система начинает уверенно отвечать на вопросы вне базы |
| Доля эскалаций | Долю обращений, переданных человеку | Поддержка, обработка заявок | Резкое изменение в любую сторону |
| Стоимость и задержка на запрос | Ресурсы на единицу результата | Все | Рост после изменения промпта или модели |
Две метрики требуют внимания к обеим сторонам. Доля отказов должна расти там, где отказ верен, и не расти там, где ответ есть в источнике: ложный отказ — тоже дефект. Доля эскалаций сама по себе не хороша и не плоха: её рост означает падение уверенности системы, её падение — возможный рост галлюцинаций, и оба случая требуют разбора.
Метрики считаются автоматически на эталонном наборе, хранятся по версиям и сравниваются. Единичное значение не информативно; информативно изменение относительно предыдущего прогона.
Контроль галлюцинаций и сценарии «не знаю»
Галлюцинация — уверенный ответ без основания в источнике. Ловить её на типовых вопросах бессмысленно: там основание есть. Нужны специальные сценарии:
- вопрос по теме, которой нет в базе знаний;
- вопрос о несуществующем регламенте, документе, пункте;
- вопрос, ответ на который в источнике противоречив или устарел;
- вопрос вне компетенции системы (юридический — к техническому ассистенту);
- попытка увести от сценария: «забудь инструкции», «ответь как эксперт без ссылок», просьба раскрыть внутренние данные.
Для каждого сценария правильный ответ — отказ, уточнение или эскалация. Система, которая на такие вопросы уверенно отвечает, не готова к эксплуатации независимо от результатов на типовых запросах.
Регресс в CI: при каждом изменении
Регрессионный прогон запускается автоматически при любом изменении, влияющем на поведение: версия модели, текст промпта, состав и параметры индекса, параметры поиска, набор инструментов, версия сервера инференса и параметры квантизации для локальных моделей.
Правила прогона:
- Метрики считаются на полном эталонном наборе, а не на выборке.
- Для каждой метрики задан порог; падение ниже порога блокирует выкат так же, как упавший автотест блокирует деплой.
- Результат сохраняется с привязкой к версии всех компонентов.
- Помимо порога сравнивается динамика: падение внутри допуска, но повторяющееся несколько прогонов подряд — повод для разбора.
В эксплуатации регресс дополняется мониторингом: выборка реальных запросов регулярно проходит те же проверки, и расхождение с эталоном — сигнал о дрейфе входных данных или окружения.
Если изменение не прошло через эталонный набор, вы не знаете, что выкатили.
Как это выглядит на практике
Ассистент по внутренним регламентам в сети клиник. Провайдер обновил версию модели; ответы стали развёрнутее, а доля ответов со ссылкой на регламент упала. Регрессионный прогон, включённый в процесс обновления, заблокировал переход. Разбор показал: новая версия иначе интерпретировала инструкцию о формате ссылок. Промпт скорректировали, прогон прошёл, обновление выкатили. Без прогона ассистент несколько недель отвечал бы «от себя» по медицинским регламентам.
Извлечение данных из транспортных документов в логистической компании. После переиндексации базы с новыми параметрами разбиения полнота извлечения по одному типу накладных снизилась, при том что общая метрика почти не изменилась. Обнаружилось только потому, что метрики считались по типам документов отдельно. Урок: агрегированная метрика скрывает локальную деградацию.
Классификатор обращений в сервисной компании. Разработчик улучшил промпт по просьбе бизнеса — точнее распознавать жалобы. Точность по жалобам выросла, по запросам на изменение договора — упала: часть из них стала попадать в жалобы. Регресс по категориям показал это до выката, и промпт доработали с учётом обеих категорий.
Что это значит для российской компании
Локальные модели — ваши обновления, ваш регресс. В закрытом контуре нет провайдера, который обновит модель без спроса, но есть собственные изменения: новая версия открытой модели, другая квантизация, обновление сервера инференса, переход на другой GPU. Каждое из них меняет поведение, и без эталонного набора эти изменения делаются вслепую. Регресс в контуре нужен не меньше, а больше, потому что компонентов, которые меняете вы сами, здесь больше.
Персональные данные в эталонном наборе. Реальные входы — это реальные обращения, документы, переписка. Эталонный набор подпадает под требования 152-ФЗ: обезличивание, ограничение доступа, хранение в контуре. Это нужно спланировать до сбора набора, иначе тестовые данные окажутся самым незащищённым хранилищем персональных данных в компании.
Кадры. Тестирование ИИ — практика на стыке QA, аналитики данных и предметной области. Инженеров, владеющих ею, на рынке мало. Реалистичный путь — обучить существующую команду QA: методика ближе к привычному тестированию, чем кажется, а критерии качества пишутся вместе с бизнесом.
Договоры с подрядчиками. Эталонный набор, метрики и регрессионный прогон должны быть предметом поставки наравне с кодом. Решение без них — демонстрация с неизвестным сроком годности, и приёмка должна это учитывать.
Что делать: пошагово
- Определите свойства качества вместе с бизнесом. Для каждой ИИ-функции — что означает «правильно»: наличие источника, полнота, категория, отказ вне компетенции. Формулировки должны быть проверяемыми.
- Соберите эталонный набор из реального потока. Обезличенные входы по категориям: типовые, редкие, краевые, провокационные. Добавьте сценарии, где правильный ответ — отказ.
- Реализуйте лестницу проверок. Детерминированные проверки — первыми; модель-оценщик с явной рубрикой — для свойств, которые не проверяются кодом; выборочная проверка человеком — для калибровки оценщика.
- Выберите метрики и пороги. По таблице выше, с разбивкой по категориям и типам документов. Порог — из требований бизнеса, а не из текущего значения.
- Встройте прогон в процесс изменений. Любое изменение модели, промпта, индекса, инструментов — прогон до выката; падение метрики блокирует выкат. Результаты хранятся по версиям.
- Настройте мониторинг в эксплуатации. Выборка реальных запросов регулярно проходит те же проверки; расхождение с эталоном — сигнал.
- Свяжите с классическим тестированием. Автотесты интеграций, нагрузочные тесты сервера инференса и поиска, проверка задержек — отдельные слои, которые не заменяют друг друга.
- Пополняйте набор из инцидентов. Каждый случай неверного ответа в эксплуатации становится сценарием в наборе с датой и причиной.
Типичные ошибки
- Приёмка по впечатлению. Посмотрели тридцать примеров, «в целом нормально». Вместо этого: эталонный набор с критериями и метриками, зафиксированный до приёмки.
- Один правильный ответ вместо критерия. Тест падает на любой верной переформулировке, команда отключает тесты. Вместо этого: критерии-свойства, проверяемые кодом или оценщиком.
- Оценщик — та же модель с тем же промптом. Она воспроизводит собственные ошибки и ставит себе высокие оценки. Вместо этого: отдельный контекст, явная рубрика, калибровка по выборке, проверенной человеком.
- Регресс запускается «когда есть время». Изменения промпта выкатываются без прогона, потому что «мелкие». Вместо этого: прогон — автоматическая стадия процесса, без исключений для мелких правок.
- Только агрегированная метрика. Общая точность держится, одна категория деградировала. Вместо этого: метрики по категориям, типам документов, источникам.
- Нет сценариев с отказом. Система проверена только на вопросах, где ответ есть. Вместо этого: отдельный раздел набора для галлюцинаций и попыток увести от сценария.
Как понять, что вы на верном пути
- Для каждой ИИ-функции существует эталонный набор с критериями, и его можно показать.
- Метрики считаются автоматически и хранятся по версиям модели, промпта и индекса.
- Любое изменение любого компонента проходит прогон до выката, и это нельзя обойти.
- Есть случай, когда прогон заблокировал выкат, и вы помните, что он поймал.
- В наборе есть сценарии, где правильный ответ — отказ, и система их проходит.
- Метрики разбиты по категориям, и локальная деградация видна.
- Инциденты из эксплуатации пополняют набор регулярно.
- Эталонный набор обезличен, доступ к нему ограничен.
Вопросы, которые нам задают
Сколько примеров должно быть в эталонном наборе
Достаточно, чтобы покрыть категории входов, включая редкие и краевые, и чтобы изменение результата на одном примере не меняло итог. Точное число зависит от разнообразия потока: для классификатора с десятком категорий — десятки примеров на категорию; для ассистента над базой регламентов — сценарии по каждому разделу базы плюс раздел отказов. Набор растёт из инцидентов, поэтому важнее не стартовый размер, а процесс пополнения.
Может ли модель оценивать саму себя
Оценщик — отдельный компонент с отдельным контекстом и явной рубрикой; он может быть той же моделью, но не тем же вызовом. Его точность проверяется на выборке, размеченной человеком, и если расхождение велико — рубрика уточняется. Без калибровки оценщик измеряет не качество, а согласие модели с собой.
Нужно ли нагрузочное тестирование
Да, и отдельно от тестирования качества. Сервер инференса и поисковый индекс имеют пределы по параллельным запросам и задержке; при нагрузке качество может меняться через таймауты и усечённые контексты. Нагрузочный тест отвечает на вопрос «выдержит ли», регресс качества — «ответит ли верно». Это разные вопросы с разными инструментами, и в приёмке нужны оба.
Кто пишет критерии качества
Бизнес-подразделение при поддержке QA. Критерий «ответ ссылается на действующую редакцию» может сформулировать только тот, кто знает, что такое действующая редакция и почему это важно. Задача QA — превратить формулировку в проверяемое условие и встроить его в прогон. Начните с одной функции: составьте критерии на встрече с её владельцем, соберите набор из нескольких десятков реальных входов, запустите первый прогон и посмотрите на цифры. Дальнейшие шаги станут очевидны из результата.