
以下是大多數開發者使用 AI 程式碼代理 (AI coding agent) 的方式:他們打開聊天視窗,輸入類似「在設定頁面新增一個深色模式切換開關」的內容。代理生成了一些東西。它似乎能用,但邊緣有些粗糙。開發者接下來的二十分鐘都在反覆修補。
然後他們得出結論:這個模型不怎麼樣。
模型沒問題。問題出在提示詞 (prompt) 身上。
提示詞中的每一個模糊不清之處,都是模型在你缺席時替你做出的決定。深色模式偏好應該在工作階段之間保留嗎?它應該尊重作業系統層級的設定嗎?這個偏好儲存在何處——localStorage、資料庫中的使用者設定檔,還是 cookie?專案中使用了哪個元件庫,它的主題系統是如何運作的?
你沒說。所以模型只能猜測。有時候它猜對了。但通常它會猜錯,於是你得到的程式碼在某個環境中可用,在另一個環境中卻會崩潰;或是生成了一個無視使用者現有偏好的元件;亦或是一個完全不起作用的切換開關,因為它壓根沒有連接到正確的上下文中。
這不是模型品質的問題。這是資訊缺失的問題。
真正有效的方法,也是那些建構嚴謹 AI 輔助開發工作流的團隊所發現的技巧是:對於如何出色地完成一項任務,模型比大多數開發者更清楚它需要什麼資訊,也更懂如何提問。
它處理過海量規格明確的工程任務。它知道一個完整的功能需求長什麼樣。它也知道一份模糊的錯誤報告通常遺漏了什麼資訊。這個訣竅就在於:在要求它執行任何操作之前,先讓它告訴你缺了什麼。
流程大致如下:
最後一個步驟是選擇性的,但非常強大。你可以問代理:「基於我的回答,請將我最初的請求重寫為一份完整的任務規範。」你得到的答覆,將是模型自己認為足夠完整、可以完美執行的一段提示詞。然後,你再將這段提示詞作為實際任務提交。
有人開始將這種方法稱為面向任務執行的「逆向提示詞工程 (reverse prompt engineering)」——你不再是從零開始寫出完美的提示詞,而是利用模型來幫你揭示完美的提示詞應該包含什麼。
假設你想要在設定頁面新增一個深色模式切換開關。我們看看這兩種方法的實際效果。
天真的方法:
「在設定頁面新增一個深色模式切換開關。」
代理生成了一個帶有寫死邏輯的切換元件,將偏好狀態保存在元件內部(一重新整理就會遺失),沒有將其連接到任何現有的主題系統,而且使用的是行內樣式 (inline styles),而不是你已經在用的 CSS 變數或主題 token。
接下來的一個小時你都在修復它。
逆向提示詞方法:
你以同樣的一句話開頭,然後問:「在你開始之前,若要妥善實作這個功能,你需要知道些什麼?我該釐清哪些細節?」
代理的答覆大概會是:
- 這個偏好狀態應該持久化存放在哪裡(localStorage、資料庫,還是 cookie)?
- 專案中有現成的主題系統嗎(next-themes、CSS 變數,還是 Tailwind 的 dark: 變體)?
- 切換開關是否需要預設尊重使用者作業系統層級的深色模式偏好?
- 它應該放在設定頁面的具體哪個位置——目前有「外觀 (Appearance)」區塊嗎?
- 如果使用者已登入,這個偏好是否應該跨工作階段 (session) 同步?
你回答了這些問題。你告訴它應用程式使用了 next-themes,偏好設定透過現有的 PATCH /users/me 端點儲存在使用者設定檔中,而且設定頁面已經有一個「外觀」區塊,裡面有其他遵循特定元件模式的開關。
現在代理掌握了必要的資訊。它交出的實作正確連接了主題提供者,使用了現有的 API,匹配了當前的 UI 模式,並處理了作業系統的退路邏輯 (fallback)。你完全不需要修補任何東西。
產出品質的落差是顯而易見的。
錯誤報告是模糊提示詞造成最大破壞的地方。因為沒有足夠上下文的模型不僅會產生平庸的程式碼,更會自信地寫出錯誤的程式碼。
想像有人提交了一個 bug:「登入按鈕有時候點不了。」
天真的方法:
你把這句話貼給代理。它開始掃描身分驗證程式碼,發現了一個可疑的 async/await 模式,斷定那就是問題所在,重寫了函式並開啟了一個 PR。結果 Bug 依舊存在,它改動的是一個毫不相干的函式。
逆向提示詞方法:
你把錯誤報告交給代理,並問它:「你需要知道什麼才能進行有效的診斷?一個資深工程師在修改程式碼之前會問哪些問題?」
它回答:
- 「點不了」是什麼意思——按鈕對點擊毫無反應、點擊觸發了但什麼也沒發生,還是顯示了某個錯誤?
- 這個問題能穩定重現,還是間歇性的?是否有規律(特定的瀏覽器、網路狀況、使用者狀態)?
- 發生問題時,主控台 (console) 有報錯或網路請求失敗嗎?
- 哪個元件負責處理按鈕點擊,哪個服務處理身分驗證?
- 是一直都壞著,還是最近才出現的退化 (regression)?如果是退化,最近改了什麼?
你找到提 Bug 的人拿到了答案:是間歇性的,只有在使用者在頁面停留超過 10 分鐘時才會發生,主控台沒有報錯,但網路請求壓根沒發出去。這完全是另外一個 Bug 了——很可能是 Token 過期問題,或是事件處理函式中出現了過時的閉包 (stale closure),根本不是什麼 async/await 問題。
你把這些資訊給代理,這次它找對了地方。它定位到了一個 useCallback,裡面的過時依賴項捕捉了初始渲染時的認證 Token。一次精準的修復,沒有引發任何附帶損害。
大多數 AI 輔助程式設計之所以感覺像是在「談判」——你來我往好幾個回合不斷打磨結果——是因為初始提示詞將太多決策權留給了模型。每一輪的修改,都是在糾正模型因為你的未曾說明而做出的隨機猜測。
逆向提示詞將這幾輪較量壓縮為一次前期對話。模型的提問精準地告訴你,它本應自行做決定的地方在哪裡。而你代替它做出了決策。因為擁有了完整的資訊,它第一次就能產出正確的結果。
還有一個額外的好處:模型問的問題就是一份檢查清單。如果你經常把相同的技巧用於類似的任務——新增設定、修復驗證 Bug、整合新 API——這些問題就會變得眼熟。久而久之,你就學會了在不用被問的情況下主動把細節放進提示詞裡,你的基準提示詞品質也就隨之提升了。
這一技巧在配合具有工具呼叫和檔案存取權限的代理(如 Cursor、Agent 模式下的 GitHub Copilot、Claude 或類似工具)時效果最佳。能閱讀程式碼庫的代理會比「盲眼」工作的代理提出具體得多的問題。
這套「來回」(你需要什麼 → 給,這是你要的 → 現在去執行)的流程確實多了一步。對於微小、定義極度明確的任務來說也許是殺雞用牛刀。但只要任務涉及到修改多個檔案、與現有系統整合,或包含不明顯的架構設計時,它所產生的結果一直都優於直接讓模型寫程式碼。
並且,第三步所生成的提示詞規範是值得保存下來的。這是一個可高度重複使用的模板。下一次再有人需要「在使用者個人資料中新增可保存的偏好設定」時,你手裡已經有一份完美的任務提示詞了。
大多數開發者給代理寫提示詞的方式是「速度至上,犧牲品質」。隨意丟一句短短的指令,收到一個馬馬虎虎的結果,然後花十分鐘收尾擦屁股——每天重複這麼幾十次。
逆向提示詞法顛覆了這種取捨。你多花一點點前期時間,確保模型擁有必要的彈藥。作為回報,它的輸出更為接近你的真實意圖,你也省下了更多「修補」的時間。
某個任務最完美的提示詞,絕不是你花 30 秒敲出來的那句話。而是模型親口告訴你,它所需要的那段話。
© Melvin Laplanche - All rights reserved.