AI测试 “我第一轮不是说过吗?“—AI 记不住上下文,5 条规矩破了 4 条

匠测AI说 · 2026年08月31日 · 292 次阅读

这个"病"长什么样

刚开工的时候,AI 表现得像个完美同事。

你定的规矩,它条条照办:Python 3.11、RESTful 命名、统一响应体、错误码规范——你说一遍,它第一版代码就全对上了。

你心里暗喜:这磨合得可以啊。

然后聊到第 6 轮、第 8 轮、第 10 轮——

它开始一点一点"失忆",而且失得很隐蔽。

不是突然翻脸,是温水煮青蛙式的漂移:

  • 第 6 轮,代码里出现一句 except ValueError, e:——Python 2 的语法,3.11 直接跑不起来
  • 第 8 轮,新写的接口开始直接 return data,你前面定的统一响应体 {code, message, data} 不见了
  • 第 10 轮,新增的 3 个接口命名全变成动词开头,跟前面的 RESTful 风格完全两套
  • 你明明说过 token 存 localStorage,它后面的代码里悄悄用上了 cookie

最要命的是:你不盯,根本发现不了。 每一段代码单看都能跑,但拼在一起,整个项目的风格是裂的。


我的真实案例

一个 20 个接口的中等项目,后端用 Python。

对话第一轮,我把技术约束交代得明明白白:

  1. Python 3.11,禁止使用任何 Python 2 语法
  2. RESTful 风格:资源名用名词复数,操作靠 HTTP 方法区分
  3. 所有接口统一返回 {code: 0, message: "success", data: {...}}
  4. 异常统一在中间件层捕获,业务代码里不允许 try-except 吞错误
  5. token 放 localStorage,前端从 Authorization 头带上来

前 4 轮,舒服得不像话。接口风格整齐划一,响应体一个模子刻出来的。

第 6 轮,我让它补一个数据导出接口。代码生成得很快,我扫一眼逻辑没问题,让它继续。

直到跑 CI 的时候挂了——语法错误。

点进去一看:

except ValueError, e:
    logger.error("parse failed: %s" % e)

except ValueError, e 是 Python 2.6 之前的写法,3.x 里早就改成 except ValueError as e 了。%s 那种老式格式化也一起回来了。

我当时的第一反应是:"我第一轮不是说了 Python 3.11 吗?"

这还没完。我往后翻它第 8、9 轮写的代码,又发现:

  • 两个新接口直接返回了裸列表 return result_list,没有响应体包装——前端那边已经按统一格式写好了解析逻辑,对接直接崩
  • 一个接口路径写的是 /createOrder,而前面 17 个接口全是 POST /orders 这种风格
  • 业务代码里出现了 3 处 try: ... except: pass——把异常全吞了,正好违反第 4 条

第 1 轮定的 5 条规矩,到第 10 轮,它违反了 4 条。

而且它态度特别好,每次指出来都秒回"抱歉,我疏忽了,马上修正",改得也很快。

但问题是:我不指出来呢?


为什么 AI 会这样?

1. 上下文窗口不是"记住",是"暂时看得到"

大模型每轮生成时,能参考的是当前上下文窗口里的内容。对话一长,最早的那些消息——包括你第一轮定的规矩——在窗口里的位置越来越靠前,模型对它们的注意力会明显衰减。

这有个专门的说法,叫"lost in the middle":模型对开头和结尾的内容最敏感,中间的最容易被忽略。 你的技术约束在开头,最新写的代码在结尾——谁权重高一目了然。

2. 它自己刚写的代码,会变成"新事实"

第 8 轮它写了一个裸返回的接口,这段代码进了上下文。到第 10 轮,模型看到的"最近的事实"是:这个项目的接口好像直接 return 数据就行。

一次漂移会污染后面所有轮次。 它不是故意违反你,是它自己的偏离输出,把自己给带跑了。

3. AI 不会"回头翻文档"

人类同事做着做着会去翻一下项目规范,确认自己没写偏。AI 不会——它没有"等一下,我回去核对一下需求"这个动作。

它每轮都在"基于最近的上下文接着往下写",至于早期约束,它默认自己"应该还记得"。

但"记得"这件事,在长对话里根本不存在。


这种病的代价

  • 🔴 风格漂移的代码混进项目里,code review 的成本指数级上升,你得逐行盯它有没有"返祖"
  • 🔴 前端按统一约定写好的对接逻辑,被一个裸返回的接口直接搞崩,联调阶段莫名其妙加班
  • 🔴 违反约束的代码留在上下文里持续污染,越聊越偏,纠一处冒三处
  • 🔴 最隐蔽的代价:你会慢慢放松警惕。前几轮它表现太好,你以为它"学会了",开始不看代码直接用——雷就是这时候埋的

怎么治

方法 1:约束写进文件,别只写在聊天里

项目根目录维护一个 SPEC.md(或 AGENTS.md),把铁律写死:

# 项目技术约束
- Python 3.11,禁止Python 2语法(except X, e / print语句 / %格式化)
- 接口RESTful:资源用名词复数,POST /orders 而非 /createOrder
- 统一响应体:{code, message, data},禁止裸返回
- 禁止 try-except-pass,异常在中间件统一处理
- token存localStorage,走Authorization头

每个新对话开头第一句话:"先读 SPEC.md,本项目所有代码必须严格遵守其中约束。"

聊天记录会被挤出窗口,文件不会——只要它每轮都读,约束就永远在"最近"的位置。

方法 2:长对话按模块拆,别一个窗口聊到底

20 个接口不要在一个对话里从头写到尾。按模块拆成多个对话:用户模块一个、订单模块一个、支付模块一个。

每个新对话:

  1. 先让它读 SPEC.md
  2. 贴上一个模块已完成的接口代码当"风格样板"
  3. 只聊当前模块

对话越短,早期约束离"现在"越近,漂移概率越低。

方法 3:每 3-5 轮设一个"对齐检查点"

定期让它自己复盘,别等它写错了再抓:

"继续之前,先列出本项目你必须遵守的技术约束,逐条说明你最近 3 个接口是怎么遵守的。"

它复述约束这一步,等于把开头的规矩重新拉回到注意力焦点上。它要是哪条说不上来,说明那条已经开始漂了——立刻补,不要等到代码里出现。

方法 4:第一次漂移就纠正,别攒着

发现它写了 Python 2 语法的当下就指出来,不要想着"先让它把这个接口写完再说"。

漂移的代码多停留一轮,就多污染一轮上下文。 攒到第 10 轮再统一清算,你面对的是一个已经被带偏了 4 轮的模型,纠正成本完全不同。

方法 5:用工具链兜底,别靠 AI 自觉

这条是测试老兵的执念:凡是能让工具检查的,就不要相信"它记住了"。

  • Python 版本和语法:pyproject.toml 里钉死 requires-python = ">=3.11",CI 跑 ruff/mypy——except ValueError, e 这种代码直接过不了 lint
  • 响应体格式:写个基类或装饰器统一包装,业务代码"想裸返回都不行"
  • 命名规范:接口路由集中注册,风格不符的在代码审查环节一眼可见

最好的约束不是"请你记住",是"你不这么写,代码就跑不起来"。


一句话总结

AI 的上下文不是硬盘,是金鱼的记忆——对话越长,你第一轮说的话死得越早。别指望它"记住",要让它每一轮都"重新看到":约束进文件、长聊拆短聊、漂移靠工具抓。

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册