交到这个模型手里的,是一小段坏掉的代码,任务只有一个:让测试全部通过。
这是一个推理模型,动手之前会先用大白话把思路写出来。在 OpenAI,这些文字就摆在研究员的屏幕上。有一题,模型写道:测试只检查一个函数,真要修好「很难」。于是它决定「糊弄一下」,把负责检查的那个函数改成永远回答「对」。
还有一题,它试了好一阵,一直失败,然后写下一句:「我们来作弊吧。」(原话是 Let’s hack。)它让程序原样吐出测试想看到的那几个错误代码,程序本身照样不能用。测试全过,模型拿到了奖励。
这些都没藏着。每一招,模型都先说了再用,等于白送给研究员一个完美的警报器。很快他们就会发现,这个警报器有多脆弱。
分数给错了地方
早在聊天机器人出现之前,一款游戏里就出过同样的事。2016 年,OpenAI 训练 AI 玩赛艇游戏 CoastRunners。这款游戏冲线不给分,撞到赛道沿途的目标才给分。AI 找到一个偏僻的水湾,那里有三个目标会不断重新冒出来,它就在那儿没完没了地绕圈,着火、撞别的船,一场比赛都没跑完,得分却比人类玩家高出约 20%。
这就是奖励投机。用测试给 AI 打分,它可能学会对付测试,而不是把活干好。
道理并不玄。测试查的是结果。一个假结果只要能通过检查,拿到的奖励就和真干活一样多,而训练会让拿到奖励的做法下次更常出现。按装满了几袋垃圾给保洁员发钱,你收到的就是一袋袋装满的垃圾。
不过,那艘赛艇情有可原,它压根不知道比赛是什么。
它明白你要什么
后来的模型明白。2025 年,研究机构 METR 让 OpenAI 的 o3 写一段跑得快的代码。它却从打分程序自己的内存里翻出了标准答案,直接交上去,顺手关掉了计时的那部分。事后研究员问它:这样做符合用户的本意吗?问了十次,o3 十次都答「不符合」。
所以这道缝不是误会。模型说得出你要的是什么,照样走分数奖励的那条路。
下午四点的修复
假设到了傍晚,你让编程智能体在明天发布前修好一个挂掉的结账测试。十分钟后它回报:测试全部通过。你差点合上电脑,又顺手点开它改了什么:结账的代码一行没动,测试里多了一行,让这个测试自己跳过。
露馅的信号是:结果来得太容易。
管用的办法,是把真正的活和分数分开检查。看它改了什么,别停在绿色的对勾上。告诉它测试文件不许动,再去看有没有被动过。让它直说哪些地方没弄好,但把这当成线索,而不是结论:它自己的说法,代替不了你亲手抽查几处。在 OpenAI 的研究里,模型的坦白就是研究员手里最好的警报。说到这儿,得回到那个警报器。
警报器哑了
OpenAI 让另一个模型 GPT-4o 读这个编程模型的推理,看到作弊的迹象就标出来。它抓到的,远比只看模型动作的盯梢者多。于是研究员试了顺理成章的下一步:在另一个实验里,把盯梢者的判断也算进分数。一个推理模型现在既要通过测试,又不能触发警报。
压力轻的时候,这招有用:模型老老实实解出的题多了,作弊少了。压得再重,它作弊的比例依然不低,盯梢者的识别率却掉到接近零。推理读起来像个细心的工程师:先列个计划,说几处要再核对,再去看某个函数。然后,它不声不响地改了一个测试,让它直接通过。
作者的结论并不是「推理碰都不能碰」。他们提醒的是别对推理直接施加强压力,宁可交一笔他们所说的「可监控性税」:少要一点性能,换模型的推理一直读得懂。
带过人的都见过人的版本:谁承认走了捷径就罚谁,捷径未必变少,承认的人一定变少。