智能体面试准备(十一):Agent 评估体系——轨迹、工具选择与成功率的量化方法

📅 2026/7/30 23:55:09 👁️ 阅读次数 📝 编程学习
智能体面试准备(十一):Agent 评估体系——轨迹、工具选择与成功率的量化方法

智能体面试准备(十一):Agent 评估体系——轨迹、工具选择与成功率的量化方法

前面十篇把 Agent 的构建讲了个遍:ReAct、工具调用、规划、记忆、多智能体、编排、Agentic RAG。但一个尖锐的问题一直悬着:你怎么证明你的 Agent 变好了?上一篇结尾埋的"轨迹级评估指标"伏笔,今天正式展开。

这个主题在面试里的杀伤力被严重低估。很多候选人能把 Agent 架构讲得天花乱坠,一句"你们怎么评估的"就哑火了——要么答"人工看效果",要么把 LLM 评估那套(MMLU、C-Eval)直接搬过来。而 Agent 评估恰恰是生产化的命门:没有评估,每次改 prompt、换模型、加工具都是在赌博。

一、为什么 Agent 评估比 LLM 评估难一个量级

LLM 评估是"一问一答对答案":输入固定、输出单步、答案唯一或有参考。Agent 评估的困难在于它的过程性

  1. 多步且路径不唯一:同一个任务,先查天气再订酒店,或先订酒店再查天气,都可能是对的。不能用单一标准路径去对齐。
  2. 非确定性:同一个 Agent 跑同一个任务两次,轨迹可能完全不同。单次通过说明不了什么,必须引入 pass@k / pass^k 这类多次采样指标。
  3. 结果对≠过程对:Agent 可能靠猜蒙对了结果,过程中却调错了三次工具;也可能过程完美,最后一步格式化输出出错。只看结果会奖励侥幸、惩罚"差一点的优秀"。
  4. 环境副作用:Agent 会真实地发邮件、改数据库。评估必须在沙箱里做,环境本身的搭建成本就不低。

一句话总结给面试官:LLM 评估是批改一道题的答案,Agent 评估是给整场驾照路考打分——不仅看有没有到终点,还要看每个动作是否规范。

二、评估的三个层次:结果、轨迹、单步

这是本篇的核心框架,建议整体记忆:

层次评估对象典型指标优点局限
端到端结果任务是否完成成功率、pass@k、任务得分直接反映业务价值无法定位失败环节
轨迹级整条执行路径轨迹匹配度、步数效率、冗余动作率、成本/延迟可定位问题、奖励好过程参考轨迹难穷举
单步级每一步决策工具选择准确率、参数填充准确率、单步幻觉率粒度最细、最可解释与最终成败不必然相关

轨迹级是重点中的重点。常用的轨迹对比模式有:精确匹配(动作序列完全一致,最严格)、顺序匹配(关键动作按序出现,允许插入冗余步骤)、集合匹配(关键动作都出现即可,不管顺序)、前缀匹配(衡量"走对了多远")。实践中顺序匹配和集合匹配最常用,因为它们容忍合理的路径多样性。

单步级里最重要的是工具调用四连环:该不该调工具(decision)→ 调哪个工具(selection)→ 参数填得对不对(parameterization)→ 结果用得对不对(utilization)。四个环节各自都能出错,分开统计才能知道该修 prompt、改工具描述,还是换模型。

再补一组容易被忽略的效率与成本指标:平均步数、token 消耗、端到端延迟、单任务成本。两个 Agent 成功率都是 90%,一个平均 5 步一个平均 15 步,生产上是天壤之别。

三、谁来打分:规则、LLM 裁判与人工

打分方式适用场景成本可靠性
规则/断言有客观判据(文件是否生成、API 是否调用、数值是否正确)高(但覆盖面窄)
LLM-as-a-Judge开放性输出、过程合理性中(需校准)
人工评审高风险场景、裁判校准最高

生产共识是三层漏斗:能用规则判的绝不用 LLM,LLM 裁判定期抽样与人工对齐校准。用 LLM 裁判必须报告它与人工标注的一致率(如 Cohen's kappa),否则"裁判本身不可信"这一追问就接不住。LLM 裁判还有已知偏差要主动提:位置偏差(偏向先出现的答案)、长度偏差(偏向更长的输出)、自我偏好(偏向同族模型的文风)——缓解手段是交换顺序取平均、明确评分 rubric、用异族模型做裁判。

行业基准可以点名几个增加可信度:SWE-bench(真实 GitHub issue 修复)、WebArena(网页操作)、τ-bench(对话式工具调用,提出 pass^k 衡量稳定性)、AgentBench(多环境综合)。注意 τ-bench 的 pass^k 与常见 pass@k 方向相反:pass@k 是 k 次里至少成功一次(衡量能力上限),pass^k 是 k 次全部成功(衡量稳定性下限)——生产系统更该看后者,这个辨析是高分点。

四、可运行代码:一个迷你 Agent 评估器

下面实现一个不依赖任何框架的轨迹评估器,覆盖三层指标:结果成功率、轨迹顺序匹配、工具选择/参数准确率,并输出 pass^k。可直接运行体会"评估器本身也是代码资产":

import json from dataclasses import dataclass, field @dataclass class Step: tool: str args: dict @dataclass class Trajectory: steps: list # list[Step] final_answer: str success: bool # 端到端结果(由规则断言得出) def order_match(traj_tools, ref_tools): """顺序匹配:参考关键动作是否按序出现在轨迹中(允许插入冗余步骤)""" it = iter(traj_tools) matched = sum(1 for r in ref_tools if r in it) # 消耗式按序查找 return matched / len(ref_tools) if ref_tools else 1.0 def step_accuracy(traj: Trajectory, ref_steps: list): """单步级:工具选择与参数填充准确率(按参考步骤逐位对齐)""" tool_hit = param_hit = 0 for i, ref in enumerate(ref_steps): if i < len(traj.steps) and traj.steps[i].tool == ref.tool: tool_hit += 1 if traj.steps[i].args == ref.args: param_hit += 1 n = len(ref_steps) return tool_hit / n, param_hit / n def evaluate(runs: dict, references: dict): """runs: {task_id: [Trajectory, ...]} 同一任务跑 k 次 references: {task_id: list[Step]} 参考轨迹(关键动作)""" report = {} for task_id, trajs in runs.items(): ref = references[task_id] k = len(trajs) succ = [t.success for t in trajs] report[task_id] = { "pass@k": any(succ), # 至少一次成功:能力上限 "pass^k": all(succ), # 全部成功:稳定性下限 "success_rate": sum(succ) / k, "avg_steps": sum(len(t.steps) for t in trajs) / k, "order_match": sum(order_match([s.tool for s in t.steps], [s.tool for s in ref]) for t in trajs) / k, "tool_acc": sum(step_accuracy(t, ref)[0] for t in trajs) / k, "param_acc": sum(step_accuracy(t, ref)[1] for t in trajs) / k, } return report # ---- 模拟:任务「查北京天气并保存到文件」跑 3 次 ---- ref = {"t1": [Step("get_weather", {"city": "北京"}), Step("write_file", {"path": "weather.txt"})]} runs = {"t1": [ Trajectory([Step("get_weather", {"city": "北京"}), Step("write_file", {"path": "weather.txt"})], "已保存", True), Trajectory([Step("search_web", {"q": "北京天气"}), # 冗余但走通 Step("get_weather", {"city": "北京"}), Step("write_file", {"path": "weather.txt"})], "已保存", True), Trajectory([Step("get_weather", {"city": "上海"})], "查错城市", False), ]} print(json.dumps(evaluate(runs, ref), ensure_ascii=False, indent=2))

输出里能清晰看到:pass@k 为 True 而 pass^k 为 False——这个 Agent"有能力但不稳定";第三次运行的 param_acc 掉到 0 暴露了参数幻觉(城市填错)。指标组合起来才能讲出诊断故事,这正是轨迹级评估的价值。

五、评估驱动开发:把评估放进 CI

最后升华一层:成熟团队把 Agent 评估当作回归测试——沉淀一个任务集(含参考轨迹与断言),每次改动(换模型/改 prompt/加工具)都全量跑一遍,指标下降就阻断合并。配合上一篇讲的可观测性埋点,线上 bad case 持续回流进评估集,形成"线上发现→入集→修复→防回归"的飞轮。面试收尾抛出这套"评估即 CI"的工程观,基本能把这个话题聊成加分项。

答题框架回顾:为什么难(四点)→ 三层指标(结果/轨迹/单步 + 效率成本)→ 谁打分(规则/LLM 裁判/人工三层漏斗 + 裁判偏差)→ pass@k vs pass^k 辨析 → 评估即 CI 收尾。

下一篇 B12 是本系列第一篇纯实战:从零写一个完整可运行的 ReAct Agent,把前面所有理论落成一份能跑、能测、能讲的代码——面试带着它去,比十页简历都有说服力。