
以下是大多数开发者使用 AI 编程智能体的方式:他们打开聊天窗口,输入类似“在设置页面添加一个暗色模式切换开关”的内容。智能体生成了一些东西。它似乎能用,但边缘有些粗糙。开发者接下来的二十分钟都在反复修补。
然后他们得出结论:这个模型不怎么样。
模型没问题。问题出在提示词上。
你提示词中的每一个模糊之处,都是模型在你缺席时替你做出的决定。暗色模式偏好应该在会话之间保持吗?它应该尊重操作系统级别的设置吗?这个偏好存储在何处 —— localStorage、数据库中的用户资料、还是 cookie?项目中使用了哪个组件库,它的主题系统是如何工作的?
你没说。所以模型只能猜测。有时它猜对了。但通常它会猜错,于是你得到的代码在某个环境中可用,在另一个环境中却会崩溃;或者生成了一个无视用户现有偏好的组件;亦或是一个完全不起作用的切换开关,因为它压根没有连接到正确的上下文中。
这不是模型质量的问题。这是信息缺失的问题。
真正有效的方法,也是那些构建严肃的 AI 辅助开发工作流的团队所发现的技巧是:对于如何出色地完成一项任务,模型比大多数开发者更清楚它需要什么信息,也更懂如何提问。
它处理过海量规格明确的工程任务。它知道一个完整的功能需求长什么样。它也知道一份模糊的错误报告通常遗漏了什么信息。这个诀窍就在于:在要求它执行任何操作之前,先让它告诉你缺了什么。
流程大致如下:
最后一个步骤是可选的,但非常强大。你可以问智能体:“基于我的回答,请将我最初的请求重写为一份完整的任务规范。”你得到的回复,将是模型自己认为足够完整、可以完美执行的一段提示词。然后,你再将这段提示词作为实际任务提交。
有人开始将这种方法称为面向任务执行的“逆向提示词工程(reverse prompt engineering)”—— 你不再是从零开始写出完美的提示词,而是利用模型来帮你揭示完美的提示词应该包含什么。
假设你想要在设置页面添加一个暗色模式切换开关。我们看看这两种方法的实际效果。
天真的方法:
“在设置页面添加一个暗色模式切换开关。”
智能体生成了一个带有写死逻辑的切换组件,将偏好状态保存在组件内部(一刷新就会丢失),没有将其连接到任何现有的主题系统,而且使用的是内联样式,而不是你已经在用的 CSS 变量或主题 token。
接下来的一个小时你都在修复它。
逆向提示词方法:
你以同样的一句话开头,然后问:“在你开始之前,若要妥善实现这个功能,你需要知道些什么?我该澄清哪些细节?”
智能体的回复大概会是:
- 这个偏好状态应该持久化存放在哪里(localStorage、数据库、还是 cookie)?
- 项目中有现成的主题系统吗(next-themes、CSS 变量、还是 Tailwind 的 dark: 变体)?
- 切换开关是否需要默认尊重用户操作系统级别的暗色模式偏好?
- 它应该放在设置页面的具体哪个位置 —— 当前有“外观(Appearance)”部分吗?
- 如果用户已登录,这个偏好是否应该跨会话同步?
你回答了这些问题。你告诉它应用使用了 next-themes,偏好设置通过现有的 PATCH /users/me 端点保存在用户资料中,而且设置页面已经有一个“外观”部分,里面有其他遵循特定组件模式的开关。
现在智能体掌握了必要的信息。它交出的实现正确连接了主题提供者,使用了现有的 API,匹配了当前的 UI 模式,并处理了操作系统的回退逻辑。你完全不需要修补任何东西。
产出质量的差距是显而易见的。
错误报告是模糊提示词造成最大破坏的地方。因为没有足够上下文的模型不仅会产生平庸的代码,更会自信地写出错误的代码。
想象有人提交了一个 bug:“登录按钮有时候点不了。”
天真的方法:
你把这句话粘贴给智能体。它开始扫描身份验证代码,发现了一个可疑的 async/await 模式,断定那就是问题所在,重写了函数并开启了一个 PR。结果 Bug 依旧存在,它改动的是一个毫不相干的函数。
逆向提示词方法:
你把错误报告交给智能体,并问它:“你需要知道什么才能进行有效的诊断?一个资深工程师在修改代码之前会问哪些问题?”
它回答:
- “点不了”是什么意思 —— 按钮对点击毫无反应、点击触发了但什么也没发生、还是显示了某个错误?
- 这个问题能稳定复现,还是间歇性的?是否有规律(特定的浏览器、网络状况、用户状态)?
- 发生问题时,控制台有报错或网络请求失败吗?
- 哪个组件处理按钮点击,哪个服务处理身份验证?
- 是一直都坏着,还是最近才出现的退化?如果是退化,最近改了什么?
你找到提 Bug 的人拿到了答案:是间歇性的,只有在用户在页面停留超过 10 分钟时才会发生,控制台没有报错,但网络请求压根没发出去。这完全是另一个 Bug 了 —— 很可能是 Token 过期问题,或是事件处理函数中出现了陈旧的闭包(stale closure),根本不是什么 async/await 问题。
你把这些信息给智能体,这次它找对了地方。它定位到了一个 useCallback,里面的陈旧依赖捕获了初始渲染时的认证 Token。一次精准的修复,没有引发任何附带损害。
大多数 AI 辅助编程之所以感觉像是在“谈判”—— 你来我往好几个回合不断打磨结果 —— 是因为初始提示词将太多决策权留给了模型。每一轮的修改,都是在纠正模型因为你的未曾说明而做出的随机猜测。
逆向提示词将这几轮较量压缩为一次前期对话。模型的提问精准地告诉你,它本应自行做决定的地方在哪里。而你代替它做出了决策。因为拥有了完整的信息,它第一次就能产出正确的结果。
还有一个额外的好处:模型问的问题就是一份检查清单。如果你经常把相同的技巧用于类似的任务 —— 添加新设置、修复认证 Bug、集成新 API —— 这些问题就会变得眼熟。久而久之,你就学会了在不用被问的情况下主动把细节放进提示词里,你的基准提示词质量也就随之提升了。
这一技巧在配合具有工具调用和文件访问权限的智能体(如 Cursor、Agent 模式下的 GitHub Copilot、Claude 或类似工具)时效果最佳。能阅读代码库的智能体会比“盲眼”工作的智能体提出具体得多的问题。
这套“来回”(你需要什么 → 给,这是你要的 → 现在去执行)的流程确实多了一步。对于微小、定义极度明确的任务来说也许是杀鸡用牛刀。但只要任务涉及到修改多个文件、与现有系统集成,或包含不明显的架构设计时,它所产生的结果一直都优于直接让模型写代码。
并且,第三步所生成的提示词规范是值得保存下来的。这是一个可高度复用的模板。下一次再有人需要“在用户个人资料中添加可保存的偏好设置”时,你手里已经有一份完美的任务提示词了。
大多数开发者给智能体写提示词的方式是“速度至上,牺牲质量”。随意扔一句短短的指令,收到一个马马虎虎的结果,然后花十分钟收尾擦屁股 —— 每天重复这么几十次。
逆向提示词法颠覆了这种权衡取舍。你多花一点点前期时间,确保模型拥有必要的弹药。作为回报,它的输出更为接近你的真实意图,你也省下了更多“修补”的时间。
某个任务最完美的提示词,绝不是你花 30 秒敲出来的那句话。而是模型亲口告诉你,它所需要的那段话。
© Melvin Laplanche - All rights reserved.