AI 重写验收不能只看最终结果
作者以将 AI 游戏实验引擎从 Python 重写为 Rust 为例,指出结果一致并不代表行为等价。验收还应核对模型实际选择的动作、可见信息与失败处理,避免重写改变实验含义。
AI 深度解读
AI 把重写软件的门槛降下来了,却没有替团队回答一个更难的问题:新版本什么时候才算能接班?作者正在探索用 Rust 重写 eSlams 的 Python 引擎。他关心的不只是游戏能否跑完,而是结果是否还代表同一场实验。
文章的结论很明确:重写完成,要能解释旧系统的哪些承诺被保留、哪些被有意改变,以及团队如何验证这些承诺。对于准备让 AI 替换旧模块、迁移技术栈的程序员,这比生成了多少代码更值得看。
同样的结果,为什么可能算错了
eSlams 让 AI 模型参与游戏,用来研究它们的决策。假设两个引擎最后得出了同一个赢家,看起来迁移很顺利。但检查对局记录后发现,新引擎把软件补上的一步操作,记成了模型自己的选择。
赢家没变,实验的含义却变了。
因此,这类引擎需要保留的不只是计分规则,还有行动归属、玩家能看到的信息,以及模型没有返回可用响应时的处理方式。否则,研究者可能把程序的兜底行为,当作模型的决策能力。
作者提出的验证办法是:让 Python 和 Rust 引擎面对相同局面、接收相同的已记录动作,逐步比较每次落子后的状态。同时检查它们是否拒绝同一种非法操作,是否维持相同的玩家信息边界。
最终输出相同,只能证明最后一步看起来一致。
这里要分清进度:作者说自己正在探索 Rust 版本,上述比较是他希望采用的方法,原文没有给出已经完成的测试结果。
API 长得一样,为什么仍然会泄露数据
作者用 Cloudflare 的 Vinext 说明,快速生成替代实现与让它可靠接班,是两段不同的工作。
按 Cloudflare 的说法,Vinext 在 Vite 上重新实现 Next.js API,初始版本由一名工程师指导 AI,在不到一周内完成,消耗约 $1,100 的模型 token。当时发布的是实验版本。七个月后,关于 1.0 版本的介绍,重点已经转向让替代实现正确运行于真实应用。
文章还引用了一份 10 月的安全公告:两个不同的缓存函数,如果使用相同的额外缓存键和参数,可能共用一条缓存记录。公告中的例子是,公开摘要路由可能返回私有收据路由缓存的数据。Vinext 1.2.0 通过把函数源代码加入缓存键修复了这个缺陷。
问题不在响应格式。调用者传入了预期参数,也拿到了有效响应,但响应里的信息不该由这条路由返回。
这说明兼容性还包含函数之间的隔离关系。参数相同,不代表两个函数承担相同职责,更不代表它们可以共享缓存结果。
重写要验收的是承诺,不能只验收响应
旧软件的承诺,有些写在文档里,有些藏在测试、历史事故和调用方的假设里。例如,某种错误会触发上游重试;两个事件的先后顺序,可能决定客户是否被重复扣费。
作者建议把这些关系变成具体的比较场景:写入后再读取、超时后重复请求、两个客户发出其他条件相同的请求。比较范围还要覆盖持久化数据和发出的事件。当前响应看着正确,下一次请求仍可能继承错误状态。
发现差异后,也不必机械复制旧行为。旧 bug 可以修,但需要有人明确决定目标行为,弄清谁依赖它,并记录变更理由。否则,很容易把实现起来方便的差异,直接当作合理差异接受。
上线也属于验收的一部分。作者倾向于先接管有限范围的工作负载,并保留退路。双版本并行有助于比较,但不能因此发送两封邮件或执行两次付款。回退是否可行,还取决于旧软件能不能读取新版本写入的数据。
我的判断
我认同作者把验收重点放在行为承诺上。前端或 Node 项目的替换,最容易被演示页面、接口返回值和构建成功吸引注意,跨请求状态与异常路径则更难看见。
但文章提供的是方法判断,不是证明某套流程效果更好的对照实验。Vinext 的时间和 token 花费描述了初始实现,不能当作完整迁移成本;eSlams 的逐步对比也仍是作者提出的验证方案。
相比只跑单元测试或检查 API 格式,新旧实现对照更容易暴露隐含差异;它的局限是,旧实现只能告诉你过去怎么做,不能自动裁定以后应该怎么做。测试发现差异之后,仍然需要业务判断。
能拿来做什么
- 用 AI 重写 Node 接口前,先列出缓存隔离、错误语义、重试行为和事件顺序等承诺,把它们作为验收条件。
- 给有状态模块准备可回放的操作序列,逐步比较新旧状态,并检查写入数据和发出事件,别只比较最后一次返回值。
- 为每处行为差异记录取舍:哪些需要兼容,哪些属于有意修复,以及哪些调用方会受影响。
- 小范围切换前,验证并行比较不会重复触发副作用,并确认旧版本能读取新版本写入的数据,让回退确实可用。