
Любая LLM, которая не просто генерирует текст, а выполняет действия — отправляет запросы в API, записывает в базу, запускает контейнеры — опирается на механизм tool calling (function calling). От того, насколько корректно модель выбирает инструмент и формирует аргументы, зависит, упадёт ли продакшен, утекут ли данные или просто не выполнится задача.
Проблема в том, что стандартные бенчмарки общего назначения не проверяют качество вызова инструментов. Модель может блестяще отвечать на вопросы, но ошибаться в типе аргумента или вызывать не тот эндпоинт. Без целенаправленного тестирования tool calling вы рискуете выпустить в прод агента, который будет стабильно делать одно и то же неверное действие.
В этой статье — набор сценариев, метрики и схема CI-пайплайна для автоматической проверки tool calling. Всё основано на реальных кейсах из документации OpenAI, Anthropic, открытых бенчмарков и практики инженерных команд.
Какие сценарии тестировать
Tool calling — это не один навык, а связка: модель должна понять, что нужен инструмент, выбрать правильный, передать корректные аргументы и корректно обработать ответ. Каждый из этих этапов требует отдельного теста.
Базовый сценарий: вызов правильного инструмента. Если пользователь пишет «Отправь письмо Ивану», модель должна вызвать send_email, а не create_draft или search_contacts. Тест: набор из 20–50 промптов с однозначной инструкцией, эталонный инструмент известен. Метрика — точность выбора инструмента (accuracy@1).
Сценарий с аргументами: корректность параметров. Модель может выбрать верный инструмент, но передать строку вместо числа или пропустить обязательное поле. Тест: для каждого инструмента подготовить 5–10 вариантов запроса с разной комбинацией аргументов. Проверять типы, наличие обязательных полей, допустимые диапазоны значений. В документации OpenAI это описано как strict schema validation — модель должна строго следовать JSON Schema инструмента.
Граничные сценарии: отказ от вызова. Бывают ситуации, когда инструмент вызывать не нужно — например, пользователь задаёт общий вопрос. Модель не должна вызывать функцию «просто потому что может». Тест: промпты, где инструмент не требуется, и проверка, что модель возвращает обычный текст, а не function call. Этот сценарий часто пропускают, а зря — ложные срабатывания засоряют логи и могут привести к лишним расходам на API.
Обработка ошибок инструмента. Что делает модель, если API вернул 500, таймаут или невалидный ответ? В идеале — повторяет вызов, логирует ошибку или сообщает пользователю. Тест: симуляция ошибочных ответов от инструмента и проверка поведения модели. Anthropic в своих примерах использует механизм tool_use с явной обработкой ошибок на стороне клиента — модель должна получить информацию об ошибке и решить, что делать дальше.
Метрики качества tool calling
Для автоматизации проверок нужны числовые метрики. Вот минимальный набор, который покрывает основные риски:
| Метрика | Что измеряет | Формула / способ расчёта |
|---|---|---|
| Tool selection accuracy | Доля случаев, когда модель выбрала правильный инструмент | Число верных выборов / общее число тестов |
| Argument validity | Доля вызовов, где все аргументы соответствуют схеме | Число валидных вызовов / общее число вызовов |
| False positive rate | Доля случаев, когда модель вызвала инструмент, хотя не должна была | Число ложных вызовов / число тестов без инструмента |
| Error recovery rate | Доля ошибок инструмента, после которых модель выбрала корректное действие | Число корректных реакций / число смоделированных ошибок |
| Latency p95 | Время от запроса до получения вызова инструмента (95-й перцентиль) | Измеряется по логам тестового прогона |
Эти метрики не абсолютны — их пороговые значения зависят от вашего сценария. Для критичных инструментов (например, списание денег) accuracy должна быть 100%, для рекомендательных — допустимо 95%. Главное — зафиксировать порог и не пропускать сборку, если метрика упала ниже.
Как собрать тестовый набор
Тестовый набор — это не просто список промптов. Каждый тест должен содержать: промпт, ожидаемый инструмент (или маркер «без инструмента»), ожидаемую схему аргументов и ожидаемое поведение при ошибке.
Вот минимальная структура тестового кейса в JSON:
{
"id": "tc-001",
"prompt": "Отправь сообщение 'Привет' пользователю user123",
"expected_tool": "send_message",
"expected_args": {
"recipient": "user123",
"message": "Привет"
},
"requires_tool": true,
"error_scenario": null
}
Для сценариев без инструмента:
{
"id": "tc-050",
"prompt": "Какая сегодня погода?",
"expected_tool": null,
"expected_args": null,
"requires_tool": false,
"error_scenario": null
}
Размер набора зависит от количества инструментов. Для 5–10 инструментов достаточно 100–200 тестов. Если инструментов больше — расширяйте набор пропорционально, минимум по 10 тестов на каждый инструмент и 20 тестов на граничные случаи.
Важно: тестовый набор должен обновляться при добавлении нового инструмента или изменении схемы существующего. Это не разовая работа, а часть CI/CD.
CI-пайплайн для проверки tool calling
Автоматическая проверка в CI — единственный способ не пропустить регрессию при смене модели или обновлении промпта. Вот примерная схема пайплайна на GitHub Actions:
- Триггер: push в ветку с изменениями промптов, добавлением инструментов или обновлением конфигурации модели.
- Прогон тестов: каждый тест из набора отправляется к LLM, результат вызова инструмента сравнивается с эталоном.
- Расчёт метрик: после прогона вычисляются tool selection accuracy, argument validity, false positive rate. Если хотя бы одна метрика ниже порога — пайплайн падает.
- Генерация отчёта: в артефактах сохраняется JSON с детальными результатами каждого теста — какие прошли, какие упали и с какой ошибкой.
- Уведомление: при падении — сообщение в Slack или Telegram с ссылкой на отчёт.
Пример конфигурации шага прогона тестов (упрощённо):
jobs:
test-tool-calling:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tool calling tests
run: python run_tool_tests.py --test-set tests/tool_calling.json --model gpt-4o --threshold-accuracy 0.95 --threshold-fpr 0.05
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: tool-calling-report
path: report.json
Сам скрипт run_tool_tests.py должен быть написан так, чтобы поддерживать разные модели и провайдеров — это позволит сравнивать качество tool calling при миграции.
Ограничения и частые ошибки
Tool calling — нестабильная область. Одна и та же модель может показывать разный результат на одинаковых промптах из-за температуры или недетерминированности. Поэтому тесты должны запускаться несколько раз (минимум 3) и усреднять метрики.
Вторая проблема — тестовый набор быстро устаревает. Если вы добавили новый инструмент, но забыли добавить тесты — пайплайн ничего не поймает. Решение: сделать добавление тестов обязательным шагом в code review при изменении схемы инструментов.
Третья — модели могут «переучиваться» на тестовый набор, если он используется в промпте системного сообщения. Не включайте тестовые примеры в продакшен-промпты, иначе метрики перестанут отражать реальное поведение.
Наконец, метрики tool calling не заменяют end-to-end тестирования агента. Можно иметь 100% accuracy на изолированных вызовах, но агент в реальном сценарии будет вызывать инструменты в неправильном порядке. Проверка tool calling — это нижний уровень, а не вся стратегия тестирования.
Что делать прямо сейчас
Если вы используете LLM с tool calling в разработке, начните с малого: соберите 30–50 тестов на самые критичные инструменты, запустите их вручную и зафиксируйте текущие метрики. Затем добавьте автоматический прогон в CI — хотя бы на один сценарий. Это сразу покажет, какие ошибки вы пропускаете сейчас.
Полезные источники для старта: документация OpenAI по function calling с примерами строгих схем, руководство Anthropic по tool use с обработкой ошибок и репозиторий с примерами. Для тестового набора можно взять за основу открытый бенчмарк Nexus, но адаптировать под свои инструменты — универсального набора не существует.