AI 评测系列(05):Agent 评测——工具调用准确率与轨迹质量

Agent 评测为什么特殊

评测一个 RAG 系统,最终答案就是评测对象------对或错,准确或不准确。

Agent 的过程本身也是评测对象。绕 3 步找到的正确答案,和调对工具但参数错误的情况,只看最终答案都会漏掉。

Agent 评测需要覆盖两个维度:

csharp 复制代码
维度 1:工具调用准确性(可自动化)
  工具名准确率:选了正确的工具?
  参数准确率:工具调用参数正确?
  步骤效率:用了多少步完成任务?

维度 2:轨迹质量(LLM-as-Judge)
  推理是否合理:每步调用有逻辑依据?
  有无冗余调用:是否存在重复或无效的工具调用?
  错误处理:工具返回空结果时有没有正确应对?

实验设计

被测 Agent: 客服助手,3 个工具:

python 复制代码
search_faq(query)                                  # 搜索产品常见问题
get_order_status(order_id)                         # 查询订单状态
calculate_refund(amount, days_since_purchase)       # 计算退款金额

15 个测试用例,覆盖三类场景:

类别 用例数 示例
简单单工具 9 个 "退款政策是什么" → search_faq
多步骤 3 个 "ORD-004 能退款多少" → get_order_status + calculate_refund
边界情况 3 个 不存在的订单、已取消的订单、无需工具的闲聊

每个用例有 ground truth:期望的工具调用序列和参数。


运行结果

工具调用准确率

ini 复制代码
  [T01] ✓ tools=['search_faq']                     name=✓  params=100%
  [T02] ✓ tools=['get_order_status']                name=✓  params=100%
  [T03] ✗ tools=[]  期望=['search_faq']             name=✗  params=100%
  [T04] ✗ tools=[]  期望=['get_order_status',...]   name=✗  params=100%
  [T05] ✓ tools=['calculate_refund']                name=✓  params=100%
  [T06] ✓ tools=['get_order_status','calculate_refund'] name=✓ params=100%
  ...
  [T10] ✗ tools=[]  期望=['search_faq']             name=✗  params=100%
  [T13] ✓ tools=[]  期望=[](闲聊,无需工具)       name=✓  params=100%
  [T14] ✗ tools=[]  期望=['get_order_status']       name=✗  params=100%

汇总指标

ini 复制代码
Tool Name Accuracy:   73%  (11/15 correct sequences)
Parameter Accuracy:  100%  (avg across all tool calls)
Step Efficiency:     0.73x  (1.0 = optimal)
Trajectory Quality:  3.73/5  (LLM-as-Judge)

Failed cases (4):
  [T03] expected=['search_faq']                actual=[]
  [T04] expected=['get_order_status', 'calculate_refund']  actual=[]
  [T10] expected=['search_faq']                actual=[]
  [T14] expected=['get_order_status']          actual=[]

Per-category breakdown:
  Simple (1 tool)        tool_acc=75%  trajectory=3.75/5
  Multi-step (2 tools)   tool_acc=67%  trajectory=3.67/5
  Edge cases             tool_acc=67%  trajectory=3.67/5

三个发现

发现 1:失败类型只有一种------"应调工具却没调"

4 个失败案例的失败模式完全一致:Agent 直接给出答案,没有调用任何工具。参数准确率 100% 说明凡是 Agent 决定调工具的情况,参数都是对的。

失败分布:

复制代码
工具选错类型(调了但选错):0 个
参数错误类型(选对但参数错):0 个
未触发工具类型(应调未调):4 个

工具执行逻辑没有问题,工具触发逻辑是瓶颈。Agent 在某些情况下认为自己知道答案,跳过了工具调用。

T03("配送需要多少天?")和 T10("我是会员,有什么优惠?")失败原因:这两类问题 glm-4-flash 有内置知识,即使 Prompt 要求"必须使用工具",模型仍然直接回答了。T04(需要先查订单再计算退款)和 T14(已取消订单的退款问题)失败原因:复合问题和边界问题,模型倾向于直接推断而不是查询。

修复方向: 在 System Prompt 里针对这些场景加更强的约束,或者用 Rule-based 路由在 LLM 判断之前预处理特定类型的问题。

发现 2:步骤效率 0.73x------低于 1.0 是因为有些任务少用了步骤

步骤效率 < 1.0 看起来是好事,实际原因是失败案例中 Agent 少做了必要步骤。

复制代码
理想情况(无失败)下的效率:
  T06(需要 2 步):Agent 用了 2 步 → 效率 1.0
  T12(需要 2 步):Agent 用了 2 步 → 效率 1.0

失败案例(减少了步骤,但答案质量下降):
  T04(需要 2 步):Agent 用了 0 步 → 效率 0.0

步骤效率低于 1.0 有两种原因:

  1. Agent 真的找到了更高效的路径(好事)
  2. Agent 跳过了必要步骤(坏事)

单看步骤效率数字无法区分这两种情况,需要结合工具名准确率一起解读。

发现 3:多步骤任务和边界情况的轨迹质量更低

ini 复制代码
Simple (1 tool):        tool_acc=75%  trajectory=3.75/5
Multi-step (2 tools):   tool_acc=67%  trajectory=3.67/5
Edge cases:             tool_acc=67%  trajectory=3.67/5

多步骤和边界情况的工具名准确率都是 67%,比简单任务的 75% 低。轨迹质量分也低。

多步骤任务的失败模式:Agent 认为可以一步完成,跳过了中间步骤。边界情况(已取消订单)的失败模式:Agent 直接推断"已取消订单没有退款",没有先查询订单状态确认信息。

这个分布符合大多数 Agent 系统的规律:简单直接的任务表现好,复合/边界任务表现差。测试集设计时必须包含足够比例的多步骤和边界用例,否则准确率数字会被单步任务拉高,掩盖真实问题。


工具调用评测的实现

工具名准确率

最严格的评测:工具调用序列必须完全匹配。

python 复制代码
def tool_name_accuracy(actual: list[str], expected: list[str]) -> bool:
    """检查工具调用序列是否完全匹配。"""
    if len(actual) != len(expected):
        return False
    return all(a == e for a, e in zip(actual, expected))

参数准确率

允许字符串部分匹配和数值容差,避免因格式差异导致漏判:

python 复制代码
def param_match_score(actual_calls, expected_args) -> float:
    """计算参数准确率,返回 0.0-1.0。"""
    total, correct = 0, 0
    for actual, expected in zip(actual_calls, expected_args):
        for key, expected_val in expected.items():
            total += 1
            actual_val = actual["args"].get(key)
            if actual_val is None:
                continue
            # 数值容差(允许 0.01 以内误差)
            if isinstance(expected_val, (int, float)):
                if abs(float(actual_val) - float(expected_val)) < 0.01:
                    correct += 1
            # 字符串部分匹配
            elif str(expected_val).lower() in str(actual_val).lower():
                correct += 1
    return correct / total if total > 0 else 1.0

轨迹质量(LLM-as-Judge)

python 复制代码
TRAJECTORY_JUDGE_PROMPT = """评估以下 Agent 执行轨迹的质量(1-5分):

用户问题:{question}
Agent 调用的工具:{tool_calls}
Agent 的最终回答:{answer}

5分:工具调用完全合理,每步都有必要,回答准确完整
4分:工具调用基本合理,有1个小问题
3分:工具调用方向正确,但有冗余或遗漏
2分:工具调用部分错误,回答质量差
1分:工具调用完全错误或完全无关

只返回 1-5 的整数分数。"""

测试集设计的三个关键

1. ground truth 需要工具序列,不只是最终答案

python 复制代码
TestCase(
    id="T04",
    question="ORD-004 这个订单能退款多少钱?",
    expected_tools=["get_order_status", "calculate_refund"],   # 工具序列
    expected_args=[
        {"order_id": "ORD-004"},
        {"amount": 99.0, "days_since_purchase": 15}
    ],  # 期望参数
    expected_min_steps=2,   # 最少需要几步
)

2. 覆盖三类难度

erlang 复制代码
简单(单工具):    测基础工具识别能力,应占 50%
多步骤(多工具):  测规划能力,应占 30%
边界情况:          测鲁棒性(不存在的资源、空结果处理),应占 20%

3. 包含"不需要工具"的用例

纯闲聊和问候测试 Agent 是否会过度调用工具。一个正确的 Agent 应该知道"你好"不需要查订单数据库。


总结

  1. 工具名准确率 73%,参数准确率 100%:失败全是"应调未调",不是"调错了";这说明工具触发逻辑是瓶颈,工具执行逻辑没问题,优化方向很清晰
  2. 步骤效率 < 1.0 需要结合工具名准确率解读:低效率可能是找到更短路径(好),也可能是跳过必要步骤(坏)
  3. 测试集必须包含多步骤和边界用例:简单单工具任务准确率 75%,多步骤和边界任务只有 67%,如果测试集全是简单任务,73% 会虚报成 85%+

参考资料


欢迎访问 PrimeSkills ------ 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。

更多实用知识和有趣产品,欢迎访问我的个人主页

相关推荐
CTA量化套保几秒前
量化脚本准备实盘了吗?TqSdk 上线前工程检查
人工智能·python
暂时先用这个名字5 分钟前
安装deepseek harness及插件
人工智能·ai·npm·pnpm·deepseek·深度求索·harness
水如烟6 分钟前
孤能子视角:EIS认识论分册总纲——同一认知呼吸的四次显影
人工智能
海兰6 分钟前
mcporter — 安装部署及使用完全指南(一)
人工智能·agent·mcp
skywalk81638 分钟前
用WorkBuddy成功把Deepseek Harness移植到FreeBSD
人工智能·deepseek·harness
JavaPub-rodert9 分钟前
我把 OpenAI 协议塞进了 Go 工具库:go-commons 开始支持 AI 了
开发语言·人工智能·golang
HZZD_HZZD11 分钟前
非侵入式负荷监测选`Seq2Point`还是`LSTM`?合众致达实测:洗衣机分解F1达0.87、`NDE`误差降27%,附PyTorch完整实现
人工智能·pytorch·lstm
嘟哩DuliDuli17 分钟前
AI 账单变高的技术原因:重复上下文和用量归属
android·人工智能·安全·ai·软件工程
Tom·Ge17 分钟前
AI创业者通识日报 | 2026年8月13日
人工智能·大模型·ai创业·ai创业者