LLMの構造化出力JSONを検証する:欠損値と事実の間違いを見分ける演習
AIの回答を表やシステムへ渡したいときは、説明文ではなく決まった項目のJSONが必要になります。Structured Outputsは対応するスキーマに沿った出力を指定する仕組みです。ただし、項目と型が正しくても、原文にない名前や数量が入れば業務では使えません。形式の確認と、事実の確認を分けて設計しましょう。[出典1]
ここでは外部サービスに接続せず、架空の研修申込文を教材にします。氏名などの実データを入力する必要はありません。ツール実行の設計についてはツール呼び出しの設計チェックリストを参照してください。本演習は、情報の抽出だけを扱います。
最初に、取り出したい項目と欠損時の値を決める
教材文を「来月の基礎研修に2名で参加したいです。請求先はまだ決まっていません」とします。保存したいのは研修名、人数、請求先です。「来月」から具体的な開催日を推測する処理は入れません。原文に書かれていない情報を補うと、読み手が抽出と推測を区別できなくなるためです。
| 項目 | この教材での型 | 不足している場合 |
|---|---|---|
| course_name | 文字列またはnull | null |
| participants | 整数またはnull | null |
| billing_destination | 文字列またはnull | null |
空文字、null、項目自体の欠落を混ぜると、後工程の判断が増えます。この教材では、項目はすべて置き、分からない値にnullを使います。「未定」と実在の会社名を同じ扱いで保存しないことも決めます。
スキーマと期待するJSONを用意する
次は演習用のJSON Schemaです。APIごとに利用できるキーワードや指定方法が異なるため、採用するAPIの現行仕様へ合わせてください。OpenAIとGeminiの構造化出力は、同じコードをそのまま使い回せるという意味ではありません。[出典1・2]
{
"type": "object",
"properties": {
"course_name": {"type": ["string", "null"]},
"participants": {"type": ["integer", "null"]},
"billing_destination": {"type": ["string", "null"]}
},
"required": ["course_name", "participants", "billing_destination"],
"additionalProperties": false
}
この教材文に対して人が先に作る期待値は、次のとおりです。
{
"course_name": "基礎研修",
"participants": 2,
"billing_destination": null
}
AIへの依頼には「原文の記載だけを抽出する」「原文にない値はnull」「人数を推測しない」と書きます。その指示で必ず正解になるとは限らないため、以下の検証を残します。
JSONを読める・型が合う・原文に合う、の3段階で確認する
パーサーで読めることは最初の条件です。次に必須項目、型、余計な項目を確認します。その後に、各値を原文と突き合わせます。たとえば人数が200になっていても、整数型という条件だけは満たしてしまいます。
| AI出力の例 | 形式確認 | 原文確認 | 扱い |
|---|---|---|---|
| participantsが"2" | 整数指定に不一致 | 数量の読み自体は近い | 変換規則を確認して修正。黙って保存しない |
| participantsが200 | 整数型は合う | 原文の2名と不一致 | 事実の誤りとして止める |
| billing_destinationが架空の会社名 | 文字列型は合う | 原文にない | 推測混入として止める |
| billing_destinationがnull | 指定どおり | 原文の未定と対応 | 後工程で確認待ちにする |
自動修正する場合も、修正前の出力と適用した規則を記録します。人が見ないまま文字列を数値へ変えると、「2〜3名」など別の入力で誤変換する可能性があります。
拒否・途中終了・通信失敗を抽出結果と混ぜない
APIから期待したデータが返らなかったとき、空の申込情報を作って成功に見せると、失敗を後から追えなくなります。OpenAI公式資料には拒否の扱いも記載されています。実際の判定は、本文だけでなく採用APIのレスポンス状態を確認してください。[出典1]
- 正常な抽出:値と原文を照合して、保存可否を決める。
- 記載不足:nullを残し、不足項目を人に確認する。
- 拒否や途中終了:業務データとして保存せず、処理結果として記録する。
- 通信失敗:回数上限などの運用規則を決めて再試行する。無限に繰り返さない。
個別適用や説明の拡張時に確認する事項:これは演習用の整理です。各APIの具体的な状態名や例外処理は、利用するSDKとAPIの版に合わせます。
確認用の5入力を固定しておく
- 研修名・人数・請求先が全部書かれている。
- 人数だけが書かれていない。
- 「2〜3名」とあり、1つの整数に確定できない。
- 研修名を訂正する文が後半にある。
- 申込文ではない文章が渡される。
それぞれの期待値を人が用意し、プロンプトやモデルを変更した後も同じ入力で確かめます。4番は「最後の訂正を優先するか」、5番は「対象外をどう返すか」という業務規則が必要です。スキーマを書くだけで、この規則まで決まるわけではありません。
構造化出力を業務へ組み込む前には、項目定義、欠損、失敗状態、原文照合、保存条件の5点を説明できるようにしましょう。JSONとして正しいことと、処理に使ってよいことを区別できれば、形式が整った誤情報の混入を見つけやすくなります。
出典
- OpenAI:Structured model outputs。スキーマ、拒否、出力内容の誤りに関する説明。
- Google:Gemini APIの構造化出力。利用時の指定方法と対応範囲。