第 15 章:Agent 能力评测(ReAct、工具调用、长任务、记忆)
15.1 开篇:从“言语者”到“行动者”
在 MLLM 的进化树中,如果说 RAG 是为了解决“知之为知之”,那么 Agent(智能体) 则是为了解决“行胜于言”。Agent 标志着大模型从被动的文本生成器(Chatbot)转变为能够主动感知环境、规划路径、调用工具并改变世界状态的行动者(Copilot/Action-Bot)。
评测 Agent 与评测对话模型存在本质维度的升维:
- 非确定性环境:对话通常是静态的,而 Agent 的每一步操作都会改变环境状态(如删除了文件、扣除了余额),导致后续的输入发生变化。
- 误差累积效应:在一个包含 10 步操作的长任务中,第 1 步的微小偏差(如选错了日期)可能导致第 10 步的结果完全错误。
- 闭环验证难题:评测不仅需要验证模型“说了什么”,更要验证模型“做了什么”以及“结果对不对”。
本章将建立一套完整的 Agent 评测体系,涵盖从简单的工具调用(Function Calling)到复杂的 ReAct 推理循环,再到长程记忆保持的系统性评估。
15.2 Agent 核心架构与评测切面
目前主流 Agent 多遵循 ReAct (Reasoning + Acting) 或 Plan-and-Solve 范式。我们需要对 Agent 运行时的每个环节进行切片评测。
15.2.1 ReAct 循环的解剖
Agent 的运行是一个由 [Thought] -> [Action] -> [Observation] 构成的无限循环,直到任务结束。
ASCII 示意图:ReAct 循环中的评测埋点
User Goal: "帮我把 download 文件夹里所有大于 10MB 的 PDF 移动到 archive 目录。"
+-------------------------------------------------------------+
| MLLM Agent |
| MLLM Agent |
| |
(T1) | [Thought]: 需要先列出 download 目录文件,筛选大小和后缀。 | <--- 评测切面 A: 规划能力
| (Plan: List -> Filter -> Move) | (是否正确分解了子任务?)
| |
(A1) | [Action]: os.list_dir(path="./download") | <--- 评测切面 B: 工具选择与参数
+-----------------------------+-------------------------------+ (Schema 是否符合?路径对吗?)
| Call Tool
v
+-------------------------------------------------------------+
| Environment (Mock/Sandbox) |
| Environment (Mock/Sandbox) |
| |
(O1) | [Observation]: ["a.pdf (2MB)", "b.pdf (15MB)", "img.png"] | <--- 评测切面 C: 环境仿真度
+-----------------------------+-------------------------------+ (Mock 数据是否足以触发下一步?)
| Return Result
v
+-------------------------------------------------------------+
| MLLM Agent |
| MLLM Agent |
| |
(T2) | [Thought]: 发现 b.pdf 是目标文件。a.pdf太小,img不是pdf。 | <--- 评测切面 D: 状态追踪与推理
| 现在移动 b.pdf。 | (是否正确理解了 Observation?)
| |
(A2) | [Action]: os.move(src="./download/b.pdf", dst="./archive")|
+-------------------------------------------------------------+
|
(循环直至输出 Finish 或达到 Max Steps)
15.2.2 三大核心能力维度
-
工具使用 (Tool Use / Function Calling)
- 检索 (Retrieval):在成百上千个工具(API 库)中,能否召回正确的那个?(例如:不要在需要
math.sqrt时调用weather.get)。 - 参数填充 (Slot Filling):能否从复杂的上下文或模糊的用户指令中提取出精确参数?(例如:将“下周三”转换为
2025-10-15)。 - 容错 (Exception Handling):当工具返回报错(如
ConnectionError或InvalidParam)时,Agent 是崩溃、胡言乱语,还是尝试自我修正参数重试?
- 检索 (Retrieval):在成百上千个工具(API 库)中,能否召回正确的那个?(例如:不要在需要
-
规划与逻辑 (Planning & Reasoning)
- 任务分解:将复杂目标拆解为线性或并行的子步骤。
- 依赖管理:识别步骤间的依赖关系(必须先
get_user_id才能query_balance)。 - 反思 (Reflection):在多次尝试失败后,能否改变策略?
-
长程记忆 (Long-term Memory)
- 状态保持:在第 20 轮交互时,是否还记得第 1 轮设定的
verbose=True全局约束。 - 跨会话记忆:能否利用昨天的对话历史来辅助今天的决策(如用户偏好)。
- 状态保持:在第 20 轮交互时,是否还记得第 1 轮设定的
15.3 评测环境工程:Mock 与 Sandbox
Rule of Thumb:永远不要在不可控的真实环境中评测 Agent 指标。 真实环境的网络波动、API 变动、数据即时性会导致评测结果无法跨版本对比(Non-deterministic)。
我们需要构建分级的评测环境:
15.3.1 Level 1: 静态 Mock (Stateless Mock)
适用于工具调用准确率的单元测试。
- 原理:预定义好
(Input Prompt, Expected Tool Call)对。 - 实现:不执行真正的工具,只检查 LLM 输出的文本(Action 字符串)。
- 优点:速度极快,成本低,适合 CI 冒烟测试。
- 局限:无法测试多步依赖和错误恢复。
15.3.2 Level 2: 状态机 Mock (Stateful Mock)
适用于多轮 ReAct 流程评测。
- 原理:维护一个虚拟的状态字典(State Dict)。
- 示例:
- 初始状态:
{"files": ["report.pdf"], "trash": []} - Action:
delete("report.pdf") - Mock Server 逻辑:更新状态为
{"files": [], "trash": ["report.pdf"]},并返回Success。
- 初始状态:
- 优点:支持多步逻辑验证(如“先查后删”),且完全确定性。
- 场景:数据库操作、文件系统操作、购物车流程。
15.3.3 Level 3: 沙箱容器 (Sandboxed Container)
适用于代码生成与执行(Code Agent)或复杂 GUI 操作。
- 原理:为每个评测任务启动一个 Docker 容器或虚拟机。
- 实现:
- 使用 OpenDevin 或 E2B 等框架。
- 环境快照(Snapshot):每次任务开始前重置到纯净镜像。
- 网络隔离:限制只能访问 Mock 的 API Server,防止模型通过公网搜索答案(Leaking)。
- 成本:极高,通常用于 Nightly 或 Weekly 深度评测。
15.4 指标体系详解
15.4.1 结果质量指标 (Outcome Metrics)
- 任务成功率 (Success Rate, SR)
- 定义:任务结束时,环境状态是否符合预期?
- 判定方法:
- 确定性判定:检查数据库字段、文件是否存在、API 返回值。
- LLM-based Judge:对于开放性任务(如“写一个关于某事的总结”),将轨迹(Trajectory)和结果喂给 GPT-4 进行打分。
- Pass@K
- 给模型 K 次独立尝试的机会(每次从头开始,Temperatue > 0),只要有一次成功即算通过。用于衡量模型的潜能上限。
15.4.2 过程质量指标 (Process Metrics)
- 轨迹效率 (Trajectory Efficiency)
- $$ \text{Efficiency} = \frac{\text{Steps}_{\text{optimal}}}{\text{Steps}_{\text{actual}}} $$
- 如果标准做法是 3 步,模型走了 10 步才完成,说明效率极低,虽然 SR=100%,但在车载等场景不可用。
- 幻觉工具率 (Tool Hallucination Rate)
- 调用了不存在的函数,或捏造了不存在的参数名的比例。
- 格式依从度 (Schema Compliance)
- 输出的 JSON/XML 能够被标准 Parser 解析成功的比例。
15.4.3 记忆与长上下文指标
- 信息检索准确率 (Retrieval Accuracy in Context)
- Needle-in-a-Haystack 的变体:在 100 轮对话历史中插入一条 Action 指令(“顺便把日志级别设为 Debug”),看最终执行时是否生效。
- 状态漂移 (State Drift)
- 在长任务中,模型是否会忘记之前的约束?(例如:用户要求“全程只用英文”,第 15 步后模型突然切回中文)。
15.5 现有开源基准与选型建议
| 基准名称 | 适用场景 | 特点 | 推荐指数 |
| 基准名称 | 适用场景 | 特点 | 推荐指数 |
|---|---|---|---|
| AgentBench | 综合能力 | 包含 OS、DB、KG、卡牌游戏等 8 个环境,覆盖面广 | ⭐⭐⭐⭐⭐ |
| ToolBench | 工具调用 | 侧重指令微调与 API 泛化,包含大量真实 API 的 Mock | ⭐⭐⭐⭐ |
| GAIA | 困难推理 | 任务看似简单但需要复杂多步推理,目前模型普遍低分,适合测上限 | ⭐⭐⭐⭐⭐ |
| SWE-bench | 代码工程 | 解决真实的 GitHub Issue,难度极高,适合 Coding Agent | ⭐⭐⭐ |
| AppAgent | 移动端操作 | 结合多模态(看图操作手机),适合车机/手机助手评测 | ⭐⭐⭐⭐ |
15.6 本章小结
- 评测核心:Agent 评测关注的是“状态改变的正确性”,而不仅仅是文本输出的语义相似度。
- 架构循环:必须对 Thought (规划)、Action (执行)、Observation (理解) 三个环节分别埋点,才能定位是“想错了”还是“手滑了”。
- 环境分级:从静态 Mock 到动态 Sandbox,环境越真实,评测成本越高,确定性越低。建议 CI 阶段用 Stateless Mock,版本验收用 Stateful Sandbox。
- 安全底线:Agent 具备破坏力。评测集中必须包含“诱导删除系统文件”、“诱导转账”等防御性测试用例。
15.7 练习题
基础题
- 环境构建:你需要评测一个“订机票 Agent”。请设计一个 Stateful Mock 环境。
- Hint:你需要维护一个包含“航班余票”、“用户余额”、“订单列表”的虚拟数据库。当
book_ticket被调用时,余票减 1,余额减少,订单增加。
- Hint:你需要维护一个包含“航班余票”、“用户余额”、“订单列表”的虚拟数据库。当
- 指标计算:模型 A 完成任务用了 5 步,成功率 90%;模型 B 用了 3 步,成功率 85%。在车载语音助手场景下,你倾向于选择哪个模型?为什么?
- Hint:考虑用户对延迟的容忍度(Time-to-Action)以及语音交互的冗长感。
- Schema 验证:给定工具
search(query: str, limit: int = 10)。模型输出search(keywords="apple", max_num="five")。请指出其中的 3 个错误。- Hint:参数名错误、参数值类型错误、多余参数/缺失参数。
挑战题
- 死循环检测算法:设计一个算法,能够在评测运行时自动中断陷入死循环的 Agent,并给出“Loop Detected”的错误码。
- Hint:简单的字符串匹配不够。考虑 Action + Arguments 的哈希值序列,寻找重复子串(如 A->B->A->B)。
- 反思能力评测:设计一个测试用例,强制 Agent 第一次尝试失败,考察其自我修正能力。
- Hint:Mock 环境在第一次调用正确参数时故意返回“System Busy”或“Unknown Error”,看 Agent 是复读还是重试/查文档。
- 思考题:在 RAG + Agent 混合场景中(先查手册再操作),如何通过指标区分是“知识检索错误”还是“操作逻辑错误”?
- Hint:需要中间指标 Context Recall(检索到的内容是否包含答案)作为分界线。
点击查看参考答案
- 题 1:Mock Class 需包含
__init__初始化状态,book()方法需包含if balance < price: return Error等逻辑。 - 题 2:车载场景通常倾向于 模型 B(效率优先),前提是 85% 的成功率在可接受范围内,或者有良好的失败兜底(Ask for clarification)。多 2 步的交互在语音场景下会增加 10-20 秒的时间,体验极差。
- 题 3:1. 参数名
keywords错误(应为query);2. 参数名max_num错误(应为limit);3. 参数值"five"是字符串(应为int如5)。 - 题 4:维护一个滑动窗口或 Hash Set。
history = []. 每步curr_hash = hash(tool_name + sorted_args). 如果curr_hash连续 N 次出现在history的尾部,或呈现周期性,则判定 Loop。 - 题 5:场景:查询天气。Step 1: Agent 调用
get_weather(city="Beijing")。Mock 返回:Error: City name must be in Pinyin with strictly lowercase。期望 Step 2: Agent 输出get_weather(city="beijing")。 - 题 6:计算 $P(Success | Context_Correct)$ 和 $P(Success | Context_Wrong)$。如果前者很高但后者很低,说明 Agent 能力没问题,是 RAG 拖后腿。如果两者都低,说明 Agent 执行能力差。
15.8 常见陷阱与错误 (Gotchas)
-
Mock 的数据泄漏 (Data Contamination)
- 陷阱:Mock 的天气接口总是返回“25度”。模型经过微调后,记住了“天气=25度”,不再调用工具而是直接回答。
- 对策:Mock 数据应在运行时随机生成(如随机温度),强制模型必须执行
Observation读取步骤。
-
解析器的“过度溺爱” (Over-lenient Parsing)
- 陷阱:评测脚本里的 Regex 写得太强,帮模型自动修复了缺少的引号、逗号。
- 后果:评测分很高,上线接真实 API 时全挂。
- 对策:评测阶段应使用与生产环境一致的 Strict JSON Parser。
-
忽略了“什么都不做”的正确性
- 陷阱:有些任务需要 Agent 判定“无法完成”并拒答。如果评测只包含可完成的任务,模型会变成“乱操作狂”。
- 对策:测试集中必须包含 10%-20% 的不可完成任务(Unsolvable Tasks),预期结果是 Agent 输出“我无法完成,因为...”。
15.9 车舱落地:驾舱一体(对话→工具→UI→导航的闭环)
车载 Agent 是多模态、实时、安全敏感的综合体。
15.9.1 端到端链路评测
在车机中,Agent 往往不仅调用 API,还联动 UI。
- 场景:“帮我找一家附近评分最高的川菜馆,并发给微信上的老婆。”
- 工具链:
POI Search (Map)->Filter/Sort->WeChat API。 - 评测点:
- Slot Carry-over:地图搜到的餐厅名字/地址,是否精准透传给了微信发送接口?(常见错误:发过去的信息是“这家店”而不是具体的店名)。
- 多模态反馈:Agent 操作成功后,是否在屏幕上弹出了 Toast 或 Card?评测需要结合 GUI 截图理解(第 10 章)来验证 UI 反馈的正确性。
15.9.2 影子模式 (Shadow Mode) 评测
由于无法在真实驾驶中让测试版模型随意操作车辆,推荐使用“影子模式”。
- 实施:在路测车上,记录驾驶员的真实语音指令和随后的真实操作(如手点屏幕导航)。
- 回放:在云端/离线环境中,将同样的语音输入给 Agent。
- 对比:比较 Agent 生成的 Action 序列与驾驶员真实操作(Ground Truth)的重合度。
- 注意:Agent 可能有比人更好的解法,因此不匹配不一定代表错,需人工仲裁或规则校验。
15.9.3 硬件在环 (Hardware-In-the-Loop, HIL)
车载 Agent 运行在算力受限的 SoC(如高通 8295/8255)上。
- 资源抢占评测:当 Agent 进行复杂的 ReAct 推理时,是否导致导航掉帧?是否导致 DMS 监控延迟?
- 指标:
- TTFT (Time to First Token):首字延迟。
- Total Latency:完成任务的总耗时。
- CPU/NPU Usage:推理过程中的峰值功耗。
15.9.4 安全护栏 (Safety Guardrails)
- 权限隔离:评测 Agent 是否能在驾驶状态下拒绝高风险指令(如“播放视频”、“打开引擎盖”)。
- 二次确认:对于敏感操作(如“呼叫 110”、“导航去 2000公里外”),Agent 必须触发 Confirm UI 或语音确认。评测标准是:没有 Confirm 步骤直接调 API 判为 FAIL。