← 返回博客

提示词的质量直接决定代码的质量

对比含糊的提示词与精确、结构良好的提示词的插图

两个人给 AI Agent 的请求看起来是一样的,得到的结果质量却截然不同。这两个请求之间究竟有什么差别,又如何能在 AI 开始工作之前就看出来?答案是一条简单的规则:对请求的描述越好、越具体,AI 执行得就越好。这听起来显而易见,但在实践中它是导致糟糕结果的最常见原因:不是模型能力不足,而是请求描述不足。

糟糕的提示词:“修复登录 bug。” 好的提示词:“在 AuthService.login() 中,当用户输入带大写字母的电子邮件时会出错,数据库比较区分大小写。请修复,使电子邮件规范化发生在比较之前;不要改动密码哈希,也不要改动 LoginThrottle.ts 中的速率限制。”

第二个提示词包含了第一个所缺少的四个关键要素:

  1. 确切的位置(文件/函数),而不是笼统的描述。
  2. 对根本原因的描述,而不仅仅是症状。
  3. 确切要做什么,而不只是“修一下”。
  4. 什么不能被破坏,即对更改范围的明确边界。

没有第 4 点,AI 往往会“改进”你从未想让它动的东西,而这恰恰是下游逻辑被破坏的时刻。

这类似于向一个五岁的孩子解释该做什么。你会告诉他做什么、怎么做,但同样重要的是告诉他不要做什么。对孩子来说,这条界线主要是教育性的;对 AI 来说,它是对不得探索或修改之处的精确界定,而且这条界线对结果的提升,远胜于任何关于该找什么的描述。

同样的逻辑适用于单个提示词内部:如果把几个互不相关的需求一股脑塞进去,AI 就不知道哪个优先,常常会以与你的本意不同的方式理解任务。因此有一条简单的规则:一个提示词 = 一件具体的事。

这一点对手写提示词和自动生成的 Task 同样适用。而这种纪律恰恰是可以自动化的:让提示词不再来自某个人碰巧记得的内容,而是来自 AITM 替你维护的、对代码真实且最新的认知(Contracts、DOM 地图、业务逻辑)。

在查看提示词结构本身之前,还有一点值得了解:AITM 并不是以同样的方式撰写每个 Task 提示词。创建 Task 时,它会先将自身归入(或由你选择)三个类别之一:bug(修复现有行为)、enhancement(改进已有的东西)或 feature(全新功能),每个类别会生成不同的需求和验证标准。现在,我们先关注这三种类型共有的部分:固定的五块结构。

AITM 实际是怎么做的:真实的提示词结构

AITM 不会随意撰写 Task 提示词。每个由 Chat 或 Brainstorm 生成的 Task 提示词都由 5 个固定的块按以下顺序组成,每个块解决一个否则会导致任务不清晰的具体问题:

  1. Role:最多 3 句话,描述 Agent 应当扮演什么角色以及采取多保守的方式。没有这个块,Agent 不知道自己被允许有多少“创造力”,而没有护栏的创造力恰恰会导致不想要的更改。
  2. Context:这个 Task 为何存在:用户的报告、问题的来龙去脉、该领域归谁负责。它以这句话与其他部分隔开:“Context (background only — implement nothing from this block)”,因为没有这句话,Agent 就有可能不小心去实现背景故事中的某些内容,而不是专注于需求本身。
  3. Requirements:每条需求一个带编号的块,每个都有精确、可验证的验收标准。将需求拆分成带编号的块,直接解决了上文讨论的问题:一个块,一件具体的事,不会把几条需求混在一句话里。
  4. Scope:三行:In scope(可以更改什么)、Out of scope(不得更改什么,以及归谁负责)、Must not break(哪些 Contracts 必须继续成立)。这是对“也要告诉 AI 不要做什么”这一规则的直接落实,没有这个块,Agent 就不知道其更改的边界在哪里。
  5. 输出与验证:该 Task 创建的每个新文件,以及仅限于这次具体更改可能破坏之处的具体 verify 命令。这样,Task 不是以“看起来完成了”结束,而是以可衡量的“这条确切的命令通过了”结束。

请留意诸如 %AUTH-012 这样的 Contract 引用,它是对某个特定 Contract 的引用,以 AITM 能识别的确切语法插入,并被自动展开为完整的行为描述。这正是“自己写提示词”与一个为你强制执行精确结构和引用的系统之间的区别。

Contract 究竟包含什么。在 AITM 中,Contract 是项目 SQLite 数据库中的一条记录,而不是代码注释。它有一个简短的 ID(模块前缀加一个数字)、一个模块(该行为属于系统的哪个部分),最重要的是一个 behavior 字段,即对机制的精确的、多句话的描述,通常会引用文件中的具体行以及该行为起源的 Task 编号。它还带有该 Contract 所涉及文件的列表,可选的 danger zone,以及与之相关的变量列表。当 Agent 在提示词中看到“Must not break”引用时,AITM 会插入这整段描述,而不是光秃秃的代码,这样 Agent 就确切知道自己不得违反哪些行为。

那么单元测试呢?它们也有自己的代码:AITM 测试中的每个测试块在其描述开头都带有一个唯一的标签。这使你可以像引用 Contract 一样精确地定位某个具体测试。Contract 还会与测试文件的路径配对,因此一个 Contract 引用最终携带的不仅是行为描述,还有指向守护它的测试的直接链接。