[RSCH] 13 分鐘閱讀OraCore 編輯部

Prompt 工程把 codegen 變成可重複流程

我拆解一篇 prompt engineering for code generation 的系統性回顧,整理成開發者可直接套用的固定 prompt 流程與模板。

分享 LinkedIn
Prompt 工程把 codegen 變成可重複流程

以前我靠靈感叫模型寫 code,現在我改用固定 prompt 流程,輸出才開始穩。

我用 LLM 寫 code 已經夠久了,久到一看輸出就知道它又在唬爛。速度很快,Demo 也很漂亮,第一版常常看起來能交差。但一進真實 codebase 就露餡:需求講得不清、邊界條件漏掉、測試沒補、還會一本正經地附和我那個其實很爛的想法。這種東西不是幫手,頂多算是更會說話的 autocomplete。

我想要的是能在專案裡真的信得過的方法。不是什麼神奇咒語,也不是今天有用、明天失靈的一句 prompt。我想要的是一套可以重複、可以檢查、可以交給團隊一起用的寫法。這篇 review 就是因為這個痛點被我翻出來。它不是在賣夢,它是在整理:到底哪些 prompt 寫法真的有助於 code generation,哪些只是大家嘴上講得很順。

觸發我拆這份觀點的來源,是 Erika Camacho、Yazmin Gutierrez、Cesar Pardo 的系統性回顧,發在 Inteligencia Artificial,DOI 是 10.4114/intartif.vol29iss78pp21-58。他們整理了 26 篇 primary studies,切成六個主題。這種東西我比較吃得下,因為我不缺又一篇「prompt 很重要」的廢話,我缺的是能直接搬去用的地圖。

別把 prompt 當成聊天語氣

訂閱 AI 趨勢週報

每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。

不會寄垃圾信,隨時可取消。

"This Systematic Literature Review examines prompt engineering in automatic code generation using large language models (LLMs). A methodological protocol identified 26 relevant primary studies to characterize the status, trends, challenges, and opportunities of prompt engineering in software development."

翻譯一下就是:作者不是憑感覺講 prompt 有沒有用,他們先定義方法,再從 26 篇研究裡整理出共通模式。這點很重要,因為業界最愛把一個漂亮 demo 當成通則,然後大家一起踩坑。

Prompt 工程把 codegen 變成可重複流程

我自己最早用 LLM 產 code 的時候也這樣。丟一句「幫我做一個 CRUD API」,結果我花在修 output 的時間,常常比自己從頭寫還久。模型不一定爛,很多時候是我問得很爛。這篇 review 的價值就在這裡:它把 prompt 拉回工程問題,不是聊天問題。

實操上,我現在會先把需求縮成一個可驗證的任務。語言、框架、輸入、輸出、不能犯的錯、驗收條件,全都直接寫。你不寫清楚,模型就會用它自己的常識補洞,而那個常識通常不是你的 stack。

  • 一句話寫清楚這段 code 要做什麼。
  • 把語言、框架、版本、相依套件講明白。
  • 把不該發生的事列出來。
  • 要求 tests 或驗證步驟一起交付。

六個分類比那些 buzzword 有用

這篇 review 把結果整理成六個 recurring themes:structured methodologies、pedagogical strategies、accuracy and robustness、code improvement techniques、security through prompts、以及 prompt engineering 在 LLM 互動中的角色。學術味很重,但我覺得拿來當工作清單其實很順手。

白話一點,prompt engineering 不是一招通吃。它是一疊不同用途的工具。某些 prompt 是在幫模型理解任務結構,某些是拿例子教它風格,某些是在壓低錯誤率,某些是拿來修舊 code,某些是直接防危險輸出,還有一些是在規範你怎麼跟模型講話。

我以前很懶,會把這些全塞進「我 prompt 寫得好不好」這個大籃子裡。那很偷懶。像我如果要它生 migration script,我先在意 correctness,再來是 security,最後才是可讀性;但如果我要它 refactor,我先在意 behavior 不要變,再來才是 style。不同任務,本來就該用不同 prompt 形狀。

實操寫法很簡單:下 prompt 前先選你要解的類別。要 correctness,就叫它補 tests、列 edge cases。要 code improvement,就先貼舊 code,再定義你要改善什麼。要 security,就直接講 threat surface,不要期待它自己自律。

  • Structured methodology:用固定欄位的模板。
  • Pedagogical strategy:給範例,讓它照著學。
  • Accuracy and robustness:要求測試、邊界條件、假設。
  • Security:直接要求它標出風險與防護點。

結構比聰明字眼更管用

我最有感的是 structured methodologies 這一塊。這跟我自己實戰看到的東西完全對得上:prompt 長得像規格書,模型就比較像在做任務;prompt 長得像閒聊,它就比較像在猜你心情。

Prompt 工程把 codegen 變成可重複流程

也就是說,prompt engineering 有一部分其實是文件設計。你不是在寫漂亮句子,你是在降低歧義。結構越清楚,模型要自己腦補的東西就越少;它腦補越少,亂編的機率就越低。不是歸零,至少少很多,這已經夠救命了。

我之前做過同一個功能,先用鬆散 prompt,再用結構化 prompt。鬆散版生出來的 code 可以 compile,但商業規則漏掉了。結構化版雖然還是要 review,至少它比較像真的有看懂需求。模型沒變,差別只是我怎麼問。

實操寫法:每次 code generation 都固定用同一套骨架。欄位不要亂跳,讓你自己和模型都習慣它。像是 goal、context、constraints、examples、output format、validation,這樣你不用每次重新發明問法。

Goal: generate code for [task]
Context: [language, framework, repo state]
Inputs: [data shape, API contract, file names]
Constraints: [performance, style, security, compatibility]
Examples: [sample input/output or existing pattern]
Output format: [files, functions, tests, explanation]
Validation: [unit tests, edge cases, lint rules]

範例不是裝飾,是教模型看你的 codebase

這篇 review 裡的 pedagogical strategies,我覺得特別實用。因為 code generation 本質上就是 pattern transfer。你有沒有給它看過你專案裡真的長什麼樣,差很多。沒給,它就會吐出一份很 generic、看起來像樣、但跟你專案氣味不合的東西。

翻譯一下就是:few-shot prompting 不只是拿來做學術 demo,它是教模型你的命名規則、錯誤處理方式、資料結構習慣。這比你在 prompt 裡多加幾個形容詞有用太多。你寫「clean」「robust」通常沒什麼屁用;你貼一個真的範例,效果就會明顯很多。

我遇過最煩的一種狀況,是我叫它寫一個 endpoint,結果它一直回我 generic exception。不是它不會,是我沒給它看我們專案習慣用 domain error。後來我直接貼一個現成 function,叫它照那個 style 寫,output 立刻順很多。不是完美,但至少不再跟 codebase 打架。

實操寫法:只放一兩個高品質範例,不要塞一堆半吊子例子。你要它寫新 endpoint,就貼一個同類 endpoint;你要它寫測試,就貼一個你團隊真的會接受的測試。模型很字面,它看到什麼就學什麼。

  • 用自己 codebase 裡的真實範例。
  • 範例若有隱含規則,直接註解出來。
  • 範例要貼近任務,不要只是「看起來類似」。
  • 把雜訊刪掉,讓模型看到 pattern,不是看到垃圾。

準確度其實是 prompt 設計問題

review 把 accuracy and robustness 拉成一個獨立主題,這點我很同意。很多人把模型品質講得像唯一變數,但實戰不是這樣。prompt 寫法會直接改變輸出形狀,這對 code review 跟維護都很重要。

白話就是:你要逼模型先證明它自己。不是哲學上的證明,是 developer 意義上的證明。叫它先列 assumptions,再列 edge cases,再附 tests,最後補一段為什麼這樣寫。這不保證正確,但至少讓你有更多地方可以抓問題。

我之前看過它產出一段看似正常的 code,直到我追問 boundary cases,才發現 null handling 根本沒補。重點不是模型突然變聰明,而是我把 prompt 寫成會逼它露餡的形式。

實操寫法:每個 code prompt 都加 validation 欄位。請它先列假設,再列測試,再列可能失敗的地方。你在 review output 時,也先看假設,因為 bug 常常先死在那裡。

安全性要直接寫進 prompt

六個主題裡有一個是 security through prompts,我覺得這個不能省。LLM 生 code 很快,但它也很容易吐出功能正常、風險很高的寫法。這種 trade 我不想要。

也就是說,安全性不能靠運氣。只要碰到 authentication、authorization、input validation、檔案處理、SQL、shell execution、secret management,我都會把安全要求寫死。你不能假設模型會自動選安全版本,有時候它會,有時候它不會,而這個不確定性本身就是問題。

我曾經叫它寫一段接受使用者輸入的 shell script,第一版簡直是 production 事故預備軍。後來我直接加上 argument escaping、禁止 shell interpolation 這種條件,輸出才往正確方向走。不是魔法,只是我終於把話講清楚。

實操寫法:把安全清單塞進模板。要求 input sanitization、least privilege、secret handling、secure defaults。如果任務碰到使用者資料,先叫模型列 threat surface,再開始寫 code。這一步很煩,但很值得。

Prompt 應該進到開發流程,不該只活在私訊裡

這篇 review 提到 2021 到 2025 之間相關研究快速增加,而且學界持續關注,代表 prompt engineering 在 software lifecycle 裡已經有實際價值。我讀起來比較像提醒:這東西早就不是個人小把戲了,但很多團隊還在把 prompt 當一次性的文字。

翻譯一下就是:prompt 應該像其他工程資產一樣被版本化、被 review、被重用。哪一個 prompt 常常產出好 migration code,就把它留著。哪一個 prompt 在某類任務上一直翻車,就記下來。prompt 本身會變成團隊知識的一部分。

我現在會把好用的 prompt 直接放進 repo,像小工具一樣管理。stack 變了就改,需求變了就修。它不是神聖不可碰,但也不是用完就丟。這個轉變很重要,因為它把 prompt engineering 從個人手感,變成團隊流程。

實操寫法:把 prompts 跟產出的 code 放在一起。每個 prompt 附上適用情境和不適用情境。如果團隊有在用 AI 做 scaffold 或 review,就把 prompt 納入 onboarding。不然每個工程師都會自己重造一個更爛的版本。

可抄的模板

# Code generation prompt template

你是我的資深工程助理,請幫我產出可直接 review 的 code。

## Task
請用 [language/framework] 寫出/修改 [specific goal]。

## Context
- Project type: [web app / API / CLI / library]
- Stack: [language, framework, runtime, DB]
- Existing pattern to follow: [貼一段真實範例或描述]
- File(s) to modify or create: [list]

## Inputs and outputs
- Input shape: [JSON, form data, function args, event payload]
- Output shape: [response, file content, return value]
- Success criteria: [什麼條件成立才算完成]

## Constraints
- Style rules: [naming, formatting, architecture]
- Do not use: [unsafe APIs, deprecated libraries, patterns to avoid]
- Security requirements: [validation, escaping, auth, secrets]
- Performance requirements: [latency, memory, complexity]

## Example
以下是我專案裡的一個範例,請盡量維持相同風格:
[PASTE EXAMPLE]

## Validation
在寫 final code 前,先做這些事:
1. 列出你做了哪些假設。
2. 找出 edge cases 和 failure modes。
3. 一起附上 tests 或 test cases。
4. 標出任何可能 unsafe 或 brittle 的地方。

## Output format
請回傳:
1. code
2. tests
3. 簡短說明 key choices
4. caveats / follow-up work

## Refactor mode
如果我給你的是既有 code,不是空白任務,請先說明你會怎麼改,再在保留行為的前提下重寫。

這段就是我會直接複製的版本。它之所以有用,不是因為它很會講,而是因為它逼模型回答我在 code review 時本來就會問的問題。這樣輸出比較好驗,也比較不容易誤讀。

你要真的用得順,不要把模板當咒語背一遍。把你專案裡真的在意的限制填進去,貼真實範例,直接寫出安全風險。你越具體,後面要收爛攤子的機會就越小。

原始來源是 Erika Camacho、Yazmin Gutierrez、Cesar Pardo 的 review,DOI 是 10.4114/intartif.vol29iss78pp21-58。我上面這份模板是我根據他們的整理做的衍生版本,不是逐字抄 paper。