04 · 怎麼和 AI 說話
提示詞不是模板遊戲,是資訊密度遊戲。同樣意思不同表達,AI 輸出天差地別——不是因為語氣,是因為資訊量。理解資訊四件套(目標 / 上下文 / 邊界 / 驗收),你給的每條指令都會立刻不一樣。
翔宇一開始也在網上搜最佳提示詞模板,照著抄,有時有效有時沒效。後來想明白了——模板不是重點,你給 AI 的資訊才是。一旦把注意力從怎麼措辭轉到給什麼資訊,一切都清楚了。——翔宇
1. 一個 40 秒和一個 5 秒
你對 Claude Code 說:幫我最佳化這段程式碼。
它改了。你一看——變數名全換了,加了一堆你不需要的註釋,還把一個函式拆成了三個。方向完全不是你想要的。你重新解釋,它再改,又錯。來回 40 秒沒辦法繼續幹活。
現在換一種說法:這段程式碼有記憶體洩漏問題,請找出洩漏點,重點關注資料庫連線和檔案控制代碼,給出修復方案,不要重新命名變數也不要拆分函式。
同一個 AI,同一段程式碼,這次的輸出精準得像換了一個人。5 秒鐘你就能繼續往下幹。
發生了什麼?AI 沒變,程式碼沒變。唯一變了的是你輸入的資訊。第一次你給了一個模糊方向(最佳化),第二次你給了精確目標(找洩漏)+ 範圍(資料庫 / 檔案控制代碼)+ 期望產出(修復方案)+ 邊界(不重新命名、不拆分)。
2. 模型不讀心
如果只能記住一句話,記這一句:模型不讀心。
它沒辦法猜你腦子裡那個具體場景。它只看到你輸入的那些字。你腦子裡清楚但沒說的部分——它當成自由發揮的空間。
flowchart LR
Brain["🧠 你腦子裡<br/>真實想要的"]
Words["⌨️ 你打出來的字<br/>只是一部分"]
AI["🤖 模型基於字推斷<br/>缺失部分用最可能的填"]
Output["📦 輸出<br/>跟你想要的差距 = 缺失部分"]
Brain -.資訊丟失.-> Words
Words --> AI
AI --> Output
Brain -.->|對照差距| Output
style Brain fill:#dcfce7,stroke:#22c55e
style Words fill:#fef3c7,stroke:#f59e0b
style AI fill:#dbeafe,stroke:#3b82f6
style Output fill:#fee2e2,stroke:#ef4444
關鍵點:輸出跟你想要的差距 = 你腦子裡有但沒說出來的部分。這跟模型聰不聰明無關——再聰明的同事,你說最佳化程式碼他也得問你最佳化什麼。
這就是為什麼資訊越精確,輸出越精準。不是提示詞模板的功勞,是資訊量的功勞。
3. 資訊四件套
要讓模型有能力做你想要的事,每條指令本質上要給 4 類資訊。這 4 類構成一套可調的工程語言:
| 欄位 | 必填 | 說明 | 例子 | 不給會怎樣 |
|---|---|---|---|---|
| 🎯 目標 | ✅ | 你要 Claude 做什麼。動詞必須具體——修復比處理好,找出洩漏點比看一下好 | 修復 / 找出 / 重寫 / 加測試 | 模型自由發揮,做最常見的幾件事(重新命名 / 加註釋 / 拆函式) |
| 📥 上下文 | ✅ | 它需要先理解什麼。程式碼片段、檔案路徑、錯誤資訊、業務背景、已有約定(CLAUDE.md 之外的臨時上下文) | src/auth/login.js + 使用者錯誤密碼後頁面空白 | 模型掃整個儲存庫找線索,token 暴漲 + 命中率低 |
| 🔒 邊界 | — | 不要碰什麼。檔案範圍、不能修改的介面、不能引入的依賴、風格約束。這條最容易漏,也最容易翻車 | 不要重新命名變數 / 只改 controllers/ 下的 | 模型"順便"做一堆你沒要求的事——重構相鄰模組、改公開 API、引入新依賴 |
| ✅ 驗收 | — | 怎麼算做完了。命令執行成功、測試透過、diff 在 N 行內、輸出符合特定格式 | pnpm test 全過 / diff < 200 行 | 模型自己判斷"差不多了"就停——可能跑通了簡單測試就當完成 |
一句話理解:目標說做什麼 + 上下文說從哪開始 + 邊界說不碰什麼 + 驗收說怎麼算完。4 件套齊了,輸出方向就穩。
把開頭那兩個例子拆成四件套對比:
❌ 模糊指令
幫我最佳化這段程式碼
| 4 件套 | 給了什麼 |
|---|---|
| 🎯 目標 | 最佳化 —— 模糊(重新命名?重構?加註釋?提速?) |
| 📥 上下文 | 這段程式碼 —— 不知道哪段 |
| 🔒 邊界 | 沒說 |
| ✅ 驗收 | 沒說 |
結果:模型自由發揮——通常會做最常見的幾件事(重新命名 + 加註釋 + 拆函式)。你想要的(效能?可讀性?測試覆蓋?)模型不知道。
✅ 精確指令
這段程式碼有記憶體洩漏問題,請找出洩漏點,重點關注資料庫連線和檔案控制代碼,給出修復方案,不要重新命名變數也不要拆分函式
| 4 件套 | 給了什麼 |
|---|---|
| 🎯 目標 | 找出洩漏點 + 給出修復方案 —— 具體動詞 |
| 📥 上下文 | 記憶體洩漏問題 + 資料庫連線和檔案控制代碼 —— 範圍明確 |
| 🔒 邊界 | 不重新命名變數 + 不拆分函式 —— 顯式排除 |
| ✅ 驗收 | 隱含修復方案(可執行) |
結果:模型只走你畫的路徑,輸出方向跟你腦子裡想的對齊。
差別不在措辭——在資訊量。
4. 把模糊變具體的 3 個槓桿
知道了四件套,怎麼讓每件都變具體?三個槓桿:
槓桿 1 · 把抽象動詞換成可驗證動詞
| ❌ 抽象 | ✅ 可驗證 |
|---|---|
| 最佳化程式碼 | 找出 N+1 查詢 + 改成 batch 查詢 |
| 改進可讀性 | 變數名改駝峰 + 超過 50 行的函式拆成 ≤ 30 行 |
| 修復 bug | 修 login.js:42 錯誤密碼空白返回,加 1 條 e2e 測試 |
| 重構模組 | 把 services/payment.ts 拆成 collector / processor / notifier 三個檔案 |
判斷標準:動詞要能驗證——做完了能不能客觀判斷完沒完?模糊動詞做不完,具體動詞做完了能跑測試。
槓桿 2 · 給顯式範圍(路徑 / 表 / 時間 / 數量)
| 含糊 | 顯式 |
|---|---|
| 看一下 webhook | 看 controllers/webhook.ts 的 handleStripeEvent 函式 |
| 改一改測試 | 改 tests/auth/login.test.ts 中標 @flaky 的 3 條 case |
| 加點日誌 | 在 services/payment.ts 的 retry 分支加 logger.warn,含 transactionId 和 attempt 數字段 |
| 最佳化最近的程式碼 | 最佳化最近 7 天 git diff 裡的 hot path(用 git log --since="7 days ago" 找) |
顯式範圍讓模型不需要猜——它直接照著做。
槓桿 3 · 顯式說出隱含約束
每個專案都有人人都知道但沒人寫下來的約定。模型沒法靠常識猜出來。
- 我們這個專案所有 API 必須返回
{ data, error }結構 → 寫進 CLAUDE.md(03 篇)或臨時說明 - 測試不要 mock 資料庫 → 寫進 CLAUDE.md,否則每次都要提醒
- 這個函式雖然看起來簡單但有 3 個隱藏呼叫方 → 臨時上下文必須寫
- 這段程式碼 2 周後要重構,臨時方案別太完美 → 邊界
每次糾正 Claude,都是在補這一類隱含約束。補一次寫進 CLAUDE.md,比補十次省心。
5. 何時用結構化提示
正常對話——四件套用自然中文寫下來,夠了。
但長指令、複雜任務、多步驟——結構化能讓模型更穩定。
<task>修复支付回调幂等性 bug</task>
<context>
- 文件:controllers/webhook.ts、queue/retry.ts
- 现象:webhook 重试时 transaction 创建多次
- 已知线索:retry.ts 第 34 行没读 idempotency_key
</context>
<constraints>
- 不改 controllers/webhook.ts 的对外接口
- transaction 表 schema 不动
- 修复 diff < 100 行
</constraints>
<acceptance>
- 跑 tests/payment/retry.test.ts 全过
- 手动跑 scripts/replay-webhook.sh 重放 3 次只创建 1 个 transaction
- 不引入新依赖
</acceptance>XML 標籤是事實標準(Claude 系列對它訓練得最熟)。4 個標籤對應 4 件套——目標、上下文、邊界、驗收。
為什麼 Claude 系列對 XML 標籤特別敏感:Anthropic 在訓練 Claude 時大量用了 XML 結構化的 prompt 資料,官方的 prompt engineering 文件也把 XML 標籤作為推薦寫法。這意味著模型在解析 <task> <context> <constraints> <acceptance> 時會把它們當作強語義邊界——比純散文段落更容易識別"這一段是目標,那一段是約束"。換成 Markdown 標題(## 目標)也能用,但 Claude 對 XML 的訓練訊號更強。這是模型偏好,不是協議要求——其它模型(GPT / Gemini)用 Markdown 反而更好。
什麼時候不用 XML:日常 1-2 句的對話不要用 XML 包裹(噪音大於訊號)。指令長度超過 200 字、或要求 ≥ 3 個獨立約束時,結構化才有收益。
6. 跟人說話 vs 跟 Claude 說話
很多人覺得跟 Claude 說話像跟實習生說話。這個比喻 80% 對——但有 20% 關鍵差異:
🧑 跟人說話
人會主動追問:
- 你說修一下,他問哪裡?
- 你說最佳化,他問怎麼算最佳化好?
- 你說不對,他問具體哪裡不對?
人有沉默成本:
- 他每追問一次都暴露不專業
- 所以會主動猜:你大概想讓我重新命名 + 加註釋吧
- 猜對了顯得專業,猜錯了再補救
人有專案記憶:
- 上週你說過 X,他記得
- 團隊風格他知道
- 一些不成文規矩他懂
🤖 跟 Claude 說話
Claude 不主動追問:
- 你說修一下,它直接動手修一個它認為最可能的地方
- 你說最佳化,它直接選最常見的幾種最佳化做下去
- 你說不對,它自己重新猜一遍方向
Claude 沒有沉默成本:
- 它不在乎顯不顯得專業
- 不知道就猜,猜錯了你來糾正
- 這是它的工作模式,不是缺陷
Claude 沒有專案記憶(除非):
結論:跟 Claude 說話前置成本更高——你得提前說清楚,因為它不會問你。但你說一次,寫進 CLAUDE.md,以後不用再說。這是值得的交易。
7. 一個反覆有效的工作流
把上面所有內容串成一個可重複的工作流:
flowchart TD
Start["📝 寫一條指令"]
Check{"4 件套<br/>都給了嗎?"}
Run["▶️ 跑一遍 Claude"]
OK{"輸出方向<br/>對嗎?"}
Done["✅ 收工"]
Diag["🔍 診斷<br/>哪一件套缺了?"]
Fix["✍️ 補缺失的"]
Save{"是不是<br/>專案級規則?"}
CLAUDE["📜 寫進 CLAUDE.md"]
Start --> Check
Check -->|是| Run
Check -->|否| Fix
Run --> OK
OK -->|對| Done
OK -->|不對| Diag
Diag --> Fix
Fix --> Save
Save -->|是| CLAUDE
Save -->|否| Run
CLAUDE --> Run
style Done fill:#dcfce7,stroke:#22c55e
style CLAUDE fill:#dbeafe,stroke:#3b82f6
style Diag fill:#fef3c7,stroke:#f59e0b
第一次問 → 檢查 4 件套齊不齊 → 跑 → 不對就診斷哪件套缺了 → 補 → 如果是專案級規則就寫進 CLAUDE.md → 再跑。
跑通幾個週期後,CLAUDE.md 越寫越完整,你給 Claude 的指令會越來越短——因為公共上下文都已經在檔案裡了,每次只需要補這次任務特有的目標 + 範圍 + 邊界。
8. 檢驗你真懂了嗎
試著用自己的話回答:
- 有人說提示詞技巧的本質是措辭,你能反駁嗎?真正決定輸出質量的是什麼?對應 §2 + §3。
- 4 件套裡最容易被忽略的是哪一件?為什麼忽略它最容易翻車?舉一個例子。對應 §3。
- 動手題 ⭐:拿出你昨天給 Claude Code 發過的最模糊的一條指令(比如"最佳化這段程式碼"、"改改這個函式")。按 4 件套(目標 / 上下文 / 邊界 / 驗收)改寫一遍,每一件至少補一句具體的。改寫完對比原版,估算新版會減少多少輪"它沒聽懂我再解釋" 的來回——這就是 4 件套省下的真實成本。 對應 §3 + §4。
過關標準:能用一句話說清——模型不讀心,輸出 = 輸入資訊密度的函式;4 件套(目標 / 上下文 / 邊界 / 驗收)是這個函式的可調欄位。
本篇術語速查表
官方資料
接下來去哪
05 · AI 怎麼決定想多深
四件套搞定輸入資訊。下一篇拆模型怎麼處理這些資訊——快思考 vs 慢思考、effort 思考深度引數。
03 · 怎麼記住你的習慣(上一篇)
複習一下:4 件套裡的公共上下文該寫進 CLAUDE.md,本次任務特有每次顯式給。
06 · 把重複的話寫成檔案(可跳讀)
如果你發現某種 4 件套組合反覆使用——這就是 Skills 的雛形。把它沉澱成可複用檔案。
不用按順序全讀。挑你最好奇的那條線走就行。