循环:意图 → 生成 → 审查 → 打磨
本书中的一切都回归到一个循环。把它内化。
循环会一直转,直到输出达到你的标准——而审查是它每次都必须穿过的关口:
┌──────────────────────────────────────────────┐
│ │
▼ │
┌────────┐ ┌──────────┐ ┌────────┐ ┌──────────┐
│ 意图 │ ─▶ │ 生成 │ ─▶ │ 审查 │ ─▶ │ 优化 │
│ 规格 │ │ (AI) │ │ 你 │ │ 你 │
└────────┘ └──────────┘ └───┬────┘ └──────────┘
│
通过? ▼
┌──────────┐
│ 交付 │
└──────────┘
- **意图。**陈述你想要什么以及关键的约束——输入、输出、边界情况、技术栈、风格。模糊的意图得到模糊的代码。
- **生成。**让模型写实现。别去手把手管语法;描述行为。
- **审查。**读返回的内容。它真的做到那件事了吗?它处理了空列表、null、失败的网络调用吗?它是能跑通的最简版本吗?
- **打磨。**指出哪里不对,给出具体的修正,然后重新生成。重复直到它达到你的标准。
大多数新手会跳过第 3 步。他们生成,它能跑,他们就继续往下走。然后它在生产环境里、在他们从未描述过的那个情况上崩掉了。审查这一步,正是工程发生的地方。
下面是这个循环里一个好的初始提示词长什么样:
写一个 TypeScript 函数 `parseDuration(input: string): number`,
把 "1h30m"、"45s"、"2d" 这样的字符串转换为总秒数。
要求:
- 支持单位: d (天), h (小时), m (分钟), s (秒).
- 多个单位可组合: "1h30m" = 5400.
- 对无效输入(空, 未知单位, 负数)抛出带清晰消息的
Error 予以拒绝。
- 不用外部库。包含覆盖边界情况的 5 个单元测试。
只展示函数和测试。
注意它的结构:一个精确的签名、明确的规则、点名列出的边界情况、陈述清楚的约束,以及对测试的要求。你不是在指望模型猜对——你是在消除那些会导致糟糕猜测的歧义。
打磨这一步和第一条提示词一样是门手艺。模糊的反馈得到模糊的修正。比较下面这两种修正:
差的: "这是错的,修一下"
好的: "parseDuration('1h30m') 返回 90 而不是 5400 —— 你把数字
相加了,却忽略了单位的倍率。在相加之前,把每个值乘以其
单位对应的秒数(d=86400, h=3600, m=60, s=1)。
另外为组合情况 '2d3h' 加一个测试。"
好的那条点名了症状、原因和修法。你是在像评审同事的 那样评审——而你指得越精确,花的回合就越少。每一圈循环都应当收敛。如果你发现自己在原地打转,那是个信号:你的意图说明不足。停止重新生成,改去重写规格。