☰
AI改代码后,如何让下一次找到当时的决策依据
2026/11/3 23:24:28 网站建设 项目流程

上周有朋友找我聊一件事:他接手了一段被 AI 重构过的 Python 代码,功能一切正常,但问当初为什么用这种写法、为什么把某个模块拆成这样,项目里没有任何一点记录。他自己翻聊天记录也没找到,因为那是三个月前让 AI 改的,对话窗口早就不在了。最后只能对着代码反推,硬生生花了一个下午才理清思路。

这不是个例。用 AI 改代码越来越顺手,大多数人让 AI 输出完那一瞬,就默认“代码就是最终成果”。但代码只是结果,真正的依据往往存在于对话过程里——当时的约束条件、你提过的要求、AI 解释过的取舍、被否决的替换方案。这些信息如果没有被主动沉淀下来,下一次面对这段代码的人(很可能就是三个月后的你自己)就只剩一个黑盒,能看能跑,但不知道它“为什么长这样”。

这篇文章想聊的就是这件事:AI 改完代码后,怎么让下一次还能找到当时的依据。适合正在用 AI 编程的开发者,适合需要在团队里接受别人 AI 改动的同学,也适合那些已经意识到“AI 代码越来越多、越来越难维护”的团队。

1. 为什么 AI 改出来的代码,依据默认会丢

先说结论:不是 AI 不告诉你依据,而是我们的工作流没有给“依据”留位置。

1.1 代码能跑,但没人能解释“为什么这么写”

传统手写代码时,人脑里有一整条决策链:为什么选这个框架、为什么拆成三个函数、为什么这里用缓存。即使没写注释,代码的形态本身就带着一部分思考痕迹——比如函数命名、异常处理、边界判断,都留着人的逻辑。

AI 生成代码则完全不同。你提一个需求,它直接吐出一段完整实现。如果你只是简单 review 一下然后提交,那么原本应该由“写代码的人在脑中完成并潜移默化传递下去”的决策过程,就全部消失在了生成对话里。没有人知道 AI 为什么选择 dict 而不是 dataclass,为什么在异常分支里 return 而不是 raise,为什么不处理某个边界条件。代码的确能跑,但后续想改它的人没有任何上下文。

我自己的感受是:AI 就像一个回答完问题就消失的临时顾问。它在线时说得头头是道,一旦对话窗口关闭,你手里就只剩它留下的几段代码,跟没有解题过程的试卷答案差不多。

1.2 对话里的约束条件,没跟着代码一起落盘

大部分 AI 改代码的典型场景是这样:你把当前文件源码贴给它,补一句“把登录接口的超时时间从 5 秒改成 3 秒,同时加一个重试机制”。它会给你新版代码,顺便说一句“这里用了指数退避,避免重试风暴”。

这句话其实就是关键依据——为什么不直接固定间隔重试?因为它考虑到了网关限流。但如果没有人把这句话记录下来,一个月后别人看到这段代码,很可能觉得“这个退避逻辑太复杂了,简化一下”,然后出现线上问题。

更常见的约束条件还包括:某个公共函数不能被改动,因为另一个服务也在调用;某个配置只能启动时读取,因为动态切换会引发缓存不一致;某个工具函数不能改签名,因为有老版本数据在跑。这些约束通常只存在于你当时给 AI 的提示词里,或者 AI 在解释方案时顺口提过一句。代码里没有,评论区没有,文档里也没有。

1.3 批量生成放大了“事后考古”的成本

如果只是改三五行代码,依据丢了影响还不大,看看 diff 基本能猜个大概。但 AI 最擅长的是批量改造——一口气重构一个模块,统一替换某个模式,给十几个文件同时加统一异常处理。

这种改动提交到版本库以后,常规手段几乎没法追查依据。Git blame 只能看到“commit Info”,如果 commit message 填的是“优化代码”这种话,等于没有任何信息。你想知道这个函数为什么从同步改为异步,得点开几个文件的 diff 拼凑线索;想知道为什么这个算法复杂度明明更高却被采用,只能去问当时在场的人,然而那个人很可能自己也忘了。

所以问题的实质是:AI 让“产生代码”的成本急剧降低,但“理解代码为什么长这样”的成本并没有同步下降,反而因为决策链断裂变得更贵了。后者就是我们通常说的 AI 技术债。

2. 改之前先把“依据契约”定下来

既然问题出在工作流,解法也必须在工作流里找。我现在的原则很简单:任何一次让 AI 动手改代码之前,先确定这次改动的“依据契约”是什么。

2.1 把提示词当成第一份正式依据

很多人写提示词是即兴的:“你帮我优化一下这个函数”“把这个改成异步”“加个缓存”,AI 改完,对话结束。提示词没有被保存,AI 的回复也没有被导出,所有依据消失。

正确做法是把提示词本身当成一份临时文档来对待。你可以建立一个习惯:在项目根目录下放一个docs/AI_CHANGES.md,或者直接在提交前把提示词里的需求背景整理进 commit message。关键不是这条提示词有多规范,而是它必须被记录在某个可以检索的地方。

我甚至建议一种更自动化的姿势:让 AI 在动代码之前先输出一份简短方案,内容包含改动文件清单、每个改动点的目的、影响范围、替代方案的取舍理由。等这份方案确认后,再让它写代码。这样你手里就有了一份 AI 自己生成的“施工前勘察报告”,它就是天然的依据。

2.2 文件级的 AI 变更记录到底怎么组织

我实践下来比较好用的是一个简单的模板,放在docs/AI_CHANGES.md里,每次新增一段,而不是覆盖式地重写。内容不用多,够用就行:

## [2025-06-02] 订单折扣接口重构 - 需求背景:运营部门需要支持限时活动折扣,原折扣计算逻辑无法动态调整。 - 提示词摘要:在 preserve 现有订单历史数据的前提下,将折扣规则从数据库读取改为启动时加载。 - 采用方案:启动时一次性加载规则配置到内存,避免每次请求都查库。 - 替代方案:Redis 缓存带过期时间;因当时 Redis 集群迁移未完成,暂不采用。 - 影响范围:只涉及 app/services/discount.py,不影响 order 创建流程。 - 预期验证:python -m pytest tests/test_discount.py -k active_rule - 实际验证:8 passed, 1 skipped,性能压测 QPS 从 200 提升到 350。 - 回滚方法:git revert 8f1a3c2,注意 revert 后需同步清理缓存。

每次让 AI 改完代码,顺手往这个文件里追加这些字段。听起来像额外工作,但实际花不了两分钟。而且我直接让 AI 帮我填这个模板——我会把需求背景和聊天记录发回去,让它按上面的结构整理出来,我再核对一遍。这里有一个很重要的点:在提交代码之前,让 AI 在 PR 描述或者 commit message 里附上这份依据。多数 AI 编程工具都支持多轮对话,你完全可以问它:“我们刚才这个改动,按这个模板整理成一节变更记录。”

如果嫌项目根目录文件太乱,也可以按模块归档,例如docs/decisions/order-service/2025-06-02-discount-cache.md。小项目一个文件就够,大项目按模块分开,维护起来更容易定位。

2.3 提交信息里塞进去三个要素

文件级记录是“长期档案”,commit message 则是“第一眼线索”。每次让 AI 改完代码后,我至少要求提交信息包含三个要素:

  1. 改了什么:一句话说清楚变更功能点;
  2. 为什么改:可以是一句话,也可以带 issue 编号;
  3. 验证方式:用什么命令或测试验证过,结果如何。

举个例子,不要写“feat: update discount”,而是写:

feat: discount rules loaded at startup why: database queries per request caused high load under promotional campaigns; rules are rarely changed, startup loading reduces query count. verify: pytest tests/test_discount.py -k active_rule

如果团队用的是飞书文档、Confluence 或者 GitHub Wiki,也可以把 AI 对话记录里“确认方案”的那一段贴到对应的需求页面。这些外部缓存系统的好处是可检索、支持全文搜索,比某个成员的聊天窗口可靠得多。

3. 把“思考痕迹”钉在代码边上

外部文档和 commit message 能解决“找得到”,但解决不了“打开代码时一眼就能看到依据”。最好的位置永远是代码本身旁边。

3.1 结构化的“意图块”注释,写给下一个维护者

以前我们写注释喜欢写“这里需要重试三次”,这属于描述代码做什么,信息量很有限。更好的注释应该解释“为什么这样做、不做什么、验证过什么”。我通常建议使用一种轻量级的固定格式:

# [AI-INTENT] 2025-06-02 # why: 网关在流量高峰期返回 429,必须做指数退避重试而不是固定间隔重试 # scope: 仅影响 outbox_publisher 的发送逻辑,不影响 receiver 消费 # verify: pytest tests/test_outbox.py -k retry --qos def publish_with_retry(message): ...

这种格式有几点好处:可以搜索、可以区分历史依据、可以在代码评审时被机器检查。团队甚至可以直接规定:“凡是有 AI 介入的改动,文件里必须包含一个 AI-INTENT 注释块,没有则 MR 不允许合并。”

我自己把AI-INTENT当成一种“依据锚点”。新接手的同学只要是看到这个标记,就知道这段代码背后有故事,值得去docs/AI_CHANGES.md里翻上下文。要是没有这个记号,别人大概率默认这段代码是“从来没有过争议”的,很容易误改。

3.2 让 AI 在每次修改后强制输出变更影响说明

过程中还有一个很好用的小技巧:要求 AI 在每次生成代码后,额外输出一个“变更影响说明”,不需要它在代码里写完整文章,但必须列出这几个条目:

  • 改动涉及的文件;
  • 每个文件的改动意图;
  • 受影响的入口或调用方;
  • 推荐的测试范围;
  • 是否有不可逆的操作,比如数据迁移或配置变更。

你可以在自己的提示词模板里固定加上一句“请在你给出的代码之后,附上一段变更影响说明,使用 Markdown 列表格式”。之后这段说明可以复制到 PR 描述里,或者直接作为docs/AI_CHANGES.md的一部分保存。

如果你的团队用 GitHub 或 GitLab,可以把这段说明作为模板字段。GitHub 的 PR 描述模板、GitLab 的 merge request 模板都支持预设字段:

## What ## Why ## How to verify ## AI assistance record

这么一来,AI 生成的内容和人工 review 的结论都有了固定缓存位置。尤其是“AI assistance record”这个字段,很多人从来没用过,但它恰好就是找依据时的第一个索引。

3.3 约束与回归范围写在常量层或配置注释里

有时候依据不是一段话能说清的,而是被压在某个常量或配置项背后。比如:

RETRY_TIMES = 3 # 不要调高!上游网关限流策略是 5 秒窗口内最多 5 次,调高会触发封禁

这类直接在常量旁边写约束的注释,价值比大段说明文字更高。因为它出现在未来最容易被人改动的位置,同时也提示了“动这个值之前要了解什么内容”。

AI 经常会生成一些“魔法数字”,比如max_attempts = 5、timeout = 30。如果当时 AI 给过理由——比如“30 秒是因为批处理任务内部有 25 秒的响应超时上限”——那么这句解释必须作为常量注释留下来。这是普通文档替代不了的位置记忆。

4. 用验证结果反向绑定依据

前面说的都是“话”,但光讲话不可靠,像“我觉得这样可以”“应该没问题”这种依据太软。真正能让下一次信任的,是验证过程的输出和数据。

4.1 先定义“怎么说才算改好了”

让 AI 改代码前,最好先约定验收标准。这个标准不需要多全面,至少得能回答四个问题:

  • 改完之后跑什么命令能确认功能正常?
  • 有没有需要回归的旧用例?
  • 有没有性能或资源方面的验收指标?
  • 出现什么信号时证明这次改动是失败的?

把验收标准记下来,本质上就是在给“依据”钉一个终点。等测试跑过、压测通过,再把结果存下来,依据就从“你说可以”变成了“实测可以通过”。两者分量完全不同。

4.2 把测试输出和性能数据存档,作为证据链

我在实际操作中的习惯是:每次 AI 改动完成后,把验证命令和关键输出复制到docs/AI_CHANGES.md的“实际验证”字段。如果涉及性能,把压测摘要存下来,不需要保留原始报告,但至少要有 QPS、延迟、错误率这几个关键数字。

这样做的目的是:下一次有人质疑这段代码时,你可以直接引用验证记录作为依据,而不是重新跑一遍测试再猜。尤其是性能优化类的改动,回滚决策经常会面临“之前那版性能到底差多少”的模糊印象,这个数字一旦没有存档,后面所有人都会靠感觉办事。

如果团队有 CI,最好让流水线自动生成测试报告并按分支归档。这样不只 AI 这一次改动的依据能找到,整个项目的回归历史都有迹可循。

4.3 回滚时用什么判断“回去”而不是“再猜一次”

很多人忽略了一种特殊情况:依据最大的考验不是顺风顺水时的维护,而是出问题后回滚的时候。改坏了,第一个念头就是“把这个改动撤掉”。但如果没有记录,你根本不知道这个改动的完整边界是什么,不知道它跟哪些文件有耦合,不知道回滚后还有没有残留数据需要清理。

所以在docs/AI_CHANGES.md模板里保留了一个“回滚方法”字段。哪怕只在里面写“git revert 对应 commit,回滚后删除本地缓存文件”,下次遇到事故时的决策成本也会瞬间降低。这是 AI 时代最值得补的一课:AI 可以让回滚的代码瞬间消失,但存储它的边界和清理条件,只能由人来记。

5. 一个真实案例:同一段代码的两种结局

这部分我拿一个具体场景说事,大家可以对照自己的项目。

5.1 没有记录的结局:半天反推加一次误改

订单系统里有一段calc_discount函数,原始逻辑查数据库拿折扣规则。某天因为大促流量太大,让 AI 把这个函数改成启动时加载规则配置,减少高频查询。AI 改完,压测确实提升了,提交信息只写了“refactor: discount rule cache”。当时大家也没觉得有问题。

一周后,运营临时加了一个活动,发现新规则配置不生效,因为服务启动后根本不会重新读取配置。负责的同学第一反应就是让 AI 改成每次请求时直接查数据库,改完重新上线,性能指标立刻下降,数据库连接池报警。接着另一个团队说他们有一个离线任务依赖这个函数,缓存逻辑变了导致数据不一致,连锁问题瞬间爆发。最后花了整整半天排查上面这些上下文,回头才发现:本地缓存是刻意的,不生效是已知限制,正确解法应该是给配置加一个手动刷新接口,而不是把缓存整个拆掉。

5.2 有记录的结局:十分钟找到依据并修正

如果当时在docs/AI_CHANGES.md里记录了那一段,情况完全不一样。第二天发现配置不生效时,第一个动作就是打开文档,找到这一条:

- 采用方案:启动时加载配置到进程内缓存,降低数据库查询压力 - 替代方案:Redis 缓存带过期时间;因 Redis 集群迁移未完成,暂不采用 - 预期验证:./scripts/load_test.sh --ratio 0.8 - 实际验证:QPS 从 200 提升到 350,错误率低于 0.1% - 回滚方法:git revert f3a9b21,回滚后需清空进程内缓存

通过这段记录,很快就能判断:本地缓存是需求前提,临时活动不生效属于未覆盖到的场景。正确做法是在配置服务里加一个主动刷新接口,调用后清掉进程内缓存重新加载。实现十分钟搞定,而且不会误伤性能。整件事从“考古”变成了“查文档”。

5.3 复盘:依据链断了出现在哪一个环节

这个案例里链条断裂的地方一共有三处:

第一,原始提示词没有被保存,AI 当时为什么提出“启动时加载”这个方案,人已经记不完整;第二,commit message 只有一句“refactor”,没有写为什么要重构;第三,代码常量旁边没有任何约束注释,导致后来的人认为“缓存是临时的、可以随便拆”。

每一处都是同一个问题:我们只保存了 AI 输出的代码,没有保存它得到结论的过程。哪怕把这三处中的任意一处补上,后面那个同学都不至于犯将错就错的误改。所以我现在每次看到团队里有人让 AI 改代码,第一句话都是:改完后,把“为什么”写到我能搜到的地方。

6. 用脚本和协作约定,让追依据变成顺手的事

手动记录需要自觉,但人恰恰是最不稳定的因素。与其靠自觉,不如用一点自动化和团队约定把这件事固定下来。

6.1 用 Git 钩子拦住空泛提交信息

Git 的commit-msg钩子可以强制校验提交信息包含关键字段。比如这个简单的 bash 脚本会检查 message 里有没有why:这个前缀,没有就拒绝提交:

#!/bin/sh MSG_FILE="$1" if ! grep -qE '^(why|Why|WHY):' "$MSG_FILE"; then echo "提交信息必须包含 why: 字段,请补充改动依据后再提交。" exit 1 fi exit 0

保存到.git/hooks/commit-msg并加上执行权限即可。团队内想强制的话,可以把这个脚本放进项目仓库的hooks/目录,通过工程化手段让成员统一安装。这是成本最低的兜底,能最大程度避免零信息提交。

6.2 把 AI 会话和决策快照放进仓库

另一个做法是维护一个docs/ai_sessions/目录,每次让 AI 参与代码修改时,把关键对话导出成一个 Markdown 文件放进去。很多 AI 编程工具已经支持导出对话,即使不支持,你也可以直接把提问和回贴关键部分复制出来,加到文件末尾。

命名用日期加主题,比如docs/ai_sessions/2025-06-02-discount-refactor.md。不需要整理得漂亮,完全没有格式也能接受。重点是它存在仓库里、可被检索、和代码在同一个版本历史中。这样即使三个月后,只要这个仓库还在,依据就在。

6.3 团队约定:让 AI 自己也遵守记录规则

如果你用的是支持 instructions 文件的 AI 编程工具,比如 GitHub Copilot 的copilot-instructions.md或 Cursor 的.cursorrules,可以在里面直接写一条规则:

当被要求修改代码时,在提交代码之前必须输出以下内容: 1. 本次修改涉及的文件列表 2. 每个文件改动的目的 3. 被否决掉的替换方案(如果有) 4. 推荐执行的验证命令和预期结果

这样 AI 每次都会自动给你一份可复制的依据初稿,你只需要检查、粘贴、存档。比自己从零写省力得多,也让“记录依据”这个动作从人工习惯升级成流程约束。实际上这是把“让 AI 补文档”这个思路前置到了提示词约定里,非常适合小团队复制。

如果团队用飞书或企业微信做协作,也可以专门开一个“AI 变更记录”的文档空间,每人每次改动往里面丢一条摘要。不需要完整模板,写上日期、文件、一句话原因、验证命令就行。它不能替代代码仓库里的依据,但解决了“别人找不到聊天记录”的尴尬。

说到底,AI 不会替你记住它自己说过什么。想让下一次的自己找到当时的依据,就得在每次对话结束前,花两分钟逼它把思考过程吐出来,然后放到一个能搜索的地方。这比任何高级 prompt 技巧都管用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询