Бенчмарки и контроль качества
🔵 agent-os bench прогоняет агентов по сценариям end-to-end и пишет отчёт — так
качество агентов проверяется автоматически, а не «на глаз».
16.1 Запуск
# против работающего сервера
agent-os bench --url https://HOST --max 5
# поднять собственный локальный сервер (нужен DEEPSEEK_API_KEY в .env)
agent-os bench --port 3001 --max 3
# конкретный агент
agent-os bench --url https://HOST --agent drom --max 5 --parallel 3
# сценарии по имени (подстрока; `a|b` = OR)
agent-os bench --url https://HOST --name "Camry|BMW" --max 10
# с LLM-судьёй качества и кодом возврата для CI
agent-os bench --url https://HOST --agent drom --judge --fail-on-error --out report.json
# 3 полных прогона с усреднением (борьба с шумом LLM/сети)
agent-os bench --url https://HOST --agent drom --repeats 3 --judge
Флаги: --url, --port (3001), --agent, --name, --max (0=все),
--parallel (4), --timeout (90), --config (корень конфигов), --out
(путь отчёта), --repeats (1), --judge, --judge-model, --fail-on-error.
Форма — --flag value.
--repeats N прогоняет весь набор сценариев N раз и усредняет: ход считается
пройденным только если прошёл во всех N прогонах (pass^N), а токены/стоимость/
время/judge — средние. Это убирает «качели» одиночных прогонов; в отчёте есть
поле repeats.
Результат — bench_report_<timestamp>.json (или --out), со счётчиками ходов
passed/failed, счётчиками сценариев scenarios_*, per-turn failures и
полным текстом ответа в поле response. --fail-on-error даёт код возврата 1,
если был хотя бы один провал.
16.2 Формат сценария
Сценарии в config/agents/<agent>/bench/scenarios.yaml:
name: "Drom Agent"
model: "drom-agent"
scenarios:
- name: "Поиск Camry"
turns:
- user: "Найди Toyota Camry"
assert:
contains: [camry]
min_links: 2
valid_urls: true
Многоходовые сценарии
- name: "Multi-turn: уточнение"
turns:
- user: "Первый вопрос"
assert: { contains: [Слово], min_links: 2 }
- user: "Уточнение"
assert: { min_links: 1 }
- user: "Финальное уточнение"
assert: { valid_urls: true }
Типы проверок
| Проверка | Смысл |
|---|---|
contains: [w1, w2] |
ответ должен содержать подстроки (без учёта регистра) |
not_contains: [w1, w2] |
этих подстрок быть не должно |
regex: ["..."] |
ответ должен соответствовать каждому regex |
min_links: N |
минимум N markdown-ссылок [text](url) |
min_urls: N |
минимум N URL (markdown-ссылки + голые http(s)://) |
valid_urls: true |
все URL начинаются с http:// или https:// |
min_chars: N |
минимальная длина ответа |
max_elapsed_ms: N |
потолок времени хода (скорость) |
max_completion_tokens: N |
потолок токенов ответа (экономия) |
max_cost_usd: X |
потолок стоимости хода |
Скорость и экономию токенов задавайте явными потолками
(max_elapsed_ms/max_completion_tokens/max_cost_usd), а не только судьёй.
16.3 Анализ результата
- Смотри консоль:
✓(pass) /✗(fail). - Читай
bench_report_*.json: поляfailuresиerror. - Сравни два отчёта (diff) для поиска регрессий.
16.4 Хранилище запусков
Запуски пишутся в logs/bench.db и видны в админ-API:
| Endpoint | Описание |
|---|---|
POST /v1/agents/:name/bench/run |
запустить бенчмарк шаблона |
GET /v1/agents/:name/bench/runs |
история запусков шаблона |
GET /v1/agents/:name/bench/runs/:id |
один запуск + его ходы (пока running — компактный статус; ?full=1 — полный) |
GET /v1/bench/runs |
последние запуски по всем шаблонам |
GET /v1/bench/catalog |
шаблоны с настроенными сценариями |
Тело запуска (все поля необязательны):
{"timeout_secs": 90, "parallel": 4, "judge": false, "judge_model": ""}.
parallel задаёт одновременно выполняемые сценарии, judge включает
LLM-оценку каждого успешного хода (средний балл — avg_judge_score).
В админ-UI эти параметры доступны на вкладке «Бенчмарки».
Пока прогон идёт (status: running), GET .../runs/:id по умолчанию отдаёт
компактный ответ (run, progress {done,total}, hint) без списка ходов —
чтобы агент, который ждёт результат, не тянул весь список на каждом опросе.
Полный список возвращается, когда status перестаёт быть running, либо по
?full=1. Агенту не нужно опрашивать чаще, чем раз в ~30 с — для этого есть
инструмент wait_tool.
Если сервер остановили/перезапустили во время прогона, такой «сиротский» запуск
при следующем старте помечается failed (finished_at + error: interrupted: server stopped before the run finished), а не висит в running.
16.5 Практики
- Каждый сценарий фокусируется на одном фильтре/потоке.
- Запросы на русском (drom/hg/ngu), английском (rss).
- Многоходовые сценарии проверяют сохранение контекста между ходами.
- Тяжёлые сценарии — комбинированные фильтры и крайние случаи.
min_links: 1для крайних случаев (редкие бренды, узкие фильтры).- Всегда
valid_urls: true— ловит сломанное форматирование ссылок.