ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

让AI只改注释不动代码:注释微重构Prompt调优全记录

让AI只改注释不动代码:注释微重构Prompt调优全记录 接手一个三年没人维护的 Python 项目我干的第一件事有点反常规把所有注释从头到尾读了一遍。不是读代码是读注释。原因很简单代码如果跑不动测试和报错会告诉我可注释一旦开始撒谎没有人会主动报错。我翻到一个函数注释写着“获取当前用户”函数体里查的却是订单表另一个配置文件里YAML 注释和字段名逐字重复真正重要的“为什么这个值不能小于 30”反而没人写。这种状态我称之为注释债务。当时我正好在系统性练习提示词工程就顺手做了一个“注释微重构 prompt”专门干这件事。所谓注释微重构就是只对注释层做局部修正改错字、补上下文、统一格式、删除明显过时信息但绝不改动代码行为。这篇文章是我自己调优这份 prompt 的完整记录包括设计思路、三个能直接套用的模板、四次翻车现场以及最终的稳定版本。如果你也在清理老项目里的中文注释想把 YAML 配置里的冗余说明统一掉或者只是想找到一个能让 AI“只碰注释、不碰代码行”的用法这篇内容应该对你有用。1. 注释会腐烂但代码不会主动告诉你1.1 注释腐烂的真实过程代码是会被测试逼着成长的。行为变了、接口变了通常有编译错误或测试失败来提醒。但注释不同它从写下来的那一刻起就开始慢慢过期。最常见的腐烂路径是需求调整后程序员改了实现逻辑却忘了同步改动旁边那段注释或者重构时抽出了公共方法原本解释“为什么这样设计”的注释被随手删掉再或者团队换了一批人新成员按自己的习惯补充注释格式和语言越来越散。我见过最典型的一段代码是这样的def get_user(uid, db): # 获取用户信息根据 id result db.query(select * from user where id ?, uid) # 如果不存在 if not result: # 返回空 return None return result[0]这段注释的问题很典型第一行注释和代码内容重复“根据 id”也说得含糊后面两句“如果不存在”和“返回空”完全是在翻译代码属于“读注释等于读代码”的低信息量注释。真正应该写清楚的是为什么用db.query而不是ORMuid是字符串还是整数查不到用户时为什么要返回None而不是抛出异常这些决策背景一个都没写。注释不会导致测试失败所以它会安静地烂在那里。等下一次重构时新人看到“获取当前用户”的注释就会真的以为这个函数返回的是当前用户然后在一个错误的前提上继续叠加新代码。到这一步注释就不再是资产而是负债。1.2 为什么我不等“以后重写”而是现在做微重构很多团队对待烂注释的策略是“等这次大重构一起收拾”。但大重构永远遥遥无期风险也高。注释微重构则像给老房子重新贴标签你不用拆承重墙只需要把墙上错误的门牌号换掉把模糊的提示条写清楚把重复的贴纸撕下来。单次成本低风险小收益却立刻能体现。我做微重构时给自己定了几条原则不改变代码逻辑不调整函数结构不重命名变量。不翻译注释除非客户或团队明确要求。不删除那些看起来“没用”但包含历史决策的信息。每一条改动都要能说清楚原因最好能逐条 review。有了这些边界才有资格谈“用 AI 批量做”。否则让模型自由发挥它很可能把注释和代码一起重构掉最后你拿到一份看起来更优雅、但没人敢合并的 diff。1.3 脚本和 IDE 为什么搞不定这个活如果你只是想统一注释前缀、检查 docstring 是否缺失工具已经做得不错了比如ruff的 pydocstyle 规则、Javadoc 的校验插件、各种格式化工具。但注释的语义问题工具完全无能为力。一个脚本可以检测出一行注释与上一行代码完全相同但它判断不了“注释写的是获取当前用户代码查的却是订单表”这种语境错位。这时候大模型就有天然优势它能理解代码语义能分辨注释是在解释“为什么”还是在复述“是什么”还能按照你给定的规范统一输出。但前提是你的 prompt 必须足够精确。这就引出了下一部分一个合格的注释微重构 prompt到底要包含哪些要素。2. 注释微重构 prompt 的五个关键要素2.1 角色设定告诉模型它是“注释医生”不是“代码架构师”很多人写 prompt 喜欢用“你是一个 AI 助手”这太模糊了。我会把角色定义成“注释维护工程师”并且加一句“你只负责注释质量无权修改代码”。角色的意义在于模型后续生成的文本风格和决策倾向会跟着角色走。当你强调“医生”而不是“外科医生”时模型会更倾向于保守治疗而不是给你动大手术。我常用的角色描述是你是注释维护工程师负责代码可读性治理。你的使命是让注释准确、简洁、可追溯同时绝不改变代码行为。这行字放在 prompt 最前面后面接任务要求比“帮我改一下注释”稳定得多。2.2 目标拆解把“微重构”变成五个可检查的动作“请优化注释”这种指令模型不知道该做到什么程度。我会拆成明确动作修正错别字、错误参数名和过时描述。统一注释位置和注释符号。补充缺失的关键上下文例如配置项的取值含义。删除与代码明显重复的“弱注释”。保留表达业务规则或历史决策的“强注释”。这些动作都是二元的模型容易执行你 review 时也有明确标准。微重构不是自由创作每一步都要有据可依。2.3 规范说明语言、格式、标签一个都不能少注释规范需要写清楚三件事语言、格式、标签风格。语言方面我默认要求“保留原注释语言”。如果你直接让模型“优化注释”它很可能把中文注释翻译成英文理由是“英文更专业”。这是模型默认倾向必须在 prompt 里强制纠正。格式方面要指定行内注释还是独立行注释、注释与代码之间留几个空格、是否有最大行长。例如 Python 的#注释和 docstring 风格YAML 的#注释统一放在键上方。这些规则要写具体模型才能稳定输出。标签方面最常见的是 TODO 和 FIXME。我会让模型把杂乱的“后面改”“这里可能要优化”统一成TODO(负责人): 事项然后把无法确认负责人的条目放到修订说明而不是直接在代码里捏造一个负责人。2.4 硬边界把“不许改代码”写进死规则这句话说几遍都不过分。模型对“优化”这件事有很强的冲动如果你只说“修改注释”它往往会顺手把变量名改了、把函数体简化了甚至调整空行。所以 prompt 里必须有单独的“禁止”段落明确列出禁止修改任何非注释的代码行。禁止重命名函数、变量、类、文件。禁止改变代码缩进、空行、换行。禁止删除无法确认意义的注释哪怕它看起来很啰嗦。禁止编造函数签名中不存在的参数或异常。这些约束不是为了让模型“不敢动”而是为了让你拿到结果后能用git diff快速确认代码部分没有任何改动。2.5 输出格式只有结构化才方便批量审查如果模型只输出“修改后的完整代码”你还需要逐行对比才知道它动了什么。但如果它输出“重构后的代码 变更列表 修订说明”你的 review 成本会指数级下降。我要求的输出格式固定为三段第一段处理后的完整代码要求“没有省略没有省略号”。第二段逐条变更列表写成位置 - 原注释 - 新注释 - 理由。第三段修订说明专门放那些“我拿不准但原文保留了”的内容并统一标记[存疑]。这个输出格式最大的好处是即使模型判断错了它也会把存疑内容暴露出来而不是偷偷摸摸写进代码里。3. 三个能直接套用的注释微重构 prompt 模板3.1 模板一Python 包和函数的 docstring 规范化场景你有一个老 Python 模块顶部没有模块 docstring函数注释散乱有的写在函数体外有的写在函数体内还有的干脆没有参数说明。你想把它整合成规范的 Google docstring。我用的 prompt 如下你是注释维护工程师。请对下面的 Python 代码做注释微重构。 任务 1. 为模块顶部补充一个 docstring概括模块用途。 2. 为每个函数补充或修正 docstring采用 Google docstring 风格。 3. docstring 中必须写清楚函数作用、参数、返回值如果代码中能看出可能抛出的异常也要写。 4. 函数内部的普通 # 注释只保留解释“为什么”的条目删除复述代码的弱注释。 5. 保留原注释语言默认不翻译。 禁止 1. 修改任何代码行包括函数名、变量名、空行、缩进、标点。 2. 编造代码中不存在的参数、类型或异常。 3. 输出时使用省略号必须给出完整代码。 输出 第一段重构后的完整代码。 第二段逐条变更列表。 第三段修订说明无法从代码确认的内容全部放在这里并标记[存疑]。配合的输入示例可以是# 获取用户 def get_user(uid, db): # 根据uid查用户表 result db.query(select * from user where id ?, uid) # 如果没有结果 if not result: # 返回空 return None return result[0]期望输出应该能生成类似这样的 docstring用户查询模块。 提供按 ID 获取用户信息的工具函数。 def get_user(uid, db): 根据用户 ID 查询用户记录。 Args: uid: 用户 ID。 db: 数据库连接对象。 Returns: 用户记录如果不存在则返回 None。 result db.query(select * from user where id ?, uid) if not result: return None return result[0]注意我特意没有要求模型补函数签名类型注解因为它无法可靠推断。如果团队用的是 NumPy docstring 风格把第一条里的“Google docstring 风格”替换掉即可其余逻辑不变。3.2 模板二老项目中文注释清洗与 TODO 标签统一场景老项目里中文注释风格混乱错别字多夹杂编码乱码还有大量“以后要改”“不知道为啥这里会这样”这类模糊句子。你希望保留中文修正表达并把 TODO 统一。这一版 prompt 我会加一个针对“历史信息”的保留条款你是注释维护工程师。请对下面的代码片段做注释微重构。 任务 1. 修正中文错别字和不通顺的句子保留原注释的中文表达。 2. 保留所有与业务规则、历史 Bug、决策原因相关的说明不要为了简洁而删除。 3. 将 TODO、FIXME、以后优化、这里可能要改 统一转换为 TODO(负责人): 说明 的格式。无法确定负责人的条目在修订说明中列出不写入代码。 4. 编码乱码如 ??、\ufffd如果上下文能推断出含义就修正不能推断则保留原样并标记[存疑]。 5. 删除明显的“读代码如读注释”的弱注释但删除行为必须写进变更列表。 禁止 1. 修改代码逻辑。 2. 将中文翻译成英文。 3. 删除带有“因为”“注意”“不要”“临时”等关键词的强注释。 输出 第一段重构后的完整代码。 第二段逐条变更列表。 第三段修订说明。输入示例def query_order(order_id, db): # 这里不能直接用 qryMap因为历史订单状态为 0 时 qryMap 查不到先按 uid 过滤 conditions {order_id: order_id} if order_id.startswith(H): conditions[status] 0 # TODO 后面优化成联合查询 # 获取??? rows db.find(order, conditions) return rows最终版会把“获取???”修成“获取订单记录”把 TODO 行转换为TODO: 之后优化成联合查询因为你没指定负责人模型会把它留在修订说明同时保留第一行那个长长的“为什么”注释因为它才是整个函数真正的灵魂。3.3 模板三YAML/配置文件的注释去重与补位场景配置文件的注释质量往往更差。很多人喜欢在字段旁边写行尾注释但行尾注释一旦多起来对齐就是灾难。还有些注释只是把字段名翻译了一遍比如port: 8080 # 端口没有任何信息增量。你希望统一为“键上方注释”删除重复注释并补充必要的取值范围或单位说明。我用的 YAML prompt你是配置文件注释编辑。请对下面的 YAML 内容做注释微重构。 任务 1. 不修改任何键名、键值、嵌套结构。 2. 将所有注释统一放在键的正上方一行不使用行尾注释。 3. 删除只是重复字段名的注释例如 port: 8080 # 端口。 4. 如果某个键明显是数值、布尔或枚举类型在注释里补充合法值或单位如果无法从当前内容推断不要编造在修订说明中标记[待确认]。 5. 保留所有与业务规则相关的注释例如“不能小于 30”“生产环境不要打开”等。 禁止 1. 改动 YAML 的缩进和引号。 2. 给布尔值编造默认值。 3. 在注释中出现任何疑似密钥或密码的信息。 输出 第一段重构后的完整 YAML。 第二段逐条变更列表。 第三段修订说明。输入示例server: # 端口 port: 8080 timeout: 30 # 超时时间 debug: false # 日志级别 log_level: info期望输出server: # 服务监听端口 port: 8080 # 请求超时时间秒 timeout: 30 # 是否开启调试输出合法值true/false debug: false # 日志级别合法值debug/info/warn/error log_level: info这个模板里timeout: 30 # 超时时间被移到了键上方并补了“秒”因为 30 这个数值从上下文看大概率是秒。但如果模型不确定它必须标记[待确认]不能直接写“秒”。这是防止幻觉的关键。三种模板覆盖了最常见的内联代码注释、历史注释和配置注释。下面进入我最想分享的部分这些 prompt 是怎么从“翻车”一步步调出来的。4. 实测调优从“AI 乱改代码”到“只动注释”4.1 第一次翻车它把代码也重写了最早一版 prompt 很简单我就写了句“请优化这两个函数的注释”。结果模型不仅整理了注释还把get_user改名成了fetch_user用列表推导式重写了db.query的返回处理甚至帮我加了个Optional类型标注。看起来确实更“现代”了但 git diff 里红绿一片代码行为虽然测试能过可我根本没法快速确认它对所有边界情况的处理没变。这次教训让我明白对于注释微重构模型的“积极性”必须被约束。光说“不要改代码”还不够要具体列出禁止重命名、禁止改缩进、禁止改空行、禁止改标点。因为模型对“优化”的理解是全面的它认为缩进和命名也是可优化对象。从那以后我把“禁止段”提到角色设定后面优先级仅次于任务。4.2 第二次翻车中文注释被翻译成了英文我第二次测试用了一个全中文注释的老模块。任务说明里写了“修正注释”结果模型把“获取用户信息”翻译成 “Fetch user info”把“如果不存在”翻译成 “Return None if not exists”。它认为这样更专业。但我所在团队的中文技术文档生态很稳定全切成英文既不必要也增加 review 成本。修复方式是加了一条显式规则保留原注释语言默认不翻译只有用户指令中出现“翻译”时才翻译。为什么必须这句话因为模型的默认行为是“应尽量使用英文技术写作”你不反向纠正它就会自由发挥。现在我把“默认保留原语言”作为所有注释类 prompt 的默认条款。4.3 第三次翻车注释里出现了签名里没有的参数有一次模型给get_user(uid, db)补 docstring写出了Raises: TypeError: 如果 uid 不是整数。函数体里根本没有类型判断这完全是它从常见编程经验里“脑补”出来的。对一个严格要求注释与代码一致的团队来说这比没有注释更危险因为假注释会误导后来者。解决办法有二。第一在禁止段里加“禁止编造代码中不存在的参数、类型和异常”。第二增加一个“修订说明”出口允许模型把不确定信息写在那里并标记[存疑]但不进入最终代码。这样既保留了模型的分析能力又守住了代码的干净程度。4.4 第四次翻车输出被省略没法 review文件一大模型就开始偷懒。我拿一个 500 行的模块去跑结果它输出到第 300 行附近给我写了一句“中间部分与原始代码一致省略”后面接最后几行。这种输出完全没法用因为我不可能再手动对一遍中间几百行是否有改动。我后来调整为两个方案。方案一是把大文件切成 80~150 行的小片段逐段跑每次都能拿到完整输出。方案二是让模型只输出git diff格式这样即使它处理长文件我也能通过 diff 一眼看出改了哪些行。但对很多不擅长生成精确 diff 的模型方案一更稳妥。我最终采用“分段输入 完整输出 变更列表”的组合。4.5 我最终在用的完整 prompt经过四轮翻车后我现在固定使用的版本是这样你是注释维护工程师负责代码可读性治理。你只修改注释与 docstring绝不修改任何代码。 任务 1. 修正注释中的错别字、错误参数名和过时描述。 2. 统一注释的位置、符号和风格具体规范由用户给定。 3. 删除与代码明显重复的弱注释。 4. 保留所有与业务规则、历史决策、风险提示相关的强注释。 5. 默认保留原注释语言不翻译除非用户明确要求。 6. 将 TODO/FIXME 统一为 TODO(负责人): 说明无法确认负责人时写入修订说明。 禁止 1. 修改任何代码包括函数名、变量名、缩进、空行、标点。 2. 删除无法确认意义的注释。 3. 编造不存在的参数、类型、异常或配置项。 4. 输出时省略代码必须逐字输出完整代码片段。 输出 第一段处理后的完整代码。 第二段逐条变更列表格式为 位置 - 原注释 - 新注释 - 理由。 第三段修订说明包含所有 [存疑] 或 [待确认] 的内容以及被删除弱注释的清单。这个版本的稳定度已经高了很多。我用它处理过 Python、Java、YAML、SQL 文件只要输入片段控制在合理长度返回结果基本可以做到“代码行零改动只动注释”。但这不意味着可以直接闭眼合并下一节要说的就是边界。5. 注释微重构的边界和人工复核清单5.1 prompt 无法判断“注释对不对”只能判断“注释和代码当不当”即使是最稳定的 prompt也只是让注释和代码在文本语义上尽量一致。它根本无法理解你的业务逻辑。比如有这么一行# 这里返回打折后的价格 return price * 1.2模型看不出“打折”和“乘以 1.2”哪个才是业务上的正确描述它只会觉得注释通顺、格式没问题。它甚至可能帮你把注释改成更通顺的“这里返回价格乘以 1.2”然后你以为原注释没问题实际上这个 bug 还是没被发现。所以注释微重构解决的是“注释可信度”问题不是“业务正确性”问题。业务校验必须靠代码审查和测试覆盖。5.2 哪些信息绝不能让它删掉模型为了追求简洁会倾向于删掉看起来“啰嗦”的注释。有几种注释在 prompt 里明文保护了我也会在人工复核时特别检查决策型注释例如“不能直接用 qryMap因为历史订单状态为 0 时查不到”。这类是灵魂删了代码就变成不可维护的黑盒。风险提示型注释例如“生产环境不要打开 debug”。这类关系到线上安全丢了会出事。历史 Bug 记录例如“修复 #123用户删除后 session 残留”。这类对后续排查问题极其重要。在每次合并前我会先看修订说明中被标记为“删除”的项目逐条确认是不是弱注释。如果发现有决策型注释被删我会手动把它补回去并调整 prompt让“保留强注释”的优先级更高。5.3 把团队规范写进 prompt而不是让 AI 自由发挥不同团队对注释的审美完全不同。有的要求函数必须有 docstring有的只要求复杂函数写有的喜欢行尾注释有的禁止行尾注释。不要拿通用 prompt 直接跑最好把你的团队注释规范压缩成十行以内粘贴到 prompt 的“规范说明”里。我自己的做法是维护了一份comment-style-guide.md每次用模板时把里面的关键词挑出来替换。比如团队规定行尾注释统一用两个空格分隔、独立注释必须有空行这些我都会写进 prompt 的规范段。点评时也更容易如果输出不符合团队规范不是模型问题是 prompt 没有把规范讲清楚。5.4 私有代码的脱敏与安全如果你用的是云端大模型在粘贴代码前要注意脱敏。密钥、数据库连接串、内网域名、真实手机号身份证号这些都要替换成 mock 值。尤其 YAML 配置文件经常藏着密码或 token我见过有人直接把password: xxxxxx发给模型这是非常危险的习惯。安全起见的做法包括移除安全字段。你也可以用本地模型处理敏感仓库速度和效果稍差但对隐私要求高的团队值得。脱敏的代码示例# 原始内容password: my_real_password # 替换为password: REDACTED等模型返回结果后再把占位符替换回真实值。5.5 一条长期有效的操作习惯最后分享一个我这半年坚持下来的习惯每次调优 prompt 后我会把“好用的版本”存成一个 Markdown 文件文件名就叫这个任务的名字里面包含 prompt、示例输入、期望输出和失败案例。时间久了注释微重构的 prompt 就变成了团队内部的规范类资产。新人接手老项目时直接拷走就能用不需要重新踩我踩过的坑。我自己再遇到烂注释从复制 prompt 到 review 完 diff通常不会超过十五分钟。这就是微重构的收益它不解决所有问题却能把最碍眼的注释债务一点点还掉。如果你也有一个注释烂到不想打开的项目不妨试试用这份 prompt 先跑一个小模块你可能会重新找回看代码的耐心。
返回列表