Bedrock バッチ推論が Converse API フォーマットに対応 ― InvokeModel形式との違いと実際の使い方を検証
Amazon Bedrock のバッチ推論で Converse API フォーマットが使えるようになりました(2026年2月27日 AWS What’s New)。これまでバッチ推論では InvokeModel API のモデル固有フォーマットしか使えなかったのですが、リアルタイム推論と同じ Converse API の統一フォーマットでバッチ処理を実行できるようになります。
実際に AWS CLI で検証してみたので、InvokeModel フォーマットとの違いや具体的な手順をまとめます。
何が変わったのか
従来、Bedrock のバッチ推論では入力データを InvokeModel API のボディ形式(モデル固有のJSON構造)で記述する必要がありました。例えば Claude を使う場合は anthropic_version や Claude 固有のパラメータを含めた形式で書く必要があります。
今回のアップデートで、バッチ推論ジョブ作成時に modelInvocationType として Converse を指定できるようになりました。これにより、入力データを Converse API のリクエスト形式で記述でき、出力も Converse API のレスポンス形式で返ってきます。
メリットは明確で、リアルタイム推論とバッチ推論で同じフォーマットのプロンプトを使い回せるようになります。モデルを切り替える際にも入力データの書き換えが不要です。
入力データの違い
バッチ推論の入力は JSONL 形式で、各行が1つのリクエストに対応します。InvokeModel フォーマットと Converse フォーマットの違いを見てみます。
InvokeModel フォーマット(従来)
{
"recordId": "REC001",
"modelInput": {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "AWSのS3とEBSの違いを簡潔に説明してください。"
}
]
}
]
}
}
anthropic_version が必須で、max_tokens(スネークケース)を使うなど、Claude 固有の形式です。別のモデルに切り替える場合はこの構造ごと書き換える必要があります。
Converse フォーマット(今回追加)
{
"recordId": "REC001",
"modelInput": {
"messages": [
{
"role": "user",
"content": [
{
"text": "AWSのS3とEBSの違いを簡潔に説明してください。"
}
]
}
],
"inferenceConfig": {
"maxTokens": 1024
}
}
}
anthropic_version は不要で、パラメータは inferenceConfig(キャメルケース)で統一されています。content 配列内の要素にも type フィールドが不要です。Converse API のリクエスト形式そのままなので、リアルタイム推論で使っているプロンプトをそのままバッチに流用できます。
実際に試してみた
以下の環境で検証しました。
- AWS CLI: aws-cli/2.34.3
- リージョン: us-east-1
- モデル: us.anthropic.claude-sonnet-4-5-20250929-v1:0(クロスリージョン推論プロファイル)
1. 入力データの準備
まず、Converse フォーマットの JSONL ファイルを作成します。3つのリクエストを含む入力ファイルを用意しました。
cat << 'EOF' > batch-converse-input.jsonl
{"recordId":"REC001","modelInput":{"messages":[{"role":"user","content":[{"text":"AWSのS3とEBSの違いを50文字以内で説明してください。"}]}],"inferenceConfig":{"maxTokens":256}}}
{"recordId":"REC002","modelInput":{"messages":[{"role":"user","content":[{"text":"Lambdaのコールドスタートとは何かを50文字以内で説明してください。"}]}],"inferenceConfig":{"maxTokens":256}}}
{"recordId":"REC003","modelInput":{"messages":[{"role":"user","content":[{"text":"DynamoDBのパーティションキーとソートキーの違いを50文字以内で説明してください。"}]}],"inferenceConfig":{"maxTokens":256}}}
EOF
2. S3へのアップロード
入力データと出力先の S3 パスを用意します。
# 入力ファイルをアップロード
aws s3 cp batch-converse-input.jsonl \
s3://my-bedrock-batch-bucket/converse-test/input/batch-converse-input.jsonl
# 出力先ディレクトリを確保(空のプレフィックス)
# S3では明示的にディレクトリを作る必要はないが、出力先パスは指定する
3. バッチ推論ジョブの作成
ここがポイントです。--model-invocation-type Converse を指定します。
aws bedrock create-model-invocation-job \
--job-name "converse-batch-test-$(date +%Y%m%d-%H%M%S)" \
--role-arn arn:aws:iam::123456789012:role/BedrockBatchInferenceRole \
--model-id us.anthropic.claude-sonnet-4-5-20250929-v1:0 \
--model-invocation-type Converse \
--input-data-config '{
"s3InputDataConfig": {
"s3Uri": "s3://my-bedrock-batch-bucket/converse-test/input/"
}
}' \
--output-data-config '{
"s3OutputDataConfig": {
"s3Uri": "s3://my-bedrock-batch-bucket/converse-test/output/"
}
}'
レスポンスとして jobArn が返ってきます。
{
"jobArn": "arn:aws:bedrock:us-east-1:123456789012:model-invocation-job/abcdef123456"
}
4. ジョブのステータス確認
get-model-invocation-job でステータスを確認できます。
aws bedrock get-model-invocation-job \
--job-identifier "arn:aws:bedrock:us-east-1:123456789012:model-invocation-job/abcdef123456"
ステータスは Submitted → InProgress → Completed と遷移します。3レコード程度のジョブでも数分かかりました。バッチ推論はリアルタイム推論とは異なり、スループット最適化のためのキューイングが入るので即座には完了しません。
5. 出力の確認
ジョブが完了すると、出力先 S3 に JSONL ファイルが生成されます。
aws s3 cp s3://my-bedrock-batch-bucket/converse-test/output/ ./output/ --recursive
cat output/*.jsonl
出力は以下のような形式になります。
{
"recordId": "REC001",
"modelOutput": {
"output": {
"message": {
"role": "assistant",
"content": [
{
"text": "S3はオブジェクトストレージで無制限容量、EBSはEC2用ブロックストレージで高速IO。"
}
]
}
},
"stopReason": "end_turn",
"usage": {
"inputTokens": 32,
"outputTokens": 38,
"totalTokens": 70
}
}
}
出力も Converse API のレスポンス形式になっています。modelOutput の中身が converse API のレスポンスそのものなので、リアルタイム推論のレスポンスパーサーをそのまま流用できます。
InvokeModel フォーマットとの出力比較
InvokeModel フォーマットで同じモデルを使った場合の出力と比較してみます。
InvokeModel フォーマットの出力
{
"recordId": "REC001",
"modelOutput": {
"id": "msg_xxxxxxxxxxxx",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "S3はオブジェクトストレージで無制限容量、EBSはEC2用ブロックストレージで高速IO。"
}
],
"model": "claude-sonnet-4-5-20250929",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 32,
"output_tokens": 38
}
}
}
Converse フォーマットの出力
{
"recordId": "REC001",
"modelOutput": {
"output": {
"message": {
"role": "assistant",
"content": [
{
"text": "S3はオブジェクトストレージで無制限容量、EBSはEC2用ブロックストレージで高速IO。"
}
]
}
},
"stopReason": "end_turn",
"usage": {
"inputTokens": 32,
"outputTokens": 38,
"totalTokens": 70
}
}
}
主な違いをまとめます。
| 項目 | InvokeModel | Converse |
|---|---|---|
| レスポンス構造 | モデル固有(Claude: id, type, model あり) | Converse API 標準(output.message にラップ) |
| content要素 | type フィールドあり | type フィールドなし |
| stop reason | stop_reason(スネークケース) | stopReason(キャメルケース) |
| usage | input_tokens / output_tokens | inputTokens / outputTokens / totalTokens |
| モデル情報 | model フィールドあり | なし |
Converse フォーマットでは totalTokens が追加で返ってくるのと、フィールド名がキャメルケースに統一されています。
コンソールからの操作
AWS CLI だけでなく、コンソールからも Converse フォーマットを指定できます。バッチ推論ジョブ作成画面で「Model invocation type」のドロップダウンから Converse を選択するだけです。
手順は以下の通りです。
- Bedrock コンソール → 左メニュー「Batch inference」→「Create job」
- Job name を入力し、モデルを選択
- 「Model invocation type」で「Converse」を選択(デフォルトは InvokeModel)
- Input data で S3 の入力ファイルパスを指定
- Output data で S3 の出力先パスを指定
- Service access でIAMロールを設定
- 「Create batch inference job」をクリック
system プロンプトやツール定義も使える
Converse フォーマットでは、リアルタイムの Converse API と同様に system プロンプトや toolConfig も指定できます。
system プロンプト付きの入力例
{
"recordId": "REC001",
"modelInput": {
"system": [
{
"text": "あなたはAWSの専門家です。質問には正確かつ簡潔に回答してください。"
}
],
"messages": [
{
"role": "user",
"content": [
{
"text": "VPCエンドポイントのゲートウェイ型とインターフェース型の違いは?"
}
]
}
],
"inferenceConfig": {
"maxTokens": 512,
"temperature": 0.3
}
}
}
InvokeModel フォーマットでは system の指定方法がモデルごとに異なりますが、Converse フォーマットなら統一された構造で書けます。
IAMロールの設定
バッチ推論ジョブには、入出力の S3 バケットへのアクセス権限を持つ IAM ロールが必要です。以下は最小限のポリシー例です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-bedrock-batch-bucket",
"arn:aws:s3:::my-bedrock-batch-bucket/converse-test/input/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-bedrock-batch-bucket/converse-test/output/*"
]
}
]
}
信頼ポリシーでは bedrock.amazonaws.com からの sts:AssumeRole を許可する必要があります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "bedrock.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "123456789012"
}
}
}
]
}
注意点
出力の順序は保証されない
公式ドキュメントに明記されていますが、出力 JSONL のレコード順序は入力と一致する保証がありません(AWS Documentation)。recordId で突き合わせる必要があるので、recordId は必ず指定しておくべきです。
入力データはフォルダパスで指定
s3InputDataConfig の s3Uri には JSONL ファイルそのものではなく、フォルダパスを指定します。そのフォルダ内のすべての JSONL ファイルが処理対象になります。複数ファイルに分割して格納することも可能です。
リアルタイム推論との使い分け
バッチ推論はスループット最適化のため、レイテンシはリアルタイム推論より大幅に長くなります。数レコードのテスト目的であってもジョブの起動や完了に数分かかるため、即座に結果が欲しい場合はリアルタイムの converse API を使うべきです。
バッチ推論が適しているのは以下のようなケースです。
- 大量のプロンプトを一括処理したい(数百〜数万件)
- リアルタイム性が不要(翌日までに結果が出ればよい)
- コストを最適化したい(バッチ推論はオンデマンドより割安)
まとめ
Bedrock バッチ推論の Converse API フォーマット対応は、地味ながら実用的なアップデートです。
一番のメリットは、リアルタイム推論とバッチ推論で入力データのフォーマットを統一できることだと思います。これまでは Converse API でプロトタイプを作ってからバッチ化する際に、InvokeModel のモデル固有フォーマットに書き換える必要がありました。今後はそのまま JSONL に詰めてバッチジョブに投げるだけです。
また、モデルの切り替えも楽になります。Claude から別のモデルに乗り換える場合でも、入力データの modelInput を書き換える必要がなく、ジョブ作成時の modelId を変更するだけで済みます。
設定は --model-invocation-type Converse を追加するだけなので、既にバッチ推論を使っている方は試してみてください。