構造化出力
構造化出力は、LLMに対して自由形式のテキストではなく、JSON Schemaのような事前定義された形式に厳密に従うレスポンスを生成させる機能です。スキーマはプロンプトで単に要求されるだけでなく、トークン生成中に強制されるため、結果は常に解析可能なデータとなり、必須フィールドの欠落や不正な構造はありません。
Structured outputは、LLMの応答をJSON Schemaのような指定されたスキーマに準拠させるものであり、解析可能なデータを確実に受け取るための中核的な仕組みです。
プロンプトで単に形式を指定するだけではなく、生成時にスキーマ外のトークンをすべてブロックするため(constrained decoding)、形式違反は構造上起こりえなくなります。
OpenAIは、Structured Outputsを備えたgpt-4o-2024-08-06が複雑なJSON Schema準拠評価で100%を記録し、これを持たないモデル(gpt-4-0613)は40%未満だったと報告しています。
OpenAI(Structured Outputs)、Anthropic(Claude)、Google(Gemini)はいずれも同じ概念をサポートしており、データ抽出、分類、エージェントによるツール呼び出しに不可欠です。
これはSEOの'structured data'(schema markup)とはまったく異なる概念です。この用語は、検索エンジン向けのマークアップではなく、LLMの出力形式を制御することを指します。
Structured Outputとは
Structured outputは、LLMに自由形式の文章を出力させるのではなく、あらかじめ定義されたスキーマ(通常はJSON Schema)に厳密に従わせる機能ですforces an LLM to follow a predefined schema (usually JSON Schema) exactly, rather than emitting free-form prose「JSONで回答してください」とプロンプトで単に依頼するだけではありません。狙いは、モデルがそもそもスキーマから逸脱した応答を生成することを不可能にすることです。その結果、欠落したキー、誤ったデータ型、壊れたJSONのない、プログラムがすぐに解析できるデータを得られます。
この概念は、LLMの出力をデータベース、API、関数呼び出しなどの下流システムに確実につなぐために生まれました。コードでモデルの応答を処理するには、毎回フォーマットが正確に一致している必要がありますが、従来のモデルは説明文を付け足したり、フィールドを省略したりして、解析エラーを引き起こすことがありました。Structured output はその不確実性を取り除き、AI search、エージェント、データ抽出パイプラインの信頼性を高める基盤を提供します。
SEOのStructured Data'
とは別物Structured output は、LLM自身が生成する応答の形式を制御する機能です。両者は目的、動作する場所、利用者が異なります。以下の表でその違いをまとめます。
項目 | Structured Output | 構造化データ (スキーママークアップ) |
|---|---|---|
目的 | LLMの応答を指定した形式に強制する | ページの内容を検索エンジンに伝える |
形式 | JSON Schema(レスポンス本文) | schema.orgの語彙をJSON-LD、Microdataなどで記述 |
配置場所 | LLM APIのレスポンス | HTML文書内のマークアップ |
消費者 | 下流のコード、API、エージェント | GoogleやBingなどの検索エンジンのクローラー |
典型例 | OpenAI Structured Outputs、Gemini responseSchema | リッチリザルトのマークアップ(星評価、FAQ、商品) |
仕組み:プロンプト指示ではなく、トークン制約
構造化出力の核心にあるのは制約付きデコーディングです。定義された JSON Schema は文法にコンパイルされ、モデルがトークンを1つずつ生成する推論ステップでは、スキーマが許可しないトークンはすべてブロックされます。言い換えれば、フォーマット違反は単に「めったに起こらない」だけではなく、構造的に不可能になります。
Anthropic の Claude ドキュメントでは、このプロセスを「JSON スキーマを grammar にコンパイルして、推論中のトークン生成を制約する」と説明しており、プロンプティングに依存しないことを明記しています。これは、あくまで「有効な JSON」だけを保証する JSON mode と、「スキーマへの厳密な準拠」も保証する structured output を分ける違いです。
Aspect | JSON Mode | Structured Outputs |
|---|---|---|
有効な JSON を保証 | Yes | Yes |
スキーマへの準拠を保証 | No | Yes |
必須フィールドの欠落を防止 | No | はい |
メカニズム | フォーマット誘導(プロンプト) | 制約付きデコーディング(トークンブロッキング) |
JSONスキーマの例
構造化出力の基盤はJSON Schemaです。JSON Schemaは、JSONデータの構造と制約を定義するための宣言的な言語で、現在推奨されているバージョンは draft 2020-12 です。たとえば、ユーザー情報を抽出するスキーマは次のようになります。
{
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"plan_interest": {
"type": "string",
"enum": ["free", "pro", "enterprise"]
},
"demo_requested": { "type": "boolean" }
},
"required": ["name", "email", "plan_interest", "demo_requested"],
"additionalProperties": false
}OpenAI API では、このスキーマをresponse_formatに渡し、さらに有効にする必要がありますstrictスキーマを強制適用するためです。OpenAI では、すべてのフィールドをrequiredに列挙し、additionalPropertiesをfalseに設定する必要があります。
response_format = {
"type": "json_schema",
"json_schema": {
"name": "user_info",
"strict": true,
"schema": { /* the schema above */ }
}
}Claude API では、同じスキーマをoutput_config.formatに渡して、type: "json_schema"、また、ツール呼び出しの引数までも厳密に強制するには、strict: trueをツール定義に追加します。Google Gemini は、responseSchema(スキーマの強制)とresponse_mime_type(JSON モード)を区別しており、Python で Pydantic、JavaScript で Zod を使ってスキーマを定義すると、そのまま利用できます。
エビデンスと測定データ
構造化出力の有効性は、各プロバイダーの公式資料によって裏付けられています。
OpenAI: Structured Outputs を備えた gpt-4o-2024-08-06 が100%複雑な JSON Schema 適合性評価において達成した一方で、旧版の gpt-4-0613 は40%未満にとどまりました。OpenAI は、可能な限り常に JSON mode より Structured Outputs を使用することを推奨しています。
Anthropic: Claude の structured output は、スキーマをグラマーにコンパイルしてトークン生成を制約するため、
JSON.parse()エラーは発生せず、スキーマ違反に対する再試行も不要であると説明しています。コンパイルされたグラマーは 24 時間キャッシュされます。とはいえ、再帰スキーマや lookahead などの一部の JSON Schema 機能は、ツール数およびパラメータ数とともに制限の対象となります。Google: Gemini のドキュメントでは、スキーマを強制することは「脆弱な出力パースの必要性をなくす」ことを意味するとし、データ抽出、分類、エージェントワークフローを代表的なユースケースとして示しています。
実装チェックリスト
可能な限り、プレーンな JSON mode ではなく、スキーマを強制する structured output を使用してください。
JSON Schemaでは、必要なすべてのフィールドを
requiredに सूचीし、additionalPropertiesをfalseに設定します(OpenAIの推奨)。列挙が必要なフィールドについては、無効な値をブロックするために
enumで有効な値のセットを絞り込みます。スキーマを手作業で書くよりも、Pydantic(Python)またはZod(JavaScript)で定義して、コードとスキーマを同期させます。
例外は、レスポンスが拒否されたのか、長さ制限によって途中で切れたのかを確認して処理します(
finish_reason).再帰的スキーマや複雑な数値制約など、一部の機能はサポートされない場合があるため、各プロバイダーのスキーマ制限を確認してください。