← 随笔

Fable 5、Opus 4.8 和 Sonnet 4.6:如何在自己的代码上公平比较 LLM

受控实验:Fable 5、Opus 4.8 和 Sonnet 4.6 用同一个提示词审计真实代码库。在自己的项目上公平比较 LLM 的方法论。

7 分钟阅读
Telegram原文
Fable 5、Opus 4.8 和 Sonnet 4.6:如何在自己的代码上公平比较 LLM

当新模型发布时,公告回答的是“它在基准测试上好了多少”——却不回答我唯一关心的问题:它会给我的工作带来什么改变。我做了一个受控实验:三个 Claude 模型—— Fable 5、 Opus 4.8 和 Sonnet 4.6 ——收到了逐字相同的任务,审计这个博客的代码库,每个都在隔离的仓库副本中运行,并采用事先商定的评分标准。文章包含可复用于任何项目的方法论、结果,以及单独一节——实验如何两次失败,以及这教会了什么。

为什么基准测试不回答我的问题

公开基准测试有两个问题,且都是根本性的。第一是数据污染:测试样本渗入训练集,模型部分“记住”答案而不是解题。这不是边缘化的怀疑,而是一整个研究方向的主题: Xu 等人(2024)的综述 系统梳理了基准污染研究,而 EMNLP 2025 的综述 记录了行业的回应——从静态测试转向动态生成。

第二个问题更简单:基准测试衡量的不是我的任务。我不需要一个最擅长解奥赛题的模型。我需要一个能在我的 Laravel 博客中找到真实 bug、不编造不存在的 bug,并证明其修复有效的模型。

由此得出一个简单的想法:比较模型的最佳测试台是自己的项目。它的代码以这种组合不会出现在训练集中,其上的任务正是我付费购买的任务,而结果我可以亲手验证,因为我了解这段代码。

实验设计:一个提示词,三个隔离世界

三个模型的任务逐字相同——只有分支名和结果文件夹不同。四个阶段:审计博客文章的双语系统,每个发现都要有证据,形式为 файл:строка 并附代码引用;为三个主要发现选择解决方案并描述权衡;实现一个修复并自检;用俄语和英语写结果说明。完整的工程工作循环,而不是孤立的“问答”——这种方法 Anthropic 也推荐:在真实产品的任务上评估智能体,按启动前商定的评分标准。

三条规则让比较变得公平:

隔离。 每个模型在单独的 git worktree 中工作——拥有自己的工作目录副本和自己的分支。模型在物理上无法看到彼此的结果或互相干扰。

在提示词本身中防幻觉。 任务的关键句:“编造的发现(不存在的代码、错误的行号)比没有发现更糟”。没有这个激励,被要求找问题的模型倾向于无论如何都“找到”它们。有了它——每个发现都必须经受手动检查。

排除提示中的送分项。 仓库里有一个 CLAUDE.md,描述了项目已知的坑——例如在带语言前缀的 URL 上会失效的相对资源路径。三个模型都读这个文件,所以这类发现是“免费的”:它们计入细致度,但不计入深度。

评分标准:只评估可以亲手验证的东西

启动前我固定了六个维度,每个五分:审计准确性(按 файл:строка手动检查发现样本)、深度(提示中没有的已确认发现)、权衡推理的质量、代码与自检的真实性、俄语和英语文本的质量、纪律性(零个人提问、零限制违规)。原则与好的代码审查相同:一个维度越少依赖品味、越多依赖可验证的事实,就越值得信任。

第一次是如何失败的

第一次运行我做错了——而这成了实验中最可迁移的部分。我在同一个仓库文件夹中并行打开了三个交互式会话。几分钟后,工作树中躺着无法归属的未提交修改:共享的 checkout 意味着当一个会话执行 git checkout -b时,三个会话的分支都会切换,它们的修改和提交混在一起。其中一个会话还执行了 git stash 并把所有东西都扫了进去——包括我自己与实验无关的文件。

“同一文件夹中的并行 AI 智能体不是并行实验。那是一个有三个作者的大冲突。”

– 让我付出重启代价的结论

两次会话的结果都不得不判定为不可用:即使它们运行到最后,我也无法诚实地说我评估的是谁的修改。第二次运行——已经在隔离的 worktree 中进行——撞上了套餐限制:两个 agent 在启动时就挂了,第三个卡住,却仍在界面上看起来“在运行”。诊断是由文件系统给出的,而不是状态指示器:二十分钟内它的工作副本里没有出现任何文件。这是第二个可迁移的教训:agent 的存活状态要通过磁盘上的变化来验证。重启之后,三个模型在同等条件下都跑完了完整流程。

结果:模型在哪里相同,在哪里不同

最重要的结果是那个没有发生的事: 三个模型都没有出现幻觉. 我手动核查了每个模型至少三条发现——所有引文和行号都精确到字符。对于审计任务来说,这是主要的信任门槛,而三者都通过了。

接下来是差异:

Fable 5 Opus 4.8 Sonnet 4.6
已确认的发现 11 5 9
非平凡的唯一发现 3 1 2
修复的自检 在临时数据库上的集成渲染、xmllint、对他人失败测试的归因 linter + 渲染;抓到了自己的 bug 只有 linter 和路由列表
Token / 时间 164k / 21 分钟 101k / 12 分钟 131k / 12 分钟
评分表总分(满分 30) 30 24 25.5

定性差异比分数更有信息量。 Opus 4.8 ——唯一一个没有注意到 sitemap 中损坏的标题 Content-Type 的模型(另外两个都发现了),并且把它留在了自己的修复里;而且它的俄语文本里混进了一个英文词——“и even путь к картинке”。 Sonnet 4.6 做了正确的修复,但它的自检是声明式的:用 linter 代替了实际运行。 Fable 5 恰恰在自检上脱颖而出:它发现 php 在我机器上是一个挂载到主目录的 docker 容器的包装器,通过一次性容器重建了所有检查,并在临时数据库上以集成方式跑通了自己的修复。“我做了”和“我证明了我做了”之间的差别——这正是 agent 任务中最具区分度的轴。

另一个有用的信号是收敛:三个模型独立地把同一个 sitemap 问题列为首要发现。当独立的审计者们在首要发现上达成一致时,这是专家间一致性的廉价替代品:这个问题几乎肯定是真实的。

参与者中的裁判

评分表评分由 Fable 5 进行——正是参与比较的同一个模型。这是一个方法论漏洞,必须直说:LLM 裁判会系统性地给自己的文本打高分,而且模型越能识别出自己的文本,这种倾向就越强——这一点在 Panickssery 等人发表于 NeurIPS 2024 的论文中已有展示。缓解偏差有两种方式,我两种都用了:第一,尽可能把评分表从口味轴转向可验证的事实——行号精确性、修复完整性、混入的外语词都不取决于裁判的偏好;第二,明确声明利益冲突,并把有争议的轴交给另一个模型或人做交叉核查。我结论中的主观轴——文本质量、推理质量——应当带着这一修正来读。

诚实性限制

每个模型只跑一次——这是 n=1:一两分的差异毫无意义,只有定性差距才值得信任——漏掉的 bug、自检的深度。实验测量的是三个模型在一个领域的一个任务上的表现;不能由此得出“Fable 5 总体上更好”的结论。而且还要记住成本:顶级模型消耗的 token 是最经济参与者的 1.6 倍,时间几乎翻倍,而 它的 token 按价目表 本身也更贵——对于常规任务来说,这是支持更简单模型的有力论据。

我给自己留下了什么

方法论归结为一份简短的清单,适用于任何项目和任何模型:

  • 测试任务是真实工作的完整流程,在自己的代码上进行,而不是合成的小题。
  • 所有人用同一个 prompt,通过独立的 worktree 隔离,结果放在独立分支。
  • 在 prompt 中明确幻觉的代价:编造的发现比没有发现更糟。
  • 所有人都能获得的提示(文档、仓库中的笔记)不计入深度评分。
  • 评分表在运行前固定,并依据可验证的事实而非印象。
  • 手动核查发现的样本;独立模型在首要发现上的一致是它们真实性的信号。
  • 参与者裁判——已声明的利益冲突:有争议的轴交给交叉评估。
  • agent 的存活状态要通过磁盘验证,而不是界面上的指示器。

计划之外的额外收获:实验自己回本了。三次独立审计在博客中发现了真实问题——从缺少英文页面的 sitemap 到控制器中的死查询——两个现成的修复已经躺在分支里,等待合并到生产环境。在自己的代码上比较模型,与阅读基准测试不同,留下的不只是一个观点。

来源与参考