Учебник «Большие языковые модели»
На эту главу ссылалась едва ли не каждая предыдущая — и не случайно. LLM-системы недетерминированы, их поведение дрейфует от версии к версии модели, а «вроде стало лучше» на трёх примерах регулярно оказывается «стало хуже» на тридцати. Оценка (в отраслевом жаргоне — evals) — это то, что превращает работу с LLM из шаманства в инженерию: без неё нельзя ни выбрать модель, ни улучшить промпт, ни решиться на дообучение, ни спокойно обновиться. Четвёртую часть — об эксплуатации — начинаем с неё.
Публичные бенчмарки — наборы задач для сравнения моделей: знания и рассуждения (MMLU и наследники), математика, программирование (HumanEval, SWE-bench — последний интересен тем, что проверяет исправление реальных ошибок в реальных репозиториях), плюс живые рейтинги на человеческих сравнениях вроде LMArena. Смотреть на них при выборе модели полезно, доверять слепо — нет, и вот системные причины. Загрязнение (глава 4): задачи просачиваются в обучающие данные, и результат меряет память, а не способность. Насыщение: на зрелых бенчмарках топ-модели различаются в пределах шума. Оптимизация под тест: бенчмарки — мишень маркетинга, и «обучение на экзамен» в индустрии не редкость. И главное — нерелевантность: олимпиадная математика ничего не говорит о том, как модель редактирует русскоязычные новости по вашему стайлгайду. Бенчмарки годятся для грубого отсева; решение принимает ваш собственный eval.
Основа — золотой набор: коллекция репрезентативных входов вашей задачи с эталонными ответами или критериями приемлемости. Реальный трафик полезен только при законном основании, минимизации данных и защите персональной информации; синтетические и специально сконструированные примеры дополняют области, которых в трафике мало. Распределение отражает реальность, но граничные и болевые случаи представлены с запасом — включая входы, где правильный ответ «данных недостаточно». Инциденты добавляйте в растущий регрессионный набор. Отдельный закрытый test-набор не меняют во время выбора промпта и модели, иначе команда постепенно обучится на экзамене. Нужный размер определяется частотой ошибок, ценой решений и желаемой статистической мощностью: десятки примеров дают ранний сигнал, но не гарантируют уверенного сравнения малых различий. Наборы версионируйте вместе с промптами.
Метрика зависит от типа задачи. Классификация и извлечение — точное сравнение с эталоном: accuracy, точность/полнота по классам (вспомните трёхуровневую задачу дедупликации новостей: доли ошибок «склеили разное» и «не склеили одно» имеют разную цену, и мерить их надо порознь). Структурированный вывод — валидность схемы плюс пополевое сравнение. Свободный текст — самое трудное: автометрики пересечения слов (BLEU/ROUGE) не всегда отражают нужное качество; применяют человеческую разметку, предметные проверки и LLM-судью, предварительно откалиброванного на людях.
Идея: сильная модель оценивает ответы слабой (или сравнивает два ответа) по заданной рубрике. Систематическое исследование на материале MT-Bench (Чжэн и др., 2023) показало полезность подхода в изученных диалоговых задачах, но результат не переносится автоматически на другую рубрику или домен. Практические правила. Рубрика конкретна: не «оцени качество от 1 до 10» (шкала без определений даёт шум), а отдельные бинарные или трёхуровневые критерии — «все факты подтверждены источниками: да/нет», «формат соблюдён: да/нет», «стиль соответствует примерам: да/частично/нет». Парное сравнение надёжнее абсолютных оценок: «какой из двух ответов лучше по критерию X» — и обязательно в обоих порядках, потому что у судей есть позиционное смещение (первый вариант выигрывает чаще). Известны и другие смещения: любовь к длинным ответам, предпочтение «своего» стиля (модель-судья завышает оценки модели своего семейства), чувствительность к формулировке рубрики и prompt injection из оцениваемого ответа. Большая или иная модель не устраняет эти смещения: судью калибруют на человеческой разметке, регулярно перепроверяют и не дают его тексту доступ к инструментам или секретам.
Эксплуатационный смысл eval — регрессионное тестирование: любое изменение промпта, модели, температуры, версии RAG-индекса прогоняется через золотой набор до выкладки. Минимальный каркас — страница кода:
import json, statistics
def run_eval(cases, system_fn, judge_fn=None):
"""cases: [{'input': ..., 'expected': ...}];
system_fn -- тестируемая система (вход -> ответ);
judge_fn -- опциональный судья (вход, ответ, эталон) -> 0/1."""
results = []
for c in cases:
out = system_fn(c["input"])
if judge_fn:
ok = judge_fn(c["input"], out, c.get("expected"))
else:
ok = (out.strip() == str(c["expected"]).strip())
results.append({"id": c.get("id", len(results)), "ok": bool(ok)})
score = statistics.mean(r["ok"] for r in results)
for r in results:
if not r["ok"]:
print("FAIL:", json.dumps(r, ensure_ascii=False))
print(f"score: {score:.1%} ({len(cases)} примеров)")
return score
Разбор провалившихся примеров важнее итоговой цифры: eval — не только градусник, но и микроскоп. Код выше печатает только идентификаторы; чувствительные входы и ответы храните в защищённом артефакте с ограниченным сроком доступа. Вместе с результатом фиксируйте снимок модели, версию промпта и индекса, параметры, задержку, usage и ошибки.
Недетерминированность возможна и при условной температуре 0: повторяйте критичные эксперименты и используйте парное сравнение на тех же примерах. Статистическая честность: показывайте доверительный интервал или bootstrap для разности; требуемый размер выборки определяйте ожидаемым эффектом и частотой ошибок. Малый дымовой набор удобен для быстрых проверок, полный закрытый test — перед решением о релизе. Считайте также цену и задержку: качество не единственная метрика системы.
Закрытый test-набор проверяет то, что вы предусмотрели; жизнь богаче. Дополняющий контур — мониторинг: логирование входов и ответов (с версиями промпта и модели — глава 8), дешёвые автоматические проверки на каждом ответе (валидность схемы, наличие обязательных полей, срабатывание «данных недостаточно» чаще обычного — сигнал деградации поиска в RAG), выборочная оценка LLM-судьёй заданной доли живого трафика, и явные сигналы от пользователей, если они есть. Телеметрия требует минимизации, редактирования секретов и персональных данных, контроля доступа и срока хранения. Новые инциденты отправляются в развивающий регрессионный набор, но не переписывают задним числом закрытый test.
Публичные бенчмарки — для грубого отсева; решения принимает ваш eval: репрезентативные наборы (включая «данных недостаточно»), метрика по типу задачи, LLM-судья с конкретной рубрикой и парными сравнениями в обоих порядках — с поправкой на его смещения. Eval встроен в процесс как регрессионный тест: прогон до каждой выкладки, внимание к провалившимся примерам, честность к шуму и размеру выборки. Мониторинг ловит непредусмотренное и пополняет регрессионный набор, а закрытый test защищает от подгонки. Одна фраза на память: нет eval — нет мнения.
Следующая глава — локальный запуск моделей: квантизация, llama.cpp и vLLM, и сколько на самом деле нужно железа.
Упражнения
1. Соберите золотой набор из 30 живых примеров своей задачи (не забудьте случаи «данных недостаточно») и прогоните через каркас из 13.4. Какая доля провалов оказалась для вас неожиданной?
2. Постройте LLM-судью для одного критерия (например, «все факты ответа подтверждены приведёнными фрагментами») и проверьте его: оцените вручную 20 ответов и посчитайте согласие судьи с вами. Затем поменяйте порядок кандидатов в парном сравнении — насколько велико позиционное смещение?
3. Прогоните один и тот же eval трижды при T = 0,7. Каков разброс итоговой оценки? Какое минимальное улучшение промпта вы теперь готовы считать реальным?