Агент на базе LLM может ошибиться в двух ключевых местах: выбрать неверный инструмент или вызвать правильный, но с некорректными аргументами. Эти ошибки требуют разных метрик оценки. Если агент вызывает lookup_order вместо refund_order — это проблема выбора инструмента. Если же он вызывает refund_order с неверным order_id — проблема в аргументах.
В этой статье разберем три метода тестирования: референсный LLM-судья, детерминированные проверки через JSON Schema и сравнение траекторий (trajectory comparison). Также покажем, как запустить эти тесты для нескольких моделей через единый API.
011. LLM Judge: оценка контекста без жестких правил
Этот метод подходит, когда правильность выбора зависит от контекста, и не существует единственного верного ответа. Например, для запроса о политике возврата агент может выбрать search_docs или lookup_order в зависимости от доступной информации. LLM-судья оценивает, насколько обоснован выбор инструмента или значение аргумента, не опираясь на фиксированный эталон.
Важно: инструкции для судьи должны быть четкими. При сравнении моделей используйте одного и того же судью с фиксированными параметрами. Если вопрос можно решить механически (через код), лучше использовать этот способ, а не LLM.
022. Детерминированные проверки (JSON Schema)
Не все ошибки требуют вызова другой модели. Если структура аргументов строго определена, используйте валидацию по JSON Schema. Это позволяет отловить:
- Отсутствующие обязательные поля (например,
order_id). - Неверные типы данных (строка вместо булевого значения).
- Лишние поля, не указанные в схеме.
Пример схемы для инструмента lookup_order:
{
"type": "function",
"function": {
"name": "lookup_order",
"description": "Look up an order by its ID.",
"parameters": {
"type": "object",
"properties": {
"order_id": { "type": "string" },
"include_items": { "type": "boolean" }
},
"required": ["order_id"],
"additionalProperties": false
}
}
}Даже если аргументы проходят валидацию схемы, они могут быть семантически неверными. Например, "order_id": "ord_7282" соответствует схеме, но если пользователь спрашивал про ord_7281, это ошибка. Поэтому валидацию структуры нужно дополнять проверкой значений.
033. Сравнение траекторий (Trajectory Comparison)
Для многошаговых агентов важна не только правильность каждого вызова, но и их последовательность. Например, для оформления возврата может требоваться строгий порядок: lookup_order → verify_refund_eligibility → issue_refund.
Существуют разные режимы сравнения:
- Strict: точное совпадение последовательности.
- Unordered: набор вызовов совпадает, порядок не важен.
- Subset/Superset: проверка наличия обязательных вызовов.
Если порядок вызовов lookup_customer и lookup_subscription не влияет на результат, не стоит требовать строгой последовательности. Лучше оценивать конечное состояние или наличие всех необходимых шагов.
04Запуск тестов через OpenRouter
Для сравнения моделей удобно использовать единый интерфейс, например, через OpenRouter. Это позволяет тестировать разные модели (Anthropic, OpenAI, Moonshot и др.) с одинаковыми параметрами.
Установите необходимые библиотеки:
pip install openai jsonschemaПример скрипта на Python для запуска тестов:
import json
import os
from jsonschema import Draft7Validator, ValidationError
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
)
tools = [
{
"type": "function",
"function": {
"name": "lookup_order",
"description": "Look up an order by its ID.",
"parameters": {
"type": "object",
"properties": {
"order_id": { "type": "string" },
},
"required": ["order_id"],
"additionalProperties": False
},
},
}
]
test_cases = [
{
"name": "known order",
"messages": [{"role": "user", "content": "Check the status of order ord_7281."}],
"expected_calls": [{"name": "lookup_order", "arguments": {"order_id": "ord_7281"}}],
},
{
"name": "no tool needed",
"messages": [{"role": "user", "content": "What does an order status of 'shipped' mean?"}],
"expected_calls": [],
},
]
models = [
"anthropic/claude-opus-5",
"openai/gpt-5.6-sol",
"moonshotai/kimi-k3",
]
def grade_case(model, case):
response = client.chat.completions.create(
model=model,
messages=case["messages"],
tools=tools,
tool_choice="auto",
extra_body={"reasoning": {"effort": "none"}}
)
# Здесь должна быть логика сравнения response с expected_calls
return response05Кому подойдёт / что запустится
- Разработчикам AI-агентов: для отладки и оценки качества вызовов инструментов в своих продуктах.
- ML-инженерам: для бенчмаркинга моделей (Claude, GPT, Kimi) на задачах с tool calling.
- Продакшен-системам: где критична точность передачи аргументов и последовательности действий.
Рекомендуется комбинировать методы: использовать JSON Schema для структурной валидации, LLM Judge для семантической оценки и Trajectory Comparison для многошаговых сценариев.
Источник: OpenRouter ↗
