Перейти к содержимому
ПереводыHugging Face

LLM Evaluation Guidebook, часть 1: инференс, токенизация и автоматические бенчмарки

Перевод вводных глав LLM Evaluation Guidebook от Hugging Face: как модель выдаёт ответ при оценке (логарифм правдоподобия или генерация), как токенизация влияет на результаты, как выбрать или собрать бенчмарк, промпт и метрику и чем грозит загрязнение данных.

Это перевод первой группы глав LLM Evaluation Guidebook — руководства по оценке языковых моделей, которое написала Клементин Фурье, одна из создателей Open LLM Leaderboard и библиотеки lighteval. Оригинал распространяется по лицензии CC BY-NC-SA 4.0, поэтому и перевод доступен на тех же условиях: с указанием авторства, некоммерчески, с сохранением лицензии. Продолжение: часть 2 — LLM-as-a-judge и оценка людьми, часть 3 — отладка инференса и воспроизводимости.

Если вы когда-нибудь задумывались, как убедиться, что LLM хорошо справляется именно с вашей задачей, это руководство для вас! Оно рассказывает о разных способах оценки модели, о том, как спроектировать собственную оценку, и делится советами и приёмами из практического опыта.

Работаете ли вы с моделями в продакшне, занимаетесь исследованиями или просто увлекаетесь — надеюсь, вы найдёте то, что нужно; а если нет, откройте issue (с предложением улучшений или недостающих материалов), и я дополню руководство!

  • Начинающим: если вы ничего не знаете об оценке, начните с разделов «Основы» в каждой главе, прежде чем углубляться. В разделе «Общие знания» есть пояснения важных тем о LLM — например, как работает инференс модели и что такое токенизация.
  • Опытным: самые практичные разделы — «Советы и приёмы» и глава «Отладка». Интересное найдётся и в разделах «Проектирование».
  • Тем, кто возвращается: каждый год я делаю обзор одной темы — загляните!

Ссылки в тексте, отмеченные ⭐, — те, что мне особенно понравились и которые я рекомендую прочитать.

Оглавление оригинала: автоматические бенчмарки (основы, проектирование, некоторые наборы данных, советы и приёмы); оценка людьми (основы, работа с разметчиками, советы и приёмы); LLM-as-a-judge (основы, как получить модель-судью, промпт для оценки, оценка оценщика, модели награды, советы и приёмы); отладка (инференс, воспроизводимость); общие знания (инференс и оценка, токенизация); ежегодные обзоры 2023–2025. Введение в тему — также пост о том, как и зачем мы оцениваем модели.

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

Это делается в два шага.

Входной текст (при инференсе его называют промптом) сначала разбивается на токены — небольшие единицы текста (от одного или нескольких символов до целого слова), каждой из которых сопоставлено число. Весь набор токенов, который модель умеет разбирать, называется её словарём. (Подробнее — в разделе «Токенизация» ниже.)

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

Оценки LLM в основном делятся на две категории:

  • дан промпт и один (или несколько) ответов: какова вероятность этих ответов для моей модели?
  • дан промпт: какой текст сгенерирует моя модель?

В оценках по логарифму правдоподобия (log-likelihood) нам нужна условная вероятность одного или нескольких вариантов при данном промпте — иначе говоря, насколько вероятно получить конкретное продолжение при данном входе. Поэтому:

  • склеиваем каждый вариант с промптом и подаём в LLM, которая выдаёт логиты каждого токена в зависимости от предыдущих;
  • оставляем только последние логиты (относящиеся к токенам варианта) и применяем log softmax, чтобы получить логарифмы вероятностей (их диапазон — [-inf, 0], а не [0, 1]);
  • складываем логарифмы вероятностей всех токенов, чтобы получить логарифм вероятности варианта целиком;
  • наконец, можно применить нормировку на длину варианта.
flowchart LR
P["Промпт: «Клетка, образующаяся при оплодотворении, — это…»"] --> A["+ «зигота» → сумма log p токенов = −1,2"]
P --> B["+ «гамета» → −3,5"]
P --> C["+ «спора» → −4,1"]
A --> W["Выбран вариант с наибольшей (нормированной) суммой"]
B --> W
C --> W
Схема переводчика вместо рисунка оригинала; числа условные

Это позволяет применить одну из метрик:

  • найти ответ, который модель предпочитает среди нескольких вариантов, как на рисунке выше. (Однако это может завысить оценки моделей, которые при свободной генерации выдали бы что-то другое, — например, «Zygote» на рисунке оригинала.);
  • проверить, больше ли 0,5 вероятность одного варианта;
  • изучить калибровку модели. Хорошо откалиброванная модель — та, у которой правильные ответы имеют наибольшие вероятности. (Подробнее о калибровке — в этой статье Anthropic: что это, как её обнаружить и как обучать хорошо откалиброванные модели, — и в этой статье о возможных пределах калибровки.)

В генеративной оценке нам нужен текст, который модель сгенерирует по входному промпту.

Он получается авторегрессионно: подаём промпт модели, смотрим на самый вероятный следующий токен, берём его как «первый токен, выбранный моделью», и повторяем, пока не выполнится условие окончания генерации (максимальная длина, специальный токен остановки и т. д.). Все сгенерированные моделью токены считаются её ответом на промпт.

Затем эту генерацию можно сравнить с эталонами и оценить расстояние между ними (простыми метриками вроде точного совпадения, более сложными вроде BLEU или с помощью моделей-судей).

Часто нужно, чтобы вывод модели следовал определённому формату, например чтобы сравнить его с эталоном.

Проще всего добавить промпт задачи с очень конкретными указаниями, как модель должна отвечать («Давай числовые ответы цифрами.», «Не используй сокращений.» и т. д.).

Это не всегда сработает, но для сильных моделей обычно достаточно. Такой подход мы использовали в статье GAIA; наш промпт задачи можно найти на вкладке Submission лидерборда, если нужно вдохновение.

Следующий способ — ограничить модель так называемым «обучением в контексте» (in-context learning). Если дать в промпте примеры (это называют few-shot prompting), модель неявно склоняется повторять ту же форму промпта для настоящего примера.

В целом этот метод работал довольно хорошо до конца 2023 года! Однако массовое распространение instruction tuning и добавление инструктивных данных на поздних стадиях предобучения (continuous pre-training), похоже, приучили более новые модели к определённым форматам вывода (то, что здесь называют «обучением на тестовой задаче», а я бы назвала «переобучением на формат промпта»). Для старых моделей с маленьким контекстом этот метод тоже бывает ограничен: часть примеров просто не помещается в контекстное окно.

Структурированная генерация заставляет вывод следовать заданному пути — например, грамматике или регулярному выражению. Библиотека outlines реализует это с помощью конечных автоматов, что очень изящно. (Есть и другие подходы, например чередующаяся генерация для JSON, но вариант с конечными автоматами мне нравится больше всего.)

Чтобы лучше понять, что происходит при структурированной генерации, загляните в наш совместный пост: структурированная генерация уменьшает разброс от промпта при оценке и делает результаты и рейтинги стабильнее. Интересные реализации и наблюдения есть и в общем блоге outlines.

Однако некоторые недавние исследования, похоже, показывают, что структурированная генерация может снижать качество на некоторых задачах (например, на рассуждениях), слишком сильно уводя априорное распределение от ожидаемого.

Большие языковые модели — это, по сути, большие математические функции, поэтому они едят числа, а не текст.

Допустим, вы хотите превратить предложение в числа. Сначала нужно решить, как разрезать предложение на маленькие кусочки, затем сопоставить каждому кусочку число; это и есть токенизация.

Раньше пытались сопоставить каждому символу текста его номер в алфавите (a → 1, b → 2 и т. д.) — это посимвольная токенизация (разрезаем между символами). На другом конце спектра пытались сопоставить каждому слову его номер в словаре (a → 1, aardvark → 2, ab → 3 и т. д.) — это пословная токенизация (разрезаем по пробелам, если в языке есть пробелы; если нет — сложнее).

У обоих методов серьёзный недостаток: они теряют информацию из входного текста. Они стирают смысловые связи, видные по форме слова (например, dis similar, similar, similar ity, similar ly), а нам хотелось бы, чтобы модель их сохраняла и связывала родственные слова. (К тому же что делать, если на входе вдруг совершенно новое слово? У него нет номера, и модель не может его обработать 😔)

Поэтому кто-то придумал разрезать слова на подслова и присваивать номера им (dis, similar, ity, ly)!

Сначала это делали по морфосинтаксическим правилам («морфосинтаксис» — что-то вроде грамматики словообразования). Сейчас большинство использует byte pair encoding (BPE) — умный статистический метод, который автоматически создаёт подслова в зависимости от их частоты в эталонном тексте.

Итак: токенизация — это способ сопоставить небольшим единицам текста (от одного или нескольких символов до целого слова) числа (вроде индекса). Когда вы обрабатываете текст, входной текст (при инференсе — промпт) разбивается токенизатором на эти токены. Весь набор токенов, который может разобрать модель или токенизатор, называется словарём.

Советую внимательно прочитать одну из первых двух ссылок.

Размер словаря показывает, сколько отдельных токенов (например, подслов) модели придётся выучить.

Слишком большой словарь может содержать очень редкие слова как целые токены (например, aardvark), и это ведёт к двум проблемам.

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

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

Слишком маленький словарь создаёт две другие проблемы: худшие возможности представления и более дорогой инференс.

Вернёмся к примеру со словами, производными от similar. Псевдо-BPE (большой словарь) разбил similarly на 2 токена (similar, ly). Если бы мы использовали посимвольную токенизацию (то есть очень маленький словарь размером с алфавит), то же слово разрезалось бы на 9 токенов (s, i, m, i, l, a, r, l, y).

Первый способ разрезает similarly на токены, у каждого из которых есть свой смысл, а второй — нет: со слишком маленьким словарём мы потеряли часть смыслового представления. Разница в длине представлений означает ещё и то, что сгенерировать слово с маленьким словарём во много раз дороже (9 токенов вместо 2 — примерно в 5 раз дороже!).

Сейчас, похоже, большинство выбирает размер словаря эвристически, и он, видимо, связан с числом охватываемых языков и размером модели. Так что, скорее всего, вам подойдёт число токенов, близкое к эталонным моделям похожего размера.

  • Пост SolidGoldMagikarp на Less Wrong — очень интересный рассказ о том, как нашли очень редкие токены в словаре OpenAI, причём без доступа к внутренностям модели (мы, например, не знаем, что в обучающих данных).
  • Fishing for Magikarp, статья Cohere — продолжение работы о поиске таких токенов.

(Рекомендуется сначала прочитать объяснение BPE.)

Когда вы строите или выбираете токенизатор, словарь строится по эталонному тексту. Значит, токенизатор будет знать слова и символы из этого текста. Обычно это данные на английском, латиницей.

Если вы хотите добавить новый язык, который пишется тем же алфавитом и имеет общие корни, теоретически можно надеяться, что часть смыслов исходного языка перенесётся на новый.

Но если вы хотите, чтобы токенизатор правильно разрезал текст на других языках (особенно с другой письменностью), лучше включить данные на этих языках при построении токенизатора. Правда, чаще всего в таких данных доля исходного языка (например, английского) будет несоразмерно больше, чем нового (например, тайского или бирманского). Поскольку самые эффективные сегодняшние методы токенизации (вроде BPE) строят сложные токены словаря по самым частым словам, большинство длинных токенов окажутся английскими словами, а слова менее частых языков будут разрезаться почти посимвольно.

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

Строя токенизатор, нужно решить, что делать с числами. Индексировать только цифры от 0 до 9 и считать все остальные числа их сочетаниями — или хранить отдельными токенами числа, скажем, до миллиарда? Известные модели используют разные подходы, и неясно, что лучше помогает математическим рассуждениям. Возможно, понадобятся новые подходы к токенизации, например иерархическая.

Примечание: отчасти пересекается с моим общим постом об оценках.

Обычно автоматические бенчмарки устроены так: вы хотите знать, насколько хорошо модель справляется с чем-то. Это «что-то» может быть чётко определённой конкретной задачей, например «Насколько хорошо моя модель отличает спам от не-спама?», или более абстрактной общей способностью, например «Насколько моя модель хороша в математике?».

Отсюда вы строите оценку, используя:

  • набор данных из примеров (samples):
    • примеры содержат вход для модели, иногда вместе с эталоном (его называют gold), с которым сравнивается вывод модели;
    • примеры обычно подбирают так, чтобы они имитировали то, на чём вы хотите проверить модель: например, для классификации писем вы собираете набор спама и не-спама, стараетесь включить трудные пограничные случаи и т. д.;
  • метрику:
    • метрика — способ выставить модели оценку. Пример: насколько точно модель классифицирует спам (правильно классифицированный пример — 1, неправильно — 0);
    • метрики оценивают выводы модели. Для LLM обычно рассматривают два вида выводов:
      • текст, который модель сгенерировала по входу (генеративная оценка);
      • логарифм вероятности одной или нескольких последовательностей, поданных модели (оценки с выбором вариантов, иногда их называют MCQA, или оценки по перплексии);
      • подробнее — в разделе «Инференс модели и оценка» выше.

Интереснее делать это на данных, которых модель никогда не видела (их нет в обучающем наборе), потому что вы хотите проверить, хорошо ли она обобщает. Например, может ли она распознать спам о товарах «для здоровья», видев только спам о поддельных банках.

Примечание: Модель, которая хорошо предсказывает только на своих обучающих данных (и не выучила скрыто более общих закономерностей), называют переобученной (overfitting). Как студент, который вызубрил экзаменационные вопросы, не понимая предмета: оценивать LLM на данных, которые уже были в её обучающем наборе, — значит ставить ей баллы за способности, которых у неё нет.

Плюсы и минусы автоматических бенчмарков

Заголовок раздела «Плюсы и минусы автоматических бенчмарков»

Преимущества автоматических бенчмарков:

  • Согласованность и воспроизводимость. Можно 10 раз прогнать один и тот же бенчмарк на одной модели и получить одинаковые результаты (с поправкой на различия железа или собственную случайность модели). Значит, легко строить честные рейтинги моделей по задаче.
  • Масштаб при небольших затратах. Сейчас это один из самых дешёвых способов оценивать модели.
  • Понятность. Большинство автоматических метрик очень понятны. Например, точное совпадение скажет, совпал ли сгенерированный текст с эталоном полностью, а точность (accuracy) — в скольких случаях выбранный вариант оказался правильным (с метриками вроде BLEU или ROUGE это уже не так очевидно).
  • Качество данных. Многие автоматические бенчмарки используют наборы, созданные экспертами, или уже существующие качественные данные (как MMLU или MATH). Но это не значит, что наборы идеальны: в MMLU позже нашли немало ошибок — от проблем разбора до просто бессмысленных вопросов, — и появились исправленные наборы вроде MMLU-Pro и MMLU-Redux.

Однако есть и ограничения:

  • Хуже подходят для сложных задач. Автоматические бенчмарки хорошо работают там, где качество легко определить и измерить (например, классификация). Сложные способности, напротив, трудно разложить на чётко определённые задачи. Например, что значит «хорош в математике»? Хорошо считает? Хорошо рассуждает логически? Способен рассуждать о новых математических понятиях? Отсюда пришли более общие оценки, которые уже не раскладывают способности на подзадачи, а предполагают, что общее качество будет хорошим заместителем того, что мы хотим измерить.
  • Загрязнение (contamination). Как только набор данных опубликован открытым текстом, он попадёт в обучающие данные моделей. Значит, оценивая модель, вы не можете быть уверены, что она не видела оценочных данных раньше.

Автоматические бенчмарки: как спроектировать свою оценку

Заголовок раздела «Автоматические бенчмарки: как спроектировать свою оценку»

Для оценки можно взять существующий набор данных (примеры — в разделе оригинала «Some evaluation datasets») или сделать свой. Всё время помните: ваша оценка будет ровно настолько хороша, насколько хорош оценочный набор.

Обязательно изучите, из чего он состоит.

Как он создавался

  • Кто создавал сами примеры? По-моему, набор от экспертов > набор от оплачиваемых разметчиков ≈ краудсорсинг > набор с Mechanical Turk. Ищите и карточку данных (data card) с демографией разметчиков — это важно, чтобы понимать языковое разнообразие набора.

  • Проверяли ли их другие разметчики или авторы? Нужно знать:

    • высока ли согласованность разметчиков на примерах (согласны ли они друг с другом);
    • и/или просмотрели ли авторы весь набор.

    Это особенно важно для наборов, созданных с помощью низкооплачиваемых разметчиков, для которых целевой язык обычно не родной (вспомните AWS Mechanical Turk), иначе можно найти опечатки, грамматические ошибки или бессмысленные ответы.

  • Были ли у разметчиков ясные инструкции? Иначе говоря, согласован ли набор внутри себя?

Примеры

Возьмите 50 случайных примеров и просмотрите их вручную:

  • на качество:
    • ясны ли и однозначны ли промпты?
    • правильны ли ответы? (Например, в TriviaQA у одного вопроса несколько эталонных ответов (поле aliases), и иногда они противоречат друг другу.)
    • не пропущена ли информация? (Например, в ряде вопросов MMLU нет схем, на которые они ссылаются.)
  • на соответствие вашей задаче:
    • на таких ли вопросах вы хотите оценивать LLM?
    • подходят ли эти примеры для вашего сценария?

Нужно знать и число примеров (чтобы результаты были статистически значимыми: для автоматических бенчмарков минимум обычно 100 примеров).

Есть три пути.

Собрать из существующих данных. Можно объединить данные из разных источников, проверяющие нужную для задачи способность. Например, многие оценочные наборы собраны из наборов для оценки людей (MATH, LSAT и др.). В этом случае следуйте шагам выше.

С помощью разметчиков-людей. Об этом целый раздел в главе «Оценка людьми» — см. часть 2.

Синтетические данные.

  • С помощью LLM. Посмотрите отличный пост Cosmopedia от коллег из HF! Он в основном о создании синтетического обучающего набора, но похожие приёмы годятся и для оценки. Обязательно потом вручную проверьте, отфильтруйте и просмотрите набор (по шагам выше).
  • С помощью правил. Если задача позволяет, это очень хороший способ получить практически бесконечный запас примеров и избежать загрязнения! Примеры: NPHardEval, DyVal, MuSR, BabiQA и др.

Нужно решить, какой метод инференса вам нужен.

Логарифмы вероятностей (MCQA — вопросы с выбором ответа) очень хороши для вопросов с вариантами (обычно чтобы проверить знания модели или умение снимать неоднозначность).

  • Плюсы:
    • все модели гарантированно «видят» правильный ответ;
    • даёт косвенную меру «уверенности» модели (и калибровки);
    • быстро, особенно если модели нужно предсказать один токен (A/B/C/D — номера вариантов, или Да/Нет и т. п.);
    • позволяет получить сигнал о качестве маленьких моделей.
  • Минусы:

Генерация (QA — ответы на вопросы) очень хороша для любых задач, где нужно проверить связность текста, рассуждения или умение модели действительно отвечать на вопросы.

  • Плюсы:
    • должна действительно коррелировать со способностью LLM генерировать связный текст — а это чаще всего и интересует людей.
  • Минусы:
    • бывает труднее оценить (см. раздел о метриках ниже);
    • обычно немного дороже оценок по правдоподобию, особенно с сэмплированием.

Промпт определяет:

  • сколько информации о задаче получает модель;
  • как эта информация ей подана.

Промпт для обычной задачи MCQA или QA обычно состоит из части элементов:

  • промпт задачи (необязательно): вводит задачу;
  • контекст: дополнительная информация к вопросу. Например, для задачи пересказа или извлечения информации — исходный текст;
  • вопрос: собственно ядро промпта;
  • для оценки с выбором — варианты ответа;
  • связующие слова (Question, Context, Choice, …).

Определяя промпт, помните:

  • даже небольшие изменения в семантически эквивалентных промптах могут сильно менять результаты (см. раздел «Другой промпт» в части 3), а форматы промпта могут давать преимущество или ставить в невыгодное положение конкретные модели:
    • как с этим бороться:
      • дорогой способ — перезапускать оценку несколько раз с вариациями промпта;
      • дешёвый способ — один раз прогнать оценку, раздав разные форматы промпта разным примерам одинаковой сложности;
  • можно дать модели примеры, чтобы ей было проще следовать ожидаемому формату (few-shot), и связующие слова в целом помогают;
  • но сейчас модели склонны переобучаться на определённые форматы промптов:
    • эта статья отлично разбирает тему и показывает, в частности, как некоторые модели получают завышенные оценки, потому что переобучились на формат тестового набора;
    • на Open LLM Leaderboard 2 мы, в частности, заметили, что Llama 3.2 и Qwen 2.5 по этой причине больше не следуют формату промпта, заданному в few-shot;
  • для ряда метрик нужна сильно ограниченная генерация или вывод. Подробнее — в разделе «Как ограничить вывод модели» выше.

Если вы смотрите на логарифмы вероятностей, с метриками просто: вам нужна точность (как часто самый вероятный вариант оказывается лучшим). Важно нормировать её по длине (на символы, токены или PMI). Можно смотреть и на перплексию, полноту (recall) или F1.

Для генеративных оценок выбор метрик шире. Нужно:

  1. решить, сравнивать генерации как есть или сначала их нормализовать:
    • нормализация легко может оказаться нечестной, если её плохо продумать, но в целом она всё равно даёт сигнал на уровне задачи;
    • она очень важна для некоторых задач, например в математике, где ответ нужно извлечь из оформленного вывода;
    • она понадобится и если вы оцениваете с дополнительными приёмами повышения точности, например с цепочкой рассуждений (Chain of Thought): рассуждение нужно отделить от собственно ответа;
  2. решить, как сравнивать генерацию с эталоном: от метрик совпадения (точное совпадение, совпадение префикса и т. д.) до метрик пересказа и перевода (ROUGE, BLEU, сравнение символьных n-грамм). Список существующих метрик — здесь.

В целом, выбирая метрику, помните, о чём на самом деле ваша задача. В некоторых областях (медицина, чат-боты для широкой публики) нужно измерять не среднее качество, а худшее качество, которое вы получите (по медицинской корректности, токсичности и т. д.). (Подробнее — в этом посте.)

Умные новые задачи: функциональное тестирование

Заголовок раздела «Умные новые задачи: функциональное тестирование»

В программировании сгенерированные программы оценивают не только по смыслу, но и по тому, работают ли они. Хороший способ — проверить, проходит ли код, сгенерированный по промпту, набор модульных тестов, подобранных под задачу.

Функциональный подход очень многообещающий, потому что:

  • тестовые случаи легче генерировать (часто — по правилам);
  • значит, меньше переобучения;
  • модель проверяется на конкретных «активных» способностях.

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

Хороший пример — IFEval, бенчмарк, проверяющий, умеет ли модель следовать инструкциям. Он даёт набор инструкций по форматированию (Сделай столько-то пунктов списка. Напиши заглавными буквами только одно предложение. и т. п.) и строго проверяет, соблюдён ли формат. Явно нужна дальнейшая работа, чтобы распространить эту идею на другие свойства текста!

Автоматические бенчмарки: советы и приёмы

Заголовок раздела «Автоматические бенчмарки: советы и приёмы»

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

Способы смягчить проблему:

  • добавить в оценочный набор строку-канарейку (canary string), как в BigBench: особое сочетание символов, которое создатели моделей могут искать в обучающих наборах; если оно нашлось, значит, туда попал оценочный набор;
  • распространять оценочные наборы в зашифрованном виде или с ограниченным доступом, чтобы их не могли легко прочитать веб-краулеры и они не попадали случайно в обучающие наборы;
  • использовать динамические бенчмарки, которые регулярно обновляются, чтобы модели не могли «выучить ответы наизусть» (но это делает наборы дороже);
  • если вы ведёте бенчмарк, пытаться обнаружить загрязнение задним числом (например, по перплексии генераций или с помощью состязательных версий промптов — но ни один метод не даёт стопроцентной гарантии).

Однако загрязнённый набор не обязательно бесполезен: он всё ещё может давать сигнал во время обучения.

Практические проблемы, с которыми вы можете столкнуться

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

Дообученные модели, системные промпты и шаблоны чата

Заголовок раздела «Дообученные модели, системные промпты и шаблоны чата»

Многие модели, прошедшие instruction tuning, покажут ужасные результаты, если не позаботиться о том, чтобы:

  • добавить их системный промпт в самое начало инференса;
  • подавать промпт через шаблон чата (обычно он добавляет префиксы Assistant и User к репликам диалога; подробнее — в хорошем руководстве).

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

  1. Токенизировать контекст и варианты вместе или раздельно. При оценке MCQA обычно нужно токенизировать контекст вместе с вариантами: так получается последовательность токенов, естественная для модели. Однако некоторые токенизаторы (например, у Llama) не удовлетворяют равенству enc(context + choice) = enc(context) + enc(choice) (добавляют или убирают пробелы). Тогда сравнивать логарифмы вероятностей вариантов непросто: токены контекста могут «перетекать» в варианты и портить сравнение. Если у вашей модели так, стоит токенизировать контекст и вариант по отдельности, а затем склеить их, удалив добавленные специальные токены начала и конца предложения.
  2. Внимание к токенам начала и конца предложения. Некоторые модели, например Gemma, крайне чувствительны к наличию токена начала предложения при инференсе. Возможно, придётся поэкспериментировать и добавлять эти токены вручную при оценке. Бывает и так, что модель не останавливается на ожидаемом токене конца (например, на \n), потому что предсказывает его не отдельно, а в составе более крупного токена (например, \n\n, который может быть одним токеном, особенно у моделей для кода). Тогда нужна отдельная проверка, которая «откатывается» по сгенерированному тексту и обрезает предложение в правильном месте до подсчёта метрик.
  3. Многоязычность и токенизация. В многоязычных оценках нужно решить, как токенизировать текст для вашей задачи и метрик. Некоторые языки не всегда разделяют слова пробелами (корейский, тайский, японский, китайский и др.), и для правильного разбиения им нужны специальные токенизаторы, иначе пострадают оценки по метрикам вроде BLEU, F1 и т. д.
  4. Оценка кода и токены конца. Модели для кода обычно обучены с \n\t как одним токеном. Значит, при генерации они часто выдают \n\t за один шаг. Задача, где \n задан как токен конца (остановки генерации), позволит модели продолжать после \n\t, если он предсказан одним токеном, ведь это не то же самое, что \n. А вы хотели бы, чтобы модель остановилась. В таких случаях нужно либо обновить токены конца, либо сделать механизм, который задним числом проверяет символьное представление последних токенов и останавливает (и обрезает) генерацию.

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

Тогда вместо number_of_choices прогонов (context + choice 1, context + choice 2 и т. д.) можно один раз прогнать инференс на context и посчитать распределение вероятностей по всему словарю (в которое войдут все однотокенные варианты), получив нужные логарифмы вероятностей за один проход. (Так это сделано в lighteval.)

Неожиданно плохие результаты генеративных оценок

Заголовок раздела «Неожиданно плохие результаты генеративных оценок»

Первым делом всегда внимательно смотрите на генерации модели. Частые причины:

  • слишком строгий разбор вывода модели (перед подсчётом метрики), из-за которого ответ теряется:
    • исправление: адаптировать разбор;
  • неспособность моделей следовать вашему формату вывода в few-shot (часто у свежих моделей, обученных на инструктивных данных, вроде Llama 3.2 или Qwen 2.5):
    • исправление: адаптировать формат промпта либо считать, что модели должны уметь следовать ему в few-shot;
  • чрезмерно многословная модель, которая так и не доходит до правильного ответа (чаще у моделей с длинным контекстом; мы наблюдали это у моделей Qwen и CommandR):
    • исправление: увеличить допустимую длину контекста, добавить в промпт задачи указание отвечать кратко или считать, что модели должны уметь отвечать сжато.
ENRU
prompt, token, vocabularyпромпт, токен, словарь
log-likelihood evaluationоценка по логарифму правдоподобия
generative evaluationгенеративная оценка
MCQA (multiple-choice question answering)вопросы с выбором ответа
gold (reference)эталонный ответ
calibrationкалибровка
few-shot, in-context learningпримеры в промпте, обучение в контексте
structured generationструктурированная (ограниченная) генерация
contamination, canary stringзагрязнение (утечка бенчмарка), строка-канарейка
exact match, BLEU, ROUGE, F1точное совпадение и метрики сравнения текстов
chat template, system promptшаблон чата, системный промпт
functional testingфункциональное тестирование (по выполнению)