構造化出力が必要な理由

実際のアプリケーションでは、AIのテキスト出力はダウンストリームシステムによって解析され使用される必要があります。構造化出力(JSON、XMLなど)により、機械による自動処理が可能になります。APIの構築、データベースへの入力、自動化ワークフローのトリガーなど、構造化出力はAIとビジネスシステムを結ぶ架け橋です。

JSONモードのプロンプト

慎重に設計されたプロンプトを通じて、モデルにフォーマットされたJSONデータを出力させることができます:

あなたは情報抽出アシスタントです。以下のユーザーメッセージから重要な情報を抽出し、JSON形式で出力してください。

出力形式:
{
  "intent": "ユーザーの意図",
  "entities": [
    {"name": "エンティティ名", "type": "エンティティタイプ"}
  ],
  "sentiment": "positive/negative/neutral",
  "summary": "一言で要約"
}

ユーザーメッセージ:明日、北京から上海への航空券を予約したいです。エコノミークラス、窓側の席で。

JSONスキーマによる制約

より深い制御として、JSONスキーマを使用して出力構造を定義できます:

以下のJSONスキーマに従って分析結果を出力してください:

{
  "type": "object",
  "properties": {
    "analysis": {
      "type": "object",
      "properties": {
        "overall_score": {"type": "number", "minimum": 0, "maximum": 100},
        "strengths": {"type": "array", "items": {"type": "string"}},
        "weaknesses": {"type": "array", "items": {"type": "string"}},
        "recommendations": {"type": "array", "items": {
          "type": "object",
          "properties": {
            "action": {"type": "string"},
            "priority": {"type": "string", "enum": ["high", "medium", "low"]},
            "expected_impact": {"type": "string"}
          },
          "required": ["action", "priority"]
        }}
      },
      "required": ["overall_score", "strengths", "weaknesses"]
    }
  },
  "required": ["analysis"]
}

Function Callingを使用した構造化出力

最新のLLM API(OpenAI、DeepSeekなど)はFunction Calling機能を提供しており、これが構造化出力を実現する最良の方法です:

import json
from openai import OpenAI

client = OpenAI()

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[
        {"role": "system", "content": "あなたはデータ分析アシスタントです"},
        {"role": "user", "content": "Q3の売上データを分析:総売上500万、前年比15%増"}
    ],
    functions=[{
        "name": "generate_report",
        "description": "売上データ分析レポートを生成",
        "parameters": {
            "type": "object",
            "properties": {
                "total_revenue": {"type": "number"},
                "growth_rate": {"type": "number"},
                "analysis": {"type": "string"},
                "recommendations": {
                    "type": "array",
                    "items": {"type": "string"}
                }
            },
            "required": ["total_revenue", "growth_rate", "analysis"]
        }
    }],
    function_call={"name": "generate_report"}
)

result = json.loads(
    response.choices[0].message.function_call.arguments
)
print(json.dumps(result, indent=2, ensure_ascii=False))

構造化出力のベストプラクティス

  • Function Callingを優先する:これが最も信頼性の高い構造化出力方法です
  • フォールバック処理を追加する:モデル出力が形式に合わない場合があるため、JSON解析の例外処理が必要です
  • enum制約を使用する:選択肢が限られているフィールドには、enumを使用して値の範囲を制限します
  • 検証レイヤーを追加する:PydanticやJSON Schemaを使用してバックエンドで出力を検証します
  • 出力例を提供する:プロンプトに期待する出力形式の例を含めます

よくある問題と解決策

問題1:出力が有効なJSONではない。解決策:正規表現でJSONブロックを抽出するか、Function Callingを使用します。問題2:出力フィールドが欠落している。解決策:必須フィールドを設定し、コードでデフォルト値を提供します。問題3:モデルが「創造的に」余分なフィールドを追加する。解決策:「指定されたフィールドのみを出力し、余分な内容を追加しないでください」と明確に指示します。