iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
AI & Data

來都來了,那就做一個GCP從0到100的AI助理系列 第 5

Google Prompting Essentials 五步驟核心(T-C-R-E-I)

  • 分享至 

  • xImage
  •  

昨天我們聊過 LLM 為什麼容易「幻覺」,甚至一本正經地說出錯誤。那我們要怎麼辦?

最快速的方式就是寫出好提示詞,也就是一直都很夯的提示工程。

提示工程各家教法其實大同小異,這邊比較推Google 在 Prompting Essentials 的教學課程,課程中提供一組簡潔的五步法,這五步是 Task / Context / References / Evaluate / Iterate,口訣是「深思熟慮地創造優質輸入」(Thoughtfully Create Really Excellent Inputs)。

五步驟核心(T-C-R-E-I)

  1. Task(任務):大多數幻覺其實源自「輸入太模糊」。對 LLM 來說,如果你只說「幫我寫程式」,它會根據訓練語料庫裡「最常見的程式」來湊答案,結果不是 Python 就是 JavaScript,而且完全不會管你的真實需求。 這就像工程團隊裡沒有 API contract 的情況:只丟一句「幫我做會員系統」,開發出來可能是 SOAP API、REST API 或 GraphQL,完全對不上。

    這就像工程團隊裡沒有 API contract 的情況:只丟一句「幫我做會員系統」,開發出來可能是 SOAP API、REST API 或 GraphQL,完全對不上。

    所以 Task 的核心是要「定錨」,告訴模型:

    • 技術棧(Java / Spring Boot 3.3 / JDK 17)
    • 功能範圍(GET /users/{id} 查詢 API)
    • 非功能性需求(必須支援 OpenAPI 文件輸出、錯誤要符合 RFC 7807)

    這些都會直接影響模型在「語料搜尋空間」中的選擇範圍,越清楚,幻覺機率越低。

    • ❌ 壞例子:幫我寫程式
    • ✅ 好例子:用 Java 寫一個查詢使用者的 API。問題:缺版本、框架、路由、參數型別、錯誤格式、驗收標準。
    
    [角色] 你是資深後端工程師(Java 17 / Spring Boot 3.3)。
    
    [任務] 實作一支查詢使用者 API:
    - 方法與路由:GET /api/v1/users/{id}
    - 需求:回傳指定 id 的基本資料,找不到要回 RFC 7807 問題細節
    - 相依:PostgreSQL、Spring Web、Spring Validation、springdoc-openapi
    
    [輸入約束]
    - path variable id:UUID 格式(如 8-4-4-4-12)
    - 接受 Header:X-Request-Id(若缺省,自動生成)
    
    [輸出格式]
    - 200:application/json,欄位 { id, name, email }
    - 404:application/problem+json(RFC 7807),欄位 { type,title,status,detail,instance }
    - 422:同上,detail 說明 id 格式錯誤
    
    [非功能性]
    - 程式碼風格:Controller→Service→Repository 三層
    - 測試覆蓋:對 Service 寫 3 組單元測試(成功/不存在/無效UUID)
    
    [交付]
    1) Controller/Service 介面與骨架程式碼
    2) 1 份 OpenAPI YAML(/v3/api-docs 可導出)
    3) 測試案例名稱清楚標明情境
    
    
  2. Context(背景):沒有背景的提示,就像把新人丟進陌生專案卻不講需求。模型不知道「受眾是誰」「語氣要怎樣」「應用情境在哪裡」,它只能輸出「一般」的答案。而上下文的價值在於:

    • 對齊受眾:同一段程式碼,解釋給 junior 要有教學口吻,對 senior 則要點出架構考量。
    • 定義輸出風格:要寫成技術文件?還是成為簡報 bullet points?
    • 縮小語境空間:避免模型回覆一堆它「以為有用」但其實無關的廢話。

    這對應到昨天提到的「上下文衰減」問題:重要的規則要在前面就給出,否則模型可能忽略。

    在工程世界裡,Context 就像 需求文件的使用情境(Use Case / User Story),缺少它,輸出永遠對不齊 stakeholder 的期待。

    • ❌ 壞例子: 解釋這段程式碼
    • ✅ 好例子:請用教學口吻,針對初學者解釋這段 Java 程式碼,並舉一個真實使用情境
    [角色] 你是帶新人入門的後端教練。
    
    [讀者] 剛入職 3 個月的 Java 新人,懂基本語法,但不了解 Spring Boot 架構。
    
    [任務] 以教學筆記解說下列 Service 程式碼的設計意圖與常見錯誤。
    
    [呈現格式]
    - 1 段「這段程式在解決什麼問題」
    - 3 條「關鍵設計決策」(每條 ≤ 40 字)
    - 1 段「新手常犯錯」+對應修正
    - 1 小段「延伸閱讀」:列 2 個關鍵字(如 “Transactional boundary”, “DTO vs Entity”)
    
    [語氣] 親和、避免術語堆砌,必要術語加括號解釋。
    
    [篇幅] 300–450 字。
    
    [素材] (貼上你的程式碼片段)
    
    
  3. References(參考資料):讓模型知道「只能用這些知識回答」。就像你把設計 ERD 丟進去,AI 就不敢亂幫你加「password」欄位;如果你沒給,它就會照過往訓練資料隨機編。

    這和昨天講的 RAG Recall 不足完全呼應:模型不是故意亂掰,而是「找不到正確依據,只好硬湊」。最重要的是 「禁止臆測條款」:明確告訴模型「沒有參考資料就回答『無資料』」,這能直接砍掉大部分幻覺。

    實務對照:

    • API 設計 → 就像 Swagger 定義先行,程式照 schema 走。

    • DB schema → 若不提供欄位設計,AI 可能隨便補一個「last_login_time」。

    • 文件生成 → 附上官方 spec,避免 AI 胡亂創建不存在的參數。

    • ❌ 壞例子:請幫我設計資料庫表格

    • ✅ 好例子:以下是 ERD,請根據這張圖生成對應的 PostgreSQL CREATE TABLE 語句

    
    [角色] 你是資深資料庫設計師(PostgreSQL 15)。
    
    [任務] 根據以下 ERD 產生 CREATE TABLE 語句,並加上必要索引與外鍵約束。
    [ERD 摘要] (貼上關鍵欄位/關聯;若很長,請先附你整理的重點表)
    
    [設計規則]
    - 命名:表 snake_case,單數名詞;主鍵 {table}_id
    - 時間:全部使用 timestamptz;欄位 created_at, updated_at
    - 文字:email 用 citext;大量文字用 text
    - 外鍵:on delete restrict,除非註明 cascade
    - 索引:對查詢條件與外鍵欄位建立 btree 索引;email 加 unique
    - 禁止臆測:若 ERD 無資訊,輸出“無資料”,不要補創任何欄位
    
    [輸出格式]
    - 以多段 SQL 區塊呈現,每段前加註解說明該表用途
    - 最後輸出「核對清單」:列出 1) 外鍵完整性 2) 索引覆蓋 3) 命名一致性 是否滿足(是/否)
    
    [素材] (貼 ERD/欄位表)
    
    
  4. Evaluate(評估):很多人卡在「AI 輸出看起來很合理」,就直接拿去用,結果踩坑。這跟工程實務一樣:只看程式跑得動,不代表它就正確、可維護。Evaluate 的重點在於:

    • 驗證正確性:透過單元測試或靜態檢查工具,確認 AI 輸出的程式碼可執行、可測。
    • 檢查一致性:確保命名規則、錯誤處理格式統一。
    • 引入「紅隊思維」:要求模型「列出可能缺漏的測試案例」或「指出此答案可能的風險」。

    這等於幫模型多加一層 自我 QA,也是把昨天講到的「自信但錯誤」反過來利用:讓它先替自己挑毛病。工程比喻來看:Evaluate 就是 Code Review + 測試驗收,沒有這一步,AI 的產出只能算是「未審核的原始碼」。

    • ❌ 壞例子:直接把 AI 產生的程式碼丟上線。
    • ✅ 好例子:先用單元測試檢查功能是否正確,再評估效能與安全性。
    [角色] 你是測試工程師(JUnit5/AssertJ)。
    
    [任務] 針對 UserService.findById(UUID) 產生單元測試。
    
    [覆蓋需求]
    - 成功:存在的 id 回傳正確 User
    - 邊界:不存在 id → 拋 NotFoundException,訊息含該 id
    - 無效:非 UUID 格式 → 拋 IllegalArgumentException
    - 性能:方法耗時 < 50ms(使用 System.nanoTime 粗測)
    
    [輸出格式]
    - 測試方法清單(方法名、Arrange/Act/Assert 摘要)
    - 關鍵斷言片段(只貼必要 5–10 行)
    - 自我檢查:列出可能缺漏的 2 項測試並說明為何未納入
    
    [輸入資料] 使用 Fakes,不連資料庫
    
    
  5. Iterate(迭代):很多人用 AI 的方式還停留在「一次丟一大坨,結果不滿意就重來」。這其實效率極低。

    正確的做法是 差分式迭代

    1. 指出錯誤點(例如:你的 OpenAPI YAML 缺少 422 錯誤碼
    2. 指定修正範圍(僅修正錯誤碼部分,其他保持不變
    3. 加入評分規則(若輸出不符合 RFC 7807 schema,請自行再修正一次

    這樣模型會在「上一版」基礎上改,而不是每次重新生成。

    這正好呼應昨天提到的「解碼策略不穩定」問題:透過迭代,你能用人為 feedback loop 去強化模型的穩定度。工程比喻來看:這就像 CI/CD Pipeline → 每次提交小修小補,跑過驗收,再往下一步,而不是推倒重建。

    [情境] 你上次輸出的 OpenAPI YAML 有 3 個問題:
    1) 缺少 422 Unprocessable Entity 的 schema
    2) 路由 /api/v1/users/{id} 少了 path 參數格式範例
    3) 描述文字過長(>120 字)
    
    [任務] 僅針對上述 3 點修正,其他內容保持不變(差分編輯)。
    
    [評分規準]
    - 正確性:是否包含 422 且 schema 符合 RFC 7807(0/1)
    - 完整性:path 參數是否附 UUID 範例(0/1)
    - 可讀性:每段描述 ≤ 120 字(0/1)
    → 得分未達 3/3 時,自行再迭代一次並附「修正說明」
    
    [輸出格式]
    - 只輸出修正後的 YAML 區塊
    - 最後附上「本次修正說明」3 行內
    

稍微 Summry

  • Task:避免模型亂猜 → 就像 API contract
  • Context:對齊受眾與場景 → 就像 Use Case
  • References:限制知識邊界 → 就像官方 spec / schema
  • Evaluate:輸出驗收 → 就像測試 + Code Review
  • Iterate:差分修正 → 就像 CI/CD

上一篇
關於幻覺
系列文
來都來了,那就做一個GCP從0到100的AI助理5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言