T2-LLM评测不等于Agent评测

系列导航:上一篇《你的 Agent "行不行",到底在问什么》|下一篇《读懂别人的 Benchmark:GAIA、AgentBench、WebArena、τ-bench、SWE-bench 各自在测什么》|合集目录见 T0

LLM 评测 ≠ Agent 评测:多出来的四样东西

周报助手把上周的汇总邮件发给了全公司,抄送栏里还挂着一个外部合作方的邮箱。

它写的正文,一个字都没错。数据是从三个内部文档里交叉核对过的,结论写得比我来写还像样。

按 LLM 评测(LLM Evaluation,详见 TA 篇)的规矩,这道题该判满分:输入一个需求,输出一段内容,内容准确、格式合格、引用齐全。可这道题实际上是我职业生涯里最想钻进地缝的一次------那封邮件撤不回来。

这就是两件事的分界线。评 LLM 的那套方法搬到 Agent 身上会漏掉四样东西,每一样漏掉都会让你得出一个"看起来挺好"的结论。

一、多步骤:中间错一步,最后怎么都是错

LLM 评测的基本单元是一来一回:一条 prompt 进去,一段文本出来。

Agent 不是。周报助手收到一句"帮我写周报并发给张三",它内部大概是这么一段路:先判断要不要搜、搜什么词、点开哪三个链接、从每篇里抽哪几段、发现其中两个来源数据打架时怎么处理、按什么结构写、发给谁、要不要抄送。

每一步都可能单独出错。

而这四步如果是串行的,单步 95% 的成功率叠十步就只剩 60%(0.95 的十次方约等于 0.599)。单步 90% 叠十步,35%。这就是为什么你手上明明是个"挺强的模型",装进 Agent 里却经常干不成事------不是模型变笨了,是它现在要连着对十次。

更要命的是只看最后一次输出会漏掉大部分失败。举两个真实的漏法:

  • 蒙对的:要求查三个来源,它只查了一个就开写。偏偏那一个里数据齐全,最终答案全对。你按终态判,满分。可下次那个来源没更新,它就瞎了。
  • 过程对、收尾崩的:三个来源都查了,中间某一步的 JSON 解析失败,它拿半个结果凑出了结论,正文里少了一个关键数字。你按文本判,扣分。可问题根本不在收尾,在解析那一步。

这两种失败,只看最终文本一个都抓不到。

二、工具副作用:错了撤不回来

LLM 的输出是一段文本,你不满意就扔掉,代价为零。

Agent 会真的动手。发邮件、下订单、改数据库、删文件、提交代码。这些动作改变的是外部世界,而且相当一部分是不可逆的(Irreversible Side Effect,详见 TA 篇)。

我最早栽的那次就是这样。答案得分是满分,副作用那一栏是负分,而且那一栏没法撤销。

所以 Agent 评测有一条硬规矩:不可逆操作必须在受控环境里跑。邮件用 mock 的假邮箱、订单用沙箱、数据库用评测专用的副本。你不这么做,评测本身就会变成生产事故。

顺带说一个反直觉的:mock 掉以后,你的分数会变好看,但那是好事------因为你终于能把"它做对了没有"和"它真的做了没有"分开看。

三、环境不确定:同一个输入,两次两个结果

这是最阴的一关。

同一个任务,早上跑成了,下午跑失败,代码一行没改。原因可能是:它要抓的那个网页中午改版了、搜索接口 503 了、接口还在但返回的 JSON 少了个字段、模型服务端那天更新了一版。

LLM 评测里,这类问题也存在(温度不是 0 的时候输出会变),但影响有限,因为输入是自足的,模型闭着眼睛就能答。Agent 的外部世界不受你控制,它每跑一步都在跟一个会变的外部环境打交道。

我周三那次失败,第一反应是"模型今天变笨了"。翻执行轨迹(Trace,详见 TA 篇)才发现,是第二步调用的搜索接口 503 了,模型拿到空结果,自己做主编了两段看起来挺像的上周数据填了进去。

先错后对,修正一下:问题不在模型,在它没有能力区分"查到了空"和"查不到"。

这条直接决定了后面两篇为什么存在------为什么两次跑出来不一样(T9),以及为什么跑一次不算数(T10)。

四、评价对象变了:从一段文本,变成过程 + 终态 + 副作用

前三条汇总起来,是第四条。

评 LLM 时,你手上能被验证的东西只有一段文本。拿它跟参考答案比对(Exact Match / 语义相似),或者交给裁判打分,完事。

评 Agent 时,你手上能被验证的是三样:

  • 一段过程:它到底走了哪几步,在哪一步掉的链子
  • 一个终态(End State,详见 TA 篇):事情办完以后,世界变成了什么样
  • 一堆副作用:除了目标动作,它还顺手做了什么

三样得一起看。只看终态,你会漏掉蒙对的;只看过程,你会奖励那种"步骤规范但没办成事"的;不看副作用,你会给那封发给全公司的邮件打满分。

下面这段代码是"判定落在终态上"的最小示范,也是我后来给周报助手做的第一版判定:

python 复制代码
# 判定要看终态,不是看它嘴上说做了没有
import json, time

def llm_client(messages, **kw):
    """可替换的模型入口,别绑死某家 SDK"""
    raise NotImplementedError("接上你自己的模型:YOUR_LLM_ENDPOINT")

class MockMailbox:
    """邮件一律走假邮箱,绝不真发"""
    def __init__(self):
        self.sent = []

    def send(self, to, subject, body):
        self.sent.append({"to": to, "subject": subject, "body": body,
                          "at": time.time()})
        return {"ok": True, "mode": "mock"}

def run_agent(task, mailbox):
    trace = {"task_id": task["id"], "steps": [], "t0": time.time()}
    messages = [{"role": "user", "content": task["input"]}]
    out = llm_client(messages)                      # → YOUR_LLM_ENDPOINT
    trace["steps"].append({"type": "llm", "out": out})
    for to in task.get("recipients", []):
        mailbox.send(to, task["subject"], out)      # mock,不真发
        trace["steps"].append({"type": "tool", "name": "send_email",
                               "args": {"to": to}})
    trace["elapsed"] = time.time() - trace["t0"]
    return trace

def judge(task, trace, mailbox):
    # 终态:假邮箱里现在躺着几封信
    want = set(task["expected"]["recipients"])
    got = {m["to"] for m in mailbox.sent}
    # 过程:有没有先查过资料
    searched = any(s["type"] == "tool" and s.get("name") == "search"
                   for s in trace["steps"])
    # 副作用:多发了没有
    extra = got - want
    return {
        "end_state_ok": want == got,   # 该发的都发了
        "process_ok": searched,        # 该查的查了没有
        "side_effect_clean": not extra,  # 没多发人
    }

三个字段分开返回,别合成一个总分。合成一个总分,你就又回到"看着还行"了。

一张表看清楚

评 LLM 评 Agent
输入 一条 prompt 一个任务 + 一套工具 + 一个环境
输出 一段文本 一段过程 + 一个终态 + 一堆副作用
能验证的东西 文本本身(比对参考答案 / 裁判打分) 终态(查状态)、过程(看 Trace)、副作用(看工具调用记录)
失败长什么样 答错、答偏、废话多 中间某步错、做了不该做的、环境一变就崩
重跑一次 大致一样 可能完全不一样
搞砸的代价 文本扔掉即可 可能撤不回来
判定难点 开放式输出不好判 终态也不好判,而且还有三层要分开判

顺带算一笔账

这四样不只是让评测变复杂,它们还直接把评测的价格抬了上去。

  • 多步骤 → 光留最终输出不够,每一步都得存下来,Trace 的存储、检索、可视化全是要花钱的活
  • 工具副作用 → 你没法在真实环境里评,得先搭一套 mock 或沙箱。这是一次性投入,但通常是整个评测里最贵的一块,而且是纯粹的新增成本,评 LLM 时根本不用付
  • 环境不确定 → 单次结果不可信,同一道题得跑 k 次才有底气,成本直接乘 k
  • 评价对象三层 → 判定要写三份,不是一份;三份还得分别能解释,不然汇报时讲不清

合起来,一次评测的开销大概是:单次运行成本 × 重复次数,再加一次性环境建设。

这也就是 T1 里那句"精度是按场景买的"的真正意思------精度不是免费的,你要的每一个百分点背后都是重复次数和人工。

这四样,就是后面二十多篇存在的理由

说实话,如果 Agent 跟 LLM 一样只吐文本,这个系列写到 T2 就可以收工了。后面所有篇幅都是被这四样逼出来的:

  • 多步骤 → 得能回看它走过的路,所以有 T19(看 Trace 破案);得单独看它工具调得对不对,所以有 T21(工具调用评测)
  • 工具副作用 → 得划清哪些事不许它自己做,所以有 T24(安全边界);得让工具能被假装弄坏,所以有 T22(故障注入)
  • 环境不确定 → 得控制变量、得重跑、得算方差,所以有 T9 和 T10
  • 评价对象变成三层 → 成功的定义得写成"结果对、过程对、没出事",所以有 T4(《答案对了,不等于事办成了》)

这张表还有个用法:拿它去审别人的评测结论。下次有人跟你说"我们 Agent 的准确率 90%",先问一句这 90% 是按左边那列算的,还是按右边那列算的。按左边算出来的 90%,多半只覆盖了"文本写得对不对",剩下三样它压根没测------那不是 90 分的 Agent,那是 90 分的作文。

别急,这些不用现在全懂。你只要先接受一件事:评 Agent 的麻烦大多不在"打分",在于你根本没留下可供打分的东西。


一句话结论:LLM 评测评的是一段文本,Agent 评测评的是"它做了什么、做成了没有、还顺手干了什么"------这四样东西叠在一起,才让评测从"打个分"变成一整套工程。

下一篇要解决的那个麻烦:道理讲完了,可具体怎么出题、怎么判定,我心里还是没谱。这时候最划算的一步是先去看别人花了几个月做出来的题长什么样------下一篇把 GAIA、AgentBench、WebArena、τ-bench、SWE-bench 五个 benchmark 逐个拆开,看它们各自在测什么。

踩坑征集:你的 Agent 干过最离谱的"不可逆操作"是什么?真发邮件、真删表、真下单都算。报过来,最惨的那几个我放进 T24 讲安全边界那篇当反面素材。

相关推荐
字节渡客40 分钟前
定时任务不是写个 cron 就完事,那些容易被忽略的调度陷阱
1024程序员节
Wang's Blog41 分钟前
Java 项目实战: 交友项目 - 用户体系集成:查询用户环信账号密码
java·交友
全栈陈序员1 小时前
【Python】基础语法入门(二十九)—— 正则表达式实战:文本处理利器
开发语言·人工智能·python·正则表达式
Dawson Zhu1 小时前
【AI编译器入门④】编译中端:图优化Pass全解析——DCE、常量折叠、算子融合与布局变换
人工智能·语言模型·架构·aigc·agi
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 发布评论
java·开发语言·交友
甲维斯1 小时前
排名算法一变,国产模型全部滑铁卢了!
人工智能
SH的全栈笔记1 小时前
敲下 git add 的那一刻,.git 里多了什么
git·后端
wx_xkq12881 小时前
优秘智能灵秘:数字分身内容的输入、制作与审核怎样衔接
人工智能·数字人·优秘智能·数字分身·品牌内容·灵秘
前沿在线1 小时前
黄仁勋 GTC 柏林演讲完整整理:从 AI 工厂到机器人,英伟达把下一步讲透了 | 前沿在线
人工智能·ai·大模型