ClaudeのJSONスキーマ構造化出力:AI抽出精度を高める実践設計
この記事の要点
Claudeのtool_useとJSONスキーマを使った構造化出力の設計方法を解説。バリデーション・リトライ・バッチ処理まで、データ抽出精度を高める実践的な手法を具体例で紹介します。
結論
Claudeから確実にJSONを得るには、「JSONで返して」と頼むよりtool_useとJSONスキーマを組み合わせる設計が正解です。構文エラーがゼロになり、後続システムへの連携が安定します。
書類からのデータ抽出・コードレビューの結果整理・フォームへの自動入力など、AIの出力を別のシステムに取り込む業務はこの設計が基本になります。ただし、構文の正確さは保証できても意味的な正しさ(金額の合計が合うか、日付が論理的か)は別途バリデーションが必要です。
プロンプトだけではJSON出力が不安定な理由
「必ずJSON形式で返してください」とプロンプトに書いても、出力が安定しないことがあります。主な原因は3つです。
理由1: Claudeは会話AIとして学習されている テキストで丁寧に説明することを得意としているため、「JSON」と指定していても補足説明や前置きを添えることがあります。
理由2: 複雑なデータ構造ほど崩れやすい 単純な1階層のJSONは問題ないことが多いですが、ネストが深い・配列が長い・条件分岐がある構造になるほど、プロンプト指示だけでは崩れやすくなります。
理由3: エッジケースで書式が変わる
「情報がない場合はnullで返す」のような指示は守られないことがあり、N/Aや空文字や「不明」など異なる形で返ってくることがあります。
tool_use + JSONスキーマの基本構造
tool_useは本来AIが外部ツールを呼び出すための機能ですが、構造化出力の強制に転用できます。Claudeに「このツールを呼び出してください」と指示することで、ツールの引数として定義したJSONスキーマに従った出力を必ず得られます。
スキーマ設計の4原則
原則1: 任意フィールドはnullableにする
元の文書に情報がない可能性があるフィールドは、requiredから外してnullを許容します。これをしないと、情報がないときにClaudeが値を作り上げてしまうリスクがあります。
{
"type": "object",
"properties": {
"invoice_number": { "type": "string" },
"total_amount": { "type": "number" },
"tax_rate": { "type": ["number", "null"] } // 記載がない場合はnull
},
"required": ["invoice_number", "total_amount"]
// tax_rateはrequiredから外してnullを許容
}
原則2: enumフィールドには”other”を用意する
分類フィールドは事前定義の選択肢に収まらないケースが必ずあります。"other"と詳細を記述する"other_detail"フィールドをセットで用意することで、分類できないデータも失わずに捕捉できます。
{
"document_type": {
"type": "string",
"enum": ["invoice", "contract", "report", "other"]
},
"document_type_detail": {
"type": ["string", "null"],
"description": "document_typeが'other'の場合に具体的な種類を記述"
}
}
原則3: 曖昧なケース用のフィールドを追加する
判断が難しいケースをunclearとして捕捉できるようにしておくと、後の分析と改善に使えます。
原則4: 日付・金額はフォーマットを統一する
プロンプト内に「日付はYYYY-MM-DD形式で」のような正規化ルールを明記します。元の文書が「令和6年1月」「2024/1」「Jan 2024」とバラバラでも、統一形式で出力させられます。
tool_choiceの3つのモード
tool_choiceの設定でClaudeのツール呼び出し動作が変わります。
| 設定 | 動作 | 使いどころ |
|---|---|---|
auto | ツールを使うかどうかClaudeが判断 | 通常の会話で必要に応じてツールを使わせたい場合 |
any | 必ずツールを使う(どれを使うかは自由) | 複数のスキーマがあり、文書タイプに応じてどれかを使ってほしい場合 |
{"type": "tool", "name": "..."} | 指定したツールを必ず使う | 特定のスキーマで必ず抽出させたい場合 |
書類からのデータ抽出では、文書タイプが事前にわからない場合はanyを使います。複数の抽出スキーマ(請求書用・契約書用・報告書用)を定義しておき、Claudeが文書を判断して適切なスキーマを選ぶようになります。
一方、「最初に必ずメタデータを抽出してから内容分析を行う」のような順序が決まっているフローでは、最初のステップで特定のツールを強制し、次のターンで追加処理を行います。
バリデーションとリトライの設計
構造化出力で構文エラーはなくなっても、意味的エラーは残ります。
| エラーの種類 | 例 | リトライで解決するか |
|---|---|---|
| 意味的エラー | 合計金額が明細の合算と一致しない | 解決することが多い |
| フィールド配置エラー | 税率の値が金額フィールドに入っている | 解決することが多い |
| 情報不在エラー | 元の文書に情報がない | 解決しない |
効果的なリトライの書き方
リトライ時は「もう一度やってください」ではなく、何が間違っていたかを明示します。
最初の抽出結果:
{ "total_amount": 50000, "line_items_sum": 43000 }
リトライ用プロンプト:
「前回の抽出に問題があります:
- total_amountが50,000円と抽出されていますが、
line_items_sumの合計は43,000円です
- 元の請求書を再確認し、合計金額と各明細の金額を正確に抽出してください
- もし元の文書に矛盾がある場合は、conflict_detectedフィールドをtrueにしてください」
リトライが無意味なケース
情報が元の文書に存在しない場合、何度リトライしても値は出てきません。例えば契約書に支払期日の記載がない場合、due_dateフィールドのリトライは意味がありません。この判断をするには、スキーマにconfidenceフィールドやsource_excerpt(抽出の根拠となった原文)を含め、なぜその値を抽出したかをClaudeに記録させると分析しやすくなります。
バッチ処理:大量文書を効率的に処理する
100件・1000件の文書を一括で処理するには、Message Batches APIが有効です。
バッチAPIの特性
- コスト削減: 通常のAPIと比べて50%の費用削減
- 処理時間: 最大24時間(SLAの保証はなし)
- 用途: 翌朝に結果が必要な夜間バッチ・週次レポート・大量文書の初回整理
向いていない用途
- ユーザーが待っているリアルタイム処理
- マージ前のコードレビュー(開発者が結果を待っている)
- 即時の顧客対応
バッチ実行の前に必ずやること
大量のバッチを投げる前に、サンプルセット(20〜30件)でプロンプトを検証します。1000件のバッチを走らせてから「プロンプトが不適切だった」とわかると、全件をやり直す必要があり時間もコストも無駄になります。サンプルで精度を確認してから本番バッチを実行します。
精度モニタリングの設計
「全体97%の精度」という数字は、表面上は良く見えても危険です。文書タイプA(シンプルな請求書)で99%、文書タイプB(複雑な長期契約書)で70%という内訳があると、全体平均は高くても特定文書タイプで大量のエラーが起きています。
精度を正確に把握する方法
セグメント別の分析: 文書タイプ別・フィールド別に精度を計測します。全体ではなく「どの文書タイプのどのフィールドが弱いか」を特定します。
高信頼度抽出のサンプリング: Claudeが「確信あり」と判断した結果でも、一定割合(例: 5%)をランダムにサンプリングして人間が確認します。新しいエラーパターンが出てきていないかの早期発見に役立ちます。
信頼度スコアの活用: フィールドごとに信頼度スコアを出力させ、低スコアのものを人間レビューにルーティングします。全件レビューではなく、不確かなものだけに人間のリソースを集中できます。
プロンプト設計の基本についてはFew-shotプロンプトで出力の一貫性を上げる方法も参考になります。マルチエージェントでサブエージェント間のデータ受け渡しに構造化出力を使う方法はマルチエージェント設計の実践パターンで詳しく解説しています。
複数インスタンスでのレビュー精度向上
同じClaudeインスタンスが自分で生成した出力を自分でレビューすると、精度が上がりにくい傾向があります。生成時の思考パターンが残っているため、同じ誤りを見逃しやすいためです。
重要度の高い文書では、別のClaudeインスタンス(前の会話履歴を持たない状態)にレビューさせることで、生成時に見逃した問題を発見できる確率が上がります。
具体的には、生成インスタンスと独立したレビューインスタンスの2つを使い、レビューインスタンスには「元の文書と抽出結果のみ」を渡します。生成時の推論経緯は渡しません。
まとめ
Claudeから確実な構造化出力を得るための実践ポイントをまとめます。
tool_use+ JSONスキーマで構文エラーをゼロにする- 任意フィールドはnullableにして、情報がない場合の値の捏造を防ぐ
- enumには
otherと詳細フィールドをセットで用意する - リトライは具体的なエラー内容を添えて行う。情報がない場合はリトライ不要
- 大量処理はバッチAPIで50%コスト削減。ただし事前にサンプル検証してから本番投入
- 精度は文書タイプ・フィールド別に計測し、全体平均だけで判断しない
この設計を組み合わせることで、書類処理・データ整理・コードレビュー結果の構造化など、AIの出力を業務システムに直結させる自動化が実現できます。
よくある質問
ClaudeでJSON形式の出力を確実に得るにはどうすればよいですか?
tool_useとJSONスキーマを組み合わせる方法が最も確実です。tool_choice: 'any'または特定ツールを指定すると、Claudeは必ずJSONスキーマに従った出力を返します。
JSONスキーマで構文エラーをゼロにできますか?
はい、tool_useによる構造化出力は構文エラーを排除できます。ただし、合計値が合わない・フィールドの意味が違うといった意味的エラーは防げないため、追加バリデーションが必要です。
リトライはどんな場合に効果的ですか?
フォーマットの不一致や構造エラーの場合はリトライが有効です。一方、元の文書に情報がそもそも存在しない場合はリトライを繰り返しても改善しません。