
大多数开发者使用 AI 编码代理的方式是这样:打开聊天窗口,输入"帮设置页面加一个深色模式切换钮"之类的句子。代理会产生一些东西。大致能用。但边边角角还很粗糙。接下来二十分钟,开发者就在来回往返中把东西补起来。
然后他们就认定这个模型不怎么样。
模型没问题。问题出在提示词。
提示词里的每一个模糊之处,都是模型在没有你的情况下所做的决定。深色模式的偏好要不要跨会话保留?要不要尊重操作系统层面的设置?偏好要存在哪里,localStorage、数据库里的用户个人档案,还是 cookie?用的是哪个组件库,主题在里面是怎么运作的?
你没说。所以模型用猜的。有时猜对。更多时候不是。于是你得到一段在一个环境正常、换个环境就坏掉的代码,或是一个忽略用户既有偏好的组件。
这是信息的问题。
认真打造 AI 辅助开发流程的团队,摸索出来的结论是这样:对于把一件事做好需要什么,模型比大多数开发者更清楚该怎么问。
模型处理过数量庞大、规格清楚明确的工程任务。所以它知道一份完整的功能请求长什么样,也知道一份模糊的错误回报通常缺了什么。诀窍是,在你要求它做任何事之前,先让它告诉你缺了什么。
流程是这样:
最后一步可有可无,但值得做。你可以对代理说:"根据我的回答,把我的原始请求改写成一份完整的任务规格。"你拿回来的,是模型自己都认为够完整、足以执行好的提示词。再把这句提示词当成真正的任务交出去。
有些人开始把这叫做任务执行的反向提示词工程。你不是从零写出一份完美提示词,而是让模型浮现出一份完美提示词该包含什么,再从这里往下走。
假设你想在设置页面加一个深色模式切换钮。两种做法是怎么展开的。
天真的做法:
"帮设置页面加一个深色模式切换钮。"
代理产出一个写死的切换钮组件,把偏好存在组件状态里(刷新就消失),不接任何已有的主题系统,而且用的是内联样式,而不是你原本在用的 CSS 变量或主题 token。
接下来一小时你都在修。
反向提示词的做法:
你从同一句话开始,然后问:"开始之前,要把这个做对,你需要知道什么?我该厘清什么?"
代理会回你大概像这样的东西:
- 偏好该存在哪里(localStorage、数据库、cookie)?
- 有既有的主题系统吗(next-themes、CSS 变量、Tailwind 的 dark: 变体)?
- 这个切换钮要不要默认尊重用户的操作系统深色模式设置?
- 它在设置页面要放哪里?有没有既有的"外观"区块?
- 如果用户已登录,偏好要不要跨会话同步?
你回答这些问题。你告诉它,这个 app 用的是 next-themes,偏好会通过既有的 PATCH /users/me 端点存进用户的个人档案,而且设置页面已经有一个"外观"区块,里面的其他切换钮都遵循特定的组件模式。
现在代理有了它需要的东西。它产出的实现会接上正确的主题提供者、用既有的 API、配合既有的 UI 模式,也会处理操作系统偏好的回退。你什么都不用修。
错误回报是模糊提示词杀伤力最大的地方。因为一个上下文不足的模型,不只产出平庸的代码,还会产出自信满满、但其实写错的代码。
想象有人回报:"登录按钮有时没反应。"
天真的做法: 你把这句话贴进代理。它开始扫描认证代码,看到一个可疑的 async/await 模式,觉得大概就是这里,改写那个函数,然后开一个 PR。错误还在。它改的那个函数根本无关。
反向提示词的做法:
你把错误回报交给代理,然后问:"要把这个诊断好,你需要知道什么?资深工程师在碰任何代码之前,会先问哪些问题?"
它会这样回应:
- "没反应"是什么意思?按钮不响应点击、点击了但什么都没发生,还是跳出错误?
- 这能稳定重现,还是断断续续?有没有什么规律(特定浏览器、网络状况、用户状态)?
- 发生时有没有控制台错误,或失败的网络请求?
- 是哪个组件处理按钮点击,哪个服务处理认证?
- 这是原本就坏,还是最近才回归?如果是回归,改变了什么?
你回头找那位回报错误的人,拿到答案:这是断断续续的,只有用户待在页面超过十分钟之后才会发生,没有控制台错误,但网络请求完全没发出去。这下是完全不同的错误了。原因很可能是 token 过期,或是事件处理器里一个过时的闭包。
你把这些信息交给代理,它这次就会去对的地方。它找到一个 useCallback,依赖项过时,从初次渲染就抓着一个认证 token。修复就是一个锁定目标的小改动,没有其他伤及无辜。
多数 AI 辅助写代码会像一场谈判,让你在好几轮里来回打磨输出,原因就是最初的提示词把太多决定留给了模型。每一轮的修改,都是你在更正模型因为你没指定而做出的猜测。
反向提示词把这些轮次的大部分,收拢成开头的一场对话。模型的提问会精确告诉你,它本来会自己做出哪些决定。你来替它做这些决定。因为信息完整,输出第一次就对了。
还有一个附带的好处。模型问的那些问题,本身就是一份检查清单。如果你对类似的任务——像是加新的设置、修认证的错误、集成新的 API——持续使用同一套技巧,那些问题会慢慢变得眼熟。久了之后,不用人问,你自然会把这些细节写进提示词里,你基本的提示词质量就提高了。
这套技巧对有工具和文件访问能力的代理效果最好,像是 Cursor 或代理模式下的 GitHub Copilot。一个能读你代码库的代理,问的问题会比两眼一抹黑、凭空工作的代理具体得多。
两轮式的流程(你需要什么 -> 给你 -> 现在做任务)确实多了一步。对又小又明确的任务来说,这有点小题大做。但只要是会碰多个文件、要跟已有系统集成、或涉及不明显的设计决策的工作,它稳定比直接动手做实现出更好的结果。
第三步产出的那份规格值得留着。它是一份可以重复使用的模板。下次有人要加一个会存进用户个人档案的设置,你手上已经有一份规格清楚的提示词了。
大多数开发者对编码代理下提示词的方式,是以牺牲质量为代价来追求速度。一句话快速丢进去、一个平庸的输出丢回来,然后花十分钟清理,一天重复几十次。
反向提示词的做法把这个取舍倒过来。你在一开始多花一点时间,确保模型有它需要的东西。回报是,输出更接近你真正想要的,你花在修正上的时间也更少。
对一项任务来说最好的提示词,是模型告诉你它需要的那一份。
© Melvin Laplanche - All rights reserved.