Amazon Bedrock は、bedrock-runtime および bedrock-mantle の両エンドポイントで、モデルが利用可能なすべてのリージョンにおいて、すべての Anthropic Claude モデルの構造化出力をサポートするようになりました。
Boto3 と bedrock-runtime API 経由でも、Messages API と bedrock-mantle エンドポイント経由でも、Claude を呼び出す際に、定義された構造に準拠したスキーマ準拠の JSON レスポンスを受け取れるようになりました。カスタムのパース処理、リトライロジック、後処理はもう必要ありません。
実用的なアプリケーション
Amazon Bedrock 上の Claude の構造化出力により、業種を問わず信頼性の高いスキーマ準拠のタスクを自動化できます。例として、財務決算レポートやコンプライアンス文書から必要な全フィールドを抽出すること、診療記録を電子カルテ(EHR)にパースすること、一貫性のある検証済みの結果で製品カタログを強化することなどが挙げられます。また、契約書の重要な条項、当事者、義務を分析したり、インテント、センチメント、エンティティが常にアプリケーションのデータモデルと一致するインテリジェントなサポートチケットのルーティングを実現したりすることもできます。
Amazon Bedrock の構造化出力で変わること
構造化出力は制約付きデコードを使用し、トークン生成中に JSON スキーマを強制します。事後処理ではありません。モデルはスキーマに違反するトークンを生成しません。これにより、出力フォーマットが確率的から決定論的へと変わります。
両方の Amazon Bedrock エンドポイントで、2 つの相補的なメカニズムが利用可能になりました。
| 機能 | 目的 | ユースケース |
| JSON Schema 出力フォーマット | モデルのレスポンス構造を制御する | データ抽出、レポート生成、API レスポンス |
| Strict tool use | スキーマに対してツールパラメータを検証する | エージェントワークフロー、関数呼び出し、多段階オートメーション |
これがユーザーにとって意味すること
各レスポンスは有効な JSON であるため、もう JSON.parse() エラーやパース例外に遭遇することはありません。レスポンスはタイプセーフでもあります。フィールドの型が強制され、必須フィールドは常に存在します。出力は常にスキーマに準拠するため、スキーマ違反に対処するためのリトライは不要となり、統合の信頼性が向上します。構造化出力は、レスポンスをスキーマで定義されたフィールドのみに制限するため、出力トークン数が削減され、大量のワークロードでは推論コストを抑えられる可能性があります。これらの特性により、構造化出力は本番環境対応となり、追加のスキーマ検証コードなしで大規模にデプロイできます。
サポートされるモデルと提供リージョン
構造化出力は バッチ推論とも連携するため、スキーマ準拠の出力を受け取りながら、大量のリクエストを非同期的に処理できます。bedrock-runtime エンドポイントでは、クロスリージョン推論にも対応しているため、追加のセットアップなしで複数の AWS リージョンにまたがって使用できます。リアルタイムのレスポンスが必要な場合は、型付きイベントとして構造化レスポンスをストリーミングできます。
仕組み
JSON スキーマを指定してリクエストを行うと、舞台裏では次のような処理が行われます。
- スキーマ検証 – Amazon Bedrock は、お客様の JSON スキーマをサポートされている JSON Schema Draft 2020-12 のサブセットに対して検証します。
- 文法のコンパイル – 新しいスキーマについては、Amazon Bedrock が文法アーティファクトをコンパイルします(最初のリクエストではやや時間がかかる場合があります)。
- キャッシング – コンパイルされた文法は24時間キャッシュされるため、以降のリクエストが高速になります。
- 制約付き生成 – モデルは、スキーマに一致する有効なJSONを生成するトークンを生成します。
パフォーマンスに関する考慮事項
パフォーマンスの観点から、新しいスキーマを使用する最初のリクエストは、Amazon Bedrockが生成開始前に文法アーティファクトをコンパイルするため、時間がかかる場合があります。その初回コンパイル以降は、同じスキーマを使用する後続のリクエストは、コンパイル済みの文法がキャッシュされているため、最小限のオーバーヘッドで実行されます。このキャッシュはアカウントにスコープされ、最初のアクセスから24時間有効です。JSONスキーマの構造を変更するとキャッシュが無効化され、新しいコンパイルがトリガーされますが、nameやdescriptionフィールドのみを変更した場合は、キャッシュされた文法はそのまま維持されます。
はじめに: InvokeModel API(bedrock-runtime)を使用した構造化出力
InvokeModel APIはAnthropicネイティブのリクエストボディを受け取るため、スキーマはその中に記述します。 output_config.format JSON文字列としてではなく、JSONオブジェクトとして扱います。次の例は、boto3とAnthropic Claudeモデルを使用して、顧客のメールから構造化されたリードデータを抽出する方法を示しています:
Python
import boto3
import json
REGION = "us-east-1" # Choose your preferred region
bedrock_runtime = boto3.client(service_name="bedrock-runtime", region_name=REGION)
# Define the JSON schema for structured output
schema = {
"type": "object",
"properties": {
"name": {"type": "string", "description": "Customer name"},
"email": {"type": "string", "description": "Customer email address"},
"plan_interest": {"type": "string", "description": "Product plan of interest"},
"demo_requested": {"type": "boolean", "description": "Whether a demo was requested"}
},
"required": ["name", "email", "plan_interest", "demo_requested"],
"additionalProperties": False
}
# Make a request with structured outputs via the InvokeModel API
# (reusing the schema defined for the Converse example)
response = bedrock_runtime.invoke_model(
modelId="global.anthropic.claude-sonnet-5-5",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"messages": [
{"role": "user", "content": (
"Paulo Santos (paulo@example.com) is interested in our Enterprise plan "
"and wants to schedule a demo for next Tuesday at 2pm."
)}
],
"output_config": {"format": {"type": "json_schema", "schema": schema}}
})
)
body = json.loads(response["body"].read())
# Check the stop reason before parsing
if body["stop_reason"] == "end_turn":
result_text = next(b["text"] for b in body["content"] if b["type"] == "text")
print(json.dumps(json.loads(result_text), indent=2))
elif body["stop_reason"] == "max_tokens":
print("Response truncated: increase max_tokens and retry.")
JSON
{
"name": "Paulo Santos",
"email": "paulo@example.com",
"plan_interest": "Enterprise",
"demo_requested": true
}
レスポンスはあなたのスキーマに準拠しています。追加の検証は不要です。
Messages API を含む追加の API 使用例については、付属の サンプルノートブック.
エージェント型ワークフローのための厳格なツール使用
Amazon Bedrock Mantle は、サーバーサイドツール、バックグラウンド推論、ステートフルな会話を備えたエージェントアプリケーション向けに設計されています。bedrock-mantleエンドポイントでのstrict tool useにより、ツールパラメータが入力スキーマと正確に一致することを保証できるようになりました。次の例は、厳密なスキーマ適用を備えたツールを定義する方法を示しています。
Import json
from anthropic import AnthropicBedrockMantle
# Reusing the client created in the Messages API example
client = AnthropicBedrockMantle(aws_region="us-east-1")
message = client.messages.create(
model="anthropic.claude-sonnet-5",
max_tokens=512,
messages=[{"role": "user", "content": "What's the weather like in San Francisco?"}],
tools=[
{
"name": "get_weather",
"description": "Get the current weather for a specified location",
"strict": True,
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g., San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location", "unit"],
"additionalProperties": False
}
}
]
)
#Tool inputs conform to the schema
for block in message.content:
if block.type == "tool_use":
print(f"Tool: {block.name}")
print(f"Input: {json.dumps(block.input, indent=2)}")
設定 strict: true モデルのツール入力がスキーマと正確に一致するよう制約されます。location フィールドは常に文字列であり、unit フィールドは常に celsius または fahrenheit のいずれかです。モデルがスキーマ外のフィールドを追加することはできないため、ツール入力にはスキーマで指定した内容のみが含まれます。
これは、Amazon Bedrock Mantle におけるエージェント的なユースケースで特に価値が高く、モデルが Web 検索やコードインタープリターといったサーバーサイドのツールを使って複数ステップのワークフローをオーケストレーションします。
Claudeの構造化出力の主なユースケース
構造化出力は、次の3つの一般的なパターンにおいて、エラー処理の複雑さを最も効果的に軽減します。
- データ抽出: 請求書、契約書、メール、文字起こしからフィールドを抽出し、常にスキーマに一致するJSONとして出力することで、データベースや顧客関係管理(CRM)システムへの読み込みがすぐに可能になります。
- 信頼性の高いエージェントのツール呼び出し: 生成時にツールの引数をスキーマに照らして検証するため、不正な形式の入力による失敗なく、マルチステップのエージェントワークフローを実行できます。
- 大規模な分類: チケット、リード、コンテンツを意図、優先度、センチメント別に分類し、ルーティング、モデレーション、評価に活用できます。
Claude Haiku 5.5は、要約、圧縮、データベースクエリ、分類リクエストなどの、迅速かつ反復的なワークロードを確実に処理します。次の例は、Invoke APIとHaiku 5.5を使用して受信データを分類およびルーティングする方法を示しています:
import boto3
import json
REGION = "us-east-1" # Choose your preferred region
bedrock_runtime = boto3.client(service_name="bedrock-runtime", region_name=REGION)
# Classification schema: enums restrict output to a fixed set of labels
schema = {
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account", "sales", "other"],
"description": "Primary ticket category"
},
"priority": {
"type": "string",
"enum": ["low", "medium", "high", "urgent"],
"description": "Urgency based on business impact"
},
"sentiment": {
"type": "string",
"enum": ["positive", "neutral", "negative"],
"description": "Customer sentiment"
},
"escalate": {"type": "boolean", "description": "Whether a human should review immediately"},
"reason": {"type": "string", "description": "One-sentence justification for the classification"}
},
"required": ["category", "priority", "sentiment", "escalate", "reason"],
"additionalProperties": False
}
ticket = (
"Our production API calls have been failing with 500 errors since this morning. "
"We're losing orders every minute. This is the second outage this month!"
)
# Make a request with structured outputs via the InvokeModel API
response = bedrock_runtime.invoke_model(
modelId="global.anthropic.claude-haiku-5-5",
body=json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"system": "You are a support ticket classifier. Classify the ticket accurately.",
"messages": [
{"role": "user", "content": f"Classify this support ticket:\n\n{ticket}"}
],
"output_config": {"format": {"type": "json_schema", "schema": schema}}
})
)
body = json.loads(response["body"].read())
# Check the stop reason before parsing
if body["stop_reason"] == "end_turn":
result_text = next(b["text"] for b in body["content"] if b["type"] == "text")
result = json.loads(result_text)
print(json.dumps(result, indent=2))
# Route the ticket based on the guaranteed-valid labels
if result["escalate"]:
print(f"Escalating to on-call: {result['category']} / {result['priority']}")
elif body["stop_reason"] == "max_tokens":
print("Response truncated: increase max_tokens and retry.")
要件とベストプラクティス
Amazon Bedrockで構造化出力を効果的に使用するには、次のガイドラインに従ってください。
- すべてのオブジェクトにadditionalProperties: falseを設定する: 構造化出力が機能するためにはこれが必要です。設定しない場合、スキーマが受け付けられません。
- 説明的なフィールド名と説明を使用する: モデルはプロパティ名と説明を使用して、抽出するデータを理解します。次のような明確な名前は
customer_emailのような汎用的な名前よりも優れた結果をもたらします。field1. - 制約付きの値にはenumを使用する: フィールドが有効な値の限られた集合を持つ場合は、
enumを使用して選択肢を制約します。 - まず基本から始め、その後複雑さを追加する: 最低限必要なフィールドから始め、段階的に複雑さを追加してください。基本的なスキーマはコンパイルが速く、デバッグが容易で、スキーマが Converse API のペイロードサイズにカウントされるため、リクエストペイロードを軽量に保てます。
- スキーマを再利用してキャッシュの恩恵を受ける: アプリケーションを、リクエスト間でスキーマを再利用できるように構成してください。24時間のグラマーキャッシュにより、繰り返しのクエリでパフォーマンスが向上します。
- すべてのレスポンスで停止理由を確認する: 2つのシナリオで非準拠のレスポンスが生成される可能性があります。拒否(モデルが安全上の理由で応答を拒否する場合)とトークン制限(完了前に
max_tokensに達した場合)です。コードで両方のケースを処理してください。 - デプロイ前に現実的なデータでテストする: 本番環境を代表する入力に対してスキーマを検証してください。実際のデータにおけるエッジケースは、スキーマ設計の問題をしばしば明らかにします。
追加のベストプラクティスとスキーマ設計の推奨事項については、Amazon Bedrock ユーザーガイドの 構造化出力 を参照してください。
サポートされている JSON Schema 機能
- すべての基本型:
object,array,string,integer,number,boolean,null. enum(文字列、数値、ブール値、または null のみ)。const,anyOf,allOf(制限付き)。$ref,$def、およびdefinitions(内部参照のみ)。- 文字列フォーマット:
date-time,time,date,duration,email,hostname,uri,ipv4,ipv6,uuid. - 配列
minItems(値 0 と 1 のみ)。
サポートされていません
これらのキーワードはAPIで受け付けられますが、生成時には強制されません。これらを含むリクエストは正常なレスポンスを返し、モデルはそれらに違反する値を返すことがあります。スキーマによる強制に頼るのではなく、アプリケーション側でこれらの制約を検証してください。
- 再帰的スキーマ。
- 外部
$ref参照。 - 数値制約(
minimum,maximum,multipleOf). - 文字列制約(
minLength,maxLength). additionalPropertiesfalse以外の値に設定された場合。
まとめ
Amazon BedrockにおけるAnthropic Claudeモデルの構造化出力は、本番AIアプリケーションに求められる信頼性を提供します。現在、bedrock-runtimeとbedrock-mantleの両エンドポイントで利用可能です。JSON Schema出力形式と厳密なツール使用を組み合わせることで、追加の検証を必要としないデータパイプラインを構築できます。また、カスタムのパース処理やリトライロジックなしで、信頼性の高いエージェント型ワークフローや本番AIアプリケーションを作成することもできます。
Amazon Bedrock上のClaude向け構造化出力が一般提供されました。詳細については、 Amazon Bedrockドキュメント をご覧いただき、 サンプルノートブック.
もぜひご覧ください。検証済みのスキーマ準拠JSONは、あなたの組織でどのようなワークフローを改善できるでしょうか。フィードバックやご質問はコメント欄でお知らせください。
