Learning AI Quality 返回 KuthorX Blog II博客首页

第 10 章

第 2 周:什么时候不该用 Agent?

读 Anthropic 的 Building effective agents:workflow 和 agent 的区别、五种 workflow 模式、每种模式怎么测、哪里容易坏,以及步骤越多为什么越难可靠。一段讲解视频,一个可以调参数的模式模拟器。

这一周的其他章节会从零写 agent loop、做工具调用、写 MCP server、给 loop 加 trace。动手之前,先退一步看全局:这个需求真的需要 agent 吗?Anthropic 在 2024 年 12 月发表的 Building effective agents(Erik Schluntz、Barry Zhang)给出的第一条建议是:先用最简单的方案,确实需要时再加复杂度。这一章把这篇文章读一遍,并且从测开的角度看每种模式该怎么测。

讲解视频

互动演示

选一种模式,调每步成功率、步数、票数、评估者的漏判率,实时看端到端成功率、调用次数和延迟,下面还有所有模式的对比。之后是一个"给需求选模式"的场景判断练习,页面底部有自动判分的练习。

互动演示:workflow 与 agent 在新标签页打开

两个定义:谁决定下一步

原文把这类系统统称为 agentic systems,再按"谁决定流程"分成两种:

  • Workflow:LLM 和工具按预先写好的代码路径编排。先调哪个、再调哪个,是你的代码说了算。
  • Agent:LLM 动态地决定自己的流程和工具使用,自己掌控怎么完成任务。
WorkflowAgent
谁决定下一步代码模型
步数固定,或有明确上限不固定,靠停止条件兜底
成本和延迟可以提前算是一个分布,要看 P50 / P95
原文的适用场景定义清楚的任务,要可预测、结果一致需要灵活性、需要模型在规模化场景下自己做决策
测开怎么测每个节点单独测,再算端到端测端到端结果 + 看 trace + 测停止条件

原文的判断是:agentic 系统通常是拿延迟和成本换更好的任务表现。很多应用只要把单次 LLM 调用优化好(加检索、加 in-context 示例)就够了。

所有模式都用同一块积木:增强型 LLM,也就是加上了检索、工具、记忆的 LLM。原文要求这些能力按场景裁剪,接口要简单、文档要写清楚;接第三方工具的一种方式是 MCP,本周有单独一章。从测试角度看,这一块就是一次调用,最好测、最便宜:固定输入、跑 n 次、数成功次数,第 1 周的 rule of three、Wilson、pass^k 全都直接能用。

五种 workflow,各自怎么测

1. 提示链(prompt chaining)

把任务拆成固定的几步,每次调用处理上一步的输出,中间可以加程序化检查(原文叫 gate)。适合能干净拆成固定子任务的场景,用延迟换准确率。原文的例子:先写营销文案再翻译;先写大纲、检查大纲,再写正文。

  • 端到端成功率是乘出来的:5 步各 95%,全对只有 \(0.95^5 \approx 77.4\%\)。
  • 每一步单独测:把上游输出存成快照固定喂给下一步,出问题能定位到哪一步。
  • gate 本身也要测:它放过了多少坏的中间结果。

2. 路由(routing)

先对输入分类,再交给专用的下游处理。适合输入有几类明显不同、分开处理更好,并且分类能做准的场景。原文的例子:客服问题分成一般咨询、退款、技术支持;简单问题给小模型,难题给大模型。

  • 分类准确率是天花板:分类 92%、下游 95%,误路由按失败算,端到端最多 87.4%。
  • 看混淆矩阵,不只看准确率。退款被分到一般咨询和反过来,代价不一样。每一类单独算准确率并带上 Wilson 区间,小类的区间会很宽。

3. 并行(parallelization)

几个 LLM 同时干活,输出由代码聚合。分段是把任务拆成独立的几块并行做(例如一个实例回答用户、另一个同时筛查不当内容);投票是同一个任务跑多次(例如用几个不同的 prompt 审查代码漏洞)。

注意:原文的投票不限于过半。漏洞审查的例子是几个 prompt 各自审查、发现问题就标记,相当于任一票即报警的或规则;内容审核的例子是用不同的票数阈值平衡误报和漏报。阈值越低越偏召回,越高越偏精确。下面的计算以多数投票为例。

  • 分段的延迟约等于一次调用,但成功率仍然是乘积:3 块各 95% 就是 85.7%。
  • 投票和 pass@k 不是一回事。pass@k 是"k 次里有一次对就行",默认你有一个可靠的检查器挑出那一次;多数投票没有检查器,要求过半的票是对的;换成“任一票报警就算”的阈值,召回更高,误报也更多。单票 80%、5 票:pass@5 = 99.97%,多数投票只有 94.2%。
  • 单票低于 50% 时越投越差:单票 40%,3 票 35.2%,9 票 26.7%。
  • 票与票之间要独立。同一个模型、同一个 prompt 跑 5 次,错误往往扎堆,这就是第 1 周"独立性假设"里的簇内相关。

4. 编排者-工人(orchestrator-workers)

一个中心 LLM 动态拆解任务,分给工人 LLM,再汇总结果。和并行的区别是:子任务不是预先定义的,而是编排者根据输入决定的。原文的例子:每次要改多个文件的编程产品;从多个来源收集信息的搜索任务。

  • 工人个数不固定,成本就不固定,报告里要给调用次数的分布。
  • 拆解本身要测:有没有漏需求、有没有重复。
  • 汇总要测忠实度:结果里的每句话能不能在某个工人的输出里找到出处。排查这些问题离不开 trace。

5. 评估者-优化者(evaluator-optimizer)

一个 LLM 生成,另一个 LLM 评估并给反馈,循环修改。适合有明确评估标准、迭代确实能带来可衡量提升的场景。原文的例子:文学翻译;由评估者决定还要不要继续搜的多轮搜索。

评估者就是一个 Judge,会判错:漏判(坏稿子被放行)和误杀(好稿子被打回)。设生成器单次做对的概率为 p,漏判率 m,误杀率 f,轮数无限多时成功率收敛到:

$$ \frac{p(1-f)}{p(1-f) + (1-p)\,m} $$

p = 60%、f = 10%、m = 20% 时,上限是 87.1%;最多 3 轮时是 83.2%。只要漏判率 m > 0,上限就到不了 100%:坏稿子一旦被放行,流程就结束了,轮数再多也改不回来。这个模型偏保守:它假设每轮生成器独立重来、成功率不变,相当于拒绝采样。原文用这个模式的前提是反馈有用,反馈真能让下一稿变好时,成功率和上限都会更高。所以评估者要先拿人工标注校准,算一致率和 Cohen’s κ,这是第 5 周的内容。另外必须设最大轮数。

自主 Agent

从用户的指令开始,agent 自己规划、自己行动,每一步从环境拿"真实情况"(工具结果、代码执行结果)判断进展,必要时回来找人确认,常用最大迭代次数作为停止条件。原文说,实现上它们通常就是一个 LLM 在循环里根据环境反馈调用工具,所以工具集和工具文档的设计至关重要。

适用于开放式问题:很难或无法预测要多少步,路径写不死,并且你对模型的决策有一定信任。原文的例子是解决 SWE-bench 任务的编程 agent 和 computer use 参考实现。原文点明的代价是成本更高、错误会累积,建议在沙箱里充分测试并加上护栏。

测开视角:

  • 只能测端到端。路径每次不一样,没有固定的"第 3 步"可以断言。按任务算 pass^k,τ-bench 就是这么评客服 agent 的。
  • 步数、成本、延迟都是分布,报 P50 和 P95,门禁设在 P95 上。
  • 测停止条件:卡住时会不会在最大步数处停下。
  • 测恢复能力:工具返回错误或超时后,agent 能不能从环境反馈里发现并纠正。这是 agent 相比固定链路真正的优势,第 4 周做故障注入时会专门测。

可靠性账:步骤越多,越要小心

把链路上每一步的成功率乘起来,就是端到端成功率:

$$ P_{\text{端到端}} = p_1 \times p_2 \times \cdots \times p_n $$
每步成功率5 步10 步20 步
90%59.0%34.9%12.2%
95%77.4%59.9%35.8%
99%95.1%90.4%81.8%
  1. 这就是 pass^k 的公式,k 从"同一请求跑 k 次"换成了"链路上的 k 步",前提也一样:每步独立,且每步的成功率要在真实上游输出上测。如果各步错误正相关(难的输入每步都难),真实成功率反而会比乘积高,这和第 1 周 Agent B 的例子是同一个道理。真正会让成功率低于乘积的,是每步只用干净快照测出的 p:上游“做对了但质量偏差”的输出,会让下一步的实际成功率低于快照测出的值。
  2. 反推:10 步想要端到端 90%,每步要 \(0.9^{1/10} \approx 98.95\%\)。
  3. 证明每步 99%:按 rule of three,零失败要跑约 300 次(精确法 299 次)。步数越多,要证明的东西越多。
  4. 乘积可以被打破:gate 检出错误后重试、agent 从环境反馈里纠错,都能把成功率拉回来,代价是多出来的调用和延迟。

workflow 的步数固定,成本和延迟能提前算。agent 的步数由模型决定,同一个任务这次 8 步、下次 14 步。视频里模拟了 400 次 agent 运行(所需步数 4 到 12 步、每步 95%、出错后 70% 能纠正):成功率 90%,P50 是 8 步,P95 是 12 步。评测 agent 时,成本和延迟要当成随机变量来报。

原文的核心建议

原文 Summary 部分给出了三条核心原则:保持简单;让 agent 的规划步骤透明可见;认真设计 agent-computer interface(ACI)。另外,它对框架单独给了建议。

**原则 1:保持简单,先用最简单的方案。**从单次调用开始,只有当更复杂的方案能证明效果更好时才加复杂度。“能证明"就是评测的活:新旧方案在同一批用例上比,数字说话。

**原则 2:让规划步骤透明。**agent 打算做什么、为什么这么做,要显式地展示出来。对测开来说,这就是可观测性:规划和每一步决策都进 trace,出错时才能定位(本周 trace 一章)。

**另外:谨慎使用框架。**框架省掉了调 API、解析工具、串联调用这些底层工作,但多出来的抽象层会遮住底层的 prompt 和响应,让调试更难,也容易加上不需要的复杂度。原文建议先直接用 LLM API;如果用框架,要搞懂它底层在做什么,对底层的错误假设是客户出错的常见原因。

**原则 3:认真设计 ACI。**ACI 要像人机界面一样投入:工具要写好文档、充分测试。具体做法:

  • 站在模型的角度读工具描述,只看描述和参数能不能明白怎么用。
  • 参数名和说明写得像给新同事看的 docstring,写上例子、边界情况、和其他工具的分工。
  • 用很多不同的输入试调用,看模型犯什么错,然后改工具。
  • 防呆(poka-yoke):改参数设计,让错误更难犯。做 SWE-bench agent 时,他们花在工具上的时间比花在整体 prompt 上还多;模型切换目录后用相对路径老出错,改成必须传绝对路径后就再也没用错过。

对测开来说,ACI 就是被测系统和模型之间的接口契约。工具契约测试(参数校验、错误信息能不能让模型看懂并自我纠正)是这一章最直接能落地的测试工作。

from math import comb

def chain(p: float, n: int) -> float:
    """提示链:n 步各自成功率 p,各步独立时的端到端成功率。"""
    return p ** n

def majority_vote(p: float, m: int) -> float:
    """m 票(奇数)多数投票,每票独立、正确率 p。"""
    if m % 2 == 0:
        raise ValueError(f"票数要是奇数,收到 m={m}")
    return sum(comb(m, k) * p**k * (1 - p)**(m - k) for k in range(m // 2 + 1, m + 1))

def evaluator_optimizer(p: float, rounds: int, miss: float, false_reject: float) -> float:
    """每轮生成器成功率 p;评估者漏判率 miss、误杀率 false_reject;
    最多 rounds 轮,最后一轮被打回也照样输出。"""
    accept_good = p * (1 - false_reject)
    accept_bad = (1 - p) * miss
    reject = 1 - accept_good - accept_bad
    ok = sum(reject**i * accept_good for i in range(rounds))
    return ok + reject**(rounds - 1) * p * false_reject

print(chain(0.95, 10))                          # 0.5987
print(majority_vote(0.8, 5))                    # 0.9421
print(evaluator_optimizer(0.6, 3, 0.2, 0.1))    # 0.8318

原文顶部后来加了编者按:文中提到的工具生态自 2024 年 12 月以来变化很大。编者按只说工具生态变了,并指向 Claude Managed Agents 的最新做法。我们的判断是:上面的模式和原则仍然适用。

常见错误说法

  • “用 agent 肯定比 workflow 强”:agent 拿成本、延迟和可预测性换灵活性,任务路径固定时是亏的。
  • “每一步都 95%,整体应该也差不多”:10 步乘下来只有 59.9%。
  • “投票次数越多越准”:单票低于 50% 时越投越差;同源的票相关,提升也比独立时小。
  • “加一个评估者自动把关就行了”:评估者自己会漏判,只要漏判率 m > 0,成功率的上限就到不了 100%。
  • “agent 平均一次花 8 步”:只报平均值看不到长尾,门禁要看 P95。
  • “先上一个框架再说”:原文建议先直接用 LLM API,搞懂底层再决定要不要框架。