Applied AI School
v0 · 規劃中
Anthropic

寫第一個 request

messages、system、max_tokens、model 四件事;最常見的兩個新手錯誤怎麼避。

TL;DR

  • 一個 request 必填四件事:modelmax_tokensmessages、(可選)system
  • systemmessages兩個獨立欄位——不要把指示塞進 user message
  • max_tokens上限不是預期長度——Claude 不會努力填到你給的數字

一個情境:兩個新手錯誤

第一次寫 Anthropic API 的時候很容易踩到這兩個雷:

錯誤 1:把指示塞進 user message

# 不要這樣
messages = [{
  "role": "user",
  "content": "你是一個專業翻譯。把下面句子翻成日文:今天天氣好"
}]

錯誤 2:把 max_tokens 當成「我要 500 字」

# 不要這樣
max_tokens = 500  # 想要 500 字的回答

兩個都會「能跑」,但會讓 prompt engineering 變得困難。第一個讓指示跟 user input 混在一起;第二個讓你以為調這個數字會影響回答長度(其實不會)。

最小可行 request

先裝 SDK:

pip install anthropic
from anthropic import Anthropic

client = Anthropic()  # 讀 ANTHROPIC_API_KEY 環境變數

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "什麼是量子運算?一句話。"}
    ]
)

print(message.content[0].text)

對應 cURL(不一定要走 SDK——server 端要極簡部署、或語言沒 SDK 的時候直接 HTTP 也行):

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "What is quantum computing?"}]
  }'

四個欄位拆開講

model

寫 model id 字串。抽成 config,不要散落在程式各處。升級新版的時候只改一個地方就好。

messages

是一個 array,每個元素是 {role, content}

role是誰
user使用者寫的、或你的 server 注入的內容
assistantmodel 上一輪的回答(multi-turn 用)

沒有 system role——system 是分離的欄位,下面講。

max_tokens

上限,不是目標。意思:

  • max_tokens=1024,Claude 答 30 token 就夠了,它就停
  • max_tokens=1024,Claude 想答 2000 token,它停在 1024,回 stop_reason: max_tokens

實務取值:

場景建議
短分類、yes/no、JSON 抽欄位256–512
一般 chat 回答1024–2048
長文生成、文章草稿4096–16K
長文 + extended thinking32K+(含 thinking budget)

太低會被截斷;太高雖然只計實際 output token、不會多付錢,但會佔走 extended thinking 的 budget 上限、也讓你 context 預算難規劃。

system

最容易被新手錯放的欄位。它跟 messages 平行:

client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system="你是一個耐心的數學家教,不要直接給答案,引導學生想。",
    messages=[
        {"role": "user", "content": "幫我解 5x + 2 = 3"}
    ]
)

為什麼分開:

  • 跨 turn 持久:multi-turn 對話 system 只寫一次,所有 turn 都吃得到
  • 不被使用者污染:user message 是 user 寫的,system 是你寫的。分開後 prompt injection 攻擊難一階
  • prompt caching 有用:長 system 可以 cache(後面章節會講)

取出回應

response 不是純字串,是物件:

message.content[0].text  # 真正的文字
message.stop_reason       # "end_turn" | "max_tokens" | "stop_sequence" | "tool_use" 等
message.usage             # {input_tokens, output_tokens, ...}

content 是 array 是因為將來 tool use、thinking、image 出現時,會有不同 type 的 block 並列。多數 chat 場景就是 content[0].textproduction 寫法

text = "".join(
    block.text for block in message.content if block.type == "text"
)

更安全,不會被 tool_use block 弄爆。

包成 helper

整本系列後面會反覆用到,先包好:

def chat(messages, system=None, **kwargs):
    params = {
        "model": "claude-sonnet-4-6",
        "max_tokens": 1024,
        "messages": messages,
        **kwargs,
    }
    if system:
        params["system"] = system
    return client.messages.create(**params)

注意 if system——API 不接受 system=None,要動態組。

接下來

下一篇處理兩個跟「對話流動性」有關的功能:multi-turn 對話(messages 怎麼接續、為什麼歷史每次都要重傳)跟 streaming(讓 user 看到 token 一個個冒出來)。