構造化出力
Structured Outputs
概要(サマリー)
構造化出力(Structured Outputs)とは、AIの返答を、決められた項目と型を持つJSONなどの形式で出力させる仕組みである。
白紙の便箋に「感想を自由に書いて」と頼むのではなく、「名前」「評価(1〜5の数字)」「感想」の欄が印刷された記入フォームを渡して、その枠どおりに書いてもらうイメージである。
LLMにプロンプトで「JSONで答えて」と頼むだけだと、「承知しました!以下がデータです」といった前置きが混ざったり、カンマが抜けたりして、プログラムが読み込めないことがある。構造化出力の機能を使うと、AIの出力が指定した形(スキーマ)に沿うよう、APIの側で制御される。そのため、AIの返答をプログラムでそのまま扱いやすくなる。
詳細解説
なぜ構造化出力が必要なのか
人間同士のチャットなら、前置きや言い回しが多少違っても困らない。しかし、AIの返答をプログラムで処理する場合は話が違う。
プログラムは、データが約束どおりの形になっていないと読み込み(パース)に失敗し、エラーで止まってしまう。たとえば「優先度」の欄に "high" が入るはずが "高め" と書かれていたら、その後の処理は正しく動かない。
構造化出力を使えば、「どの項目があり、それぞれどんな型か」をあらかじめ決めておける。AIを部品としてシステムに組み込むときの、つなぎ目の事故を減らす仕組みである。
プロンプトでの指示との違い
| 項目 | プロンプトで「JSONで出力して」と頼む | 構造化出力の機能を使う |
|---|---|---|
| 前置きや説明文 | 混ざることがある | 原則として出力されない |
| 項目名や型 | 綴りの間違いや型の違いが起きることがある | 指定したスキーマに沿うよう制御される |
| JSONの文法ミス | 起きることがある | 起きにくい |
| 実装の手間 | 失敗時のやり直し処理がほぼ必須 | チェックは必要だが、やり直しの頻度を減らせる |
スキーマの書き方
構造化出力では、出力してほしい形をJSON Schemaという書き方で指定することが多い。以下は、タスク情報を出力させるスキーマの例である。
{
"type": "object",
"properties": {
"taskName": { "type": "string" },
"priority": { "type": "string", "enum": ["low", "medium", "high"] },
"estimatedMinutes": { "type": "integer" },
"isBlocked": { "type": "boolean" }
},
"required": ["taskName", "priority", "estimatedMinutes", "isBlocked"],
"additionalProperties": false
}
enum は「この中から選ぶ」という指定で、priority には low / medium / high のどれかしか入らない。additionalProperties: false は「ここに書いていない項目を勝手に足さない」という指定である。
どうやって形を守らせているのか
AIは文章を少しずつ(トークンごとに)予測して出力している。構造化出力では、その予測の段階で「スキーマに合わない文字」を選べないように制限する仕組みが使われることが多い。
たとえば estimatedMinutes の値を書いている最中は、数字以外を選べないようにする。お願いして守ってもらうのではなく、出力の段階で枠をはめているのが、プロンプトでの指示との大きな違いである。
AIコーディングとの関係
AIをアプリに組み込む場面では、構造化出力はよく使われる部品である。
- 問い合わせの自動仕分け: 長文の問い合わせから「内容の要約」「緊急度」「担当部署」を取り出し、そのままデータベースに保存する
- エージェントの判断結果の受け渡し: AIエージェントが次にどの道具を使うか、どんな値を渡すかを決まった形で出力させる
- コードの解析結果の一覧化: 問題のあるファイル名、行番号、重要度、修正案を表の形で受け取る
実装では、PythonのPydanticやTypeScriptのZodといったライブラリでデータの形を定義し、それをスキーマとしてAPIに渡す方法がよく使われる。
よくある勘違い
ツール呼び出し(Function Calling)と同じもの?
関係は深いが、目的が違う。ツール呼び出しは、AIに「どの関数を、どんな引数で呼ぶか」を決めさせる仕組みである。構造化出力は、AIの返答そのものを決まった形のデータとして受け取る仕組みである。サービスによっては、ツール呼び出しの引数にも同じようにスキーマを厳密に守らせる設定が用意されている。
構造化出力を使えば、中身も必ず正しい?
いいえ。構造化出力が守らせるのは「形」であって、「中身の正しさ」ではない。項目と型は合っていても、要約が的外れだったり、数値が間違っていたりすることはある。また、出力の長さの上限に達して途中で切れた場合や、AIが回答を拒否した場合など、期待した形で返ってこないケースもある。受け取ったデータは、プログラム側でもバリデーションしておくと安心である。
どんなに複雑なスキーマでも使える?
入れ子になったオブジェクトや配列など、多くの形は指定できる。ただし、サービスごとに使えるスキーマの書き方に制限があることがある。また、階層が深すぎたり条件が複雑すぎたりすると、AIが中身を考えにくくなり、内容の質が下がることもある。できるだけシンプルな形に保つのがコツである。
まとめ
- 構造化出力は、AIの返答を決められた項目と型を持つJSONなどの形式で出力させる仕組みである
- 前置き文や文法ミスを減らし、AIの返答をプログラムでそのまま扱いやすくする
- 守られるのは「形」であり「中身の正しさ」ではないため、受け取った後のチェックも必要である
情報ソース
より詳しくAIに聞いてみよう
- OpenAI APIやGemini APIで構造化出力を使う、最小限のコード例を教えてください。
- PydanticやZodでデータの形を定義し、構造化出力のスキーマとして使う方法を教えてください。
- 構造化出力とツール呼び出し(Function Calling)の使い分けを、具体例で説明してください。
- 構造化出力で受け取ったデータを、プログラム側でさらにチェックすべき理由と方法を教えてください。
- 入れ子の多いスキーマを、AIが扱いやすい形に整理するコツを教えてください。