マルチモデル API ゲートウェイの構造化出力: JSON スキーマ、ツール呼び出し、セマンティック ガードレール
複数の LLM プロバイダーにわたって信頼性の高い構造化出力を実現する実用的なアダプター パターン。スキーマの正規化、応答の検証、ツール呼び出しの処理、失敗のログ記録、本番ワークフローに到達する前に安全でないアクションのブロックを行います。
モデルに「JSON を返す」よう促すことは実稼働契約ではありません。間違った列挙型で有効な JSON が生成されたり、必要なビジネス ルールが省略されたり、ユーザーが許可していないアクションを堂々と要求したりする可能性があります。マルチプロバイダーのワークフローでは、問題はさらに難しくなります。各プロバイダーは、異なる構造化出力メカニズムとツール使用メカニズムを公開し、それぞれが JSON スキーマ ユニバースの一部のみをサポートします。
実際的な解決策は、1 つの魔法のプロンプトではありません。これは階層化されたゲートウェイ パターンです。開発者が希望するスキーマを正規化し、可能であればプロバイダー ネイティブの構造化出力またはツール呼び出し形式に変換し、返されたオブジェクトを検証し、副作用が発生する前にセマンティック ガードレールを適用します。
このガイドでは、混同されることが多い 3 つの異なる目標を分けて説明します:
- 構文の有効性: 応答は解析可能です JSON.
- スキーマの有効性: JSON は必須のフィールド、型、列挙型、および構造ルールに一致します。
- ビジネス上の正確性: オブジェクトは安全で、ユーザーの意図に忠実であり、下流のアクションに対して有効です。
本番環境の失敗: 有効 JSON、間違ったアクション
受信チケットをルーティングするサポートの自動化を検討してください:
{
"ticket_id": "t_481",
"category": "billing",
"priority": "urgent",
"action": "refund_customer",
"amount_usd": 499
}
このオブジェクトは構文的に有効です。 action が文字列で amount_usd が数値の場合は、単純なスキーマを渡すこともできます。しかし、それでも間違っている可能性があります。おそらく顧客は請求書のコピーだけを要求したのでしょう。おそらく 100 ドルを超える払い戻しにはマネージャーの承認が必要です。おそらくユーザーには払い戻しをトリガーする権限がまったくない可能性があります。
構造化された出力により、解析の失敗が減少します。これらは、認可、ポリシーチェック、在庫チェック、価格設定チェック、冪等性、または危険な操作に対する人間による確認に代わるものではありません。
事実: プロバイダーの構造化出力モードが行うことと約束しないこと
プロバイダーの状況は急速に変化しますが、アーキテクチャにとって重要な安定した事実がいくつかあります:
- JSON モードは有効な JSON を生成するのに役立ちますが、有効な JSON は特定のスキーマに準拠することと同じではありません。
- プロバイダーネイティブの構造化出力モードは、スキーマの遵守を向上させるように設計されていますが、通常は JSON スキーマのサブセットのみをサポートします。
- 通常、ツール呼び出しは自由形式 JSON よりもアクションに適しています。これは、モデルが宣言されたツールを選択して構造化引数を返し、アプリケーションが実行の責任を負うためです。
- プロバイダーが異なれば、公開されるコントラクトも異なります。厳密な JSON スキーマ応答形式を使用する場合もあれば、ツール入力スキーマを使用する場合もあり、検証と再試行のフォールバックを必要とする場合もあります。
- スキーマが有効な出力であっても、データベース、ワークフロー、または有料アクションに到達する前に意味的に間違っている可能性があります。
アーキテクチャ上の意味は単純です。OpenAI 互換の API はクライアント インターフェースを標準化できますが、信頼性レイヤーは依然としてプロバイダーの機能を理解し、生成後の出力を検証する必要があります。
推奨アーキテクチャ: 構造化出力アダプター
アプリケーション コードとプロバイダー API の間でゲートウェイ側アダプターを使用します。アプリケーションは 1 つのスキーマ インテントを送信します。ゲートウェイは、そのインテントをサポートされている最も強力なプロバイダー メカニズムにマッピングします。
1.アプリケーション
から正規化されたリクエストを 1 つ受け入れますクライアントはプロバイダーごとに個別のコード パスを必要とする必要はありません。実際のリクエスト エンベロープには、モデル設定、タスク入力、スキーマ、スキーマ メタデータ、リスク レベルが含まれます:
{
"model": "auto:accurate",
"messages": [
{"role": "system", "content": "Extract invoice fields. Do not infer missing values."},
{"role": "user", "content": "Invoice text..."}
],
"structured_output": {
"schema_id": "invoice_extraction",
"schema_version": "2026-08-01",
"mode": "json_schema",
"strict": true,
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["invoice_number", "vendor_name", "total", "currency", "due_date"],
"properties": {
"invoice_number": {"type": "string"},
"vendor_name": {"type": "string"},
"total": {"type": "number", "minimum": 0},
"currency": {"type": "string", "enum": ["USD", "EUR", "GBP"]},
"due_date": {"type": "string", "format": "date"},
"confidence": {"type": "number", "minimum": 0, "maximum": 1}
}
}
},
"metadata": {
"workflow": "accounts_payable",
"risk_level": "medium"
}
}
このコントラクトは、プロバイダー ネイティブの実装を選択し、検証を実行し、意味のある障害データをログに記録するために十分な情報をゲートウェイに提供します。
2.プロバイダー機能マトリックスを維持する
ゲートウェイは、「すべての OpenAI 互換モデルが同じスキーマ動作をサポートする」などの前提に依存するのではなく、機械可読な機能マトリックスを保持する必要があります。有用な行列には次のものが含まれます:
- プロバイダーとモデル名。
- JSON モードをサポートします。
- JSON スキーマ応答形式をサポートします。
- ツール呼び出しをサポートします。
- 厳密なスキーマ モードをサポートします。
- 既知の JSON スキーマ サブセットの制限事項。
- 並列ツール呼び出しが厳密スキーマ モードと互換性があるかどうか。
- 要求されたモードがサポートされていない場合のフォールバック動作。
能力レコードの例:
{
"provider": "provider_a",
"model": "model_x",
"json_mode": true,
"json_schema_response": true,
"tool_calls": true,
"strict_schema": true,
"schema_limitations": ["no oneOf", "limited format validation"],
"fallback": "reject_or_route_to_compatible_model"
}
このマトリックスはバージョン管理してテストする必要があります。プロバイダーが動作を変更する場合、または新しいモデルが追加される場合は、運用ルーティングの前に構造化出力の互換性を検証する必要があります。
3.最強のプロバイダネイティブコントラクトに変換
アダプターは明確な優先順位に従う必要があります:
- 選択したモデルとスキーマでサポートされている場合は、厳密なプロバイダー ネイティブの構造化出力を使用します。
- アクションや関数のようなタスクを呼び出すプロバイダー ネイティブ ツールを使用します。
- 厳密モードが使用できない場合は、検証と再試行を伴う非厳密構造化出力または JSON モードを使用します。
- リスクの高いワークフローの場合は、リクエストを拒否するか、互換性のあるフォールバック モデルにルーティングするか、アクション以外の応答を返します。
リスクの高い操作を厳密なスキーマ モードから「ベスト エフォート JSON」にサイレントにダウングレードしないでください。アプリケーションが厳密な動作を要求し、選択されたプロバイダーがそれをサポートできない場合、ゲートウェイはエラー、ルーティング決定、または明示的なダウングレード フラグを通じてそれを可視化する必要があります。
実行前の 3 つの検証層
レイヤー 1: 解析検証
まず、応答を予想されるエンベロープに解析できるかどうかを判断します。不正な形式の JSON、欠落しているツール呼び出しブロック、切り捨てられた応答、または混合自然言語と JSON (契約で禁止されている場合) ではフェイルファーストします。
function parseStructuredResponse(raw) {
try {
return { ok: true, value: JSON.parse(raw) };
} catch (error) {
return { ok: false, failure_type: "parse_failure", error: String(error) };
}
}
プロバイダー ネイティブ ツールの呼び出しでは、生のテキスト BLOB の解析は必要ないかもしれませんが、それでもエンベロープ検証が必要です。モデルは既知のツールを選択しましたか、引数を提供しましたか、そしてツールの実行のために期待どおりに停止しましたか?
レイヤー 2: JSON スキーマ検証
次に、サーバー側バリデーターを使用して、宣言されたスキーマに対してオブジェクトを検証します。プロバイダーが厳密なスキーマのサポートを主張している場合でも、これを実行してください。ゲートウェイ側の検証により、一貫した障害ログが得られ、統合ミスから保護され、ダウンストリームの非互換性が検出されます。
const validate = schemaValidator.compile(schema);
const valid = validate(object);
if (!valid) {
return {
ok: false,
failure_type: "schema_failure",
errors: validate.errors
};
}移植性を高めるために、共通のサブセットを念頭に置いてスキーマを設計します。
- 明示的な
type、required、properties、enum、additionalProperties: falseを優先します。 - ターゲット プロバイダーがサポートしていることがわかっていない限り、深くネストされた
oneOf、anyOf、条件付きスキーマなどの複雑な組み合わせは避けてください。 - アクションの引数は小さく、具体的なものにしてください。
- ダウンストリーム システムで別のタイプが必要な場合を除き、ID、日付、コードには文字列を使用します。
confidence、missing_fields、requires_human_reviewなどのフィールドを使用して不確実性を明示的に表します。
レイヤー 3: セマンティックおよびビジネスの検証
最後に、構造化された結果がタスクに対して正しいかどうかを検証します。このレイヤーはドメイン固有であり、JSON スキーマのみにアウトソーシングすることはできません。
請求書抽出の場合、セマンティック チェックには次のものが含まれる場合があります:
- 合計は負ではなく、許容範囲内の広告申込情報と一致します。
- 通貨はソース文書に表示されます。
- 期日は、ありえないほど過去または未来ではありません。
- このベンダーは承認されたベンダー リストに存在します。
- 信頼度は自動エントリに十分高いです。
リードの適格性を確認するために、次のようなチェックが行われる場合があります:
- 選択したセグメントは、営業チームのアクティブなセグメントの 1 つです。
- ユーザーが予算を指定しなかった場合、要求された予算は作成されません。
- 「ブックデモ」アクションは、ユーザーが明示的に要求しない限り実行されません。
パートナー API の自動化の場合、チェックには次のものが含まれる場合があります:
- リセラー アカウントには、要求された顧客またはキーを作成する権限が与えられています。
- リクエストされた支出制限はパートナー ポリシーの範囲内です。
- この操作にはべき等キーがあります。
- アクションは実行前に監査ログに記録されます。
ツール呼び出し: モデル出力を実行ではなくリクエストとして扱います
モデルがアプリケーションに何かを行う必要がある場合、ツール呼び出しは適切なパターンです。たとえば、チケットの作成、Telegram ボット コマンドの送信、価格の検索、顧客レコードの更新、ワークフローの開始などです。
安全なツール ループは次のようになります:
- アプリケーションは、利用可能なツールとその入力スキーマを宣言します。
- モデルは構造化引数を使用したツール呼び出しを返します。
- ゲートウェイはツール名と引数を検証します。
- アプリケーションは、認可、ポリシー、冪等性、およびユーザー確認要件をチェックします。
- その後のみ、アプリケーションはツールを実行します。
- 会話を続行する必要がある場合、ツールの結果がモデルに送り返されます。
ツールの呼び出しを、アクションが実行されるべきであるという証拠として扱わないでください。構造化された提案として扱います。副作用に対する権限は引き続きアプリケーションにあります。
マルチモデル ワークフロー向けの安全なフォールバック ラダー
ゲートウェイは、インシデントが発生する前にフォールバック動作を定義する必要があります。実際のはしごは次のとおりです:
- Primary: 優先モデルの厳密に構造化された出力。
- 互換性のあるフォールバック: 同じ厳格なスキーマ要件をサポートする別のモデル。
- 検証と再試行: 厳密なサポートのないプロバイダー。リスクが許容する場合にのみ使用されます。
- 人間によるレビュー: 構造化された結果とソース コンテンツを承認のためにキューに入れます。
- 非アクション応答: システムが操作を安全に完了できないことを説明します。
再試行は、フォーマットや軽度のスキーマ障害に役立ちますが、安全戦略ではありません。オブジェクトが意味的に安全でない場合、プロンプトを繰り返すと、正しい拒否が危険な実行可能オブジェクトに変わる可能性があります。リスクの高いアクションの場合は、強制的に成功を試みる試みを繰り返すよりも、レビューまたは拒否を優先します。
可観測性: 構造化された出力のすべての決定をログに記録します
構造化出力の障害は動作信号です。不必要な機密コンテンツを公開することなく、ルーティング、スキーマ、およびプロンプトを改善するのに十分な詳細を記録してください。
推奨フィールド:
schema_idとschema_version.- プロバイダーとモデル。
- 要求されたモードと使用される実際のモード。
- 解析失敗ステータス。
- スキーマ障害ステータスと検証エラー。
- セマンティック検証失敗の理由。
- 再試行回数。
- レイテンシ.
- トークンの使用量とコスト。
- 最終アクションのステータス: 実行、キューに登録、拒否、またはユーザーに返されました。
- チーム、プロジェクト、API キー、またはパートナー アカウント識別子(該当する場合)。
これらのログは、デバッグ、コスト分析、プロバイダーの比較、チーム API のガバナンスをサポートします。また、「最も多くの再試行が発生するスキーマ バージョンはどれですか?」などの質問に答えるのにも役立ちます。および「構文はパスしますが、ビジネス検証に失敗するフォールバック モデルはどれですか?」
スキーマのバージョン管理ルール
スキーマは実稼働インターフェースです。 API 件の契約書と同様に扱います。
- リクエストのメタデータとログに
schema_idとschema_versionを含めます。 - 既存のオートメーションの必須フィールドをサイレントに変更しないでください。
- クライアントの移行中も古いスキーマを利用できるようにします。
- 必須にする前に、新しいオプションのフィールドを追加してください。
- ルーティング プール内のすべてのプロバイダーとフォールバック モデルに対してスキーマをテストします。
- すべての副作用のあるアクションにどのスキーマ バージョンが使用されたかを記録します。
バージョニングは、多くの下流顧客が安定した構造化された契約に依存している可能性がある代理店、再販業者、パートナー API 自動化にとって特に重要になります。
構造化された結果を実行しない場合
次のいずれかの状況が発生した場合は、ハード ストップを使用してください:
- 応答は解析できません。
- オブジェクトは JSON スキーマ検証に失敗します。
- 列挙値はサポートされていないか、作成されたものです。
- 数量、価格、日付、通貨は指定できません。
- 結果はユーザーが述べた意図と矛盾します。
- モデルは信頼性が低いか証拠が欠けていることを示しています。
- ユーザーの指示があいまいです。
- このアクションには副作用があり、確認が不足しています。
- アカウント、チーム、または API キーが承認されていません。
- プロバイダーの応答には、拒否または安全関連の無応答が含まれます。
推奨事項と予測
推奨事項: 可能な場合はプロバイダー ネイティブの構造化出力を使用し、すべての応答をゲートウェイ側で検証し、アクションのツール呼び出しを優先し、機能マトリックス、バージョン スキーマを維持し、セマンティック チェックに合格するまで副作用をブロックします。
予測: 構造化出力に対するプロバイダーのサポートは強化され、より一貫性のあるものになる可能性がありますが、モデル ファミリ、スキーマ サブセット、およびツール呼び出しループは一夜にして同一になるわけではないため、移植性は引き続きゲートウェイの懸念事項となります。検証、可観測性、スキーマのバージョン管理を構築するチームは、すべてのワークフローを書き直すことなく、新しいプロバイダーの機能を採用できるようになります。
実用的な実装チェックリスト
- アプリケーションの正規化された構造化出力リクエスト形式を定義します。
- ルーティング プール内のモデルごとにプロバイダー機能マトリックスを作成します。
- 移植可能な JSON スキーマ サブセットを使用してスキーマを設計します。
- サポートされている場合は、リクエストを厳密なプロバイダー ネイティブのメカニズムに変換します。
- 生成後に解析可能性、スキーマの適合性、ビジネスの正確性を検証します。
- 副作用のある操作にはツール呼び出しを使用します。
- モデル外での承認、冪等性、確認が必要です。
- スキーマのバージョン、プロバイダー、検証の失敗、再試行、レイテンシー、コスト、アクションのステータスをログに記録します。
- ワークフローのリスク レベルごとにフォールバック動作を定義します。
- 依存する自動化が移行されるまで、古いスキーマを利用可能なままにしておきます。
実際的な目標は、すべてのモデルを同じように動作させることではありません。これは、ゲートウェイがプロバイダーの違いを正直に処理しながら、アプリケーション開発者に 1 つの安定した契約を提供するためです。構造化された出力は、信頼性の高い AI 自動化に必要なインフラストラクチャですが、実稼働境界は、オブジェクトが安全に使用できるかどうかを決定する検証レイヤーとポリシー層です。