ClaudeとOpenAIがそれぞれ、モデルに正しいJSONを確実に出力させる方法を提供。その違いとは
両社は現在、モデルが正しく整形することを期待するのではなく、スキーマに適合した出力を保証する厳格モードを提供している。設定には具体的なルールがあり、OpenAIの公式ガイダンスでは、モデルに一度に渡すツール数にも依然として上限の目安が示されている。
ひとことで言うと
検証や再試行が不要な構造化出力を得るために、ClaudeとOpenAIはどのような方法を推奨しているのか?
両社とも厳格モードを提供している。Claudeではツール定義に`strict: true`を指定し、OpenAIではレスポンス形式に`strict: true`を指定したStructured Outputsを使用する。OpenAIでは`additionalProperties: false`を設定し、すべてのフィールドを必須として列挙する必要がある。任意項目は省略可能にするのではなく、nullを許容する型にする。両社のガイドは、曖昧な関数説明や利用可能なツールの多さが、気づかないうちに精度を低下させるとも警告している。
要点
- OpenAIのStructured OutputsとClaudeの厳格なツール利用は、いずれもスキーマへの準拠を保証する。従来の「JSONモード」方式にはその保証がなく、不正な形式の出力が返される可能性がある。
- OpenAIの厳格なスキーマでは、`additionalProperties: false`を設定し、すべてのフィールドを`required`に含める必要がある。このリストから除外される任意フィールドという考え方はなく、代わりにnull許容型として定義する。
- OpenAIの公式ガイダンスは、ターン開始時に利用可能な関数を20個未満に抑えることを推奨している。各定義が入力トークンとして数えられ、選択肢が増えるほど精度が低下するためだ。
- Claudeは、モデル間に実際の信頼性の差があると説明している。プロンプトに必須パラメーターが欠けている場合、Opusは確認質問をしやすいが、Sonnetは代わりに妥当と思われる値を推測しやすい。
- 両プラットフォームとも、ツールや関数の定義を呼び出しのたびに通常の入力トークンとして課金する。Claudeは、それによって生じる正確なトークンオーバーヘッドをモデル別に公開している。
LLMに関数を呼び出させたりJSONを返させたりする仕組みは、以前から「たいていは」動作してきた。しかし、これはまったく動かないより厄介な問題だ。障害は手作業で試した99回ではなく、1万回目の呼び出しでパーサーがクラッシュするなど、後工程で表面化する。ClaudeとOpenAIは現在、この文から「たいていは」を取り除くモードを公開しており、それぞれの公式な設定ルールは、推測せずそのまま実践できるほど具体的だ。
両社の厳格モード
Claudeでは、カスタムツールの定義にstrict: trueを追加すると、Claudeのツール呼び出しがスキーマに適合することが保証される。OpenAIではStructured Outputsと呼ばれ、text: { format: { type: "json_schema", strict: true, schema: … } }で設定する。OpenAIはこれを従来の「JSONモード」の後継と明確に位置づけている。JSONモードではスキーマへの準拠までは保証されなかったが、Structured Outputsでは保証される。
初めて見る人にも分かる関数説明を書く
OpenAIは、同社が「インターンテスト」と呼ぶ基準を満たすよう、関数名、パラメーターの説明、利用手順を明確に記述することを勧めている。つまり、新入社員がほかの文脈を与えられなくても、ドキュメントだけで関数を正しく使える状態だ。そのためには、関数を呼ぶべき場合と呼ぶべきでない場合を、境界事例の例も添えてシステムプロンプトに明記する必要がある。明らかに呼ぶべき状況で関数が何をするのかを説明するだけでは不十分だ。
ツールを減らせば精度が上がる
手持ちのツールをすべてモデルに渡し、どれを使うべきか判断させたくなるかもしれない。しかしOpenAIのガイダンスは、これを明確に戒めている。精度を高めるには、ターン開始時に利用可能な関数をおおむね20個未満に抑えるべきだという。また、そのターンで実際に使われるかどうかにかかわらず、すべての関数定義が入力トークンとして数えられる。常に同じ順序で呼び出す一連の関数がある場合、モデルに毎回複数の呼び出しを正しく連鎖させるのではなく、1つの処理にまとめることをOpenAIは提案している。
Claudeのモデルは同じようには失敗しない
Claudeのドキュメントには、本番環境で初めて気づくのではなく、事前に考慮しておく価値のある、モデル単位の信頼性に関する具体的な注意事項が記されている。ユーザーが実際に入力した内容に必須パラメーターが欠けている場合、Opusはその不足に気づいて確認質問をする可能性がかなり高い。一方、Sonnetは妥当と思われる値を自ら推測しやすく、たとえば場所を尋ねる代わりに推定する傾向がある。いずれの方向も保証された挙動ではないが、各モデルにはこうした傾向があり、能力の低いモデルで曖昧なプロンプトを処理すると問題はさらに大きくなる。
呼び出しの強制と複数呼び出しの同時実行
両プラットフォームとも、ツールを使用するかどうかをClaudeやOpenAIの標準判断に委ねず、強制的に呼び出すことができる。Claudeではtool_choiceを指定し、デフォルトの{"type": "auto"}に任せず呼び出しを強制する。OpenAIでは、GPT-5以降で組み込みツールの並列関数呼び出しに対応している。1ターンにつき最大1回の呼び出しに限定したい場合は、parallel_tool_calls: falseを指定できる。ただし組み込みツールは、この設定にかかわらず並列グループとして一括実行できない。
日付を確認すること。 OpenAIの公式ドキュメントは、新しいStructured Outputsプロジェクトにgpt-5.6を推奨し、ツール検索はgpt-5.4以降でのみ利用できるとしている。Claudeは、現行世代のモデルごとにツール利用時のトークンオーバーヘッドを公開している。どちらの数値も新モデルの登場に伴って変わるため、上記の値を恒久的なものとみなさず、リンク先のページを直接確認すべきだ。
よくある質問
- Structured Outputsは従来のJSONモードと同じものか?
- 違う。OpenAIはStructured OutputsをJSONモードの発展形と説明している。JSONモードはスキーマへの準拠を保証しないが、Structured Outputsは保証する。OpenAIの比較表では、従来のJSONモードはgpt-4o-2024-08-06より前のモデルに限って推奨されている。
- 厳格モードでは、スキーマに具体的に何が求められるのか?
- OpenAIでは、すべてのオブジェクトに`additionalProperties: false`を設定し、全プロパティを`required`に列挙する必要がある。任意フィールドは必須リストから除外せず、null許容型として表現する。Claudeでは、ツール定義に`strict: true`を追加する。
- 利用可能なツールを増やせば、常にモデルにとって有利になるのか?
- ならない。OpenAIのガイダンスは、精度を保つため、1ターンで利用可能な関数をおおむね20個未満に抑えることを明確に推奨している。また、そのターンで実際に使用されるかどうかにかかわらず、各定義は入力トークンとして課金される。
- モデルに特定のツールを強制的に呼び出させることはできるか?
- 両プラットフォームで可能だ。Claudeでは、ツール利用の強制に関するドキュメントに記載された`tool_choice`パラメーターを使用する。OpenAIでは、`parallel_tool_calls: false`の設定と明示的なツール選択を組み合わせることで、呼び出しを正確に1回に限定できる。
出典
- Tool use with Claude — Anthropic
- Function calling — OpenAI
- Structured model outputs — OpenAI
- Introduction to Structured Outputs — OpenAI