Messages APIにリクエストを行うと、Claudeのレスポンスには、モデルがレスポンス生成を停止した理由を示すstop_reason
フィールドが含まれます。これらの値を理解することは、異なるレスポンスタイプを適切に処理する堅牢なアプリケーションを構築するために非常に重要です。
APIレスポンスのstop_reason
の詳細については、Messages APIリファレンスを参照してください。
stop_reasonとは何か?
stop_reason
フィールドは、すべての成功したMessages APIレスポンスの一部です。リクエスト処理の失敗を示すエラーとは異なり、stop_reason
はClaudeがレスポンス生成を正常に完了した理由を教えてくれます。
{
"id": "msg_01234",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "あなたの質問に対する回答です..."
}
],
"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
制限に達したため停止しました。
# トークン制限付きのリクエスト
response = client.messages.create(
model="claude-3-7-sonnet-20250219",
max_tokens=10,
messages=[{"role": "user", "content": "量子物理学について説明してください"}]
)
if response.stop_reason == "max_tokens":
# レスポンスが切り捨てられた
print("レスポンスがトークン制限で切り捨てられました")
# 続きを取得するために別のリクエストを検討する
stop_sequence
Claudeがカスタム停止シーケンスの1つに遭遇しました。
response = client.messages.create(
model="claude-3-7-sonnet-20250219",
max_tokens=1024,
stop_sequences=["END", "STOP"],
messages=[{"role": "user", "content": "ENDと言うまでテキストを生成してください"}]
)
if response.stop_reason == "stop_sequence":
print(f"シーケンスで停止: {response.stop_sequence}")
Claudeがツールを呼び出し、あなたがそれを実行することを期待しています。
response = client.messages.create(
model="claude-3-7-sonnet-20250219",
max_tokens=1024,
tools=[weather_tool],
messages=[{"role": "user", "content": "天気はどうですか?"}]
)
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-3-7-sonnet-20250219",
max_tokens=1024,
tools=[{"type": "web_search_20250305", "name": "web_search"}],
messages=[{"role": "user", "content": "最新のAIニュースを検索してください"}]
)
if response.stop_reason == "pause_turn":
# 会話を続ける
messages = [
{"role": "user", "content": original_query},
{"role": "assistant", "content": response.content}
]
continuation = client.messages.create(
model="claude-3-7-sonnet-20250219",
messages=messages,
tools=[{"type": "web_search_20250305", "name": "web_search"}]
)
停止理由を処理するためのベストプラクティス
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)
else:
# end_turnやその他のケースを処理する
return response.content[0].text
2. max_tokensを適切に処理する
トークン制限によりレスポンスが切り捨てられた場合:
def handle_truncated_response(response):
if response.stop_reason == "max_tokens":
# オプション1:ユーザーに警告する
return f"{response.content[0].text}\n\n[レスポンスが長さの制限により切り捨てられました]"
# オプション2:生成を続ける
messages = [
{"role": "user", "content": original_prompt},
{"role": "assistant", "content": response.content[0].text}
]
continuation = client.messages.create(
model="claude-3-7-sonnet-20250219",
max_tokens=1024,
messages=messages + [{"role": "user", "content": "続けてください"}]
)
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-3-7-sonnet-20250219",
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("レスポンスが切り捨てられました")
except anthropic.APIError as e:
# 実際のエラーを処理する
if e.status_code == 429:
print("レート制限を超えました")
elif e.status_code == 500:
print("サーバーエラー")
ストリーミングに関する考慮事項
ストリーミングを使用する場合、stop_reason
は:
- 最初の
message_start
イベントではnull
message_delta
イベントで提供される
- 他のすべてのイベントでは非nullである
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"ストリームが終了しました: {stop_reason}")
一般的なパターン
ツール使用ワークフローの処理
def complete_tool_workflow(client, user_query, tools):
messages = [{"role": "user", "content": user_query}]
while True:
response = client.messages.create(
model="claude-3-7-sonnet-20250219",
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-3-7-sonnet-20250219",
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": "中断した箇所から続けてください。"}
]
return full_response
stop_reason
の値を適切に処理することで、異なるレスポンスシナリオを適切に処理し、より良いユーザーエクスペリエンスを提供する、より堅牢なアプリケーションを構築できます。