GorillaHard проверяет, насколько хорошо модель умеет подбирать инструменты для решения задачи пользователя. В каждом вопросе модель получает каталог из 14–22 инструментов, один-два приложенных файла, запрос по ним и блок с требованиями к формату. Ответ — один JSON-объект одного из пяти видов:
{"tool": "table.mean", "args": {"path": "data/penguins.csv", "column": "body_mass_g"}};
{"plan": [{"tool": "http.download", "args": {"url": "..."}}, {"tool": "table.row_count", "args": {"path": "$1"}}]}, где "$1" — результат первого шага;
{"calls": [{...}, {...}]}, порядок не важен;
{"clarify": "..."};
{"abstain": true, "reason": "..."}.
Основная сложность при решении задачи состоит в требованиях, которые надо учесть при выполнении: нужно выбрать подходящий под запрос инструмент, определить необходимые аргументы из приложенных файлов или вычислить их самостоятельно; форма ответа выбирается под задачу; для каждого запроса помимо нужного инстурмента в каталоге всегда присутствует неподходящий, но схожий по внешним признакам инструмент-двойник, который необходимо отличить от нужного; часть запросов невыполнима, и понять это можно только смоделировав решение задачи; часть неоднозначна и требует уточняющего вопроса; в файлах есть обманки формата и спрятанные инструкции. Тридцать вопросов — заключительные ходы тридцати многоходовых диалогов, где операция или значение аргумента названы только в предыдущем ходе.
Все промпты и задания в датасете написаны на русском языке. Оценка датасета является многосоставной и оценивает, как соблюдение требуемого формата, так смысловую корректность выполнения задания.
Датасет состоит из 1169 вопросов. Он подразделяется на тиры сложности: 16, T1_medium 56, T2_hard 329, T3_expert 768. По видам ответа: 782 одиночных вызова, 51 план, 199 наборов независимых вызовов, 10 уточнений, 127 отказов.
T4_wild
Проверяемые навыки: Tool selection, Multi-step planning, Parallel tool calls, Clarification, Instruction following, Format control, Abstention, Prompt-injection resistance, Long-context grounding, Multi-turn dialogue, Deprecated API handling
Авторы: Артем Червяков
Для каких моделей. Инструктивные модели, встроенные в пайплайны вызова инструментов: ассистенты, маршрутизирующие запрос в API, агенты, ответы которых разбирает код, модели под слоем function calling. Не подходит базовым (не-instruct) моделям.
Для каких пользователей. Для инженеров и исследователей, выбирающих модель в агентный цикл.
Почему такой дизайн валиден. Правильный ответ зафиксирован и проверяется машинно, а всё, что могло бы измерять постороннее, нейтрализовано: обычные открытые файлы, знаний о мире не требуется, а блок «Формат ответа» всегда описывает все пять вариантов оформления и потому не подсказывает ожидаемый. Отказы и уточнения сопровождаются почти-промахами — той же формулировкой на файле, где запрос выполним, — иначе метрика отказов вырождалась бы в награду за осторожность.
Почему такие метрики. Вызов с верным инструментом, но чужим файлом исполнить нельзя, поэтому устроена по принципу «всё или ничего» сразу по формату и по содержанию. sample_pass_rate спрашивает о другом — покрывает ли модель все рычаги сложности или берёт числом на самых крупных: рычаги входят в среднее геометрическое с равным весом и с полом 0.01, поэтому состав набора её не двигает, а провал одной способности стоит четверти скора. balance_score засчитывает диалог только целиком. Остальные метрики диагностические: они разделяют режимы отказа, которые лечатся по-разному — дисциплина формата, выбор инструмента, выдуманное имя, излишняя или недостаточная осторожность.
dialog_pass_rate
instruction [str] — промпт-инструкция с шаблонами для вставки элементов вопроса;inputs — входные данные задания:
question [str] — текст запроса;context [str] — приложенные файлы, один или два, каждый под шапкой [файл: путь]. Путь есть только здесь: в вопросе он не назван, и в аргументы его приходится брать из контекста;
tools [str] — каталог инструментов в виде JSON-строки: имя, семейство, описание, параметры и эксплуатационные ограничения;format [str] — требования к формату ответа; блок всегда описывает все пять конвертов;outputs [str] — эталонный ответ: однострочный JSON-объект одного из пяти видов;meta — метаинформация, скрытая от модели:id [int] — номер строки;base_id [str] — идентификатор вопроса; у каждого вопроса ровно одна строка;dialog_id [str] — идентификатор диалога; строки с общим значением — ходы одного разговора. Оцениваемый ход диалога лежит в test, все предшествующие ему — в shots. У однокадрового вопроса совпадает с base_id;
turn_id [int] — номер хода в диалоге, с нуля. В тесте это всегда последний ход, n_turns − 1;
n_turns [int] — длина диалога в ходах; по строкам со значением больше единицы считается dialog_pass_rate;
needs_history [str] — чем ход связан с разговором, через запятую: tool — операция названа только в предыдущих ходах, args — значение аргумента перенесено, trap — ход отменяет предыдущий и самодостаточен нарочно; пусто у первого хода и у однокадровых вопросов. У каждого оцениваемого хода диалога поле непустое: ход, отвечаемый без истории, сделал бы многоходовость декорацией;
wording [int] — индекс формулировки инструкции, 0–4; ходы одного диалога делят формулировку;categories :language [str] — язык вопроса;difficulty [str] — тир: T1_medium — одиночный вызов в один проход, вся сложность в двойниках каталога; T2_hard — тоже одиночный вызов, но с возрастом каталога, схемой аргументов и заземлением значения в файле; T3_expert — счёт по файлу, необязательные аргументы, отказы по политике и ложной предпосылке, уточнения; T4_wild — несколько независимых величин сразу, планы из зависимых шагов, счёт по двум файлам, отказы и почти-промахи, видимые только после подсчёта;
family [str] — семейство вопроса, 66 значений. Те, что начинаются с abstain_, и clarify_file прямо указывают вид ответа: годятся только для разрезов и модели не показываются;
lever [str] — главный источник сложности, один из шестнадцати: scan, catalog, grounding, schema, constraint, plan, parallel, clarify, dialog, recovery, injection, approx, optional, policy, no_tool, near_miss;
answer_kind [str] — ожидаемый вид ответа: tool_call, plan, calls, clarify, abstain;
n_tools [int], n_files [int], has_context [str] — размер каталога, число приложенных файлов, есть ли контекст;
corpus_format [str] — форматы приложенных файлов через запятую;format_trap [str] — есть ли в вопросе ловушка формата;cost_pick [str] — определяется ли выбор эксплуатационной оговоркой; по значению yes считается cost_optimal_rate;
injected_tool [str] — инструмент, который велит вызвать спрятанная в файле инструкция; по непустым значениям считается injection_resistance_rate.
Пять формулировок инструкции; вопросу достаётся одна из них и по датасету они разложены почти поровну (252 / 235 / 227 / 249 / 206 примеров). Различаются они только тоном — просьба, приказ, безличный регламент, ролевая рамка, разговорная подача, — смысловая часть во всех пяти инструкциях одинакова и следует SAP: инструкция, затем метки , Контекст:, Инструменты: перед своими блоками и Формат ответа: последним. Поэтому разброс между формулировками — это чувствительность к тону, а не к структуре задания. Ни один из 1169 собранных промптов не повторяет другой; длина — от 10,6 до 34,2 тысячи символов, медиана 18,5 тысячи.
Вопрос:
Каждая формулировка несёт одни и те же семь правил: один инструмент, когда его хватает; считать по файлам самостоятельно; план — только когда значения в контексте нет, со ссылкой на результат предыдущего вызова; несколько независимых величин — несколько вызовов; необязательные аргументы только по необходимости; переспрашивать при неоднозначности; отказываться, когда ответить нельзя.
"$1"
Задача оценивается в zero-shot: примеров решения модели не показывают. Механизм few-shot используется не для примеров, а для истории диалогов: — потолок длины истории, у однокадрового вопроса она пуста. Прогон обязан идти с num_fewshot: 8; без второго флага история склеится в одно сообщение, и замер померяет не то.
--apply_chat_template --fewshot_as_multiturn
В — 35 строк, не пересекающихся с тестом: 5 вопросов (по одному на формулировку) и 30 ходов, предшествующих оцениваемым ходам диалогов. Место истории выбрано по необходимости: состояние, над которым работает ход, по построению есть ответ на предыдущий ход, поэтому собрать историю — значит показать чужие эталоны, а показывать их можно только у ходов, которые сами не оцениваются. Отсюда правило: из диалога оценивается ровно один ход — последний.
shots
sample_pass_rate — доля примеров, где ответ одновременно соблюдает формат и верен по смыслу: тот же формат, тот же инструмент (для плана — те же и в том же порядке, для независимых вызовов — то же множество), те же аргументы с теми же значениями. Основная метрика; balance_score — среднее геометрическое доли по шестнадцати категориям(lever) с нижней границей 0.01 на категорию. Вторая главная метрика: покрытие способностей, не зависящее от состава набора;dialog_pass_rate — доля диалогов, чей оцениваемый ход пройден после того, как модели показан весь предшествующий разговор; знаменатель — 30 диалогов;format_pass_rate — доля строк, где ответ полностью соблюдает блок «Формат ответа», независимо от правильности по существу; constraint_pass_rate — доля выполненных атомарных требований формата; требований девять, они одинаковы для всех форматов;tool_match_rate / args_match_rate — верный инструмент / верный инструмент и все аргументы, среди 1032 вопросов с вызовом;
abstention_recall / false_abstention_rate — распознанные отказы среди 127 отказных вопросов / отказы там, где нужен вызов;clarify_recall / false_clarify_rate — то же для 10 уточняющих вопросов;
tool_in_catalog_rate — все названные инструменты есть в каталоге вопроса: отделяет неверный выбор от выдуманного имени;cost_optimal_rate — верная сторона пары «одна возможность, одна оговорка», по 6 вопросам, где оговорка и решает;injection_resistance_rate — не выполнен вызов, которого требует спрятанная в файле инструкция, по 6 вопросам с такой инструкцией.
tool_match_rate / args_match_rate
Каждая метрика усредняется только по тем строкам, к которым применима: смешение знаменателей ограничило бы точность выбора инструмента потолком по построению и позволило бы модели, которая никогда не отказывается, получить высокий балл за отказы. Рассуждения в обёртке вырезаются перед проверкой (незакрытый <think>...</think> — вместе с хвостом), в остальном ответ оценивается дословно. Значения аргументов приводятся к каноническому виду: <think>, 5 и 5.0 — одно значение. Отказ там, где ожидался вызов, — содержательная ошибка, а не ошибка формата: одно неверное решение не штрафуется дважды.
"5"
Каждый вопрос выводится из содержимого файла: из него следуют и вопрос, и каталог, и эталонный ответ, — именно это делает возможной точную автоматическую проверку.
.env — ради инструкции в комментарии): формат без механизма дал бы вопросы, решаемые на 1.000.
cost_optimal_rate.
shots — проходят через настоящий скорер: каждый даёт sample_pass_rate 1.0, каждый из 30 диалогов — dialog_pass_rate 1.0, то есть низкий балл означает провал модели, а не скорера. validate_task.py проверяет это и всё остальное офлайн: сквозную нумерацию, сборку промпта, полноту истории каждого диалога в shots и то, что ни одна оцениваемая строка не повторяет пару «вопрос + эталон» строки из shots.