Temperature 與 Structured Outputs
用 temperature 控制隨機性;用 prefill + stop_sequence 穩穩拿到 JSON / 結構化資料。
TL;DR
temperature是 0–1 的「創意度」旋鈕。0 趨近 deterministic、1 最發散- 想穩拿 JSON:prefill 一段
assistant訊息開頭 + 設 stop_sequence 收尾 - 真的要鐵口直斷的 JSON:用 tool use 的 schema 機制(後面章節)
一個情境:從 email 抽欄位
「這封報名信寫了報名人姓名、活動日期、繳費金額——幫我抽出來,回 JSON 給我寫進 DB。」
直覺寫法:
add_user(messages, f"從這封信抽出 name、date、amount,回 JSON:\n\n{email}")
res = chat(messages)
print(res.content[0].text)
實際拿到:
這是抽取結果:
```json
{
"name": "陳小明",
"date": "2026-05-10",
"amount": 1500
}
```
如果還需要其他欄位請告訴我。
JSON 是對的,但包在 markdown code fence 裡 + 前後有解釋文字,json.loads() 直接吃下去會炸。Claude「太熱心」是這個任務的反效果。
Temperature:第一個調的旋鈕
Temperature 控制 model 在「下個 token 機率分佈」上的銳利度:
| temperature | 行為 | 適用 |
|---|---|---|
0.0 | 幾乎只挑機率最高的——每次跑結果接近一樣 | 抽欄位、分類、code、事實題 |
0.3 | 略有變化,但仍偏 deterministic | 摘要、客服回信 |
0.7 | 平衡 | 一般 chat、教學內容 |
1.0(API 預設) | 最發散,常見較稀有的選擇 | brainstorm、創意寫作、笑話 |
「temperature=0 就 deterministic」是常見誤解。Anthropic API 在 0 也不保證每次結果一樣(內部仍有少量隨機性,特別是平手的 token),但會「很接近」。
res = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=512,
temperature=0, # ← 結構化任務通常設 0
messages=messages,
)
三招拿到乾淨 JSON
招 1:prompt 寫死格式
最弱但最簡單:
add_user(messages, """從信件抽欄位,**只回 JSON**,不要任何解釋或 markdown。
格式:{"name": str, "date": "YYYY-MM-DD", "amount": int}
信件:
""" + email)
成功率取決於 model;Sonnet 4.6 大致穩,Haiku 偶爾會包 markdown。不是首選。
招 2:Prefill + stop_sequence(穩很多)
關鍵手法:用一個 assistant message 假裝 Claude 已經開始講了。它就會「順著講下去」。
messages = [
{"role": "user", "content": f"從信件抽 name、date、amount,回 JSON。信件:\n{email}"},
{"role": "assistant", "content": "{"}, # ← prefill 一個開頭
]
res = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=512,
temperature=0,
messages=messages,
stop_sequences=["}"], # ← 看到 "}" 就停(簡單 schema 用)
)
raw = "{" + res.content[0].text + "}" # 補回 prefill 開頭跟結尾
data = json.loads(raw)
兩個容易踩到的點:
- Prefill 的字不會出現在
content[0].text——Claude 是「順著 prefill 繼續講」,所以拿回來的 text 不含開頭的{,要自己補。 - Stop token 也不在 response 裡——
stop_sequences命中時,命中的字串本身不會回給你(API 行為),所以結尾的}也要自己補。stop_reason會是stop_sequence、stop_sequence欄位告訴你命中哪一個。
原理:Claude 看到 assistant: "{" 會以為自己已經開始寫 JSON 了,不會再加 markdown fence、不會加解釋文字。
招 3:Tool use schema(最穩)
Anthropic 後面章節會講的 tool use 機制可以強制 Claude 輸出符合 JSON schema 的結果。tool call 本來就是 schema-validated。
預告寫法(細節見 tool use 章):
tools = [{
"name": "extract_email",
"description": "從信件抽欄位",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"date": {"type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$"},
"amount": {"type": "integer"},
},
"required": ["name", "date", "amount"],
},
}]
API 確保 Claude 回的是 valid JSON 符合 schema。production 抽欄位首選。
三招怎麼選
| 任務 | 用哪招 |
|---|---|
| 一次性 prototyping | 招 1(prompt 寫死) |
| 簡單扁平 schema、跑量大 | 招 2(prefill + stop) |
| 巢狀結構、production、不能 fail | 招 3(tool schema) |
接下來
Section 1 到這裡完整把 request、multi-turn、streaming、temperature、結構化輸出都串起來了。下一章換個角度——怎麼客觀衡量 prompt 改得好不好。沒 eval 的 prompt engineering 就是猜,先把工程基礎建好。

