
> 本文编译自外网
既然模型会胡说,为什么不在半路截住它
用大模型写代码,大家最头疼的往往就是幻觉——那些不存在的 API、凭空捏造的 import,还有看着格外逼真的假函数。
很多人自然会冒出一个工程直觉:既然模型容易胡说八道,为什么不在网线中间挂一个拦截代理?代码刚吐出来就查一遍,把假代码当场掐死。顺着这个直觉,我花了大约 120 个小时写代码和搭评测,做了一个叫 Anubis 的本地代理。
它挂在本地的 7878 端口,不管你用 Claude Code、OpenCode 还是 Cursor,只要把 API 地址指给它,它就会截断每一条模型返回的代码流。里面排了四层检查,从正则、符号缓存、语法树作用域分析一直到模型裁判,专门排查不存在的 API 和未声明变量。为了支持流式输出,我还专门把 Anthropic 的 tool_use 事件做了拦截和重写。
这套软件写得一点都不含糊。一千两百多个自动化测试全部跑通,双协议字节级透明转发,代码扫描延迟控制在毫秒级。在合成评测集上,上一代论文宣称的 90% 准确率我也完整复现了。
但在跑完大约 100 个小时的真实 Agent 流量之后,我亲手把它关掉了,顺便把整个项目开源了(开源链接见文末的“阅读原文”)。
原因说白了很反直觉:它在工程上完全实现了所有设计目标,但在真实场景里,它几乎没有发出过任何一条既真实又有用的警告。
跑分先涨了 33 个点,把底牌翻开看
把检测器做出来之后,我做的第一件事是跑对照实验。实验选了 SWE-bench Verified 里的 24 个任务,分两组跑:实验组流量全部经过 Anubis,开了警告模式;对照组直接连模型。
第一轮用的模型是 GLM-5-Turbo,属于能力很强的一梯队代码模型。跑完之后的数据非常诱人:直接连模型的对照组只解出了 6 个任务,而挂了 Anubis 的实验组解出了 14 个,成功率从 25% 飙升到了 58.3%。如果只看这个数字,很多人大概已经在写推特宣布安全中间件的胜利了。但我点开运行记录,一行一行翻 transcript,结果整个人愣住了。
在整整 50 个任务小时的流式代码里,Anubis 一共只触发了一次警告。那一次警告还是个误报:模型在解释代码时引用了 Sphinx 源码里的类型注解 List[str],因为代理只能看到模型吐出来的片段,看不到本地文件里早就导入了 List,就把这行代码当成未定义变量标红了。
说白了,整整 50 个小时里,真实的有效拦截是零。多出来的 8 个成功任务,完全是因为 Agent 本身的随机性:那时候的 Agent 偶尔会出现莫名其妙提前退赛的毛病,什么代码都没改就直接退出了。
在这轮测试里,对照组遇到了 11 次这种倒霉的退出,而实验组只遇到了 7 次。强模型在知名开源仓库里写代码的时候,吃过的开源项目太多,本来就极少犯那些低级的 API 幻觉。在没有幻觉的地方找幻觉,抓出来的自然只能是巧合。
唯一一次把警告真递进去,发生了什么
为了验证是不是因为模型太聪明才测不出效果,我把测试模型的档位往下调,换成了本地的 Qwen 3.5 9B。相同的 24 个任务,相同的代理配置,重新跑了一遍。
这一次数字马上变得难看了起来:直接跑的对照组解出了 9 个任务,挂了 Anubis 的实验组只解出了 7 个。相同的代码,相同的题目,仅仅换了一个模型,实验组领先 33 个百分点的神话就当场反转,变成了落后 8 个点。

上面的对比图把两次测试摆在一起,左边看似是一场大胜和一场小败,右边的非因果噪声却完全对称。决定最终胜负的根本不是检测器,而是谁在那一轮遇到了更多由于偶发 Bug 导致的空补丁提前退赛。
模型变弱之后,Anubis 的报警器确实响得更频繁了,一共报了 11 次,但这 11 次报警里有 10 次都是上下文缺失造成的误报。
更关键的是那唯一一次实时注入:当时模型正在写补丁,Anubis 判定它写了一行有问题的调用,直接在流式返回的尾巴上追加了一段警告文字,告诉它上一句话里有未定义的符号。收到这段突然出现的警告之后,这个小模型明显慌了神,开始在原地转圈解释自己为什么犯错,接着思路彻底散架,直接退出了编辑状态,提交了一个空补丁。
而在没有任何人打扰的对照组里,同样的小模型虽然写得踉踉跄跄,最后却顺利把同一个题目修好了。弱模型在复杂任务里的上下文本来就像纸糊的房子,经不起风吹。你给它塞一句突如其来的机械警告,不但没帮它纠错,反而直接把它仅存的一点推理注意力全吹散了。

上面的架构对比图清楚地展示了两种路径的分野。检测器试图在网线中间拦截错误,结果却往往不如让代码直接去撞本地真实的编译器。
换到模型没背熟的新框架,41 次报警里有多少真货
两次实验下来,我已经隐约感觉到不对劲,但心里总归有点不服气:前面的测试用的都是 Django、SymPy 这类二十年历史、在训练集里被背烂了的老项目。如果拿模型没背得那么熟、版本频繁变动的现代技术栈去考它呢?
我挑出了 25 个针对这类硬骨头的任务:Rust 的 Axum、TypeScript 的 tRPC、Go 的 gRPC,以及跨版本 API 大换血的 GDScript。这次搭配的是 Qwen 2.5 Coder 7B,并且把所有可能会产生波动的模型裁判全关了,只留最底层的确定性语法检查。
这次 Anubis 彻底兴奋了,在 10 个任务里一口气报了 41 次警告。第一眼看过去我觉得稳了,肉眼扫下来估计抓到了十几个真缺陷。按照我给项目定下的及格线,只要能确认 6 个以上的独立真缺陷,项目就继续做。但我请了一位独立同事做对抗性审计,让他对着这 41 个警告和生成的每一份源码做全量复核。
审计结果彻底击穿了我的底线:

从上面审计图里能清楚地看到,在整整 41 次声嘶力竭的报警里,真正有价值的独立代码缺陷只有 4 个:一个是 TypeScript 里在模块外层用了一个没声明的泛型 T,一个是 Go 里漏了 os/signal 包,剩下两个是 C# 代码里漏写了命名空间引用。
我之前以为的十几个,是因为同一个变量报错被我重复数了四遍。比 17% 的低精度更让人难堪的是漏报:在那些被 Anubis 打了零警告、判定为完全健康的生成文件里,审计员找出了 20 多个严重的幻觉,包括从 trpc-playground 里导入一个压根不存在的方法、在声明为 Godot 4 的脚本里写 Godot 3 的旧语法、在 Axum 0.7 时代调用早被删掉的 Server::bind。整套系统在这些频繁迭代的现代框架上,真实召回率只有可怜的 10% 到 15%。
更尴尬的是,那 4 个被抓住的所谓真缺陷,任何一个程序员在本地敲一下 tsc、go vet 或者 cargo check,编译器都会在两百毫秒内给出明确的报错行号。本地编译器本来就是免费、现成而且绝对精确的——Anubis 费了半天劲,只是用极高的误报代价,做了一套残缺不全的低配版编译器。
论文里 90% 的召回率,是怎么在实战里蒸发的
当然也总有人会问:那些发在顶会上的代码幻觉检测论文,动辄宣称 90% 的召回率,难道数据全是编出来的?数据大概率是真的。Anubis 严格实现了论文里的 FORGE 语法树检查管道,在论文标准的单文件填空测试集上,我也测出了接近满分的漂亮数字。
问题不在于学术界有没有造假,而在于把一个学术指标翻译成工程产品时,中间隔着四个完全没被验证过的假设。一个安全检测中间件要想在实战里创造净收益,它的期望价值取决于下面四个概率的乘积:
真实价值 = P(产生幻觉) × P(无法自愈) × P(检测准确) × P(干预正向)
只要有一项接近零,整个系统的价值就是零。
第一项面对强模型时直接归零,只要 prompt 没写崩,它在主流语言里吐出假 API 的概率极低。
第二项在真实 Agent 循环里被再次稀释,Agent 有终端、会跑测试、会看报错,写错函数名下一秒看终端报错自己就改过来了,根本不需要第三者在旁边指手画脚。
第三项是检测器自己的硬伤:网络代理天生是个瞎子,只能看到代码流而看不到完整文件树和依赖版本,为了防误报加的各种白名单,刚好把最致命的跨版本调用放跑了。第四项面对小模型甚至是个负数,打断模型思路的代价远高于让它把错代码写完再去撞编译器。把这四个项乘在一起,结果清清楚楚地写在终端里:除了增加几十毫秒的网络延迟,它什么都没有改变。
让代码去撞南墙,别在半路大喊大叫
发现自己花了一个多月搭出来的轮子其实毫无意义,心情肯定不会太好。但按照我自己在开工前签下的机械门禁规则,只要真阳性低于 6 个,项目就必须原地解散。
所以我把代码库封存,写了这篇复盘公开发了出来。这几个星期的折腾,至少给我撞出了几条相当清醒的常识。写代码跟写散文不一样,代码天然存在一个绝对权威的真理来源,那就是语言工具链本身。
如果你想拦截语法错误、符号未定义或者类型不匹配,不要去大模型或者代理网关里搞什么推理和正则,直接把语言自带的 LSP 和编译器跑起来。任何试图在网络层靠静态文本去揣摩运行时状态的做法,最后都会在漫无边际的跨版本兼容和符号可见性里被折磨致死。
如果你一定要在模型生成时做拦截,就必须先拿真实的基线发生率去算账。一个在测试集里刷到 99% 召回率的检测器,一旦放到发生率只有 1% 的生产环境里,扑面而来的误报就会彻底淹没真正的问题。既然代码最后总要去撞编译和测试的南墙,那就让它去撞。撞完之后把最真实的错误堆栈还给模型,往往比在半路上拉住它大喊一声可能有鬼,要管用得多。
-- 完 --
机智流推荐阅读:
1.
2.
3.
4.
cc | 大模型技术交流群 hf | HuggingFace 高赞论文分享群 lc|LangChain 技术交流群 code | AI Coding 交流群 具身 | 具身智能交流群 硬件 | AI 硬件交流群 推理 | AI 推理框架交流群 智能体 | Agent 技术交流群