Loading...
    • 構建
    • 管理
    • 模型和定價
    • 客戶端 SDK
    • API 參考
    Search...
    ⌘K
    第一步
    Claude 簡介快速開始
    使用 Claude 構建
    功能概覽使用 Messages APIClaude API 技能處理停止原因
    模型功能
    擴展思考自適應思考努力任務預算 (測試版)快速模式 (測試版:研究預覽)結構化輸出引用流式傳輸消息批量處理搜索結果流式傳輸拒絕多語言支持嵌入
    工具
    概覽工具使用如何運作網絡搜索工具網絡獲取工具代碼執行工具顧問工具記憶工具Bash 工具計算機使用工具文本編輯器工具
    工具基礎設施
    工具參考工具搜索程序化工具調用細粒度工具流式傳輸
    上下文管理
    上下文窗口壓縮上下文編輯提示詞緩存令牌計數
    處理文件
    Files APIPDF 支持圖像和視覺
    技能
    概覽快速開始最佳實踐企業技能API 中的技能
    MCP
    遠程 MCP 服務器MCP 連接器
    提示詞工程
    概覽提示詞最佳實踐Console 提示詞工具
    測試和評估
    定義成功並構建評估在 Console 中使用評估工具降低延遲
    加強護欄
    減少幻覺提高輸出一致性緩解越獄減少提示詞洩露
    資源
    詞彙表
    發佈說明
    Claude Platform
    Console
    Log in
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...
    Loading...

    Solutions

    • AI agents
    • Code modernization
    • Coding
    • Customer support
    • Education
    • Financial services
    • Government
    • Life sciences

    Partners

    • Amazon Bedrock
    • Google Cloud's Vertex AI

    Learn

    • Blog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Company

    • Anthropic
    • Careers
    • Economic Futures
    • Research
    • News
    • Responsible Scaling Policy
    • Security and compliance
    • Transparency

    Learn

    • Blog
    • Courses
    • Use cases
    • Connectors
    • Customer stories
    • Engineering at Anthropic
    • Events
    • Powered by Claude
    • Service partners
    • Startups program

    Help and security

    • Availability
    • Status
    • Support
    • Discord

    Terms and policies

    • Privacy policy
    • Responsible disclosure policy
    • Terms of service: Commercial
    • Terms of service: Consumer
    • Usage policy
    模型功能

    串流訊息

    了解如何使用伺服器發送事件 (SSE) 來串流 Claude API 回應

    Was this page helpful?

    • 使用 SDK 進行串流
    • Ping 事件
    • 內容區塊 delta 類型
    • 文字 delta
    • 輸入 JSON delta
    • 思考 delta
    • 完整 HTTP 串流回應
    • Claude 4.5 及更早版本
    • Claude 4.6

    建立訊息時,您可以設定 "stream": true 以使用伺服器發送事件 (SSE) 來逐步串流回應。

    使用 SDK 進行串流

    Python 和 TypeScript SDK 提供多種串流方式。PHP SDK 透過 createStream() 提供串流功能。Python SDK 允許同步和非同步串流。請參閱每個 SDK 中的文件以了解詳細資訊。

    client = anthropic.Anthropic()
    
    with client.messages.stream(
        max_tokens=1024,
        messages=[{"role": "user", "content": "Hello"}],
        model="claude-opus-4-7",
    ) as stream:
        for text in stream.text_stream:
            print(text, end="", flush=True)

    取得最終訊息而不處理事件

    如果您不需要在回應到達時處理文字,SDK 提供了一種方式來在幕後使用串流,同時返回完整的 Message 物件,與 .create() 返回的物件相同。這對於具有大型 max_tokens 值的請求特別有用,其中 SDK 需要串流以避免 HTTP 逾時。

    .stream() 呼叫透過伺服器發送事件保持 HTTP 連線活躍,然後 .get_final_message()(Python)或 .finalMessage()(TypeScript)累積所有事件並返回完整的 Message 物件。在 Go 中,您在串流迴圈內呼叫 message.Accumulate(event) 來建立相同的完整 Message。在 Java 中,使用 MessageAccumulator.create() 並在每個事件上呼叫 accumulator.accumulate(event)。在 Ruby 中,在串流上呼叫 .accumulated_message。在 PHP SDK 中,您手動迭代串流事件以累積回應。

    事件類型

    每個伺服器發送事件都包含一個命名的事件類型和相關的 JSON 資料。每個事件使用 SSE 事件名稱(例如 event: message_stop),並在其資料中包含匹配的事件 type。

    每個串流使用以下事件流:

    1. message_start:包含一個 Message 物件,其 content 為空。
    2. 一系列內容區塊,每個區塊都有一個 content_block_start、一個或多個 content_block_delta 事件和一個 content_block_stop 事件。每個內容區塊都有一個 index,對應於其在最終訊息 content 陣列中的索引。
    3. 一個或多個 message_delta 事件,表示對最終 Message 物件的頂層變更。
    4. 最後一個 message_stop 事件。

    message_delta 事件的 usage 欄位中顯示的權杖計數是累積的。

    Ping 事件

    事件串流也可能包含任何數量的 ping 事件。

    錯誤事件

    API 可能偶爾在事件串流中發送錯誤。例如,在高使用量期間,您可能會收到 overloaded_error,在非串流上下文中通常對應於 HTTP 529:

    範例錯誤
    event: error
    data: {"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}

    其他事件

    根據版本控制政策,可能會新增新的事件類型,您的程式碼應該優雅地處理未知的事件類型。

    內容區塊 delta 類型

    每個 content_block_delta 事件都包含一個 delta,其類型會更新給定 index 處的 content 區塊。

    文字 delta

    text 內容區塊 delta 看起來像:

    文字 delta
    event: content_block_delta
    data: {"type": "content_block_delta","index": 0,"delta": {"type": "text_delta", "text": "ello frien"}}

    輸入 JSON delta

    tool_use 內容區塊的 delta 對應於區塊的 input 欄位的更新。為了支援最大的粒度,delta 是部分 JSON 字串,而最終的 tool_use.input 始終是物件。

    您可以累積字串 delta,並在收到 content_block_stop 事件後解析 JSON,方法是使用像 Pydantic 這樣的庫來進行部分 JSON 解析,或使用 SDK,它們提供幫助程式來存取已解析的增量值。

    tool_use 內容區塊 delta 看起來像:

    輸入 JSON delta
    event: content_block_delta
    data: {"type": "content_block_delta","index": 1,"delta": {"type": "input_json_delta","partial_json": "{\"location\": \"San Fra"}}

    注意:目前的模型一次只支援從 input 發出一個完整的鍵和值屬性。因此,使用工具時,在模型工作時串流事件之間可能會有延遲。一旦累積了 input 鍵和值,它們就會作為多個 content_block_delta 事件發出,並帶有分塊的部分 json,以便該格式可以在未來自動支援更精細的粒度。

    思考 delta

    使用擴展思考並啟用串流時,您將透過 thinking_delta 事件接收思考內容。這些 delta 對應於 thinking 內容區塊的 thinking 欄位。

    對於思考內容,在 content_block_stop 事件之前會發送一個特殊的 signature_delta 事件。此簽名用於驗證思考區塊的完整性。

    當在思考配置上設定 display: "omitted" 時,不會發送 thinking_delta 事件。思考區塊開啟,接收單個 signature_delta,然後關閉。請參閱控制思考顯示。

    典型的思考 delta 看起來像:

    思考 delta
    event: content_block_delta
    data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}

    簽名 delta 看起來像:

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

    完整 HTTP 串流回應

    使用串流模式時,請使用用戶端 SDK。但是,如果您正在建立直接 API 整合,您需要自己處理這些事件。

    串流回應由以下部分組成:

    1. 一個 message_start 事件
    2. 可能多個內容區塊,每個區塊包含:
      • 一個 content_block_start 事件
      • 可能多個 content_block_delta 事件
      • 一個 content_block_stop 事件
    3. 一個 message_delta 事件
    4. 一個 message_stop 事件

    整個回應中也可能分散著 ping 事件。有關格式的更多詳細資訊,請參閱事件類型。

    基本串流請求

    回應
    event: message_start
    data: {"type": "message_start", "message": {"id": "msg_1nZdL29xx5MUA1yADyHTEsnR8uuvGzszyY", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-4-7", "stop_reason": null, "stop_sequence": null, "usage": {"input_tokens": 25, "output_tokens": 1}}}
    
    event: content_block_start
    data: {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}}
    
    event: ping
    data: {"type": "ping"}
    
    event: content_block_delta
    data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "Hello"}}
    
    event: content_block_delta
    data: {"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": "!"}}
    
    event: content_block_stop
    data: {"type": "content_block_stop", "index": 0}
    
    event: message_delta
    data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence":null}, "usage": {"output_tokens": 15}}
    
    event: message_stop
    data: {"type": "message_stop"}
    

    使用工具的串流請求

    工具使用支援細粒度串流用於參數值。使用 eager_input_streaming 為每個工具啟用它。

    此請求要求 Claude 使用工具來報告天氣。

    Response
    event: message_start
    data: {"type":"message_start","message":{"id":"msg_014p7gG3wDgGV9EUtLvnow3U","type":"message","role":"assistant","model":"claude-opus-4-7","stop_sequence":null,"usage":{"input_tokens":472,"output_tokens":2},"content":[],"stop_reason":null}}
    
    event: content_block_start
    data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
    
    event: ping
    data: {"type": "ping"}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Okay"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" let"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"'s"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" check"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" weather"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" San"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Francisco"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":","}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" CA"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":":"}}
    
    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":"tool_use","id":"toolu_01T1x1fJ34qAmk2tNTrN7Up6","name":"get_weather","input":{}}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"location\":"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"San"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" Francisc"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"o,"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" CA\""}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":","}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" "}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"\"unit\": \"fah"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"renheit\"}"}}
    
    event: content_block_stop
    data: {"type":"content_block_stop","index":1}
    
    event: message_delta
    data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":89}}
    
    event: message_stop
    data: {"type":"message_stop"}

    使用延伸思考的串流請求

    此請求啟用延伸思考與串流,以查看 Claude 的逐步推理。

    Response
    event: message_start
    data: {"type": "message_start", "message": {"id": "msg_01...", "type": "message", "role": "assistant", "content": [], "model": "claude-opus-4-7", "stop_reason": null, "stop_sequence": null}}
    
    event: content_block_start
    data: {"type": "content_block_start", "index": 0, "content_block": {"type": "thinking", "thinking": "", "signature": ""}}
    
    event: content_block_delta
    data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "I need to find the GCD of 1071 and 462 using the Euclidean algorithm.\n\n1071 = 2 × 462 + 147"}}
    
    event: content_block_delta
    data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n462 = 3 × 147 + 21"}}
    
    event: content_block_delta
    data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\n147 = 7 × 21 + 0"}}
    
    event: content_block_delta
    data: {"type": "content_block_delta", "index": 0, "delta": {"type": "thinking_delta", "thinking": "\nThe remainder is 0, so GCD(1071, 462) = 21."}}
    
    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": "The greatest common divisor of 1071 and 462 is **21**."}}
    
    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 搜尋網路以取得目前的天氣資訊。

    Response
    event: message_start
    data: {"type":"message_start","message":{"id":"msg_01G...","type":"message","role":"assistant","model":"claude-opus-4-7","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":2679,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":3}}}
    
    event: content_block_start
    data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"I'll check"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the current weather in New York City for you"}}
    
    event: ping
    data: {"type": "ping"}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."}}
    
    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":"server_tool_use","id":"srvtoolu_014hJH82Qum7Td6UV8gDXThB","name":"web_search","input":{}}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"query"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"\":"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"weather"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" NY"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"C to"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"day\"}"}}
    
    event: content_block_stop
    data: {"type":"content_block_stop","index":1 }
    
    event: content_block_start
    data: {"type":"content_block_start","index":2,"content_block":{"type":"web_search_tool_result","tool_use_id":"srvtoolu_014hJH82Qum7Td6UV8gDXThB","content":[{"type":"web_search_result","title":"Weather in New York City in May 2025 (New York) - detailed Weather Forecast for a month","url":"https://world-weather.info/forecast/usa/new_york/may-2025/","encrypted_content":"Ev0DCioIAxgCIiQ3NmU4ZmI4OC1k...","page_age":null},...]}}
    
    event: content_block_stop
    data: {"type":"content_block_stop","index":2}
    
    event: content_block_start
    data: {"type":"content_block_start","index":3,"content_block":{"type":"text","text":""}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":"Here's the current weather information for New York"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":" City:\n\n# Weather"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":" in New York City"}}
    
    event: content_block_delta
    data: {"type":"content_block_delta","index":3,"delta":{"type":"text_delta","text":"\n\n"}}
    
    ...
    
    event: content_block_stop
    data: {"type":"content_block_stop","index":17}
    
    event: message_delta
    data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":10682,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":510,"server_tool_use":{"web_search_requests":1}}}
    
    event: message_stop
    data: {"type":"message_stop"}

    錯誤恢復

    Claude 4.5 及更早版本

    對於 Claude 4.5 模型及更早版本,您可以恢復因網路問題、逾時或其他錯誤而中斷的串流請求,方法是從串流中斷的位置繼續。此方法可讓您避免重新處理整個回應。

    基本恢復策略涉及:

    1. 擷取部分回應:儲存在錯誤發生前成功接收的所有內容
    2. 構建續行請求:建立新的 API 請求,其中包含部分助手回應作為新助手訊息的開頭
    3. 繼續串流:從中斷的位置繼續接收回應的其餘部分

    Claude 4.6

    對於 Claude 4.6 模型,您應該新增一個使用者訊息,指示模型從中斷的位置繼續。例如:

    Sample prompt
    Your previous response was interrupted and ended with [previous_response]. Continue from where you left off.

    錯誤恢復最佳實踐

    1. 使用 SDK 功能:利用 SDK 的內建訊息累積和錯誤處理功能
    2. 處理內容類型:注意訊息可以包含多個內容區塊(text、tool_use、thinking)。工具使用和延伸思考區塊無法部分恢復。您可以從最近的文字區塊繼續串流。
    client = anthropic.Anthropic()
    
    with client.messages.stream(
        max_tokens=128000,
        messages=[{"role": "user", "content": "Write a detailed analysis..."}],
        model="claude-opus-4-7",
    ) as stream:
        message = stream.get_final_message()
    
    print(message.content[0].text)
    client = anthropic.Anthropic()
    
    with client.messages.stream(
        model="claude-opus-4-7",
        messages=[{"role": "user", "content": "Hello"}],
        max_tokens=256,
    ) as stream:
        for text in stream.text_stream:
            print(text, end="", flush=True)
    client = anthropic.Anthropic()
    
    tools = [
        {
            "name": "get_weather",
            "description": "Get the current weather in a given location",
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g. San Francisco, CA",
                    }
                },
                "required": ["location"],
            },
        }
    ]
    
    with client.messages.stream(
        model="claude-opus-4-7",
        max_tokens=1024,
        tools=tools,
        tool_choice={"type": "any"},
        messages=[
            {"role": "user", "content": "What is the weather like in San Francisco?"}
        ],
    ) as stream:
        for text in stream.text_stream:
            print(text, end="", flush=True)
    client = anthropic.Anthropic()
    
    with client.messages.stream(
        model="claude-opus-4-7",
        max_tokens=20000,
        thinking={"type": "adaptive", "display": "summarized"},
        messages=[
            {
                "role": "user",
                "content": "What is the greatest common divisor of 1071 and 462?",
            }
        ],
    ) as stream:
        for event in stream:
            if event.type == "content_block_delta":
                if event.delta.type == "thinking_delta":
                    print(event.delta.thinking, end="", flush=True)
                elif event.delta.type == "text_delta":
                    print(event.delta.text, end="", flush=True)
    client = anthropic.Anthropic()
    
    with client.messages.stream(
        model="claude-opus-4-7",
        max_tokens=1024,
        tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}],
        messages=[
            {"role": "user", "content": "What is the weather like in New York City today?"}
        ],
    ) as stream:
        for text in stream.text_stream:
            print(text, end="", flush=True)