JSON Mode(JSON出力モード)(ジェイソンモード)
LLMの出力をJSON形式に強制する推論モード。フリーテキストではなく構造化データとしてモデル応答を受け取り、アプリケーション間のデータ連携やパース処理を確実にする。
JSON Modeとは
JSON Mode(JSON出力モード)は、LLMの応答を有効なJSON形式に制約する推論モードである。通常のLLM応答はフリーテキストであり、JSONを要求してもマークダウンのコードブロックで囲んだり、前後に説明文が入ったりしてパースが失敗することがある。JSON Modeを有効にすると、モデルは必ず有効なJSON(かつJSONのみ)を出力するよう制約される。
JSON Modeの進化
| 世代 | 名称 | 制約レベル | 代表 |
|---|---|---|---|
| 第1世代 | プロンプト指示 | 弱(違反頻発) | 全モデル |
| 第2世代 | JSON Mode | 中(JSON保証、スキーマ非保証) | GPT-4 Turbo(2023年11月) |
| 第3世代 | Structured Outputs | 強(スキーマ100%準拠保証) | GPT-4o(2024年8月) |
第1世代はプロンプトに「JSONで出力してください」と指示するだけで、モデルが従わないことが頻繁にあった。第2世代のJSON Modeは出力が有効なJSONであることを保証するが、スキーマ(フィールド名や型)の準拠は保証しない。第3世代のStructured OutputsはJSON Schemaに100%準拠した出力を保証する。
主要プロバイダの対応
| プロバイダ | JSON Mode | Structured Outputs | 設定方法 |
|---|---|---|---|
| OpenAI | ○ | ○(response_format) | response_format: {type: "json_object"} |
| Anthropic | △(tool_useで代替) | ○(tool_use + schema) | toolsパラメータにスキーマ定義 |
| Google Gemini | ○ | ○(responseSchema) | generationConfig: {responseMimeType: "application/json"} |
| Mistral | ○ | × | response_format: {type: "json_object"} |
| Llama 3.1+ | ○(via vLLM) | ○(Outlines連携) | guided_json パラメータ |
JSON ModeとStructured Outputsの違い
JSON Modeは出力が有効なJSONであることのみ保証する。{"name": "太郎", "age": 30} も {"x": [1,2,3]} も有効なJSON。
Structured Outputsは事前定義したJSON Schemaに100%準拠することを保証する。必須フィールドの欠落、型の不一致、未定義フィールドの追加が発生しない。
実装上の違い:
- JSON Modeはトークン生成時にJSON構文トークンのみを許可するフィルタリング
- Structured Outputsはコンパイル済みのJSON Schema FSM(有限状態機械)でトークン候補を制限
ローカルLLMでのJSON制約
vLLMやllama.cppでは以下の方式でJSON制約を実現する:
- Outlines: 正規表現やJSON Schemaから有限状態機械を構築し、許可トークンのみをサンプリング。vLLMに統合済み
- GBNF(Grammar-Based): llama.cppのBNF文法でJSON構文を定義。軽量だが複雑なスキーマには不向き
- SGLang: 独自のJSON制約エンジンで高速な構造化出力を実現
FAQ
Q: JSON Modeを使うとモデルの品質は落ちるか?
A: JSON制約によりトークン候補が制限されるため、理論上は自由応答より品質が若干低下する可能性がある。しかし実用上の差異は極めて小さく、構造化データが必要な場面ではパース失敗のリスク排除のメリットが圧倒的に大きい。
Q: Structured Outputsで定義できないスキーマはあるか?
A: OpenAIのStructured Outputsではrecursive types(再帰型)やunion types(OpenAPI oneOf/anyOf相当)に制限がある。複雑なスキーマは単純化するか、複数回の呼び出しに分割する設計が必要。
Q: ストリーミング出力とJSON Modeは併用できるか?
A: ほぼ全プロバイダで併用可能。ストリーミング中は部分的なJSON(パース不可能な状態)が流れるため、完全なJSONを受け取ってからパースすること。一部ライブラリ(langchain等)は部分JSONのインクリメンタルパースをサポートしている。