使用 API
處理停止原因
了解如何處理 Claude API 回應中的 stop_reason 欄位,以建立更強健的應用程式。
當您向 Messages API 發出請求時,Claude 的回應會包含一個 stop_reason
欄位,指示模型為何停止生成回應。理解這些值對於建立能適當處理不同回應類型的強健應用程式至關重要。
有關 API 回應中 stop_reason
的詳細資訊,請參閱 Messages API 參考。
什麼是 stop_reason?
stop_reason
欄位是每個成功的 Messages API 回應的一部分。與表示處理請求失敗的錯誤不同,stop_reason
告訴您 Claude 為何成功完成其回應生成。
Example response
{
"id": "msg_01234",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Here's the answer to your question..."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 100,
"output_tokens": 50
}
}
停止原因值
end_turn
最常見的停止原因。表示 Claude 自然地完成了其回應。
if response.stop_reason == "end_turn":
# 處理完整回應
print(response.content[0].text)
max_tokens
Claude 停止是因為達到了您在請求中指定的 max_tokens
限制。
# 具有有限 token 的請求
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=10,
messages=[{"role": "user", "content": "Explain quantum physics"}]
)
if response.stop_reason == "max_tokens":
# 回應被截斷
print("Response was cut off at token limit")
# 考慮發出另一個請求以繼續
stop_sequence
Claude 遇到了您的自定義停止序列之一。
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
stop_sequences=["END", "STOP"],
messages=[{"role": "user", "content": "Generate text until you say END"}]
)
if response.stop_reason == "stop_sequence":
print(f"Stopped at sequence: {response.stop_sequence}")
tool_use
Claude 正在呼叫工具並期望您執行它。
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[weather_tool],
messages=[{"role": "user", "content": "What's the weather?"}]
)
if response.stop_reason == "tool_use":
# 提取並執行工具
for content in response.content:
if content.type == "tool_use":
result = execute_tool(content.name, content.input)
# 將結果返回給 Claude 以獲得最終回應
pause_turn
與伺服器工具(如網路搜尋)一起使用,當 Claude 需要暫停長時間運行的操作時。
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=[{"type": "web_search_20250305", "name": "web_search"}],
messages=[{"role": "user", "content": "Search for latest AI news"}]
)
if response.stop_reason == "pause_turn":
# 繼續對話
messages = [
{"role": "user", "content": original_query},
{"role": "assistant", "content": response.content}
]
continuation = client.messages.create(
model="claude-sonnet-4-20250514",
messages=messages,
tools=[{"type": "web_search_20250305", "name": "web_search"}]
)
refusal
Claude 由於安全考量拒絕生成回應。
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "[Unsafe request]"}]
)
if response.stop_reason == "refusal":
# Claude 拒絕回應
print("Claude was unable to process this request")
# 考慮重新措辭或修改請求
處理停止原因的最佳實踐
1. 始終檢查 stop_reason
養成在回應處理邏輯中檢查 stop_reason
的習慣:
def handle_response(response):
if response.stop_reason == "tool_use":
return handle_tool_use(response)
elif response.stop_reason == "max_tokens":
return handle_truncation(response)
elif response.stop_reason == "pause_turn":
return handle_pause(response)
elif response.stop_reason == "refusal":
return handle_refusal(response)
else:
# 處理 end_turn 和其他情況
return response.content[0].text
2. 優雅地處理 max_tokens
當回應由於 token 限制而被截斷時:
def handle_truncated_response(response):
if response.stop_reason == "max_tokens":
# 選項 1:警告使用者
return f"{response.content[0].text}\n\n[Response truncated due to length]"
# 選項 2:繼續生成
messages = [
{"role": "user", "content": original_prompt},
{"role": "assistant", "content": response.content[0].text}
]
continuation = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=messages + [{"role": "user", "content": "Please continue"}]
)
return response.content[0].text + continuation.content[0].text
3. 為 pause_turn 實施重試邏輯
對於可能暫停的伺服器工具:
def handle_paused_conversation(initial_response, max_retries=3):
response = initial_response
messages = [{"role": "user", "content": original_query}]
for attempt in range(max_retries):
if response.stop_reason != "pause_turn":
break
messages.append({"role": "assistant", "content": response.content})
response = client.messages.create(
model="claude-sonnet-4-20250514",
messages=messages,
tools=original_tools
)
return response
停止原因與錯誤
區分 stop_reason
值和實際錯誤很重要:
停止原因(成功回應)
- 回應主體的一部分
- 指示生成正常停止的原因
- 回應包含有效內容
錯誤(失敗請求)
- HTTP 狀態碼 4xx 或 5xx
- 指示請求處理失敗
- 回應包含錯誤詳細資訊
try:
response = client.messages.create(...)
# 使用 stop_reason 處理成功回應
if response.stop_reason == "max_tokens":
print("Response was truncated")
except anthropic.APIError as e:
# 處理實際錯誤
if e.status_code == 429:
print("Rate limit exceeded")
elif e.status_code == 500:
print("Server error")
串流考量
使用串流時,stop_reason
是:
- 在初始
message_start
事件中為null
- 在
message_delta
事件中提供 - 在任何其他事件中不提供
with client.messages.stream(...) as stream:
for event in stream:
if event.type == "message_delta":
stop_reason = event.delta.stop_reason
if stop_reason:
print(f"Stream ended with: {stop_reason}")
常見模式
處理工具使用工作流程
def complete_tool_workflow(client, user_query, tools):
messages = [{"role": "user", "content": user_query}]
while True:
response = client.messages.create(
model="claude-sonnet-4-20250514",
messages=messages,
tools=tools
)
if response.stop_reason == "tool_use":
# 執行工具並繼續
tool_results = execute_tools(response.content)
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
else:
# 最終回應
return response
確保完整回應
def get_complete_response(client, prompt, max_attempts=3):
messages = [{"role": "user", "content": prompt}]
full_response = ""
for _ in range(max_attempts):
response = client.messages.create(
model="claude-sonnet-4-20250514",
messages=messages,
max_tokens=4096
)
full_response += response.content[0].text
if response.stop_reason != "max_tokens":
break
# 從中斷處繼續
messages = [
{"role": "user", "content": prompt},
{"role": "assistant", "content": full_response},
{"role": "user", "content": "Please continue from where you left off."}
]
return full_response
通過適當處理 stop_reason
值,您可以建立更強健的應用程式,優雅地處理不同的回應情況並提供更好的使用者體驗。