招待して報酬

招待報酬の仕組み

招待リンクを共有します。友だちがリンクから登録してチャージすると、その後のチャージごとに表示された報酬を受け取れます。

大規模PDFから表データを抽出し数値を検証する方法

Gemini APIを用いて大規模なPDFドキュメントから表データを抽出するための実践的なワークフローを解説。欠損値や不鮮明な箇所での推測プレッシャーを和らげるnull許容スキーマの設計(ハルシネーションを完全に防ぐものではなく原本の不確実性が残る点に留意)、ドキュメントの規模に応じたFiles APIの選定基準、探索の手がかりとしての引用テキストや推定ページ番号の取得方法、そして最終エクスポート前に視覚的レンダリングと照合して数値の整合性を担保するエンドツーエンドの検証プロセスまでを体系的にまとめました。

目次
大規模PDFから表データを抽出し数値を検証する方法

複数ページにわたる機器の点検報告書や財務諸表など、複雑なPDFドキュメントを扱う現場において、均一でクリーンなテキストばかりが存在することは稀です。実際のエンタープライズ文書では、デジタル生成されたページとスキャンされた用紙が混在し、表に明確な罫線が存在しなかったり、重要な指標が細かな脚注に埋もれていたりすることが珍しくありません。

こうしたファイルをそのままマルチモーダルモデルに入力し、その出力を直接本番データベースへ書き込む運用には大きなリスクが伴います。基底モデルは本質的に確率論的なシステムであるため、信頼性の高い抽出パイプラインを構築するにあたってモデルを盲信することはできません。意図的に設計されたスキーマ、監査のための文脈的手がかりの収集、そして元ドキュメントの視覚的レンダリングと突き合わせた厳格な事後検証を軸にした設計が不可欠です。


1. データスキーマ:フィールドの固定とnullの許容

Gemini Structured Outputs の仕組みにより、モデルの応答が宣言されたスキーマに厳密に準拠し、構文的に正しいJSONを出力することが保証されます。プロパティが数値型として宣言されていれば、余計な会話調テキストが混入することはありません。

しかし、構文的なスキーマ準拠が防げるのは構造上のエラーのみであり、意味的な正確さ(事実の正しさ)まで保証されるわけではありません:

  • 罫線のない密集した表では、モデルが隣接する行を取り違えたり、列を入れ替えて解釈したりすることがあります。
  • 画質の低下したスキャン画像では、数字の 83 に誤読されやすく、小数点が見落とされることも頻繁に発生します。
  • 指標が欠落していたり不鮮明であったりする場合、値の省略が明示的に許可されていないと、モデルはもっともらしい数値を捏造しようと試みるおそれがあります。

ハルシネーションのリスクを軽減するためには、スキーマ側で各フィールドをnull許容(Optional または null)として宣言し、同時にプロンプト内で「高い確信度で数値を読み取れない場合は必ず null を返すこと」を明示的に指示する必要があります。nullの返却を許容することで、モデルが当てずっぽうで値を推測するプレッシャーを大幅に緩和できますが、それ単体でハルシネーションを完全に防止できるわけではありません。


2. ファイルの送信:Files APIを選択すべきタイミング

公式のGeminiドキュメント処理に関するドキュメントによると、PDFファイル1点あたりの処理制限は最大50 MB、または最大1,000ページと定められています(ファイルサイズとページ数の制約は同時に適用され、両方の最大値を同時に達成できる保証はありません。いずれかの制限に達した時点で処理は停止します)。

最適な送信方法は、ドキュメントのサイズと運用パターンによって異なります:

  • インラインデータ送信(Inline data passing):小さなドキュメントや、1回限りの単発抽出呼び出しに最適です。
  • Files API(client.files.upload:より大きなファイルや、同じドキュメントに対して複数回にわたりクエリを実行するマルチターンワークフロー(例:最初にセクション分類を行い、続いて対象の表を抽出するなど)向けに設計されています。Files APIを使用すれば、呼び出しのたびにドキュメントのペイロード全体を再アップロードするオーバーヘッドを回避できます。

3. データのクエリ:スキーマ、引用ヒント、そして仮想のレスポンス

抽出されたデータの監査性を確保するため、対象となる数値データとともに補助的なメタデータを返却するようモデルに促します。具体的には、おおよそのページ番号(page_number)と、短く正確な原文の引用スニペット(evidence_quote)です。

極めて重要な区別: page_numberevidence_quote事実の証明ではありません。これらはあくまで探索のためのヒューリスティックな手がかり(検索ヒント)に過ぎません。モデル自身がこれらのフィールドを生成するため、引用スニペットにOCR起因のノイズが含まれたり隣接行が結合されたりする可能性があり、出力された視覚上のページ番号がPDFコンテナ内の物理的なシート番号(枚数インデックス)とずれることもあります。

仮想的な課題設定

(実際のPDFファイルは提供・アップロード・分析されておらず、実際のAPIクエリも実行されていない)仮想的な課題設定として、ポンプ点検報告書からサマリー指標を抽出するケースをモデル化して考えてみます。この例示では、以下のような仮想の2行の表を対象とします:

識別子 (Identifier)圧力 (Pressure / MPa)振動 (Vibration / mm/s)状態 (Status)備考 (Notes)
Н-101-А1.452.1正常 (В норме)定期点検 (Scheduled inspection)
Н-102-В(判読不能)7.8要注意 (Внимание)ガタつき増大 (Increased play)

以下に、Pydanticを用いて定義したスキーマの例と、公式SDKを使用した呼び出し構文を示します:

from google import genai
from pydantic import BaseModel, Field
from typing import List, Optional

class PumpRecord(BaseModel):
    unit_id: str = Field(
        description="Идентификатор агрегата точно как в таблице"
    )
    inlet_pressure_mpa: Optional[float] = Field(
        default=None,
        description="Давление в МПа. Если значение неразборчиво или отсутствует — null"
    )
    vibration_mms: Optional[float] = Field(
        default=None,
        description="Уровень вибрации в мм/с. При отсутствии данных — null"
    )
    status: str = Field(
        description="Статус узла (например, 'В норме', 'Внимание')"
    )
    page_number: Optional[int] = Field(
        default=None,
        description="Оценочный номер страницы документа (подсказка для аудитора, не подтверждена)"
    )
    evidence_quote: Optional[str] = Field(
        default=None,
        description="Короткий фрагмент строки (до 10 слов), откуда взяты числа (подсказка, не подтверждена)"
    )

class InspectionPayload(BaseModel):
    records: List[PumpRecord]

client = genai.Client()

uploaded_file = client.files.upload(file="hypothetical_inspection.pdf")

response = client.interactions.create(
    model="gemini-3.8-flash",
    input=[
        {
            "type": "document",
            "uri": uploaded_file.uri,
            "mime_type": uploaded_file.mime_type,
        },
        {
            "type": "text",
            "text": (
                "Извлеки показатели агрегатов в соответствии со схемой. "
                "Если число неразборчиво или отсутствует, возвращай null. "
                "Для каждой записи заполни номер страницы и короткую цитату-подтверждение."
            ),
        },
    ],
    response_format={
        "type": "text",
        "mime_type": "application/json",
        "schema": InspectionPayload.model_json_schema(),
    },
)

payload = InspectionPayload.model_validate_json(response.output_text)

モデルからの例示的なJSONレスポンス

以下のJSONは、このリクエストに対するモデルの仮想的なレスポンスを示したものです。あらためて強調しますが、この出力は仮想的な構造の例示であり、実際のAPI実行結果や現実の物理的な測定値ではありません:

{
  "records": [
    {
      "unit_id": "Н-101-А",
      "inlet_pressure_mpa": 1.45,
      "vibration_mms": 2.1,
      "status": "В норме",
      "page_number": 12,
      "evidence_quote": "Н-101-А 1.45 2.1 В норме"
    },
    {
      "unit_id": "Н-102-В",
      "inlet_pressure_mpa": null,
      "vibration_mms": 7.8,
      "status": "Внимание",
      "page_number": 12,
      "evidence_quote": "Н-102-В [пятно] 7.8 Внимание"
    }
  ]
}

この仮想レスポンスにおいて、2箇所の page_number: 12 と2箇所の evidence_quote は、いずれも未検証のヒントとしての位置づけにとどまります。モデルは2基目の判読不能な圧力値に対して適切に null を出力していますが、抽出された属性のいずれも、アプリオリ(事前)に確認済みの事実とみなすことはできません。


4. 視覚的原本との突き合わせ照合とエクスポートルール

抽出されたレコードを、検証なしにダウンストリームのデータベースへ直接書き込むことはできません。ソースPDFページの視覚的レンダリング画像と各フィールドを突き合わせて比較するエンドツーエンドの監査が必要です。

本事例に関する重要な明確化: ここで取り上げる2行の表、12ページ、物理的な14枚目シートのオフセット、コンプレッサー室、および視覚的照合ワークフローは、プロセスの純粋な仮想的例示に過ぎません。実際のPDFドキュメントが提供・精査されたわけではなく、以下に述べる手順は、仮に視覚的レンダリングによって記載の値が確認された場合にレビュー担当者が実務上どのような検証を行い、どのような条件付き判断を下すかを定式化したものです。

レコードごとの段階的検証:レビュー担当者が確認する項目

  1. ユニット Н-101-А:

    • ページと位置の特定(Page and Localization): モデルはヒントとして page_number: 12 を返却しました。レビュー担当者は12ページの視覚的レンダリング(表紙や前付により物理的なオフセットが生じている場合は14枚目のシート)を確認し、対象となるコンプレッサー室の表を特定します。
    • 識別子(Identifier): 1列目において、識別子 Н-101-А が完全に一致しているかを確認します。
    • 圧力と単位(Pressure and Units): 入口圧力の列で、数値 1.45 が明瞭に読み取れるか、また工学単位がスキーマの想定(МПа / MPa)と一致しているかを検証します。
    • 振動と単位(Vibration and Units): 振動の列で、2.1 の値と単位の表記(мм/с / mm/s)を確認します。
    • 状態(Status): 稼働状態の欄で、В норме(正常 / Normal)の記載があることを確認します。
    • 条件付き判断(Conditional Decision): レンダリング画像上で全フィールド、数値、物理単位が正当であると確認できた場合、この行は**エクスポート承認(Export / Accepted)**となります。
  2. ユニット Н-102-В:

    • ページと位置の特定(Page and Localization): 同じ仮想の表において、レビュー担当者は2行目の確認に進みます。
    • 識別子(Identifier): 識別子 Н-102-В の存在を確認します。
    • 振動と状態(Vibration and Status): 振動値 7.8 および状態 Внимание(注意 / Warning / Attention)を視覚レイヤーと突き合わせ照合します。
    • 圧力(Pressure): モデルは null を返却しました。担当者はレンダリング画像の該当セルを調査します。測定値の代わりに黒くにじんだ汚れ(スキャンの不具合)が確認できれば、モデルが null を返した判断の妥当性は裏付けられますが、極めて重要な物理測定値が欠落していることには変わりありません。
    • 条件付き判断(Conditional Decision): 視覚的な確認により重要な圧力測定値の欠落が確定したため、この行は自動エクスポートから除外され、**手動レビュー(Hold for manual review)**に回されます。現場での再スキャン依頼や、バックアップの保守台帳との突き合わせが必要となります。

検証後の確認済み出力(Checked Output)

以下のまとめの表は、レビュー担当者が具体的に何を検査し、視覚的な確認を経て検証パイプラインがどのような条件付きルーティング判断を下すかを詳述したものです:

ユニット圧力 (MPa)振動 (mm/s)状態レビュー担当者が確認する項目(仮想検証)パイプラインの条件付き判断(レンダリングで値が確認された場合)
Н-101-А1.452.1В норме (Normal)レンダリング画像と照合し、識別子の一致、数値、単位(MPa, mm/s)を確認エクスポート承認(取り込み可能) — 全フィールドの完全な視覚的確認を条件とする
Н-102-Вnull (欠落)7.8Внимание (Warning)圧力セルのスキャン欠陥(汚れ)を確認し、振動の数値を照合手動レビュー保留(オペレーターによるトリアージ) — 重要な指標の欠落が確認されたため

アーキテクチャ上のバリデーションパターン

堅牢なドキュメント取り込みパイプラインは、処理されたレコードを2つの独立したストリームへとルーティングします:

  • グリーンコリドー(検証済みエクスポート / Green Corridor): すべての必須フィールドがソースページの視覚的レンダリングと照合されて裏付けが取れ、すべての物理単位がスキーマ標準に正規化されている行のみに限定されます。
  • レビューキュー(隔離 / Review Queue): 重要フィールドに null が含まれるレコード、測定単位の不一致、曖昧な引用が存在するレコードは、人間のオペレーターによる手動レビューのために隔離されます。

公式ドキュメントとガイド

LLM ワークフローを最適化しませんか?

単一 API でモデルを接続し、キーと AI コストを管理できます。

無料で始める