NTT東日本の自治体クラウドソリューション

Amazon BedrockのStructured Outputs(構造化出力)を使うとレスポンスは遅くなるのか?従来手法と速度比較検証してみた!

こんにちは。エンジニアの森です。

NTT東日本では、電話 × 生成AI(LLM)を組み合わせたシステムの開発に力を入れています。

私自身もAmazon ConnectとBedrockと使用したIVRソリューション(AI-IVR)の開発に携わっており、LLMの出力を後続処理で扱うためにJSON形式で構造化されたデータを返させるという課題に日々向き合っています。

これまで私は、プロンプトでJSON出力を指示し、assistantロールに「{」を事前入力しておくことでJSONを出力させる手法を使ってきました。

以前のコラムでご紹介した「ロールベース形式」のテクニックの応用です。

そんな中、2026年2月にAmazon BedrockにStructured Outputs(構造化出力)という機能が登場しました。

スキーマを渡すだけでJSONが保証されるとても便利な機能で、「これは使いたい!」と感じたのですが、一つ気になることがありました。

それは、この機能を使用することでレスポンスが遅くなるのではないか?ということです。

AI-IVRでは、レスポンスの遅延がお客さまの満足度に直結しますので便利でも遅くなるなら従来手法のほうがいいという判断もあり得ます。

そこで本コラムでは、Structured Outputsと従来手法でレスポンス速度を計測し、比較検証してみました。

Amazon Bedrock活用に関するご相談などありましたら、NTT東日本のクラウドエンジニアがお応えしますので、お気軽にお問い合わせください!

NTT東日本のクラウド事業をご紹介!登録不要・無料公開中、詳細はこちら

1. Amazon Bedrock Structured Outputs(構造化出力)とは?

LLMをシステムに組み込む際、モデルに構造化されたデータ(JSON)を出力させることにより、後続処理で扱いやすくできます。

出力されたデータが自然言語のままでは下流のシステムがうまく受け取れないからです。

「どうやってLLMにJSONを返させるか」は実用上の重要課題として長らく議論されてきましたが、Amazon Bedrockでは現在、主に以下の方法が提供されています。

方法 概要
ツールユース(toolConfig) モデルに「ツールを呼ぶ」形式でスキーマを渡し、JSONを出力させる
outputConfig json_schema 出力フォーマットの制約としてJSONスキーマを渡す(JSON出力専用の後発機能)
プロンプト指定 + {事前入力 プロンプトでJSON出力を指示し、assistantロールに「{」を事前入力する従来手法
プロンプト指定のみ プロンプトで「JSONで返して」と指示するだけ

上の2つ(ツールユース・outputConfig json_schema)がAmazon BedrockのStructured Outputs機能です。

スキーマを渡すだけでJSONが保証されるため、パースエラーのリスクがなくなりとても便利です。

しかし、Structured Outputsは、全てのモデルで使用できるわけではなく、最新の2026年4月現在、最新のAnthropic Claude Sonnet 4.6などは正式対応していないようです。

最新情報はAmazon Bedrockのユーザーガイドをご確認ください。

Structured Outputsは、このようにとても便利な機能ですが、Bedrock内でJSONに変換する処理があると考えるとオーバーヘッドが伴うのではないか?という疑問があります。

Amazon Bedrock活用に関するご相談などありましたら、NTT東日本のクラウドエンジニアがお応えしますので、お気軽にお問い合わせください!

2. なぜレスポンス速度が重要なのか:音声 × 生成AIにおけるCXへの影響

NTT東日本では、先述の通り、Amazon Connect(電話)とBedrock(LLM)を組み合わせたシステム(生成AIを活用したIVRソリューション等)を開発しています。

テキストベースのチャットとは異なり、音声対話ではレスポンスの遅延がCX(顧客体験)に直結します。

NTTコムオンラインが2024年8月に1,047名を対象に実施した調査(2024年度版調査レポート)では、コールセンターに電話をかけた際の不満として以下が報告されています。

  • 「オペレータとつながるまでの待ち時間が長い」 → 全体の6割以上が不満と回答
  • 「つながってからも待たされた、対応に時間がかかった」 → オペレータ接続後の不満で最多

人間のオペレータにつながる時でさえ「待たされること」が最大の不満要因です。

AI-IVRでは、ユーザーの発話後にSTT(音声認識)→ LLM推論 → TTS(音声合成)の全処理が加算されるため、LLMの処理が0.5秒余計にかかるだけで、体験が大きく損なわれることになります。

そのため、Structured Outputsの導入によるオーバーヘッドがどの程度かを把握することは、設計判断に不可欠です。

3. 検証で比較した4パターンの構成と検証方法

今回の検証では、4パターンの構成でテストし、速度比較を行いました。

3-1. 4パターンの概要

今回比較した4パターンの構成は以下です。

  • 横にスクロールします
パターン 方式 Structured Outputs 概要
Pattern 1 ツールユースによるStructured Outputs あり toolConfigでスキーマを渡し、toolUse.inputとしてdictが返る
Pattern 2 outputConfig json_schemaによるStructured Outputs あり outputConfigでJSONスキーマを渡し、テキストとしてJSONが返る
Pattern 3 プロンプト指定 + アシスタント事前入力 + プログラム変換 なし
(従来手法)
プロンプトでJSON出力を指示し、assistantロールに「{」を事前入力する
Pattern 4 プロンプト指定のみ なし
(従来手法)
プロンプトでJSON出力を指示するのみ。最もシンプルだが最も不安定

Pattern 3がこれまで使ってきた方法であり、Pattern 1・2が今回追加された機能であるStructured Outputsです。

Pattern 4は最もシンプルなベースラインとして位置づけています。

3-2. 検証構成

検証はAWS LambdaからBedrock(Converse API)を呼び出す単純な構成です。

Lambda(Python 3.14)からAmazon Bedrock(Converse API)へ4つのパターンでそれぞれ30回ずつ実行し、ap-northeast-1にルーティングされたもののみを集計します。

検証条件は以下の通りです。

項目 設定
実行環境 AWS Lambda(Python 3.14、メモリ256MB)
API Bedrock Converse API
モデル Anthropic Claude Sonnet 4.5(JPクロスリージョン)
試行回数 各パターン30回ずつ
リージョン JPクロスリージョン推論を使用し、ap-northeast-1(東京)にルーティングされたもののみ集計
プロンプトキャッシュ 無効(純粋な推論時間を計測するため)
温度 0(固定)

リージョンの条件をそろえている理由は、クロスリージョン推論では負荷状況に応じてリクエストが東京や大阪に分散されるため、ネットワーク往復によるレスポンスの時間が変わってしまうからです。

そのため、東京リージョンにルーティングされたもののみを抽出して比較しています。

3-3. テストシナリオ

テストシナリオは、お客さまからの電話問い合わせ内容を分類し、JSON形式で回答情報を返すというユースケースです。

NTT東日本が開発する電話 × 生成AIのユースケースに近い内容にしています。

入力するお客さまの問い合わせ文:

> 戸籍謄本を取りに行きたいのですが、必要なものはなんですか?

期待する出力(JSON形式)

{
  "inquiry_type": "family_register",
  "answer": "証明書の交付時に本人確認資料の提示をお願いしていますので、ご本人であることの確認できるものをお持ちください。",
  "pattern": "guidance",
  "destination": "na",
  "summary": "戸籍謄本取得時に必要なもの"
}

以下の5つのフィールドを正しく返せるかを検証します。

フィールド 内容
inquiry_type 問い合わせ種別(family_register / others)
answer 対応する回答文
pattern 対応パターン(guidance / transfer / recording / others)
destination 転送先(不要の場合は na)
summary 問い合わせ内容の要約

4. Structured Outputsの仕組みの違い:ツールユースを使うと何が変わるのか

4パターンのコードを比較しながら、それぞれの仕組みの違いを見ていきます。

4-1. ツールユース(Pattern 1)の内部動作

ツールユース(Function Calling)はもともと「モデルが外部関数を呼び出す」ために設計された機能です。

Structured Outputsとして使う場合、実際には関数を呼ばず、スキーマだけを与えて「この形式で返せ」と強制する使い方になります。

resp = bedrock.converse(
    modelId=MODEL_ID,
    system=[{"text": SYSTEM_PROMPT}],
    messages=[{"role": "user", "content": [{"text": USER_PROMPT}]}],
    inferenceConfig={"temperature": TEMPERATURE},
    toolConfig={
        "tools": [{"toolSpec": TOOL_SPEC}],
        "toolChoice": {"tool": {"name": "classify_inquiry"}},
    },
)
 
# レスポンスは toolUse.input として辞書型で返る(パース不要)
for block in resp["output"]["message"]["content"]:
    if "toolUse" in block:
        result = block["toolUse"]["input"]

toolChoiceでツールを強制指定しているため、モデルは「どのツールを呼ぶか」を推論するステップが加わります。

レスポンスはtoolUse.inputとしてすでにパース済みのdictで返るため、呼び出し元でのjson.loadsは不要です。

4-2. outputConfig json_schema(Pattern 2)の内部動作

こちらはJSON出力専用の後発機能です。

ツールユースの「関数呼び出し」ではなく、出力フォーマットの制約として純粋にスキーマを渡す設計になっています。

resp = bedrock.converse(
    modelId=MODEL_ID,
    system=[{"text": SYSTEM_PROMPT}],
    messages=[{"role": "user", "content": [{"text": USER_PROMPT}]}],
    inferenceConfig={"temperature": TEMPERATURE},
    outputConfig={
        "textFormat": {
            "type": "json_schema",
            "structure": {
                "jsonSchema": {
                    "schema": JSON_SCHEMA,
                    "name": "classify_inquiry",
                    "description": "お客さまからの問い合わせを分類し、回答情報をJSON形式で返す",
                }
            },
        }
    },
)
 
# レスポンスはテキストとして返るため、json.loads が必要
result = json.loads(resp["output"]["message"]["content"][0]["text"])

モデルは通常の推論を行い、出力形式だけが制約されます。

レスポンスはテキストとして返るため、呼び出し元でjson.loadsする必要があります。

ストリーミングとの親和性が高いのもこの方式の特徴です。

4-3. 従来手法(Pattern 3・4)との本質的な違い

Pattern 3(事前入力) は、assistantロールに 「{」を事前入力することでモデルに「自分はすでにJSONを書き始めている」と認識させる手法です。

resp = bedrock.converse(
    modelId=MODEL_ID,
    system=[{"text": SYSTEM_PROMPT}],
    inferenceConfig={"temperature": TEMPERATURE},
    messages=[
        {"role": "user",      "content": [{"text": prompt}]},
        {"role": "assistant", "content": [{"text": "{"}]},  # ← ここが事前入力
    ],
)
 
# 先頭の { を結合してからパース
raw = "{" + resp["output"]["message"]["content"][0]["text"]
result = json.loads(raw)

Pattern 4は、最もシンプルで、プロンプトでJSON出力を指示するだけです。

resp = bedrock.converse(
    modelId=MODEL_ID,
    system=[{"text": SYSTEM_PROMPT}],
    inferenceConfig={"temperature": TEMPERATURE},
    messages=[{"role": "user", "content": [{"text": prompt}]}],
)
 
raw = resp["output"]["message"]["content"][0]["text"]

4-4. 各パターンの特性比較

  • 横にスクロールします
特性 Pattern 1(ツールユース) Pattern 2(json_schema Pattern 3(事前入力) Pattern 4(プロンプトのみ)
JSONスキーマの保証 あり あり なし なし
パースの手間 不要(dictで返る) json.loadsが必要 「{」結合 + json.loads Markdownブロック除去 + json.loads
ストリーミング対応 制限あり 対応 対応 対応
出力の安定性 高い 高い 中程度 低い

Structured Outputs(Pattern 1・2)にはスキーマバリデーションが保証されるという大きな利点があります。

Amazon Bedrock活用に関するご相談などありましたら、NTT東日本のクラウドエンジニアがお応えしますので、お気軽にお問い合わせください!

5. レスポンス速度比較:Structured Outputsは従来手法より遅いのか

5-1. 結果一覧

各パターン30回実行した結果を以下にまとめます。

  • 横にスクロールします
パターン 方式 平均(sec) 従来手法比 最小(sec) 最大(sec) 正答率
Pattern 1 ツールユース(SO) 1.972 +36.5% 1.741 2.821 100%
Pattern 2 json_schema(SO) 1.872 +29.5% 1.499 3.415 100%
Pattern 3 Prompt + 事前入力(従来) 1.445 基準 1.211 1.617 100%
Pattern 4 Prompt のみ(ベースライン) 1.668 +15.4% 1.386 2.576 100%
  • SO = Structured Outputs
  • 従来手法比 = Pattern 3(従来手法)の平均を基準とした増加率

5-2. Structured Outputsは従来手法より約30〜37%遅い

最速はPattern 3(従来手法: 事前入力)で平均1.445秒。

一方、Structured Outputsの2パターンは以下の通りです。

  • Pattern 1(ツールユース):平均1.972秒(従来手法比 +36.5%、約0.53秒増)
  • Pattern 2(json_schema):平均1.872秒(従来手法比 +29.5%、約0.43秒増)

この差はテキストチャットなどでは無視できてもAI-IVRでは深刻です。

また、Pattern 3は最大値のばらつきも小さく(最大1.617秒)、速度だけでなく安定性においても優れていることが分かりました。

5-3.Structured Outputs同士の比較:ツールユース vs json_schema

Structured Outputs同士を比較すると、Pattern 2(json_schema)のほうがPattern 1(ツールユース)より約0.1秒(+5.4%)速い傾向にあります。

ツールユースはもともと外部関数呼び出しのための機能であり、「どのツールを呼ぶか」を推論するステップが加わります。

このオーバーヘッドは小さいですが確かに存在します。

Structured Outputsを使うのであれば、json_schema(outputConfig)方式のほうが速いと言えます。

5-4. 正答率は全パターン100%だが注意点はある

今回の検証では、全パターンで正答率100%(30回中30回正解)となり、精度面の差は出ませんでした。

ただし、以下の注意点もあります。

  • Pattern 3・4 はモデルやプロンプトによっては ` ```json ` で囲まれたり、余計な説明、解説が付与されるリスクがあり、実運用ではパースエラーの原因になる可能性があります。
    今回はClaude Sonnet 4.5の高い指示追従性のおかげで問題が出なかったと考えられます。
  • Structured Outputs(Pattern 1・2)は、スキーマに沿った出力が構造的に保証されるため、モデルのバージョンアップやプロンプト変更時の安心感があります。
    これは速度では測れない大きな利点です。

Amazon Bedrock活用に関するご相談などありましたら、NTT東日本のクラウドエンジニアがお応えしますので、お気軽にお問い合わせください!

6. まとめ

今回の検証結果をまとめます。

  • Structured Outputsと従来手法の速度差は、Structured Outputsが約30〜37%(0.4〜0.5秒)遅い。
  • Structured Outputs同士の速度差は、ツールユースが+5.4%遅い。
  • 正答率は、全パターン100%であったが、Pattern3・4はリスクあり。

Structured Outputsは便利で確実な機能ですが、AI-IVRのようにレスポンス速度が重視されるようなユースケースでは、この差は無視できないと感じました。

Structured Outputsは確実性を得るための保険として捉え、ユースケースに応じて使い分けることが重要です。

本コラムが、Amazon BedrockでStructured Outputsの採用を検討されている方の参考になれば幸いです。

NTT東日本では、今回ご紹介したBedrockをはじめとしたLLMを使用し、音声 × 生成AIのプロダクト開発に力を入れています。

コンタクトセンターやAI-IVRなどにお困りの方、ご興味がある方はぜひお問い合わせください。

また、コンタクトセンターではないが、クラウド導入でお困りという方ももちろん大歓迎です!

Amazon Bedrock活用に関するご相談などありましたら、NTT東日本のクラウドエンジニアがお応えしますので、お気軽にお問い合わせください!

  • Amazon Web Services(AWS)は、米国その他の諸国における、Amazon.com, Inc.またはその関連会社の商標です。

ページ上部へ戻る

相談無料!プロが中立的にアドバイスいたします

クラウド・AWS・Azureでお困りの方はお気軽にご相談ください。