最近在 Hacker News 上有一篇值得关注的文章,作者是 Armin Ronacher(Python 圈子里熟悉的名字,Sentry 和 Flask 的贡献者)。标题本身就足够反直觉:“Better Models: Worse Tools”——更强的模型,更差的工具。
发生了什么
Ronacher 在使用 Pi(他开发的一个 AI 编程工具)时发现,新版本的 Claude 模型在调用编辑工具时,开始出现大量”幻觉参数”——模型会生成 schema 中根本不存在的字段。
比如一个正常的工具调用是这样的:
{
"path": "some/file.py",
"edits": [
{
"oldText": "text to replace",
"newText": "replacement text"
}
]
}
但新版本 Claude(Opus 4.8 和 Sonnet 5)会生成这样的调用:
{
"path": "some/file.py",
"edits": [
{
"oldText": "...",
"newText": "...",
"requireUnique": true
}
]
}
或者这样:
{
"oldText": "...",
"newText": "...",
"oldText2": "",
"newText2": ""
}
Ronacher 在反复测试中观察到一整个”动物园”般的多余字段:type、id、kind、unique、requireUnique、matchCase、in_file、forceMatchCount、children、notes、cost……甚至在 edit 对象内部出现了 event.0.additionalProperties 这种完全不合语法的 key。
更诡异的是:这个问题只在最新的 Opus 4.8 和 Sonnet 5 中出现,旧的模型反而没有这个问题。 即 SOTA 模型在工具调用这个具体任务上,比它们自己的老版本更差。
为什么这很重要
Ronacher 解释了底层原因。工具调用本质上是文本生成——模型收到一个系统提示和工具 schema,然后生成看起来像”调用这个工具”的文本。模型并没有真正理解 schema 的约束,它只是在遵循训练时学到的格式惯例。
这就引出了两种不同的技术路线:
- 事后验证:让模型生成 JSON,然后验证格式,不对就重试
- Grammar-aware decoding(语法感知解码):在采样阶段就约束模型,不允许生成违反 schema 的 token
大多数生产级 AI 编程工具用的都是第一种方案。这意味着当模型”发明”了 schema 中不存在的字段时,工具会拒绝调用,要求重试。对于简单的任务这无伤大雅,但当一个复杂的多步骤编辑因为参数格式问题反复失败时,就从”AI 帮你写代码”变成了”AI 让你不断重试”。
真正的危险:能力越强,问题越隐蔽
这件事最值得警惕的地方在于:Opus 4.8 的推理能力确实更强(benchmark 更好),但工具调用的可靠性反而下降了。这不是功能退步,而是能力增长带来的副作用——更强的模型在推理上更敢”发挥”,反而更容易生成看似合理但 schema 不支持的参数组合。
对于把 AI 编程工具用在生产环境的开发者来说,这意味着什么?
Ronacher 的建议是:如果你依赖精确的工具调用(文件编辑、代码重构),不要盲目追新版本。至少在 Anthropic 修好这个问题之前,测试你的工作流在新版本上的表现。
一个更大的问题浮出水面
这件事也折射出 AI 编码工具的一个根本矛盾:更强的模型能力和可靠的工具调用之间存在张力。当模型的”创造力”超出 schema 约束范围时,工具不是在帮你写代码,而是在给你添乱。
对于 AI 编程工具的开发者来说,这是一个需要在产品层面认真对待的问题——不是简单升级模型版本就能解决的。