Бенчмарки

Откуда берутся цифры: какие данные, какие проверки, какие инструменты — и когда цифрам верить нельзя.

English

Что такое бенчмарк

Бенчмарк — это экзамен для промпта.

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

Смысл в том, чтобы вместо «мне кажется, так промпт работает лучше» иметь «на двухстах примерах стало 0.83 против 0.71».

Экзамен состоит из трёх частей:

Датасет

Сами задачи и эталонные ответы к ним. Одна задача — одна строка файла.

Проверяльщики (graders)

Небольшие куски кода, которые сравнивают ответ модели с эталоном и ставят оценку от 0 до 1. У каждой задачи свои — арифметику и перевод нельзя проверять одинаково.

Прогон

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

Какие датасеты здесь есть

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

ДатасетПримеровЧто проверяетОткуда
entity-extraction6Вытащить людей и места из фразы в JSON.Демо, чтобы пощёлкать кнопки
entity-extraction-hard200То же, но с ловушками: титулы, отрицания, страна как прилагательное, повторы, случаи с пустым ответом.40 руками, 160 сгенерировано
multiconer-en200Люди и места в предложениях, специально подобранных как неоднозначные.публичный MultiCoNER v2
few-nerd200Люди, места, организации.публичный Few-NERD
gsm8k120Школьные текстовые задачи по арифметике в несколько действий.публичный GSM8K
mbpp80Написать функцию на Python по описанию.публичный MBPP
support-classification150Разложить обращения в поддержку по четырём категориям. 54 примера намеренно пограничные.Сгенерировано
summarization120Сжать документ до 170 символов, не потеряв ни одного имени, числа и даты.Сгенерировано
translation120Перевести с английского на испанский, обязательно применив заданный глоссарий.Сгенерировано
grounded-qa120Ответить строго по приложенным источникам. В 30 примерах ответа в источниках нет — надо честно сказать INSUFFICIENT_EVIDENCE, а не додумать.Сгенерировано
agents120Задачи, где нужно вызвать инструмент: калькулятор или счётчик слов.Сгенерировано

Не бери entity-extraction для выводов. Шесть примеров, и на них базовый промпт уже выдаёт 1.0 — расти некуда, любая техника выглядит одинаково хорошо. Это набор «посмотреть, как работает интерфейс». Реальный запас для улучшений есть у entity-extraction-hard, multiconer-en и few-nerd.

Что за публичные корпуса

Публичный корпус — это набор задач, который собрала и разметила чужая исследовательская группа и выложила открыто. Ценность в том, что данные никто здесь не подгонял под удобный результат.

КорпусЧто это простыми словамиЛицензия
MultiCoNER v2
SemEval-2023, задача 2
Соревнование по распознаванию имён, собранное специально из сложных случаев: названия, которые выглядят как обычные слова, редкие имена, неоднозначные фразы. Самый близкий публичный аналог нашего entity-extraction-hard.CC-BY-4.0
Few-NERDКрупный размеченный набор предложений с людьми, местами и организациями.CC-BY-SA-4.0
GSM8K
OpenAI
Школьные задачки «в лавке было столько-то, продали столько-то». Именно на нём в своё время показали, что просьба «рассуждай по шагам» даёт прирост. Здесь он нужен как противовес: все остальные наши задачи — чтение, а не счёт, и на чтении рассуждения обычно только мешают.MIT
MBPP
Google Research
Простые задачи на программирование, к каждой приложены свои тесты. Оценка ставится не сравнением текста, а запуском кода.CC-BY-4.0

Импорт делается командой prompt-playoff import-hf, лицензия и ссылка на статью печатаются при каждом импорте.

Как импорт не портит данные

Как проверяется ответ

Проверяльщик получает ответ модели и эталон, а возвращает число от 0 до 1. Их два семейства.

Проверки смысла — правильный ли ответ

field_f1Частичный зачёт по списку. Нашла три сущности из четырёх — примерно 0.86, а не ноль. Лишнее, чего в эталоне не было, тоже штрафуется. Это главная оценка для извлечения.
exact_matchСовпало ли всё целиком, без поблажек. Почти всегда сильно ниже field_f1 — это нормально.
label_accuracyУгадана ли категория. Для классификации.
numeric_closeСовпало ли число с эталоном. Оформление не учитывается — важен сам ответ.
unit_testsКод из ответа реально запускается и прогоняется через тесты задачи. Оценка — доля пройденных тестов. Запуск идёт в песочнице с ограниченным набором модулей.
glossary_consistencyДоля обязательных терминов, переведённых так, как велел глоссарий.
grounding_overlapКакая доля слов ответа вообще встречается в приложенных источниках. Грубая, но рабочая проверка на выдумывание.
contains_allВсе ли обязательные факты попали в ответ.
coverageТолько полнота: сколько нужного нашлось. Лишнее не штрафуется.
tool_successВсе ли вызовы инструментов вернули результат, а не ошибку.
agreementНасколько сходятся между собой несколько ответов, если техника генерирует их пачкой.

Проверки формы — правильно ли оформлен

json_validityРаспарсился ли ответ как JSON.
json_schemaСовпал ли со схемой полностью.
schema_shapeДоля обязательных полей, которые на месте. Частичный зачёт по форме.
no_proseНет ли болтовни вокруг ответа.
allowed_labelsМетка взята из разрешённого списка, а не придумана.
length_limitУложился ли ответ в лимит символов.
omission_checkНе обрезан ли ответ и не раздут ли — длина сравнивается с длиной исходника.
deduplicationНет ли повторов внутри списков.
python_syntaxПарсится ли код, который выдала модель.
regex_matchСовпал ли ответ с заданным шаблоном.

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

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

Как из проверок получаются две главные цифры

quality — это одна выбранная проверка смысла, та, что подходит задаче: field_f1 для извлечения, label_accuracy для классификации, numeric_close для арифметики, unit_tests для кода. В таблице Graders она помечена как headline, остальные показываются рядом для справки.

reliability — это доля правильно оформленных ответов, умноженная на стабильность (даёт ли модель один и тот же ответ на один и тот же вход).

Что с этими числами делать дальше — на странице Справка.

Пять правил, без которых цифра ничего не значит

1. Сто примеров минимум. На шести примерах разница в 5% — это один пример туда-сюда. На сорока примерах порог, ниже которого разница неотличима от шума, — примерно 0.04. Меньше этого не считается результатом.

2. Repeats = 3. При одном прогоне стабильность равна 1.000 по определению — не потому что стабильно, а потому что сравнивать не с чем.

3. Пустые примеры обязательны. Случаи, где правильный ответ — «ничего», держат промпт честным. Без них выигрывает тот, кто угадывает.

4. Оптимизацию смотри только на held-out. Оптимизатор подгоняется под примеры, которые видел. Прирост считается только на отложенной части, которую он не видел.

5. Цифра принадлежит паре «модель + датасет». Перенеси её на другую модель — и это снова догадка. Инструмент честно пишет measured там, где мерил, и prior only там, где предполагает.

Какие инструменты задействованы

ЧтоЗачемНужно ставить?
Собственный движокПрогон примеров, проверки, подсчёт качества, надёжности, стабильности, времени и токенов. Внешних зависимостей не требует.Встроен
OllamaЛокальные модели на своей машине. Вариант по умолчанию: бесплатно и без ключей.Отдельная программа
OpenAI-совместимые APIОблачные модели: OpenAI, Anthropic, DeepSeek, Together, OpenRouter, Groq, Fireworks. Годятся, когда локальная модель слишком слабая.Нужен ключ в переменной окружения
Hugging Face datasetsИмпорт публичных корпусов (import-hf). Hugging Face — главный публичный склад датасетов и моделей.Дополнительно
DSPyБиблиотека автоматического подбора промптов. Даёт три алгоритма поиска для кнопки Optimize.Дополнительно
promptfooЭкспорт промпта в чужой прогонщик тестов, если у команды он уже используется. Выгружается только первая стадия техники.Дополнительно
Langfuse / PhoenixТрейсинг: складывают каждый вызов модели в общий журнал, чтобы потом посмотреть, что именно уходило и приходило.Дополнительно

Четыре алгоритма в Optimize

nativeВстроенный жадный цикл: модель критикует свой же промпт и переписывает его, лучший вариант остаётся. Ничего доставлять не нужно.
DSPy MIPROv2Байесовский подбор: предлагает варианты инструкции и примеров и учится на том, какие оценки они получили. На наших замерах это единственный, который дал прирост.
DSPy GEPAЭволюция: держит набор непобеждённых вариантов и скрещивает их дальше.
DSPy BootstrapFewShotИнструкцию не трогает, подбирает только примеры для промпта.

Что уже намеряно

Готовые отчёты лежат в docs/benchmarks/. Коротко, что из них вышло:

Свои данные

Встроенные наборы — чтобы разобраться. Выводы про свою задачу можно делать только на своих данных. Файл .jsonl, по одной задаче на строку, загружается прямо в интерфейсе:

{"id": "1", "input": "Мара вошла в Вейр с Капитаном Орином.",
 "expected": {"people": ["Мара", "Капитан Орин"], "places": ["Вейр"]}}

Обязательны только id и input. Проверяльщики подберутся сами по виду эталона; можно задать их вручную полем graders.

Главное правило. Эталонный ответ должен встречаться в тексте слово в слово. Если в тексте «Капитаном Орином», а в эталоне «Капитан Орин» — модель получит незачёт за то, что не угадала твою форму записи. И оставь примеры, где правильный ответ пустой.

Чего бенчмарк не умеет

Подробности по каждому набору — в docs/datasets/, отчёты о прогонах — в docs/benchmarks/.