延伸思考為 Claude 提供了增強的推理能力,用於處理複雜任務,同時在提供最終答案之前提供不同程度的透明度來了解其逐步思考過程。

支援的模型

延伸思考在以下模型中受支援:
  • Claude Sonnet 4.5 (claude-sonnet-4-5-20250929)
  • Claude Sonnet 4 (claude-sonnet-4-20250514)
  • Claude Sonnet 3.7 (claude-3-7-sonnet-20250219) (已棄用)
  • Claude Haiku 4.5 (claude-haiku-4-5-20251001)
  • Claude Opus 4.1 (claude-opus-4-1-20250805)
  • Claude Opus 4 (claude-opus-4-20250514)
API 行為在 Claude Sonnet 3.7 和 Claude 4 模型之間有所不同,但 API 形狀保持完全相同。如需更多資訊,請參閱不同模型版本間的思考差異

延伸思考的工作原理

當延伸思考開啟時,Claude 會建立 thinking 內容區塊,其中輸出其內部推理。Claude 在製作最終回應之前會納入此推理中的見解。 API 回應將包括 thinking 內容區塊,後面跟著 text 內容區塊。 以下是預設回應格式的範例:
{
  "content": [
    {
      "type": "thinking",
      "thinking": "讓我逐步分析這個...",
      "signature": "WaUjzkypQ2mUEVM36O2TxuC06KN8xyfbJwyem2dw3URve/op91XWHOEBLLqIOMfFG/UvLEczmEsUjavL...."
    },
    {
      "type": "text",
      "text": "根據我的分析..."
    }
  ]
}
如需更多關於延伸思考回應格式的資訊,請參閱訊息 API 參考

如何使用延伸思考

以下是在訊息 API 中使用延伸思考的範例:
curl https://api.anthropic.com/v1/messages \
     --header "x-api-key: $ANTHROPIC_API_KEY" \
     --header "anthropic-version: 2023-06-01" \
     --header "content-type: application/json" \
     --data \
'{
    "model": "claude-sonnet-4-5",
    "max_tokens": 16000,
    "thinking": {
        "type": "enabled",
        "budget_tokens": 10000
    },
    "messages": [
        {
            "role": "user",
            "content": "Are there an infinite number of prime numbers such that n mod 4 == 3?"
        }
    ]
}'
若要開啟延伸思考,請新增 thinking 物件,將 type 參數設定為 enabled,並將 budget_tokens 設定為延伸思考的指定代幣預算。 budget_tokens 參數決定了 Claude 被允許用於其內部推理過程的最大代幣數。在 Claude 4 模型中,此限制適用於完整思考代幣,而不適用於摘要輸出。較大的預算可以透過為複雜問題啟用更徹底的分析來改善回應品質,儘管 Claude 可能不會使用整個分配的預算,特別是在 32k 以上的範圍內。 budget_tokens 必須設定為小於 max_tokens 的值。但是,當使用與工具交錯的思考時,您可以超過此限制,因為代幣限制變成您的整個上下文視窗(200k 代幣)。

摘要思考

啟用延伸思考後,Claude 4 模型的訊息 API 會傳回 Claude 完整思考過程的摘要。摘要思考提供了延伸思考的完整智能優勢,同時防止濫用。 以下是摘要思考的一些重要考慮事項:
  • 您需要為原始請求生成的完整思考代幣付費,而不是摘要代幣。
  • 計費的輸出代幣計數將不符合您在回應中看到的代幣計數。
  • 思考輸出的前幾行更詳細,提供了詳細的推理,特別有助於提示工程目的。
  • 隨著 Anthropic 尋求改進延伸思考功能,摘要行為可能會發生變化。
  • 摘要化保留了 Claude 思考過程的關鍵思想,同時增加最少的延遲,實現可流式傳輸的使用者體驗和從 Claude Sonnet 3.7 到 Claude 4 模型的輕鬆遷移。
  • 摘要化由與您在請求中指定的模型不同的模型處理。思考模型看不到摘要輸出。
Claude Sonnet 3.7 繼續傳回完整思考輸出。在罕見情況下,如果您需要存取 Claude 4 模型的完整思考輸出,請聯絡我們的銷售團隊

串流思考

您可以使用伺服器傳送事件 (SSE) 串流延伸思考回應。 當為延伸思考啟用串流時,您會透過 thinking_delta 事件接收思考內容。 如需更多關於透過訊息 API 進行串流的文件,請參閱串流訊息 以下是如何處理思考串流的方法:
curl https://api.anthropic.com/v1/messages \
     --header "x-api-key: $ANTHROPIC_API_KEY" \
     --header "anthropic-version: 2023-06-01" \
     --header "content-type: application/json" \
     --data \
'{
    "model": "claude-sonnet-4-5",
    "max_tokens": 16000,
    "stream": true,
    "thinking": {
        "type": "enabled",
        "budget_tokens": 10000
    },
    "messages": [
        {
            "role": "user",
            "content": "What is 27 * 453?"
        }
    ]
}'
串流輸出範例:
event: message_start
data: {"type": "message_start", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [], "model": "claude-sonnet-4-5", "stop_reason": null, "stop_sequence": null}}

event: content_block_start
data: {"type": "content_block_start", "index": 0, "content_block": {"type": "thinking", "thinking": ""}}

event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "讓我逐步解決這個問題:\n\n1. 首先分解 27 * 453"}}

event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n2. 453 = 400 + 50 + 3"}}

// 其他思考 delta...

event: content_block_delta
data: {"type": "content_block_delta", "index": 0, "delta": {"type": "signature_delta", "signature": "EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds..."}}

event: content_block_stop
data: {"type": "content_block_stop", "index": 0}

event: content_block_start
data: {"type": "content_block_start", "index": 1, "content_block": {"type": "text", "text": ""}}

event: content_block_delta
data: {"type": "content_block_delta", "index": 1, "delta": {"type": "text_delta", "text": "27 * 453 = 12,231"}}

// 其他文字 delta...

event: content_block_stop
data: {"type": "content_block_stop", "index": 1}

event: message_delta
data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence": null}}

event: message_stop
data: {"type": "message_stop"}
當使用啟用思考的串流時,您可能會注意到文字有時以較大的塊到達,交替進行較小的逐代幣傳遞。這是預期的行為,特別是對於思考內容。串流系統需要以批次方式處理內容以獲得最佳效能,這可能導致這種「分塊」傳遞模式,串流事件之間可能有延遲。我們正在持續努力改進這種體驗,未來的更新將專注於使思考內容流式傳輸更順暢。

延伸思考與工具使用

延伸思考可以與工具使用一起使用,允許 Claude 推理工具選擇和結果處理。 當使用延伸思考與工具使用時,請注意以下限制:
  1. 工具選擇限制:思考工具使用僅支援 tool_choice: {"type": "auto"} (預設) 或 tool_choice: {"type": "none"}。使用 tool_choice: {"type": "any"}tool_choice: {"type": "tool", "name": "..."} 將導致錯誤,因為這些選項強制工具使用,與延伸思考不相容。
  2. 保留思考區塊:在工具使用期間,您必須將 thinking 區塊傳回 API 以用於最後的助手訊息。將完整的未修改區塊傳回 API 以維持推理連續性。

在對話中切換思考模式

您無法在助手轉向中間切換思考,包括在工具使用迴圈期間。整個助手轉向必須在單一思考模式中運作:
  • 如果啟用思考,最終助手轉向必須以思考區塊開始。
  • 如果停用思考,最終助手轉向不得包含任何思考區塊
從模型的角度來看,工具使用迴圈是助手轉向的一部分。助手轉向在 Claude 完成其完整回應(可能包括多個工具呼叫和結果)之前不會完成。 例如,此序列全部是單一助手轉向的一部分:
User: "What's the weather in Paris?"
Assistant: [thinking] + [tool_use: get_weather]
User: [tool_result: "20°C, sunny"]
Assistant: [text: "The weather in Paris is 20°C and sunny"]
儘管有多個 API 訊息,但工具使用迴圈在概念上是一個連續助手回應的一部分。

常見錯誤情景

您可能會遇到此錯誤:
Expected `thinking` or `redacted_thinking`, but found `tool_use`.
When `thinking` is enabled, a final `assistant` message must start
with a thinking block (preceding the lastmost set of `tool_use` and
`tool_result` blocks).
這通常發生在以下情況:
  1. 您在工具使用序列期間停用了思考
  2. 您想再次啟用思考
  3. 您的最後助手訊息包含工具使用區塊但沒有思考區塊

實用指南

✗ 無效:在工具使用後立即切換思考
User: "What's the weather?"
Assistant: [tool_use] (thinking disabled)
User: [tool_result]
// 無法在此啟用思考 - 仍在同一助手轉向中
✓ 有效:首先完成助手轉向
User: "What's the weather?"
Assistant: [tool_use] (thinking disabled)
User: [tool_result]
Assistant: [text: "It's sunny"] 
User: "What about tomorrow?" (thinking disabled)
Assistant: [thinking] + [text: "..."] (thinking enabled - new turn)
最佳實踐:在每個轉向開始時規劃您的思考策略,而不是嘗試在轉向中間切換。
切換思考模式也會使提示快取對訊息歷史記錄無效。如需更多詳細資訊,請參閱延伸思考與提示快取部分。
以下是一個實際範例,展示在提供工具結果時如何保留思考區塊:
weather_tool = {
    "name": "get_weather",
    "description": "Get current weather for a location",
    "input_schema": {
        "type": "object",
        "properties": {
            "location": {"type": "string"}
        },
        "required": ["location"]
    }
}

# 第一個請求 - Claude 以思考和工具請求回應
response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000
    },
    tools=[weather_tool],
    messages=[
        {"role": "user", "content": "What's the weather in Paris?"}
    ]
)
API 回應將包括思考、文字和 tool_use 區塊:
{
    "content": [
        {
            "type": "thinking",
            "thinking": "使用者想知道巴黎的目前天氣。我可以存取函數 `get_weather`...",
            "signature": "BDaL4VrbR2Oj0hO4XpJxT28J5TILnCrrUXoKiiNBZW9P+nr8XSj1zuZzAl4egiCCpQNvfyUuFFJP5CncdYZEQPPmLxYsNrcs...."
        },
        {
            "type": "text",
            "text": "我可以幫助您取得巴黎的目前天氣資訊。讓我為您檢查一下"
        },
        {
            "type": "tool_use",
            "id": "toolu_01CswdEQBMshySk6Y9DFKrfq",
            "name": "get_weather",
            "input": {
                "location": "Paris"
            }
        }
    ]
}
現在讓我們繼續對話並使用工具
# 提取思考區塊和工具使用區塊
thinking_block = next((block for block in response.content
                      if block.type == 'thinking'), None)
tool_use_block = next((block for block in response.content
                      if block.type == 'tool_use'), None)

# 呼叫您的實際天氣 API,這是您的實際 API 呼叫將進行的地方
# 讓我們假設這是我們得到的回傳
weather_data = {"temperature": 88}

# 第二個請求 - 包括思考區塊和工具結果
# 回應中不會生成新的思考區塊
continuation = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000
    },
    tools=[weather_tool],
    messages=[
        {"role": "user", "content": "What's the weather in Paris?"},
        # 注意 thinking_block 與 tool_use_block 一起傳入
        # 如果未傳入,將引發錯誤
        {"role": "assistant", "content": [thinking_block, tool_use_block]},
        {"role": "user", "content": [{
            "type": "tool_result",
            "tool_use_id": tool_use_block.id,
            "content": f"Current temperature: {weather_data['temperature']}°F"
        }]}
    ]
)
API 回應現在包括文字
{
    "content": [
        {
            "type": "text",
            "text": "巴黎目前的溫度是 88°F (31°C)"
        }
    ]
}

保留思考區塊

在工具使用期間,您必須將 thinking 區塊傳回 API,並且必須將完整的未修改區塊傳回 API。這對於維持模型的推理流和對話完整性至關重要。
雖然您可以從先前的 assistant 角色轉向中省略 thinking 區塊,但我們建議始終將所有思考區塊傳回 API 以進行任何多轉向對話。API 將:
  • 自動篩選提供的思考區塊
  • 使用必要的相關思考區塊來保留模型的推理
  • 僅對顯示給 Claude 的區塊計費輸入代幣
在對話期間切換思考模式時,請記住整個助手轉向(包括工具使用迴圈)必須在單一思考模式中運作。如需更多詳細資訊,請參閱在對話中切換思考模式
當 Claude 呼叫工具時,它會暫停其回應的構建以等待外部資訊。當工具結果返回時,Claude 將繼續構建該現有回應。這需要在工具使用期間保留思考區塊,原因有幾個:
  1. 推理連續性:思考區塊捕捉了導致工具請求的 Claude 逐步推理。當您發佈工具結果時,包括原始思考可確保 Claude 可以從中斷的地方繼續推理。
  2. 上下文維護:雖然工具結果在 API 結構中顯示為使用者訊息,但它們是連續推理流的一部分。保留思考區塊在多個 API 呼叫中維持這個概念流。如需更多關於上下文管理的資訊,請參閱我們的上下文視窗指南
重要:提供 thinking 區塊時,連續 thinking 區塊的整個序列必須符合模型在原始請求期間生成的輸出;您無法重新排列或修改這些區塊的序列。

交錯思考

Claude 4 模型中的延伸思考與工具使用支援交錯思考,這使 Claude 能夠在工具呼叫之間進行思考,並在接收工具結果後進行更複雜的推理。 透過交錯思考,Claude 可以:
  • 在決定下一步之前推理工具呼叫的結果
  • 在推理步驟之間鏈接多個工具呼叫
  • 根據中間結果做出更細緻的決定
若要啟用交錯思考,請將 beta 標頭 interleaved-thinking-2025-05-14 新增至您的 API 請求。 以下是交錯思考的一些重要考慮事項:
  • 使用交錯思考時,budget_tokens 可以超過 max_tokens 參數,因為它代表一個助手轉向內所有思考區塊的總預算。
  • 交錯思考僅支援透過訊息 API 使用的工具
  • 交錯思考僅支援 Claude 4 模型,使用 beta 標頭 interleaved-thinking-2025-05-14
  • 直接呼叫 Claude API 允許您將 interleaved-thinking-2025-05-14 傳遞到任何模型的請求中,沒有任何效果。
  • 在第三方平台上(例如 Amazon BedrockVertex AI),如果您將 interleaved-thinking-2025-05-14 傳遞到除 Claude Opus 4.1、Opus 4 或 Sonnet 4 之外的任何模型,您的請求將失敗。
import anthropic

client = anthropic.Anthropic()

# 定義工具
calculator_tool = {
    "name": "calculator",
    "description": "Perform mathematical calculations",
    "input_schema": {
        "type": "object",
        "properties": {
            "expression": {
                "type": "string",
                "description": "Mathematical expression to evaluate"
            }
        },
        "required": ["expression"]
    }
}

database_tool = {
    "name": "database_query",
    "description": "Query product database",
    "input_schema": {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "SQL query to execute"
            }
        },
        "required": ["query"]
    }
}

# 第一個請求 - Claude 在所有工具呼叫之前思考一次
response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000
    },
    tools=[calculator_tool, database_tool],
    messages=[{
        "role": "user",
        "content": "What's the total revenue if we sold 150 units of product A at $50 each, and how does this compare to our average monthly revenue from the database?"
    }]
)

# 回應包括思考,然後是工具使用
# 注意:Claude 在開始時思考一次,然後做出所有工具決定
print("First response:")
for block in response.content:
    if block.type == "thinking":
        print(f"Thinking (summarized): {block.thinking}")
    elif block.type == "tool_use":
        print(f"Tool use: {block.name} with input {block.input}")
    elif block.type == "text":
        print(f"Text: {block.text}")

# 您將執行工具並返回結果...
# 在獲得兩個工具結果後,Claude 直接回應而不進行額外思考
在此不使用交錯思考的範例中:
  1. Claude 在開始時思考一次以理解任務
  2. 預先做出所有工具使用決定
  3. 當工具結果返回時,Claude 立即提供回應而不進行額外思考
import anthropic

client = anthropic.Anthropic()

# 與之前相同的工具定義
calculator_tool = {
    "name": "calculator",
    "description": "Perform mathematical calculations",
    "input_schema": {
        "type": "object",
        "properties": {
            "expression": {
                "type": "string",
                "description": "Mathematical expression to evaluate"
            }
        },
        "required": ["expression"]
    }
}

database_tool = {
    "name": "database_query",
    "description": "Query product database",
    "input_schema": {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "SQL query to execute"
            }
        },
        "required": ["query"]
    }
}

# 第一個請求,啟用交錯思考
response = client.beta.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000
    },
    tools=[calculator_tool, database_tool],
    betas=["interleaved-thinking-2025-05-14"],
    messages=[{
        "role": "user",
        "content": "What's the total revenue if we sold 150 units of product A at $50 each, and how does this compare to our average monthly revenue from the database?"
    }]
)

print("Initial response:")
thinking_blocks = []
tool_use_blocks = []

for block in response.content:
    if block.type == "thinking":
        thinking_blocks.append(block)
        print(f"Thinking: {block.thinking}")
    elif block.type == "tool_use":
        tool_use_blocks.append(block)
        print(f"Tool use: {block.name} with input {block.input}")
    elif block.type == "text":
        print(f"Text: {block.text}")

# 第一個工具結果(計算機)
calculator_result = "7500"  # 150 * 50

# 使用第一個工具結果繼續
response2 = client.beta.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000
    },
    tools=[calculator_tool, database_tool],
    betas=["interleaved-thinking-2025-05-14"],
    messages=[
        {
            "role": "user",
            "content": "What's the total revenue if we sold 150 units of product A at $50 each, and how does this compare to our average monthly revenue from the database?"
        },
        {
            "role": "assistant",
            "content": [thinking_blocks[0], tool_use_blocks[0]]
        },
        {
            "role": "user",
            "content": [{
                "type": "tool_result",
                "tool_use_id": tool_use_blocks[0].id,
                "content": calculator_result
            }]
        }
    ]
)

print("\nAfter calculator result:")
# 使用交錯思考,Claude 可以思考計算機結果
# 在決定查詢資料庫之前
for block in response2.content:
    if block.type == "thinking":
        thinking_blocks.append(block)
        print(f"Interleaved thinking: {block.thinking}")
    elif block.type == "tool_use":
        tool_use_blocks.append(block)
        print(f"Tool use: {block.name} with input {block.input}")

# 第二個工具結果(資料庫)
database_result = "5200"  # 範例平均月收入

# 使用第二個工具結果繼續
response3 = client.beta.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000
    },
    tools=[calculator_tool, database_tool],
    betas=["interleaved-thinking-2025-05-14"],
    messages=[
        {
            "role": "user",
            "content": "What's the total revenue if we sold 150 units of product A at $50 each, and how does this compare to our average monthly revenue from the database?"
        },
        {
            "role": "assistant",
            "content": [thinking_blocks[0], tool_use_blocks[0]]
        },
        {
            "role": "user",
            "content": [{
                "type": "tool_result",
                "tool_use_id": tool_use_blocks[0].id,
                "content": calculator_result
            }]
        },
        {
            "role": "assistant",
            "content": thinking_blocks[1:] + tool_use_blocks[1:]
        },
        {
            "role": "user",
            "content": [{
                "type": "tool_result",
                "tool_use_id": tool_use_blocks[1].id,
                "content": database_result
            }]
        }
    ]
)

print("\nAfter database result:")
# 使用交錯思考,Claude 可以思考兩個結果
# 在制定最終回應之前
for block in response3.content:
    if block.type == "thinking":
        print(f"Final thinking: {block.thinking}")
    elif block.type == "text":
        print(f"Final response: {block.text}")
在此使用交錯思考的範例中:
  1. Claude 最初思考任務
  2. 收到計算機結果後,Claude 可以再次思考該結果的含義
  3. Claude 然後根據第一個結果決定如何查詢資料庫
  4. 收到資料庫結果後,Claude 再思考一次兩個結果,然後制定最終回應
  5. 思考預算分佈在轉向內的所有思考區塊中
此模式允許更複雜的推理鏈,其中每個工具的輸出通知下一個決定。

延伸思考與提示快取

提示快取與思考有幾個重要考慮事項:
延伸思考任務通常需要超過 5 分鐘才能完成。考慮使用1 小時快取期限來維持跨越較長思考會話和多步驟工作流的快取命中。
思考區塊上下文移除
  • 來自先前轉向的思考區塊會從上下文中移除,這可能會影響快取斷點
  • 在使用工具繼續對話時,思考區塊會被快取並在從快取讀取時計為輸入代幣
  • 這造成了權衡:雖然思考區塊在視覺上不消耗上下文視窗空間,但在快取時仍計入您的輸入代幣使用量
  • 如果思考被停用,如果您在目前工具使用轉向中傳遞思考內容,請求將失敗。在其他情況下,傳遞給 API 的思考內容會被忽略
快取失效模式
  • 思考參數的變化(啟用/停用或預算分配)會使訊息快取斷點無效
  • 交錯思考會放大快取失效,因為思考區塊可能發生在多個工具呼叫之間
  • 系統提示和工具儘管思考參數變化或區塊移除仍保持快取
雖然思考區塊被移除以進行快取和上下文計算,但在使用工具繼續對話時必須保留它們,特別是使用交錯思考時。

理解思考區塊快取行為

當使用延伸思考與工具使用時,思考區塊表現出特定的快取行為,影響代幣計數: 工作原理:
  1. 快取僅在您進行包含工具結果的後續請求時發生
  2. 進行後續請求時,先前的對話歷史記錄(包括思考區塊)可以被快取
  3. 這些快取的思考區塊在從快取讀取時計為您的使用指標中的輸入代幣
  4. 當包含非工具結果使用者區塊時,所有先前的思考區塊都會被忽略並從上下文中移除
詳細範例流程: 請求 1:
User: "What's the weather in Paris?"
回應 1:
[thinking_block_1] + [tool_use block 1]
請求 2:
User: ["What's the weather in Paris?"], 
Assistant: [thinking_block_1] + [tool_use block 1], 
User: [tool_result_1, cache=True]
回應 2:
[thinking_block_2] + [text block 2]
請求 2 寫入請求內容的快取(不是回應)。快取包括原始使用者訊息、第一個思考區塊、工具使用區塊和工具結果。 請求 3:
User: ["What's the weather in Paris?"], 
Assistant: [thinking_block_1] + [tool_use block 1], 
User: [tool_result_1, cache=True], 
Assistant: [thinking_block_2] + [text block 2], 
User: [Text response, cache=True]
因為包含了非工具結果使用者區塊,所有先前的思考區塊都會被忽略。此請求將被處理為與以下相同:
User: ["What's the weather in Paris?"], 
Assistant: [tool_use block 1], 
User: [tool_result_1, cache=True], 
Assistant: [text block 2], 
User: [Text response, cache=True]
關鍵點:
  • 即使沒有明確的 cache_control 標記,此快取行為也會自動發生
  • 無論使用常規思考還是交錯思考,此行為都是一致的
from anthropic import Anthropic
import requests
from bs4 import BeautifulSoup

client = Anthropic()

def fetch_article_content(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')

    # 移除指令碼和樣式元素
    for script in soup(["script", "style"]):
        script.decompose()

    # 取得文字
    text = soup.get_text()

    # 分解成行並移除每行上的前導和尾隨空格
    lines = (line.strip() for line in text.splitlines())
    # 將多個標題分解成一行
    chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
    # 刪除空行
    text = '\n'.join(chunk for chunk in chunks if chunk)

    return text

# 取得文章內容
book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
book_content = fetch_article_content(book_url)
# 使用足夠的文字進行快取(前幾章)
LARGE_TEXT = book_content[:5000]

SYSTEM_PROMPT=[
    {
        "type": "text",
        "text": "You are an AI assistant that is tasked with literary analysis. Analyze the following text carefully.",
    },
    {
        "type": "text",
        "text": LARGE_TEXT,
        "cache_control": {"type": "ephemeral"}
    }
]

MESSAGES = [
    {
        "role": "user",
        "content": "Analyze the tone of this passage."
    }
]

# 第一個請求 - 建立快取
print("First request - establishing cache")
response1 = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=20000,
    thinking={
        "type": "enabled",
        "budget_tokens": 4000
    },
    system=SYSTEM_PROMPT,
    messages=MESSAGES
)

print(f"First response usage: {response1.usage}")

MESSAGES.append({
    "role": "assistant",
    "content": response1.content
})
MESSAGES.append({
    "role": "user",
    "content": "Analyze the characters in this passage."
})
# 第二個請求 - 相同的思考參數(預期快取命中)
print("\nSecond request - same thinking parameters (cache hit expected)")
response2 = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=20000,
    thinking={
        "type": "enabled",
        "budget_tokens": 4000
    },
    system=SYSTEM_PROMPT,
    messages=MESSAGES
)

print(f"Second response usage: {response2.usage}")

# 第三個請求 - 不同的思考參數(訊息快取未命中)
print("\nThird request - different thinking parameters (cache miss for messages)")
response3 = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=20000,
    thinking={
        "type": "enabled",
        "budget_tokens": 8000  # 已變更思考預算
    },
    system=SYSTEM_PROMPT,  # 系統提示保持快取
    messages=MESSAGES  # 訊息快取已失效
)

print(f"Third response usage: {response3.usage}")
from anthropic import Anthropic
import requests
from bs4 import BeautifulSoup

client = Anthropic()

def fetch_article_content(url):
    response = requests.get(url)
    soup = BeautifulSoup(response.content, 'html.parser')

    # 移除指令碼和樣式元素
    for script in soup(["script", "style"]):
        script.decompose()

    # 取得文字
    text = soup.get_text()

    # 分解成行並移除每行上的前導和尾隨空格
    lines = (line.strip() for line in text.splitlines())
    # 將多個標題分解成一行
    chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
    # 刪除空行
    text = '\n'.join(chunk for chunk in chunks if chunk)

    return text

# 取得文章內容
book_url = "https://www.gutenberg.org/cache/epub/1342/pg1342.txt"
book_content = fetch_article_content(book_url)
# 使用足夠的文字進行快取(前幾章)
LARGE_TEXT = book_content[:5000]

# 無系統提示 - 改為在訊息中快取
MESSAGES = [
    {
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": LARGE_TEXT,
                "cache_control": {"type": "ephemeral"},
            },
            {
                "type": "text",
                "text": "Analyze the tone of this passage."
            }
        ]
    }
]

# 第一個請求 - 建立快取
print("First request - establishing cache")
response1 = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=20000,
    thinking={
        "type": "enabled",
        "budget_tokens": 4000
    },
    messages=MESSAGES
)

print(f"First response usage: {response1.usage}")

MESSAGES.append({
    "role": "assistant",
    "content": response1.content
})
MESSAGES.append({
    "role": "user",
    "content": "Analyze the characters in this passage."
})
# 第二個請求 - 相同的思考參數(預期快取命中)
print("\nSecond request - same thinking parameters (cache hit expected)")
response2 = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=20000,
    thinking={
        "type": "enabled",
        "budget_tokens": 4000  # 相同的思考預算
    },
    messages=MESSAGES
)

print(f"Second response usage: {response2.usage}")

MESSAGES.append({
    "role": "assistant",
    "content": response2.content
})
MESSAGES.append({
    "role": "user",
    "content": "Analyze the setting in this passage."
})

# 第三個請求 - 不同的思考預算(預期快取未命中)
print("\nThird request - different thinking budget (cache miss expected)")
response3 = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=20000,
    thinking={
        "type": "enabled",
        "budget_tokens": 8000  # 不同的思考預算破壞快取
    },
    messages=MESSAGES
)

print(f"Third response usage: {response3.usage}")
以下是指令碼的輸出(您可能會看到略有不同的數字)
First request - establishing cache
First response usage: { cache_creation_input_tokens: 1370, cache_read_input_tokens: 0, input_tokens: 17, output_tokens: 700 }

Second request - same thinking parameters (cache hit expected)

Second response usage: { cache_creation_input_tokens: 0, cache_read_input_tokens: 1370, input_tokens: 303, output_tokens: 874 }

Third request - different thinking budget (cache miss expected)
Third response usage: { cache_creation_input_tokens: 1370, cache_read_input_tokens: 0, input_tokens: 747, output_tokens: 619 }
此範例演示當快取設定在訊息陣列中時,變更思考參數(budget_tokens 從 4000 增加到 8000)使快取無效。第三個請求顯示沒有快取命中,cache_creation_input_tokens=1370cache_read_input_tokens=0,證明當思考參數變化時訊息快取無效。

延伸思考的最大代幣和上下文視窗大小

在較舊的 Claude 模型(Claude Sonnet 3.7 之前)中,如果提示代幣和 max_tokens 的總和超過模型的上下文視窗,系統會自動調整 max_tokens 以適應上下文限制。這意味著您可以設定一個大的 max_tokens 值,系統會根據需要自動減少它。 使用 Claude 3.7 和 4 模型,max_tokens(啟用思考時包括您的思考預算)被強制執行為嚴格限制。如果提示代幣 + max_tokens 超過上下文視窗大小,系統現在將傳回驗證錯誤。
您可以閱讀我們的上下文視窗指南以進行更徹底的深入探討。

延伸思考的上下文視窗

計算啟用思考時的上下文視窗使用量時,需要注意一些事項:
  • 來自先前轉向的思考區塊被移除,不計入您的上下文視窗
  • 目前轉向思考計入該轉向的 max_tokens 限制
下圖演示了啟用延伸思考時的專門代幣管理: 延伸思考的上下文視窗圖 有效上下文視窗計算為:
context window =
  (current input tokens - previous thinking tokens) +
  (thinking tokens + encrypted thinking tokens + text output tokens)
我們建議使用代幣計數 API 來獲得您特定用例的準確代幣計數,特別是在使用包含思考的多轉向對話時。

延伸思考與工具使用的上下文視窗

當使用延伸思考與工具使用時,思考區塊必須明確保留並與工具結果一起返回。 延伸思考與工具使用的有效上下文視窗計算變為:
context window =
  (current input tokens + previous thinking tokens + tool use tokens) +
  (thinking tokens + encrypted thinking tokens + text output tokens)
下圖說明了延伸思考與工具使用的代幣管理: 延伸思考與工具使用的上下文視窗圖

使用延伸思考管理代幣

鑑於 Claude 3.7 和 4 模型的上下文視窗和 max_tokens 行為,您可能需要:
  • 更積極地監控和管理您的代幣使用
  • 隨著提示長度的變化調整 max_tokens
  • 可能更頻繁地使用代幣計數端點
  • 意識到先前的思考區塊不會在您的上下文視窗中累積
此變更已進行以提供更可預測和透明的行為,特別是隨著最大代幣限制大幅增加。

思考加密

完整思考內容被加密並在 signature 欄位中返回。此欄位用於驗證思考區塊是否由 Claude 生成,當傳回 API 時。
僅當使用帶延伸思考的工具時才嚴格必要傳回思考區塊。否則您可以從先前的轉向中省略思考區塊,或讓 API 為您移除它們(如果您傳回它們)。如果傳回思考區塊,我們建議按照您接收的方式傳回所有內容以保持一致性並避免潛在問題。
以下是關於思考加密的一些重要考慮事項:
  • 串流回應時,簽名通過 content_block_delta 內的 signature_deltacontent_block_stop 事件之前新增。
  • signature 值在 Claude 4 模型中的長度明顯長於先前的模型。
  • signature 欄位是一個不透明欄位,不應被解釋或解析 - 它僅出於驗證目的而存在。
  • signature 值在平台之間相容(Claude API、Amazon BedrockVertex AI)。在一個平台上生成的值將與另一個平台相容。

思考編輯

偶爾 Claude 的內部推理會被我們的安全系統標記。發生這種情況時,我們會加密 thinking 區塊的部分或全部,並將其作為 redacted_thinking 區塊返回給您。redacted_thinking 區塊在傳回 API 時被解密,允許 Claude 繼續其回應而不會失去上下文。 在構建使用延伸思考的面向客戶的應用程式時:
  • 請注意 redacted thinking 區塊包含出於安全原因未加密的內容
  • 考慮提供簡單的解釋,例如:“Claude 的某些內部推理已自動加密以確保安全。這不會影響回應的品質。”
  • 如果向使用者顯示思考區塊,您可以篩選出 redacted 區塊,同時保留正常思考區塊
  • 透明地說明使用延伸思考功能可能偶爾導致某些推理被加密
  • 實施適當的錯誤處理以優雅地管理 redacted thinking,而不會破壞您的 UI
以下是顯示正常和 redacted thinking 區塊的範例:
{
  "content": [
    {
      "type": "thinking",
      "thinking": "讓我逐步分析這個...",
      "signature": "WaUjzkypQ2mUEVM36O2TxuC06KN8xyfbJwyem2dw3URve/op91XWHOEBLLqIOMfFG/UvLEczmEsUjavL...."
    },
    {
      "type": "redacted_thinking",
      "data": "EmwKAhgBEgy3va3pzix/LafPsn4aDFIT2Xlxh0L5L8rLVyIwxtE3rAFBa8cr3qpPkNRj2YfWXGmKDxH4mPnZ5sQ7vB9URj2pLmN3kF8/dW5hR7xJ0aP1oLs9yTcMnKVf2wRpEGjH9XZaBt4UvDcPrQ..."
    },
    {
      "type": "text",
      "text": "根據我的分析..."
    }
  ]
}
在您的輸出中看到 redacted thinking 區塊是預期的行為。模型仍然可以使用此 redacted 推理來通知其回應,同時維持安全護欄。如果您需要在應用程式中測試 redacted thinking 處理,可以使用此特殊測試字串作為提示:ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING_46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB
在多轉向對話中將 thinkingredacted_thinking 區塊傳回 API 時,您必須將完整的未修改區塊傳回 API 以用於最後的助手轉向。這對於維持模型的推理流至關重要。我們建議始終將所有思考區塊傳回 API。如需更多詳細資訊,請參閱上面的保留思考區塊部分。
此範例演示如何處理當 Claude 的內部推理包含被安全系統標記的內容時可能出現的 redacted_thinking 區塊:
import anthropic

client = anthropic.Anthropic()

# 使用觸發 redacted thinking 的特殊提示(僅用於演示目的)
response = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=16000,
    thinking={
        "type": "enabled",
        "budget_tokens": 10000
    },
    messages=[{
        "role": "user",
        "content": "ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING_46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB"
    }]
)

# 識別 redacted thinking 區塊
has_redacted_thinking = any(
    block.type == "redacted_thinking" for block in response.content
)

if has_redacted_thinking:
    print("Response contains redacted thinking blocks")
    # 這些區塊在後續請求中仍然可用

    # 提取所有區塊(redacted 和非 redacted)
    all_thinking_blocks = [
        block for block in response.content
        if block.type in ["thinking", "redacted_thinking"]
    ]

    # 在傳遞到後續請求時,包括所有區塊而不進行修改
    # 這保留了 Claude 推理的完整性

    print(f"Found {len(all_thinking_blocks)} thinking blocks total")
    print(f"These blocks are still billable as output tokens")

不同模型版本間的思考差異

訊息 API 在 Claude Sonnet 3.7 和 Claude 4 模型之間以不同方式處理思考,主要是在編輯和摘要行為方面。 請參閱下表以進行簡明比較:
功能Claude Sonnet 3.7Claude 4 模型
思考輸出傳回完整思考輸出傳回摘要思考
交錯思考不支援使用 interleaved-thinking-2025-05-14 beta 標頭支援

定價

延伸思考使用標準代幣定價方案:
模型基本輸入代幣快取寫入快取命中輸出代幣
Claude Opus 4.1$15 / MTok$18.75 / MTok$1.50 / MTok$75 / MTok
Claude Opus 4$15 / MTok$18.75 / MTok$1.50 / MTok$75 / MTok
Claude Sonnet 4.5$3 / MTok$3.75 / MTok$0.30 / MTok$15 / MTok
Claude Sonnet 4$3 / MTok$3.75 / MTok$0.30 / MTok$15 / MTok
Claude Sonnet 3.7$3 / MTok$3.75 / MTok$0.30 / MTok$15 / MTok
思考過程產生的費用包括:
  • 思考期間使用的代幣(輸出代幣)
  • 後續請求中包含的最後助手轉向的思考區塊(輸入代幣)
  • 標準文字輸出代幣
啟用延伸思考時,會自動包含專門的系統提示以支援此功能。
使用摘要思考時:
  • 輸入代幣:原始請求中的代幣(不包括先前轉向的思考代幣)
  • 輸出代幣(計費):Claude 內部生成的原始思考代幣
  • 輸出代幣(可見):您在回應中看到的摘要思考代幣
  • 無費用:用於生成摘要的代幣
計費的輸出代幣計數將不符合回應中的可見代幣計數。您需要為完整思考過程付費,而不是您看到的摘要。

延伸思考的最佳實踐和考慮事項

使用思考預算

  • 預算最佳化:最小預算為 1,024 代幣。我們建議從最小值開始,逐步增加思考預算以找到您的用例的最佳範圍。較高的代幣計數可實現更全面的推理,但根據任務的不同會有遞減的回報。增加預算可以改善回應品質,但代價是增加延遲。對於關鍵任務,測試不同的設定以找到最佳平衡。請注意,思考預算是目標而不是嚴格限制 - 實際代幣使用可能因任務而異。
  • 起點:為複雜任務從較大的思考預算(16k+ 代幣)開始,並根據您的需求進行調整。
  • 大型預算:對於超過 32k 的思考預算,我們建議使用批次處理以避免網路問題。推動模型思考超過 32k 代幣的請求會導致長時間運行的請求,可能會遇到系統超時和開放連接限制。
  • 代幣使用追蹤:監控思考代幣使用以最佳化成本和效能。

效能考慮

  • 回應時間:為推理過程所需的額外處理做好準備,可能導致更長的回應時間。考慮生成思考區塊可能會增加整體回應時間。
  • 串流要求:當 max_tokens 大於 21,333 時需要串流。串流時,準備好處理思考和文字內容區塊,因為它們到達。

功能相容性

  • 思考與 temperaturetop_k 修改以及強制工具使用不相容。
  • 啟用思考時,您可以將 top_p 設定為 1 到 0.95 之間的值。
  • 啟用思考時無法預填充回應。
  • 思考預算的變化會使包含訊息的快取提示前綴無效。但是,快取系統提示和工具定義在思考參數變化時將繼續工作。

使用指南

  • 任務選擇:對特別複雜的任務使用延伸思考,這些任務受益於逐步推理,如數學、編碼和分析。
  • 上下文處理:您不需要自己移除先前的思考區塊。Claude API 自動忽略先前轉向的思考區塊,在計算上下文使用時不包括它們。
  • 提示工程:如果您想最大化 Claude 的思考能力,請查看我們的延伸思考提示提示

後續步驟