拿到 PAST-Bench 的归因结果,直接翻到分数最低的那一列、盯住那条失败样本,是最容易走偏的读法:执行层的工具报错、环境超时、参数校验失败,常常和模型能力不足长得几乎一样。建议的阅读顺序是先按环节分组看整体分布,再把执行层的机械失败摘出去,然后回到规划层核对任务拆解,最后才讨论要不要换模型。下面示例里的 stage、error_type、success 这类键名都只是占位,需要替换成你自己结果文件的真实 schema。
读归因结果的顺序应是先分大类、再进环节、最后才谈模型替换。判断依据是环节分组后的计数与比例,而不是单条最低分样本;样本量不足的组只记录观察,不下结论。执行层失败要先单独标记并排除,剩下的掉分再回规划层看任务拆解是否漏步或拆错。换模型是有条件动作,前提是前两层已排查清楚,并按同一最小对照范围重跑。
先看环节分组,不看单条样本
分组维度通常有三类:按 Agent 流程环节分(任务解析、检索、规划、工具调用、结果汇总)、按任务类型分、按失败类型分。第一遍建议只用“流程环节”这一层维度,避免一次交叉太多维度导致每组样本太薄。
每组样本量需要有个下限。具体阈值要结合你的任务规模和任务变体数量确认,可以先给自己定一个保守门槛,比如每条环节至少覆盖几十条样本,达不到就先不下结论。样本量不足时,记录的是:该组实际样本数、观察到的失败类型清单、以及对应原始记录的路径或行号,把它标成“证据不足”,而不是写成“该环节能力不行”。
用脚本把结果按环节聚合成分布
目的是得到可以横向比较的环节数据。假设结果是逐行 JSON(JSONL),每条记录带环节名和成功标记,骨架如下:
import json
from collections import Counter, defaultdict
RESULTS_PATH = "results.jsonl" # 替换为你的结果文件
records = []
with open(RESULTS_PATH, encoding="utf-8") as f:
for line in f:
line = line.strip()
if line:
records.append(json.loads(line))
total = len(records)
by_stage = defaultdict(lambda: {"count": 0, "fail": 0, "errors": Counter()})
for r in records:
stage = r.get("stage", "unknown") # 替换为实际环节字段
ok = r.get("success") # 替换为实际成败判定字段
by_stage[stage]["count"] += 1
if not ok:
by_stage[stage]["fail"] += 1
by_stage[stage]["errors"][r.get("error_type", "unlabeled")] += 1
for stage, s in sorted(by_stage.items()):
ratio = s["fail"] / s["count"] if s["count"] else 0.0
print(stage, s["count"], s["fail"], f"{ratio:.2%}", dict(s["errors"]))
print("sum =", sum(v["count"] for v in by_stage.values()), "total =", total)运行后先做自检:每组计数之和应等于总样本数。不相等通常说明环节字段存在空值或多种写法(None 与 "unknown" 被算成两组)、记录被重复读入,或过滤条件丢掉了行。先修好这个口径问题,再看比例。
先排除执行层的机械失败
属于执行层的失败信号一般有:工具返回 HTTP 4xx/5xx、鉴权或配额错误、请求超时、命令非零退出码且指向环境、依赖或容器缺失、文件路径不存在、沙箱权限拒绝、输出格式被解析器硬性拒绝。
区分方法看两点:失败发生在模型输出之后还是之前;工具返回的是结构化错误(状态码、stderr、异常栈),还是任务层面的判断错误。可以加一个 failure_layer 标记字段,把这类记录标成 mechanical,单独统计后再看剩余分布。如果排除后某个环节的失败比例明显回落,说明原来的掉分主要来自环境与工具链,而不是模型判断。
再回到规划层看任务拆解
规划层掉分的可观察信号包括:步数明显多于或少于同类任务预期、反复调用同一个工具、跳过了任务必需环节、步骤顺序与依赖关系颠倒、子目标没有对应的完成证据、最终答案缺中间产物支撑。
需要回看的记录片段是完整步骤序列、每一步的输入摘要、模型给出的计划文本本身,以及“从哪一步开始偏离任务要求”这个分界点。定位到分界点后,再看那一跳的输入里是否缺少必要上下文,这属于规划问题还是信息缺失问题。
最后才决定是否换模型
换模型前建议先满足:执行层失败已被单独标记并排除;环节分布显示掉分集中在少数环节,而不是全环节均匀下滑;同一提示词与同一工具配置下多次运行结果大致稳定;手上有一个可复现的最小任务集。
换完后需要重跑的最小对照范围通常是:只重跑掉分最集中的那一两个环节,使用同一批样本、同一工具与环境配置、同一判定脚本,其余层保持不动。这样比较的是环节分布的变化,而不是单个总分,也便于判断新掉分是不是换了模型才引入的。