本文へスキップ
スキルアップカレッジ

出力制御——構造化、JSON Schema、Markdown/XML

レッスン4:出力制御——構造化、JSON Schema、Markdown/XML

このレッスンで学ぶこと

  • 構造化出力がなぜ実務で重要なのかを理解する
  • JSON Schema による出力指定の基本を押さえる
  • XML タグでの構造化(Anthropic 推奨パターン)を学ぶ
  • Constrained Generation の仕組みと使いどころを区別できる
  • 出力検証とリトライ設計の発想を持つ
  • 長い出力での失敗パターンを把握する

前回のレッスンで、Few-shot と Chain-of-Thought を通じて「LLM に何を考えさせるか」を扱いました。今回は、「LLM の出力をどう受け取るか」に焦点を当てます。LLM を業務システムに組み込むとき、自然言語の自由形式では後段のプログラムが処理できません。構造化出力——JSON、XML、Markdown——をどう設計し、どう検証するかが、実務の中核技術になります。

なぜ構造化出力が必要か

LLM の自然な出力は「自然言語の文章」です。これは人が読むには便利ですが、システムが処理するには扱いにくい形です。

自然言語出力のままだとどうなるか

質問:「次の顧客レビューから、評価と理由を抽出してください」 LLM の出力:「このレビューは肯定的で、特に対応の早さを評価しています。ただ、価格については少し高いと感じているようです」

この出力は人が読めば理解できますが、

  • 評価を「ポジティブ/中立/ネガティブ」のどれと判定したか
  • 理由を箇条書きで抽出したいときに、どう取り出すか
  • 後段の集計・通知・データベース保存にどう渡すか

が、システム的には曖昧です。100 件のレビューを処理しようとした瞬間、破綻します。

構造化出力にすると

出力:

{
  "sentiment": "positive",
  "positive_points": ["対応の早さ"],
  "negative_points": ["価格が高い"]
}

これなら、後段のプログラムが data.sentiment === "positive" のように判定でき、自動的に集計・通知・保存ができます。

💡 ポイント 「LLM を試しに使ってみる」段階では自然言語出力で十分ですが、「業務システムに組み込む」段階では構造化が必須です。本レッスンはその段階での設計を扱います。

JSON Schema による出力指定

JSON は構造化出力の最も標準的な形式です。「JSON Schema」を使って、期待する形を明示するのが推奨パターンです。

JSON Schema の基本

JSON Schema は、JSON の構造(プロパティ名、型、必須項目、列挙値など)を記述する仕様です。LLM に直接渡すこともあれば、API のパラメータとして渡すこともあります。

例:顧客レビュー分析の JSON Schema

{
  "type": "object",
  "properties": {
    "sentiment": {
      "type": "string",
      "enum": ["positive", "neutral", "negative"]
    },
    "positive_points": {
      "type": "array",
      "items": { "type": "string" }
    },
    "negative_points": {
      "type": "array",
      "items": { "type": "string" }
    }
  },
  "required": ["sentiment"]
}

このスキーマで「sentiment は 3 値の列挙、positive/negative_points は文字列の配列、sentiment は必須」が明示されます。

Structured Outputs(API レベルでの強制)

2024 年以降、OpenAI・Anthropic・Google などの主要 API は「Structured Outputs」と呼ばれる、JSON Schema に必ず従う出力モードを提供しています。プロンプトで「JSON で返してください」と書くだけより、API レベルで強制する方が、確実性が高くなります。

📝 補足 Structured Outputs は便利ですが、複雑なスキーマでは LLM が無理に値を埋めようとして、嘘の値を作る場合があります(「sentiment は必須だが、レビュー内容が判定不能」のときに、根拠なく "neutral" を返す等)。「埋められない場合は null を返す」「不明 enum を用意する」などの設計で対処します。

XML タグでの構造化(Anthropic 推奨)

Claude シリーズを開発する Anthropic は、入出力の構造化に「XML タグ」を使うことを公式ドキュメントで推奨しています。Claude シリーズは XML タグ構造に特に強い反応を示すよう訓練されているためです。

入力の構造化

長い指示やデータを LLM に渡すとき、XML タグで区切ることで、LLM が「どこからどこまでが何の情報か」を判別しやすくなります。

例:

以下の指示と文書から、要約と論点を抽出してください。

<instruction> 文書を 300 文字以内で要約し、論点を 3 つ箇条書きで抽出する </instruction>

<document> (ここに文書本文) </document>

出力の構造化

出力側でも XML タグで返させることができます。これは JSON より自然言語に近く、長文の入れ子に強いという利点があります。

例:

出力形式: <summary>...</summary> <key_points> <point>...</point> <point>...</point> <point>...</point> </key_points>

JSON と XML の使い分け

場面 推奨
プログラムで機械処理する JSON(パース容易、Schema 強制可能)
Claude シリーズに長文を渡す 入力は XML タグで区切る
入れ子・自由テキストが多い XML タグ(パースより構造の柔軟性)
API の Structured Outputs を使う JSON Schema

💡 ポイント 入力を XML タグで区切り、出力は JSON Schema で受ける、というハイブリッドが現場では多く使われます。「入力は人と LLM が読みやすい、出力は機械が処理しやすい」という非対称な設計が、運用上で機能します。

Constrained Generation(制約付き生成)

Constrained Generation は、LLM の出力を「文法的に必ず正しい JSON や特定の構造に従わせる」技術です。

仕組みの概要

LLM は次トークンを確率で選びますが、Constrained Generation では「次に許される文字/トークン」をフィルタリングし、JSON 文法から外れるトークンを生成しないようにします。例えば、JSON のキー直後は : しか許されないなら、それ以外のトークン候補を強制的に除外します。

主要ベンダーでの提供

  • OpenAI:Structured Outputs(JSON Schema に従う)
  • Anthropic:Tool Use や Response Format による構造化
  • Google:JSON Mode、Response Schema

効用と限界

効用:

  • 出力がパースエラーで失敗することがなくなる(JSON は必ず妥当な JSON になる)
  • 後段のリトライ・ハンドリングコードがシンプルになる

限界:

  • スキーマが複雑すぎると、LLM が無理やり値を埋める
  • 「妥当な JSON」と「正しい内容」は別問題で、内容のハルシネーションは別途検証が必要

⚠️ 注意 Constrained Generation は「形式の正しさ」を保証しますが、「内容の正しさ」は保証しません。形が正しくて内容が嘘の JSON も、平気で返ってきます。レッスン 5 で扱う評価セットと組み合わせて、内容の妥当性を別途検証する運用が必要です。

Markdown テンプレート

人が読む出力(メール、文書、Slack 投稿など)では、Markdown テンプレートを指定する方法が便利です。

例:

出力形式:

件名

(件名を 1 行で)

本文

(3 段落以内)

アクション

  • (箇条書き 3 個以内)

Markdown は人が読みやすく、後段で HTML 変換や PDF 生成にも繋ぎやすい形式です。

📝 補足 Markdown 出力は「人が見る最終成果物」を作るタスクで効きます。Web のフロントエンドに渡してそのまま表示する、メールに整形して送る、社内 Wiki に投稿する、などの用途では JSON より Markdown が適します。

出力検証とリトライ設計

構造化出力を業務で使うときに、必ず必要になるのが「出力検証」と「リトライ設計」です。

出力検証の 3 層

検証内容
①形式の検証 JSON が妥当か、スキーマに従っているか
②値の検証 列挙値が許容範囲か、必須項目が空でないか、型が正しいか
③意味の検証 内容が事実と矛盾しないか、入力と整合しているか

①②はプログラムで自動検証できます。③は LLM-as-a-Judge(後のレッスン)や人手による確認が必要です。

リトライ設計

検証に失敗したとき、どう対処するか:

  • シンプルリトライ:同じプロンプトで再実行(温度が 0 でない限り別の結果が出る可能性)
  • エラーフィードバック付きリトライ:「前回の出力はこういう問題があった。次は……」をプロンプトに追加して再実行
  • フォールバック:N 回失敗したら、別のモデル/別のプロンプト/人手対応に切り替える

💡 ポイント 業務システムでは「3 回失敗したら人手対応キューに送る」のような設計が現実的です。LLM は確率モデルなので、100% の成功は期待できません。失敗時のフォールバックを最初から組み込むのが、本気の運用設計です。

長い出力での失敗パターン

文脈窓が広がった 2026 年の主要モデルでも、長い出力には特有の失敗パターンがあります。

①出力打ち切り(truncation)

トークン上限に達して、JSON が途中で切れる。フォーマットエラーになります。

対策:上限値を余裕を持って設定/出力を分割設計(チャンク単位で生成)

②中間の品質低下(lost in the middle)

長い文脈や長い出力の「中盤」で、品質が下がる傾向(Liu らの 2024 年研究などで指摘)。冒頭・末尾は精度が高いが、真ん中で抜けや誤りが増える現象です。

対策:重要な指示は冒頭と末尾に重複させる/長い出力は分割する

③整合性の崩れ

長い出力の途中で、自分が前段で言ったことと矛盾する。

対策:出力を 2 段階で生成(要約→詳細)、整合性チェックを別プロンプトで実行

⚠️ 注意 「文脈窓が 100 万トークンあるから、長い文書もそのまま渡せる」のは半分本当で半分嘘です。物理的には収まりますが、中間部分の品質が下がる現象が確認されています。長い文書は、分割して処理し、後で統合する設計のほうが、安定することが多いです。

講師の現場メモ:「JSON が壊れる」問題を解いた話

私(西脇)が SaaS スタートアップ PM だった頃、社内 AI 機能でいちばん多かったバグ報告が「JSON が壊れて画面が真っ白になる」でした。

調査してみると、原因は次のように分散していました。

  • 文字列内のクォートのエスケープ漏れ:30%
  • 末尾のカンマ余分・抜け:25%
  • 文脈窓上限で出力が途切れる:20%
  • LLM が説明文を JSON の前後に付け加える:15%
  • スキーマと違うキー名で返す:10%

最初に試したのは、プロンプトの末尾に「JSON 以外の文字を一切出力しないでください」と書く対策でした。これで「説明文の付加」は減りましたが、ほかの問題は残りました。

次に、JSON Schema をプロンプトに含めて期待形式を明示しました。これで「キー名違い」が減りました。

決定打になったのは、API レベルの Structured Outputs(当時はベータ)を採用したことでした。これで「文字列のエスケープ」「末尾のカンマ」「キー名違い」がほぼ消え、残ったのは「文脈窓上限による打ち切り」だけになりました。

打ち切り問題への対策として、私たちは「出力の上限を超えそうなときは、まず『概要だけ』を返し、続きは別呼び出しで詳細化する」設計に切り替えました。トータルのコストは少し上がりましたが、エラーレートは 5% から 0.3% に下がりました。

このときに改めて感じたのが、出力制御は「プロンプトだけ」「API 機能だけ」「設計だけ」の単一手段では解決せず、これらを組み合わせて初めて運用に耐えるということです。本レッスンで層別の検証・リトライ・分割設計に触れたのは、こうした経験が背景にあります。

まとめ

このレッスンでは、以下のことを学びました。

  • 構造化出力は、LLM を業務システムに組み込むときの必須技術
  • JSON Schema:プロパティ名・型・必須・列挙値を記述する標準仕様。Structured Outputs で API レベル強制も可能
  • XML タグ(Anthropic 推奨):入力の区切り、長文・入れ子の自然な構造化に向く
  • 使い分け:入力は XML タグで区切り、出力は JSON Schema で受けるハイブリッドが現場で多い
  • Constrained Generation:形式の正しさは保証するが、内容の正しさは別途検証が必要
  • Markdown テンプレート:人が読む最終成果物(メール・文書・Slack 投稿)に向く
  • 出力検証の 3 層:形式/値/意味
  • リトライ設計:シンプルリトライ/エラーフィードバック付きリトライ/フォールバック
  • 長い出力の失敗パターン:打ち切り/中間の品質低下(lost in the middle)/整合性の崩れ

次のレッスンでは、本コースの中心テーマである「評価とイテレーション」を扱います。プロンプト評価セットの作り方、量的指標と質的レビュー、A/B 比較、エラー分析、LLM-as-a-Judge の限界と使い方を学びます。


確認クイズ

このレッスンの理解度をチェックしましょう。