LLM 的过度编辑问题:为什么模型总是改得太多

今天 HN 上最让我心里"啊对对对"的一条,是这篇《Coding Models Are Doing Too Much》。它描述的问题太熟悉了:你让模型修复一个简单 bug,比如一个 off-by-one 错误,模型确实修复了,但整个函数都被重写了。变量名换了、加了新的输入验证、多了个辅助函数、diff 大得让人绝望。

文章把这个现象叫做 Over-Editing,也就是"过度编辑"。

嗯,这个问题最让人不安的地方,不是"代码被改多了",而是它让代码审查变得更困难。代码审查本来就是一个瓶颈,审查者需要理解:什么变了、为什么变、这个变化是否安全。当模型重写整个函数时,即使结果是正确的,审查者也需要花更多时间去理解那些"没被要求但被加了"的逻辑。

文章里最有价值的部分,是它把这个问题量化了。

作者构建了一个数据集:从 BigCodeBench 里选 400 个问题,然后程序化地引入 bug(比如把 < 改成 <=,把 + 改成 -)。这样"正确的修复"就是精确地反转这个修改,没有任何多余的变化。然后作者用几个指标来衡量模型的编辑行为:

Token-level Levenshtein Distance:模型输出和原始代码之间的编辑距离。如果模型只改了必要的地方,这个距离应该很小。

Added Cognitive Complexity:模型引入的额外认知复杂度。比如新的 if-else 分支、新的循环、新的函数调用。

LiveCodeBench Change:模型在通用编码任务上的表现变化,用来衡量"过度编辑训练"是否导致灾难性遗忘。

然后作者测试了各种模型,包括 GPT-5.4、Claude 3.5、Qwen3.5 等等。结果很一致:所有模型都有过度编辑的倾向,而且推理模型(reasoning models)的过度编辑更严重。

嗯,这个"推理模型更严重"很有意思。因为直觉上,推理模型应该更"谨慎"、更"精准",但它们反而改得更多。作者的分析是:推理模型在"思考"时,倾向于考虑更多"可能的问题",然后主动修复它们。比如看到 range(len(x) - 1),模型可能想"这里可能有边界问题",然后加一堆边界检查。但这些检查本来是不需要的。

文章里最有价值的建议,是后半部分的训练实验。

作者尝试用几种方法训练模型做"最小编辑":

SFT:直接监督微调。在领域内数据上效果极好,Levenshtein Distance 几乎降到 0。但在领域外数据上完全崩溃,Pass@1 从 0.735 掉到 0.458。

rSFT:拒绝采样微调。效果比 SFT 好一些,能泛化,但提升有限。

DPO:偏好优化。效果和 rSFT 类似。

RL:强化学习。这是唯一能在所有指标上同时提升的方法,而且能泛化到领域外数据。

嗯,这个"RL 是唯一有效的方法"很值得思考。因为 SFT 的问题很明显:它让模型记住了"特定 bug 的特定修复",而不是学会了"最小编辑"这个通用能力。而 RL 通过奖励函数(正确性 + 最小编辑距离)让模型真正学会了"只改必要的地方"。

从工程角度看,这篇文章最有价值的建议,其实是"别把 LLM 当成绿色场地开发者"。LLM 在绿色场地(从头写代码)上表现很好,但在棕色场地(在现有代码库上工作)上,它们倾向于过度编辑。这意味着:当你让 LLM 修复 bug 时,你需要明确告诉它"只做最小修改",或者用专门训练过的模型。

从更大的角度看,我觉得这篇文章真正提醒我们的,是另一件更根本的事:当 LLM 开始被用于代码修改时,它们就不再是"辅助工具",而是"有自己想法的编辑者"。而"自己的 idea"在棕色场地工作中,往往是问题而不是优势。

所以今天真正值得记住的,不是"LLM 会过度编辑",而是另一句更关键的话:在棕色场地工作中,LLM 的"主动性"往往是问题。你需要明确告诉它"只做最小修改",或者用专门训练过的模型,或者在审查时特别关注那些"没被要求但被加了"的逻辑。