你有没有遇到过这种同学:平时考试成绩特别好,但你稍微换个问法他就懵了?
这不是段子,这是最近一批研究者在测试AI编程能力时真实撞见的现象。而且这次撞上的不是某个无名小卒,是当下最主流的代码评测标杆,SWE-bench。
先说个可能颠覆你认知的事实。你可能以为,AI在SWE-bench上拿到70%甚至更高的分数,说明它已经具备了相当靠谱的软件工程能力,能真的看懂一个陌生代码库,找到bug,然后修好它。但上海交通大学等机构的研究者们做了一个实验后发现,事情没那么简单。他们让人类专家像挤牙膏一样,一点点地给AI透露某个SWE-bench任务的线索,从最模糊的描述开始,逐步给出更具体的信息。结果呢?
在四个测试模型里,每个模型都有超过65%的任务,在几乎还没看到任何仓库文件、没看到正确答案、没看到测试代码之前,就已经开始"回忆"起了具体的修复逻辑,甚至直接说出补丁的内容。这不是推理出来的,这是背出来的。
这件事听起来有点尴尬,但仔细想想也不奇怪。
问题出在哪儿
SWE-bench这个评测集,取材自Django、requests这类超级知名的开源项目。这些项目的代码、issue讨论、修复记录,早就散落在互联网的各个角落,很可能已经被塞进了各种大模型的训练数据里。
这就好比一场"公开题库"的考试。如果你知道某场考试的题目和答案早就被泄露到了培训机构的资料库里,那这场考试还能不能用来判断学生是真的学会了知识,还是背下了答案?显然不能,因为你无法区分这两种情况。如果不做任何处理,继续沿用这套题库来打分,你测出来的高分可能根本不是能力,只是记忆力。
之前也有团队尝试过修补这个漏洞,比如SWE-bench Live和SWE-rebench,它们的思路是不断往里加新题,专挑模型发布之后才出现的issue,这样就能保证模型没提前见过。这个思路没错,但有个先天短板:新题目的数量和多样性,永远追不上那些经年累月积累下来的经典老项目里包罗万象的bug类型。
那怎么办?把老题目重新出一遍,但换个"马甲"。
这就是这篇论文的核心思路,研究者管它叫SchrodingerRepo(薛定谔的代码仓库)。
代码仓库的"薛定谔态"
这个名字取得挺有意思,借用了那只著名的既死又活的猫。核心思想是:同一个任务的代码仓库,不再是一份固定不变的"标准答案版本",而是变成一个只有在AI真正打开评测环境的那一刻,才会被随机生成出来的具体样子。
换句话说,AI每次进考场,看到的都是同一道题的不同"变装版"。
引用块:SchrodingerRepo:一种评测框架,它不直接复用SWE-bench原本固定的代码仓库展示形式,而是在评测运行时动态生成一个语义完全等价、但表面特征被打乱的仓库版本,用来检测AI是不是靠"认出"仓库表面特征来蒙对答案的。
这套框架具体分成四个变形层级,一层比一层狠。
第一层是问题描述重写。用两阶段的LLM流程,先把issue的原始描述换一种说法重新表述,再用另一个模型检查有没有把关键约束漏掉或改错,如果漏了就打回去补上。这一层动的只是文字表面,不动代码本身。
第二层叫命名空间映射,这是四层里最狠的一层,后面会详细说。
第三层是文件内部布局重排。同一个文件里,函数和类的定义顺序被打乱重排,但保证代码逻辑不受影响。
第四层是功能保持的代码重写,把和bug直接相关的代码段用完全不同的写法重新实现一遍,但功能不变。
这四层可以单独测,也可以叠加一起测,用来观察到底是哪一层的"伪装"最能戳中AI的软肋。
命名空间映射:把熟悉的名字全换掉
这一层最值得展开讲讲,因为效果最猛。
它做的事情说白了就是给整个代码仓库里所有"仓库自己起的名字",包括类名、函数名、文件路径、模块名,统一换一套新的命名体系。但注意,它不改第三方库的函数名,不改Python自带的关键字,只改仓库开发者自己写的那些专属名词。
具体操作是先用抽象语法树分析代码结构,把所有属于仓库自己的标识符挑出来,拆成更小的词根单元,比如QuerySet可以拆成Query和Set,然后给每个词根找一个语义上说得通的替代词,比如Query统一换成Ledger,Set统一换成Suite,这样QuerySet就变成了LedgerSuite。整个仓库里所有出现Query的地方,都会被一致地换成Ledger,保证替换后的代码风格看起来依然自然,该是驼峰命名的还是驼峰命名,该是大写常量的还是大写常量。
引用块:抽象语法树(AST):一种把源代码解析成树状结构的表示方法,能精确定位代码里每个变量、函数、类分别在哪里、彼此之间怎么引用,是做这种大规模精准改名的技术基础。
这一步最关键的设计是"可逆"。AI看到的是改名之后的虚拟版本,但它执行代码、跑测试的时候,系统会在后台把AI的操作实时翻译回原始仓库,保证测试结果真实可信,不会因为改名导致代码跑不起来。
这就像给一个熟悉某公司业务系统的老员工,突然调到一个刚重新装修、所有部门牌子都换了新名字的分公司上班。业务流程和数据库结构其实一模一样,走的路线也没变,只是"财务部"现在叫"账目司","审批系统"叫"核准平台"。如果这个老员工真正理解的是业务逻辑本身,换个牌子他照样能干活。但如果他靠的其实是"看到财务部这个牌子就知道往左走"这种条件反射,牌子一换,他就得重新在楼里绕圈子找路。如果不做这层改名测试,你根本无法区分这个员工是真懂业务,还是纯粹记熟了走廊布局。
结果证实了这个猜测。数据说话最实在。
四个模型全线溃败的证据
研究者测试了四个当下主流模型:GPT 5.1、GPT-5.4-mini、DeepSeek-v4-Flash、Gemini-3.1-Flash-Lite,评测基准是SWE-bench Verified,一个人工精挑细选出的500道题的子集。
引用块:Pass@1:让AI针对每道题只尝试一次,看它能不能一次性把bug修对,是最直接的成功率指标。
当四层变形全部同时打开的时候,各模型的表现是这样的:
GPT-5.4-mini从46.8%掉到35.6%,跌了11.2个百分点。GPT 5.1从44.6%掉到36.2%,跌了8.4个百分点。DeepSeek-v4-Flash从72.8%掉到66.8%,跌了6个百分点。Gemini-3.1-Flash-Lite从56.7%掉到42.3%,跌了14.4个百分点,跌幅最大。
这些下降在统计上都是显著的,不是运气不好的偶然波动。
单独看四层里谁的破坏力最强,答案毫无意外是第二层命名空间映射。GPT 5.1单独遇到这一层就掉了7.4个百分点,GPT-5.4-mini掉了6.4个百分点,DeepSeek-v4-Flash掉了6个百分点,而且交互成本暴涨,平均动作数涨了63%到112%,输入token消耗涨了超过160%到超过200%。相比之下,只重写问题描述文字的第一层几乎没什么杀伤力,两个模型分数完全没变。
这个对比本身就是个很清楚的信号:AI依赖的不是理解issue描述的语言能力,而是认得代码仓库里那些熟悉的名字和路径。
一旦这些名字被换掉,它就像突然失明了一样,开始在陌生的走廊里到处乱撞。
多花的时间到底花在哪儿了
这就引出了第二个关键发现:变形之后,AI并没有真的"想更多",它只是在瞎逛的时间变多了。
研究者把AI在解题过程中的每一步操作,归到六类里:navigate(浏览目录)、search(搜索关键词)、read(读文件)、probe(运行代码试探)、edit(改代码)、test(跑测试)。
结果显示,在完全变形的环境下,多出来的动作里,DeepSeek-v4-Flash有83.6%都花在了前四类探索性动作上,只有16.5%花在真正的修改和测试上。GPT-5.4-mini的比例是81.6%对应探索,情况几乎一模一样。
这意味着,AI并不是遇到难题后开始更深入地推理,而是花了大部分额外精力在"我到底在哪儿,这个文件夹叫什么"这种基础定位问题上。
这就好比一个快递员,本来每天送的都是熟悉小区,抬头看一眼门牌就知道该往哪拐。突然把整个小区的路牌、楼号全换了新编号,快递员多花的时间不是用来琢磨怎么把包裹送得更快更准,而是纯粹花在了"这栋楼现在叫几号"这种本该早就心里有数的事情上。如果快递员真正靠的是记住小区的地图逻辑(哪个方向、哪种分布规律),换路牌影响不大;但如果他靠的是死记硬背每个门牌号对应哪家,换了牌子他就得重新一栋一栋地敲门确认。
有意思的是,两个模型面对这种"迷路"状态的应对策略还不一样。DeepSeek-v4-Flash更喜欢用probe(跑代码试探)来摸清现状,本来动作数就多,遇到变形后进一步狂加探索动作,靠这种"死磕式"的多跑几遍来找回一部分丢失的分数,但代价是token消耗翻了两倍还多。GPT-5.4-mini则更保守,主要靠read和search去看代码看文档,很少直接跑代码试探,动作数增加得没那么夸张,但分数掉得更惨。
这暴露出一个有意思的权衡:越舍得花力气到处探索的模型,越能在陌生环境里找回损失的表现;越追求效率、依赖捷径的模型,一旦捷径消失就越脆弱。
这个效应不只出现在修bug上
研究者接着把同一套变形框架用在了另一个任务上,叫SWE-QA,是让AI回答关于代码仓库的问题,比如"这个函数是干什么的""这段逻辑在哪里被调用了"这类问答任务。
结果发现,GPT-5.4-mini的答题质量从70.35分掉到65.71分,降了4.64分,而且还是那个第二层命名空间映射造成的伤害最大。DeepSeek-v4-Flash掉分幅度小一点,从72.97到72.42,但动作数从24.49猛增到35.02,涨了43%,输入token涨了59%。
这说明这个问题不是SWE-bench这个特定评测集独有的怪癖,而是一种更普遍的现象:AI对代码仓库里那些"熟脸"(熟悉的命名和结构)的依赖,渗透到了各种不同类型的代码理解任务里。
这真的是任务变难了吗
看到这里你可能会想,会不会只是研究者把题目出得更难了?换个名字、打乱顺序,这本身不就是增加难度吗?
研究者专门设计了一个对照实验来回答这个疑问。他们找了110道在GPT-5.4-mini发布之后才创建的全新issue,也就是模型绝对不可能提前见过的题目,对这批新题也套用完整的四层变形。
结果非常关键:Pass@1完全没变,还是17.27%,跟没变形之前一模一样。但动作数从15.82涨到17.11,输入token涨了22%。
这个对照实验说明了什么?说明变形本身并没有让题目变得"更难解",因为如果真的变难了,从没见过原题的模型在这批新题上表现应该同样受打击。但事实是分数纹丝不动,只有交互成本涨了。
这就好比给一个从没去过某个城市的游客发一份地图,无论地图上的路名用中文还是用某种他完全陌生但逻辑一致的编号系统标注,只要地图的结构信息是准确的,他找到目的地所需要的努力其实差别不大,因为他本来就没有"这条路我以前走过"的记忆优势可以依赖。但如果换成一个本地老居民,你把路名全换了,他原本凭记忆抄近道的优势瞬间消失,只能像个游客一样重新一步步摸索。这恰好印证了:在SWE-bench Verified上观察到的分数下降,根子上不是题目变难了,是这些模型原本就在偷偷"抄近道",而这次近道被堵死了。
一个具体案例看得更清楚
论文里举了一个具体例子,django__django-11999这道题,issue讲的是用户自定义的get_FOO_display()方法被Django自动生成的同名方法覆盖了。
在原始仓库环境下,AI话不多,认出issue里提到的Django术语后,直接去django/db/models/目录下搜索get_.*_display,一步就命中了正确文件,很快定位出问题代码,整个过程只用了37步动作。
同一个issue放进变形后的仓库,AI完全找不到熟悉的路径名和类名了,只能从列目录、翻文件、搜索display相关方法开始一步步摸索,兜了一大圈才在改名后的文件里找到对应逻辑,还得反复核对新名字和原始行为是否对得上号,最终花了217步动作,是原来的将近六倍,但修出来的补丁是同一个补丁。
这个案例把前面所有数据背后的机制具象化了:不是任务本身变了,是找到答案的路变陌生了。
写在后面
读完这篇论文,最触动我的其实不是那个"AI靠记忆蒙分"的结论本身,这多少可以被猜到,而是那个人类专家逐步透露线索的实验设计。研究者没有直接说"我怀疑AI背题",而是设计了一套渐进揭示信息的流程,像剥洋葱一样一层层地试探AI到底提前知道多少。这种"审问式"的验证方法,比单纯跑一个变形基准更能直击问题核心,因为它证明的是记忆确实发生了,而不只是推测记忆可能发生了。
还有一个细节值得单独说一说:DeepSeek-v4-Flash和GPT-5.4-mini在应对策略上的分歧,一个靠多跑代码探索来硬扛,一个靠更省力的读文档策略来应付,这其实暴露了一个更大的问题:现在评估AI编程能力的时候,我们往往只看最终分数,却很少去问"它是怎么得到这个分数的"。两个模型可能考出差不多的分,但一个是真本事撑住的,一个是靠押题技巧撑住的,这种差异在传统评测里完全看不出来,只有引入这种"换马甲"式的对抗测试才能显现。
这也让我想起小时候考试,有些同学能把课本例题的解法一模一样地套到考试原题上拿高分,但换一道稍微变形的题就完全懵了。这篇论文本质上是在给AI做同样的"变形应用题"测试,而结果告诉我们,至少目前这批主流模型,还没能完全摆脱这种"死记硬背式高手"的嫌疑。
那么下一个问题来了:如果连命名空间这么表层的改动都能让分数掉十几个点,那些真正需要跨仓库迁移、跨语言迁移的编程能力,现在到底还剩下多少是真实存在的?
Q&A
Q1:SchrodingerRepo是什么?
A:SchrodingerRepo是一种新的评测框架,它不再用固定不变的代码仓库版本来测试AI,而是在AI进入评测环境的那一刻才动态生成一个语义等价但表面特征被打乱的仓库版本,用来检验AI是否依赖记忆而非真实推理来解题。
Q2:为什么AI在SWE-bench上表现好却可能是"背答案"?
A:因为SWE-bench的题目取材自Django等知名开源项目,这些代码和修复记录很可能已经出现在AI的训练数据里。实验发现超过65%的任务中,AI在几乎没看到仓库文件前就能说出具体修复逻辑,说明存在明显的记忆现象而非真实推理。
Q3:命名空间映射为什么破坏力最大?
A:因为它把仓库里所有专属的类名、函数名、路径统一替换成新名字,AI原本靠"认脸"式记忆快速定位代码的捷径完全失效,只能重新摸索,导致分数下降最多、交互成本涨得最猛,几个模型都出现6到7个百分点的下滑。







