用 30 道题量化我和 Claude.ai 的差距
一次 harness 的诚实体检
昨天写白皮书时,我抛出了一个主观估计:自己手搓的 agent 大约只兑现了 Claude.ai 50% 的体验。今天我跑完了第一轮 eval,把这个数字钉死了。
起点:一个让我不安的主观估计
如果你看过我昨天那篇白皮书,应该记得它的核心论点是:
模型给你 100% 的潜能,harness 决定能兑现多少。
这个论点的引子,是我用两三天手搓了一个 Claude.ai 的仿品——lite-claude-ui——实现了搜索、代码运行、长文档生成这些核心能力。功能维度上看上去很全了,但实际用起来,我心里清楚:跟原版差着一截。当时我拍脑袋估了一个数字——"大约 50%"。
白皮书的下半篇通篇都在讲 eval-driven 的方法论。但写完之后我有点心虚:我自己还没真正用这套方法量过自己的差距。这就像写了一篇"如何科学减肥"的文章,但作者自己没踩过秤。
所以今天的任务很明确:踩秤。
实验设计:三组对比,一个反直觉的筛选
我设计了三组:
| 组别 | 是什么 | 工具 | 轮数 |
|---|---|---|---|
| A 组 | 裸模型,单轮 API | 无 | 1 |
| B 组 | 我的 harness | web_search + fetch_url + run_code | 最多 8 |
| C 组 | Claude.ai 官方 | 官方 harness | 不限 |
所有三组用的都是同一个模型:claude-sonnet-4-6。这是整个实验最关键的控制变量——把模型固定,变量只剩 harness。
测试集是 30 道题,从 GAIA 和 FRAMES 里挑出来的。但筛选方式比较特别——我先用 A 组跑全量候选题,只保留 A 组答不对的题。
| 数据集 | 候选题 | 筛出 |
|---|---|---|
| GAIA L1 | 42 题 | 15 题 |
| GAIA L2 | 66 题 | 5 题 |
| FRAMES | 30 题 | 10 题 |
第一击:三组阶梯效应
先承认那个让人扎心的事实:我昨天估的 50% 是乐观了。实际兑现率是 37% / 80% ≈ 46%。
但更值得看的是这个阶梯的形状。从 0% 到 37% 是 harness 的"基础税"——只要你能让模型搜索、能让模型 fetch、能让模型循环几轮,你就能拿到接近 40 个点。从 37% 到 80% 是 harness 的"精修溢价"——这 43 个百分点不是靠"加功能"加出来的,是靠把每个环节都做对加出来的。
按数据集分一下,会更有意思:
| 数据集 | A 组 | B 组 | C 组 |
|---|---|---|---|
| GAIA L1 (15 题) | 0% | 53% | 87% |
| GAIA L2 (5 题) | 0% | 40% | 60% |
| FRAMES (10 题) | 0% | 10% | 80% |
GAIA L1 上 B 组还能跟一跟,53% 对 87%——差距存在但不离谱。FRAMES 上 B 组直接崩了,10% 对 80%。
FRAMES 是 Google 出的多跳推理数据集,典型题型是"X 公司的 CEO 出生的城市,在 2020 年的人口是多少"——你得先搜 CEO 是谁,再搜他出生地,再搜人口。搜索单步对了不够,你要能把搜索结果消化好、用作下一步的输入。
拆解那 43% 的差距
整个实验里最有价值的部分,是逐题对 B/C 做的失败归因。下面是 15 道"C 通过但 B 失败"的题的根因分布:
| 失败类型 | 题数 | 代表题 |
|---|---|---|
| 搜索质量差 | 5 | gaia_043, gaia_110, gaia_134, gaia_154, frames_140 |
| 推理链断裂 | 5 | gaia_156, frames_562, frames_763, frames_808, frames_810 |
| 未触发搜索 | 2 | gaia_099, frames_647 |
| 搜索策略低效 | 2 | gaia_029, frames_241 |
| Fetch 失败 | 1 | gaia_110 |
搜索质量:差距的最大单一来源
5 道题。我用的是 Serper / Tavily / Google CSE / Brave / DuckDuckGo 这一堆"兜底"组合。C 组用的是 Anthropic 自家的搜索栈。
差距怎么体现?举个例子:同样的问题,我搜出来一堆带广告 SEO 的聚合页,C 组的第一条结果就是原始论文/原始数据源。搜索是 agent 的眼睛,眼睛分辨率不够,后面再聪明也白搭。
推理链断裂:FRAMES 上崩盘的元凶
也是 5 道题,但更难治。失败形态是:第一跳搜对了,第二跳基于第一跳的结果生成新 query,但新 query 跑偏了一点,然后误差一路放大。等到第 5 跳,完全偏离原题。
C 组在这种题上稳得吓人。搜索次数中位数只有 2-3 次,但每一次都精准。它不是"搜得多",是"搜得准 + 中间不出错"。
这部分我推测和 system prompt 设计、context 管理都有关。Anthropic 的 harness 应该在"如何把上一步结果浓缩进下一步 prompt"这件事上有大量积累——这正好对应白皮书里讲过的"context engineering"。
未触发搜索:模型自己拍脑袋
2 道题,B 和 C 都没搜,直接凭记忆答。区别是:B 答错,C 答对。
理论上同模型同问题,为什么一个对一个错?我倾向于认为是 system prompt 的差异引导了不同的回答倾向。我的 prompt 没有强引导"事实性问题必须搜",所以模型有时候过于自信。
反向启示:B 通过但 C 失败的两题
整个表里有两道反向异常:
- gaia_153 (魔方逻辑推理):B 写了代码验证,通过。C 纯推理,推错了。
- gaia_002 (Nature 文章统计):B 搜到了精确数字,通过。C 搜到了同一篇,但推理环节出错。
这两题指向了一个有意思的设计权衡:Claude.ai 似乎倾向于让模型自己推理,而我的 harness 更"工具优先"。在某些需要硬验证的题上,工具优先反而胜出。
Harness 的设计空间不是一维的,"更像 Claude.ai" ≠ "永远更好"。Anthropic 也做了取舍,只是他们的取舍在大部分情况下比我的好。
一个意外发现:数据集泄露
gaia_016 和 gaia_029 这两道题,C 组的搜索记录显示——Claude.ai 直接搜到了 HuggingFace 上 GAIA 数据集的 ground truth 页面,然后把答案抄了过来。
这并不是 Claude.ai 作弊——它就是诚实地按搜索结果回答。但这暴露了一个评测的硬伤:任何在公网有 ground truth 的数据集,对带搜索的 agent 都不公平。
好消息是这对 B/C 对比不影响——理论上 B 也能搜到。下一轮我会考虑用 FRAMES 的 test split,或者干脆自己造一批从 2026 年新闻里抽的题。
速度的差距同样不可忽视
| 指标 | B 组 | C 组 |
|---|---|---|
| 通过题的平均耗时 | 31s | 16s |
| 失败题的平均耗时 | 55s | 37s |
| 通过题的平均搜索次数 | 3.2 | 2.1 |
下一步:改进的优先级
实验跑完,改进方向自然就浮现了:
- 接更好的搜索后端 (Anthropic 同款,或者 Google 直连)
- Fetch 失败重试 + Jina Reader 兜底
- 预期增益:+5~8 题
- 显式要求模型先规划再搜索
- 涉及计算时强制
run_code验证 - 连续 2 轮无新信息时提前终止
- "事实性问题必须先搜"写进 prompt
如果都做到,理论上 B 组能从 37% 拉到 55~65%。距离 80% 还差一截,但已经能踩进同一个量级。
写在最后:这才是方法论真正的样子
回头看,这次实验最有价值的产出不是那个 37% 的数字,而是这套流程本身能跑通这件事:
- 定义对比组
- 用 baseline 筛题
- 跑完三组
- 逐题归因
- 优先级排序
- 下一轮迭代
绝大多数 agent 项目的失败,根因不是模型不够强,也不是开发者不够聪明,而是缺少一个能"用数据说话"的反馈回路。
今天我用自己的项目验证了这句话另一半:有了这个回路,优化方向不再是凭感觉,而是排好优先级、按预期增益估算的 backlog。
我现在知道下一周该改什么、不该改什么、改完应该看到多少提升。这种"知道自己在干什么"的踏实感,大概就是 eval-driven 这套方法论真正在乎的东西。
下一篇会写 P0 优化跑完之后的结果。如果 +10 个点能兑现,这套方法论就算在我自己身上立住了。