從網頁對話到 coding agent第 3 篇,共 9 篇

寫 prompt 與選模型

指令怎麼寫、模型怎麼選,決定結果與用量。

發佈於

模型愈來愈強,以往須用上許多技巧才做得好的事,如今一句話便能做到,許多人也因此不再重視下指令的方式。指令寫得粗略仍做得成,是因為模型力大磚飛;但模型的進步同時提高了下限與上限,需求寫得愈準確,結果才愈接近上限。

Prompt 技巧與協作的做法

Prompt 是使用者送給 LLM 的那段文字。許多人給的資訊常常不夠,現在的 agent 雖然會盡量從專案的內容推測使用者的意圖,但推測既浪費 token 與時間,也仍會出錯,如果它沒有先向使用者確認就照著推測做下去,浪費更大。

Anthropic 與 OpenAI 各有寫給開發者與使用者的指南,說明如何替自家的模型與 agent 寫 prompt:

以下各項多出自這幾份指南與幾份研究,出處隨文註明,並改以資料分析的情境說明,大致依重要程度排列。

網路上流傳的技巧有兩類本篇不收。一類是給小費、威脅、刻意客氣與全大寫的加重語氣,不收的原因是沒有可靠的效果:前三者經 Wharton 的實測(客氣、小費與威脅),整體都沒有可靠的效果,個別題目時好時壞,事先無法得知;全大寫的加重語氣,Anthropic 的指南也建議改回平常的說法。

另一類是要它「一步一步想」,不收的原因是模型已內建這個做法。這個做法稱為 chain of thought(CoT),早期的模型須在 prompt 裡要求先推理再作答,正確率才會提高。其後的模型已將這個做法學了進去,許多更內建了思考模式,回答之前本來就會先推理,等於每一則 prompt 都已帶著這句話,再寫一次只是重複;推理多少則由 effort 決定,見「模型規模與 effort」一節。Wharton 的實測也發現,在這類模型上加這句話,正確率幾乎沒有提高,卻明顯更慢、更耗 token。

寫明要什麼樣的產出

兩家的指南都指出模型有自己偏好的回覆樣式,如果不指定,得到的往往是冗長且滿是條列的回答;格式、長度、文體都應直接交代。

比較這兩個模型的配適結果。用一張表列出 AIC、BIC 與殘差標準差,
表後以一段文字說明選哪一個以及理由,不超過 150 字,不要用條列。

寫明怎樣算完成

Anthropic 的指南指出,agent 做到看起來完成便會停下,如果沒有可以執行的檢查,「看起來完成」是它唯一的依據,驗收便全落在使用者身上。因此 prompt 裡須給它一個對照,且應是使用者已經知道、與 agent 無關的事實,例如資料的列數、某一欄的總和、手算過的一個例子:

合併之後的資料應該仍是 4,812 列,每個 id 只出現一次。
改完執行一次,把列數與重複的 id 數印出來給我看。

寫明做到哪一步

兩家的指南都以「可以幫我……嗎」這類問句為例,說明模型可能將其理解為徵詢意見而只給建議,也可能理解為授權而直接動手,兩家模型的傾向不同,同一家的新舊模型也不同。因此與其依賴模型猜測,不如直接寫明是要建議還是要改動,以及改動的範圍。

這份清理腳本有哪些地方可能誤刪資料?只提出建議,不要修改檔案。
直接修改 clean.R:把欄位名稱統一成小寫加底線。只改欄位名稱,
其他邏輯不要動,改完執行一次確認沒有錯誤。

以 @ 指明檔案

在輸入框鍵入 @ 再接檔名,即可將該檔案加入對話,agent 會先讀過再回答,不必自己搜尋,也不會找錯;Codex 可將檔案拖入輸入框,或同樣以 @ 加檔名指明。

@R/clean.R 執行之後為什麼少了三百多列?

請 agent 先問

Agent 遇到沒說清楚之處,多半自行假設後直接動手;研究指出 agent 不易分辨一份 prompt 是否說得夠清楚,而讓它發問之後,表現明顯提高(Vijayvargiya 等,2025)。因此要不要先問,需要由使用者明說。當需求連自己也說不清楚時,可以請它反過來訪問:

我想比較三個學院的畢業起薪,但還沒想清楚怎麼做。動手之前先訪問我,
一次問一個問題,顯而易見的不必問,問我可能沒想到的地方。
問完把做法寫成 docs/plan.md,先不要執行。

需求已大致清楚時,只需加一句「動手之前,先列出你打算自行決定的事項」。

走偏時立刻打斷

不必等 agent 做完。Claude 桌面 app 可按停止鈕中斷,也可以不中斷,直接鍵入更正並送出,agent 做完手上這一步便會讀到,再調整下一步;Codex 同樣可在執行中補上訊息。

糾正兩次仍不對便重開

Anthropic 的指南建議,同一個問題糾正超過兩次便開新對話。原因在於失敗的嘗試與當時的推理都還留在對話裡,而 LLM 是接著既有的文字往下寫,讀到這些內容,便傾向於沿著原來的思路再試一次,糾正得愈多,堆著的錯誤做法也愈多。一份模擬實驗也發現,LLM 在對話中一旦走錯便不易回頭,同樣的資訊分多次給,表現平均比一次給完低了近四成(Laban 等,2025)。重開時把先前學到的寫進第一則 prompt,一次說完:

把 survey.csv 的日期欄統一成 YYYY-MM-DD。這一欄混有民國年(如 112/3/5)與西元年,
直接用 as.Date() 會把民國年變成缺失值,不要這樣做。

我個人重開時,也會一併換成更大一級的模型,因為做不對的原因也可能是這件事超出了目前模型的能力,分級見「模型規模與 effort」一節。

另開新對話審查

Agent 改完之後,另開一個新對話審查,不要在原對話裡請它自己檢查,原因與「糾正兩次仍不對便重開」一項相同。這就像剛寫完報告的人自己校稿,讀到的是心裡想寫的意思,不是紙上實際寫的字,換一位同學來看,才看得出哪裡漏了。新的對話沒有先前的推理,只看得到資料夾裡的檔案,處境與那位同學相同。Anthropic 的指南即指出,新的 context 有助於審查,因為 Claude 不會偏袒自己剛寫的 code;研究也發現,沒有外部的回饋時,LLM 自行修正答案反而可能愈改愈差(Huang 等,2024)。

在 Claude 桌面 app 裡點選側邊欄的 New session(Windows 上也可按 Ctrl+N),選取同一個資料夾,交代它要檢查什麼。審查時常會換用較大的模型或調高 effort,因為找錯比照著做更需要推理,而審查只讀不改,來回的次數少,多耗的用量有限;兩者的選擇見「模型規模與 effort」一節。一次只交代一個角度,並寫明要看哪些檔案、找哪一類問題:

這個資料夾裡有一份已完成的分析。只檢查資料處理:讀 clean.R 與它輸出的 CSV,
列出哪些列被刪除或改動、依據是什麼、有沒有刪錯的可能。模型與結論先不要看。
不要修改任何檔案,只列出問題與對應的檔案位置。

模型設定、結論與數字是否相符,可以同樣的方式各查一次。

審查者列出的問題同樣是 LLM 的輸出,也可能有誤;被要求找問題時,即使成果沒有問題,它通常也會找出幾條。因此其作用是指出該看哪裡,不必每條都改,判斷仍由使用者自己決定。

指定角度與讀者,不指定角色

審查時交代的角度指的是要檢查什麼,不是要它扮演誰;「你是資深統計學家」這類開頭,已有研究指出對答題的準確率沒有幫助,有時反而更低(Basil 等,2025;Zheng 等,2023),Anthropic 的說明也已改為直接寫明要哪個視角,往往比指定角色有效。

指定讀者則是另一回事。本系列撰寫時,便經常請 Claude 以沒有 CS 背景的讀者的立場讀一遍草稿,列出看不懂或有疑問之處。這是在交代要檢查什麼,即哪些詞沒有解釋、哪一步跳得太快,並不是指望它換了身分便答得更準。

讀 posts/plain-text-workflow.md。假設讀者是沒有 CS 背景的統計系學生,
列出他會看不懂的詞、沒有解釋就用上的概念,以及前後接不上的地方,各自註明行數。
不要修改檔案。

中立提問與反向再問

使用者說得愈肯定,LLM 愈傾向附和(Bhalla 與 Gligorić,2026),「這個結果很顯著對吧」得到的多半是同意。同一份研究發現,只加一句「不要附和我」效果有限,有時適得其反,較可靠的是請它把正反兩面都說出來:

收入與年資的關係用線性模型是否合適?分別列出合適與不合適的證據,
各自引用 output 資料夾裡的數字,最後才給判斷。

重要的結論可以再從相反的方向問一次。另開一個新對話,把問法反過來:

有人認為這份資料不適合用線性模型。請找出支持這個看法的證據,
引用 output 資料夾裡的數字。

兩次的回答如果各自順著問法說,表示它只是在附和,結論還不能採信;兩次都指向同一處,才較可靠。

進度寫成檔案

每個新對話都由空白開始,自動帶過去的只有規範檔與 agent 自己寫成檔案的記憶(見「Context window」一節),而記憶存不存、存什麼由 agent 決定,Codex 更是預設關閉,不能指望。一件事一次做不完時,結束前請它寫一份交接筆記,下一次對話先讀這一份:

把目前的進度寫成 docs/progress.md:目標、已完成的部分、已排除的做法與原因、
下一步要做什麼。

本系列也是這樣寫成的:各篇的排序與未決事項記在一個檔案,各篇讀完能做到的事記在另一個,查證過的事實與來源又另存,每次開新對話,agent 先讀這幾份,便知道寫到哪裡、哪些事已有定論。

規矩附上理由

Anthropic 的指南舉的例子是「絕不使用刪節號」不如寫成「回覆將由語音合成軟體朗讀,它不會唸刪節號,因此不要使用」,模型知道理由之後,沒被列出的情形也能自行推斷。資料分析裡也一樣:

不要刪除含缺失值的列。這份資料的缺失與收入有關,之後要比較幾種處理方式的差別。

只寫前半句,agent 會照辦,但不會留意 lm() 預設就略去含缺失值的列;知道了理由,它較可能主動指出這一點。

附上範例

Anthropic 的指南指出範例是引導輸出的格式、語氣與結構最可靠的方式之一,並建議範例貼近實際用途、彼此有所變化,以免模型把無關的共同點也學了去,數量建議三至五個,並以 <example> 與 </example> 這一對標籤包起來,標籤標出範例的起訖,模型便分得出哪一段是範例、哪一段是 prompt 本身。要求 agent 依某種樣式寫東西時,與其描述樣式,不如直接給它看,此處為省篇幅只列一個:

替 R/ 資料夾裡的每個函數補上說明註解,格式照下面的範例:
<example>
# 計算各組的平均數與標準誤
# 輸入:df,資料框;group,分組欄位的名稱;value,數值欄位的名稱
# 輸出:資料框,每組一列,含 mean 與 se 兩欄
</example>

專案裡如果已有滿意的成品,例如一張調整好的圖,直接指明檔案請它照做,同樣是範例。

請 agent 說明改動

Agent 改完之後顯示的是逐行的對照,不熟悉 code 的人未必看得懂;請它以白話逐項說明改了哪裡、為什麼改、哪一項會影響結果,既便於驗收,也是學習的機會。說明同樣是 LLM 生成的文字,須與對照互相核對。

用白話逐項說明這次改了哪些地方、各自的原因,以及哪一項會改變分析的結果。

告知自己的改動

使用者如果手動改了檔案,或退回了 agent 的某一處修改,下一則 prompt 須說一聲,否則它可能依對話裡的舊印象再改一次,把使用者的改動蓋掉。

我把 plot_trend.R 的配色改回原來的了,之後不要再動配色。

將互不相干的工作分給 subagent

Agent 在對話中可以另外啟動一個 agent,稱為 subagent。它有自己的 context window,過程都留在那裡,做完後只把結論交回主對話(Claude、Codex)。適合交給它的是彼此不相干、過程又冗長的工作,例如翻遍數十個檔案才能回答的問題、由幾個方向尋找論文、重新執行全部腳本並讀完整份輸出。Subagent 可以同時啟動數個,各做一個方向,主對話只多出幾段結論。

Claude 會依任務自行決定是否啟動 subagent,使用者不必開口;桌面 app 的 tasks 窗格會列出執行中的 subagent,點選即可查看它的輸出或將它停止。Codex 則須在 prompt 裡明說才會啟動。兩者都可以直接指名,並寫明各做什麼、回報什麼:

啟動三個 subagent,各查一個方向的文獻:這個方法的原始論文、近五年比較各種做法的研究、
公開的實作。每個回報五篇以內,附標題、年份、連結與一句摘要,找不到便說找不到。

文獻同樣可能是編造的,連結須自己點開確認。驗證也是同樣的寫法,例如改完 code 之後,請一個 subagent 重新執行全部腳本,比對輸出與改動之前是否相同,只回報不同之處。

Subagent 讀到的 prompt 是主對話的 agent 依使用者的話另寫的,並非原文,細節可能在轉述時遺漏。條件較多時,可要求將 prompt 原樣轉交,不要改寫。

每個 subagent 的用量都與主對話計入同一個額度,同時啟動數個,消耗便隨個數增加;交回的結論也仍佔主對話的 context window。因此只讀兩三個檔案、搜尋一兩次的事不值得另起。Anthropic 的指南也提到,較新的模型有過度使用 subagent 的傾向;見到 agent 為小事啟動 subagent 時,可在 prompt 裡寫明直接做。

分出去的工作應以讀檔、搜尋、執行為主。須修改檔案時,寫明各自改哪些檔案,彼此不要重疊;同時開著兩個對話時,也只讓其中一個修改檔案。

請 agent 代寫 prompt

Prompt 也可以請它代寫。把零散的想法、要求與先前試過不行的做法一併交給 agent,請它整理成一份完整的 prompt,自己看過、改過,再拿到新對話使用。OpenAI 的指南稱此為 meta-prompting,並提醒它補不了缺少的資料,也替代不了先想清楚要什麼。

把這次對話裡我提過的要求、已確定的做法與試過不行的做法,
整理成一份給新對話用的 prompt,存成 docs/prompt.md。不確定我要什麼的地方先問我。

反覆使用的 prompt 存成檔案,便是規範檔與 skill 的由來。規範檔與 skill一篇的規範檔即由 agent 起草,不少 skill 也是這樣寫成的,Anthropic 並提供專門代寫 skill 的工具。

模型規模與 effort

兩家都將模型依規模分檔,大致可排成最大、大、中、小四檔,愈大者推理能力愈強,同時也愈慢、消耗的用量愈多。其中 Codex 目前只有三個型號,中間一檔從缺。下表為 2026-10-08 查證的結果,型號更替很快,請以官方頁面為準(Claude、Codex)。

Claude官方定位Codex官方定位
最大Fable 5.1最困難、耗時最長的任務Astra最強,用於複雜的工作
大Opus 5.5複雜的推理GPT-6.1 Sol接近 Astra,成本較低
中Sonnet 5.5日常工作
小Haiku 5.5簡單的任務,最快GPT-6 Luna最省,用於範圍明確的大量工作

切換模型的位置,Claude 桌面 app 是送出按鈕旁的下拉選單,對話中途也可更換;ChatGPT 桌面 app 則是對話框下方的模型切換器。

Effort 是另一個獨立的旋鈕,決定同一個模型在回答前花多少工夫推理。Claude 分為 low、medium、high、xhigh、max 五級,Opus 5.5、Sonnet 5.5 與 Haiku 5.5 的預設都是 medium;Codex 則由 Light 起,經 Medium、High、Extra High、Max 至 Ultra。Codex 的 effort 與模型在同一個切換器裡調整。

模型與 effort 都不是愈大愈好。較大的模型與較高的 effort 會多讀檔案、多做檢查,對於改一個圖例、重新命名幾個欄位這類範圍明確的小事,只是更慢、更耗用量,結果沒有分別;Anthropic 的文件也提到,Opus 5.5 在 medium 的表現已相當於前一代在 high 的表現,建議由 medium 開始。本系列的建議是日常維持預設,遇到以下情形才調高,即 agent 在同一個問題上反覆修改仍未解決,或任務須同時顧及多個檔案與多項條件,例如將整個專案的 code 重新分檔整理。反之,只是請它解釋一段 code 或做機械式的改寫,可以換成較小的模型。

Prompt 的由來與別名

「基本原理」一節已說明,LLM 所做的事是讀進一段文字,再接著往下寫,讀進去的這段文字便稱為 prompt。Prompt 在英文裡是提詞的意思,劇場裡替忘詞的演員提一句開頭,演員便能接著演下去。LLM 最初的用法正是如此,使用者寫下一段開頭,由它續寫或補完。對話是其後才有的形態,做法是將雙方說過的話排成一份標明誰說了什麼的紀錄,交給 LLM 續寫下一句回答,本質上仍是續寫,prompt 一詞也就沿用了下來。

CS 習慣替同一件事取好幾個名字,prompt 尤其如此,同一份文件裡前後換用兩三個詞也很常見。讀官方文件與網路文章時會遇到的叫法,依所指的東西整理如下:

  • 使用者送出的那段話:prompt、user message,中文有提示詞、指令、指示,指的都是同一件事。
  • 框架先寫上的那一段:system prompt、instructions,ChatGPT 與 Codex 的 custom instructions 也屬此類。Anthropic 的文件多稱 system prompt,OpenAI 的文件則寫 instructions。
  • 寫 prompt 這件事:prompt engineering(提示工程)。
  • LLM 每次讀進的全部文字:context,即「Context window」一節所說白板上的所有內容。

Prompt 一詞本身也有兩種用法,狹義只指使用者送出的那段話,廣義則連框架先寫上的部分一併算入,讀到時須依上下文判斷;本篇寫 prompt 時指的是狹義。