Наверняка вы сталкивались с ситуациями, когда модель начинает вести себя в проде не так, как задумывалось: например, ведётся на провокации пользователя или даёт некорректные ответы. Зачастую такие ошибки безобидны, но случаются и не очень приятные ситуации. А если речь идёт о чат-боте, который отвечает на вопросы в юридической или медицинской сфере — практически любая ошибка может быть критичной.
Итак, мы плавно подошли к тому, что нужно каким-то образом валидировать ответы LLM. Давайте разберёмся, как это делать.

Что не так с LLM
Обычная LLM (вернее, простейший чат-бот с LLM под капотом) работает так: пользователь пишет запрос, мы добавляем системный промпт, закидываем эту прекрасную пару в LLM и показываем пользователю ответ.

Схема максимально простая, но у неё есть, как минимум, три минуса:
Актуальностью данных: например, когда LLM училась, пенсионный возраст для мужчин был равен 60 годам, а сейчас он составляет 63 года, поэтому на вопрос о возрасте выхода на пенсию модель ответит неправильно.
Незнание специфики: LLM плохо работает с вопросами из узких или региональных доменов. Например, LLM от Open AI мало что знает про работу ИП в России в 2025 году.
Галлюцинации: модель может уверенно выдавать небылицу — от правовых рекомендаций до советов по здоровью.
Зачем нужен RAG
Все три перечисленные проблемы частично решает RAG (retrieval-augmented generation). Это подход, в котором при обработке запроса пользователя мы обращаемся к нашей LLM-ке как к дополнительной базе знаний, откуда можно достать нужный контекст. Грубо говоря, даём нашей LLM-ке «погуглить» прежде чем давать ответ.

Но у нас всё ещё остаётся пара проблем:
Отсутствие нужного куска информации в базе знаний. Либо случаи, когда идеальный документ был, но мы его не нашли из-за ошибки retrieval — механизма поиска по нашей базе знаний, который, естественно, тоже может работать неидеально. В этом случае мы возвращаемся к трём перечисленным выше проблемам.
Игнорирование контекста. Даже если мы дали модели идеальный контекст, это не гарантирует, что она будет на него опираться и корректно цитировать.
Первую проблему надо чинить на уровне наполнения базы знаний и механики поиска релевантных документов, а вот вторая проблема, по-хорошему, должна решаться ещё на этапе (до)обучения LLM. Но для того, чтобы что-то улучшить, надо научиться это что-то измерять. Поэтому давайте разбираться, как мы можем измерить, насколько сильно модель опирается в своём ответе на факты из контекста.
Что именно валидировать
Можно условиться, что правильные ответы — хорошие, а неправильные — плохие. Но с такой терминологией сложно работать. Давайте попробуем для начала определить, ошибки какого рода делают ответ плохим.
Если изучить статьи о специфике галлюцинаций LLM (например, опираться вот на это исследование), можно выделить две основные группы:
Factuality hallucination — случаи, когда модель генерирует недостоверные утверждения о мире или оперирует неверными логическими цепочками (например, «если все кошки в комнате белые, то и все кошки в мире белые».
Faithfulness hallucination — случаи, когда ответ модели не соответствует вопросу или контексту. Например, мы спросили её «как включить холодильник?», а она ответила, как его выбросить.
Определившись с типологией, мы выбираем для себя два ключевых критерия для оценки ответов LLM:
Критерий следования моделью инструкции — правда ли мы отвечаем на вопрос пользователя и соблюдаем заданные им ограничения? Назовём его критерием соответствия ответа вопросу.
Критерий следования моделью контекста — правда ли мы опираемся на факты из контекста? Или же критерий соответствия ответа контексту.
Однако помимо того, что мы хотим избежать галлюцинаций, мы бы также хотели, чтобы наша модель (LLM) придерживалась определенного стиля в общении: не ругалась матом, не обсуждала сексуальную ориентацию и не цитировала Гитлера, например. Для этого давайте введём дополнительный, третий критерий: tone-of-voice, который будет бинарно (или почти бинарно) отвечать нам на вопрос, устраивает ли нас в конкретном случае стиль общения нашей LLM-ки.
Способы валидации
Когда мы разобрались, что именно хотим проверять, давайте обсудим, как часто мы хотим это делать. Допустим, модель уже работает в проде, и вы начали задумываться о том, чтобы контролировать качество её ответов. Есть вот такие варианты:
Просто выкатить новую версию и смотреть за бизнес-метриками — при таком раскладе можем потерять и деньги, и пользователей. Но зато точность отменная: вы будете на 100% уверены, что модель работает хуже/лучше.
Ввести прокси-метрику — например, добавить в пользовательский интерфейс лайки и дизлайки, чтобы понять, как пользователи оценивают старую и новую модель (лучше в формате А/В-теста). Но будьте готовы, что далеко не все пользователи будут ставить какие-либо оценки. Статзначимую разницу вы получите, вероятно, очень нескоро.
Использовать автовалидаторы — до того, как показать ответ пользователю, на лету валидируем его с помощью легковесной модели-классификатора. Про них мы далее поговорим очень подробно: разберёмся, как собрать их на коленке и где искать данные.
Первые два варианта позволяют напрямую получить обратную связь от пользователей. Последний — самый дешёвый и быстрый, так как для каждого диалога у нас будет численная оценка, и мы сможем оценить здоровье модели в конкретный момент времени. Но и он не даёт полной картины. Поэтому в идеале нужно комбинировать все три подхода: следить за бизнес-метриками, вводить лайки/дизлайки, но при этом не оставлять тестирование сервиса на откуп пользователю. И в дополнение обязательно самостоятельно контролировать, что происходит в проде.
В офлайне для сравнения моделей можно использовать:
Открытую чат-бот арену, или поднять свою, что сложно, долго и дорого, так как на неё будут уходить колоссальные асессорский ресурсы.
Benchmark + human eval — подготовить golden set вопросов и сравнивать людьми ответы моделей.
Benchmark + GPT-Judge — использовать мощную модель и прогоняться ей по golden-сету. Последние статьи (да и не только последние) подтверждают, что GPT-Judge справляется не сильно хуже человека.
И, опять же, использовать автовалидаторы — автоматически проверять по критериям, соответствует ли ответ вопросу, контексту и другим параметрам.
Однако здесь та же ситуация, что и с методами онлайн-оценки: в идеале стоит использовать несколько из перечисленных подходов.

Почему нельзя просто взять готовый бенчмарк
Причины две:
Большинство бенчмарков — англоязычные. Есть переводы, но они не такие качественные, как первоисточник.
Мы хотим валидировать не качество модели в общем, а модель на своих конкретных задачах. Например, нам важно, чтобы она умела в суммаризацию и RAG — не перевирала контекст и легко находила в нём нужные факты.
Поэтому придётся собирать бенчмарк своими руками. Давайте разберёмся, как это сделать.
Собираем свой бенчмарк
Теперь, когда мы определились, что нам нужен бенчмарк и разобрались, какие метрики нам в нем нужны, давайте поймём, как валидировать каждую из них и какие данные брать в качестве бенчмарка.
Для начала слегка конкретизируем метрику соответствия ответа контексту. Разобьём её на две: грубо говоря, это будет precision и recall, где precision — процент галлюцинаций в ответе, а recall — процент попавших в ответ фактов от всех фактов в приведённом контексте.
Ну и дополнительно давайте введём метрику корректности ответов на атомарные вопросы — чисто для бенчмарка, но не для регулярного мониторинга. Будем проверять, насколько модель перевирает отдельные факты из контекста, проверяя её на простеньких вопросах о содержании текста.
Итак, вводные есть, давайте углубляться.

Рассмотрим подробнее каждый из критериев:
Перевирание отдельных фактов: самый простой из наших критериев, нужен лишь на оффлайн-оценке перед релизом. Оцениваем, насколько хорошо модель умеет вытаскивать факты из текста. В данном случае мы хотим валидировать только короткие ответы в два-три слова от LLM, поэтому можем просто сравнить косинусную близость и смотреть на BLEU (грубо говоря, пересечение по словам).
Для валидации нужны данные, в виде следующих троек: контекст, вопрос, правильный ответ. Это довольно сложный формат данных, которого в интернете не так много. Однако решение, где взять такие данные, всё-таки существует — это школьные учёбники с вопросами для самопроверки в конце главы. Но так как парсить целые PDF не очень приятно, лучше использовать аналогичные онлайн-порталы для школьников. Таким образом можно легко напарсить около 40 000 данных для этого критерия нашего бенчмарка. А дальше кормим вопросы + контексты к ним в нашу модель, сверяем ответы с каноничными и считаем метрику по бенчмарку. Профит!

Соответствие ответа вопросу: важно, чтобы модель отвечала именно на тот вопрос, который ей задали. Здесь на помощь приходит NLI (Natural Language Inference). Канонически, это задача определения наличия логической связи между текстами. Например, мы хотим оценивать, насколько второе предложение следует из первого. Для этого мы склеиваем предложения в один текст и ожидаем, что моделька выдаст значение от нуля до единицы — грубо говоря, вероятность наличия логической связи в приведённой паре предложений.
В нашем случае вместо primese и hypothesis (двух предложений, которые мы хотим проверить на правильность следования) идёт просто вопрос и ответ. Их мы склеиваем в единый текст и пытаемся предсказать бинарную метку, которая отвечает на вопрос «правда ли, что приведённый ответ является ответом на заданный вопрос?». С данными здесь ещё проще, чем в прошлом случае: как для обучения нашей NLI-модельки, так и для бенчмарка мы можем просто взять чаты службы поддержки или любые другие диалоговые данные.

Tone of voice: составляем список бинарных меток — структурность текста, использование мата, политика, токсичность и другие ред флаги ?. Можно сделать несколько бинарных классификаторов или один мультилейбл (мы выбрали этот вариант чтобы сэкономить на ресурсах).
Главный вопрос — где найти данные. Тут на помощь приходят, внезапно, Telegram-каналы, потому что где ещё искать столько мата и расизма, как не в политических пабликах? ?
Парсим эти данные, а для баланса докидываем данные, которые соответствуют нашему стилю — например, комментарии сотрудников службы поддержки. Потом закидываем всё это в GPT с промптом, способным оценить каждый из наших критериев. В итоге получаем синтетические метки. Часть из них отправляем на разметку асессором, чтобы проверить, насколько эта синтетика хороша, и как только мы удостоверились в качестве данных можем стартовать обучение валидатора.

Процент галлюцинаций и соответствие ответа контенту: эти задачи будем решать одновременно, тем более, что произросли они из одного критерия — соответствия ответа контексту.
Можно использовать подход, основанный на статье FactScore. Идея в том, что мы разбиваем ответ LLM на факты, а потом проверяем для каждого, соответствует ли он статье, на которую опиралась модель.
Позднее этот подход преобразовали в статье FacTool. Там авторы выделяют факты не только из ответа модельки, но и из контекста. Получается два сета фактов, которые нужно сравнить.
Опираясь на эти две статьи, мы пошли третьим путем: мы разбиваем контекст на атомарные на факты, а дальше прицельно для каждого факта проверяем, упомянут ли он в том или ином виде в ответе модели.
Предположим, что ответ занимает 100 токенов. Автовалидатор (а вернее, конкретная модель нашей системы автовалидации) должен выдать, с какого по какой токен встречается конкретный факт. Таким образом, мы можем померить, какая часть фактов из контекста упомянута в ответе (recall), и какая часть ответа покрыта фактами (precision). Дополнительно мы хотим уметь понимать, какие фрагменты текста относятся к стилистическому шуму и не являются галлюцинациями.

Например, в тексте ниже «Дорогой клиент» и «спасибо» — это просто шум, а «Точка Банк выдаёт кредиты» — факт из контекста. Белая часть, которая никак не отмечена — галлюцинации, потому что ни к факту, ни к шуму это не относится.

Получается классическая задача NER, где мы пытаемся предсказать, с какого по какой токен встречается конкретная информация. Для каждого факта получаем маску из нулей и единиц, и то же самое делаем для шума.
Причем для бенчмаркинга этого критерия нам не нужны специфичные данные, поэтому можно просто взять какой-нибудь FAQ и статьи по вашей доменной тематике, чтобы нагенерить в GPT вопросов к ним, например.
Но чтобы выкрутить сложность задачки на уровень hard и проверить, правда ли модель всегда следует информации из контекста не смотря на её бредовость, нужно подавать тексты, которые не соответствуют знаниям о реальном мире. Тут отлично подходят теории заговора ?. И вот у вас уже есть отличный набор данных для валидации «повиновения» модели контексту, каким бы бредовым он ни был.
И вот у нас с вами на руках полноценная система оценки качества LLM-систем: автовалидаторы для онлайн-мониторинга и бенчмарки для оффлайн-сравнений. . Дополнительный бонус — большую часть получившихся валидаторов можно переиспользовать на других проектах, даже не LLM-ных. Например, ту же модельку tone-of-voice можно использовать как out-of-the-box модельку модерации для входящих/исходящих коммуникаций.

Что делать дальше
Когда вы построите систему автовалидации и бенчмарков, можно:
Переводить датасеты. Например, мы скоро будем тюнить ALMA, чтобы можно было использовать англоязычные датасеты и бенчмарки. Так как количество задач, которые решаются LLM-ками, растёт, сложно успевать покрывать все эти кейсы своими бенчмарками.
Покрывать бенчмарками другие задачи, например, делать автовалидаторы бенчмарков под function calling, суммаризацию и т.д. Либо же брать готовое, но уметь хорошо переводить на русский.
Настраивать alignment, используя данные, которые вы получили в результате работы автовалидатора, чтобы работать с причиной, а не со следствием.