基准测试与质量控制

🔵 agent-os bench 按端到端场景运行智能体并生成报告——这样智能体的质量是自动检验的,而不是“凭肉眼”判断。


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),而 token/成本/ 时间/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 回答 token 上限(节省)
max_cost_usd: X 单轮成本上限

速度和 token 节省请用明确的上限 (max_elapsed_ms/max_completion_tokens/max_cost_usd)来设定,而不仅仅依靠 judge。

16.3 结果分析

  1. 看控制台:✓ (pass) / ✗ (fail)。
  2. 阅读 bench_report_*.json:字段 failures 和 error。
  3. 对比两份报告(diff)以查找回归。

16.4 运行存储

运行会写入 logs/bench.db,并可在 admin-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)。 在 admin-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 实践