なぜモデルの出力をソースエビデンスに結び付けることが、ドキュメントAIにおいて最も重要でありながら最も語られない概念なのか
1万件の契約書を読み込み、重要な日付・名称・義務をすべて抽出して整理されたスプレッドシートを作成するアナリストチームを雇ったとします。ところが、その内容が正しいかどうかを確認する手段が一切ないとしたらどうでしょう。無作為抽出でチェックすることも、元の文書と照合することも、何一つできません。ただ出力を信頼し、システムに流し込んで先に進むしかない。
これが、今日ほとんどの組織がAIを文書抽出に活用している実態です。そして、業界が認めているよりもずっと静かな危機を孕んでいます。
この状況を一変させる概念がグラウンディング(grounding) です。
グラウンディングとは何か?
グラウンディングとは、出力をソースエビデンスに結び付けることです。すなわち、抽出されたすべての主張が、ソースドキュメント内の特定かつ検証可能な箇所に追跡できることを保証することです。文書データ抽出において、それはモデルが述べる内容を、文書が実際に含んでいる内容に根付かせる実践を指します。文脈から妥当に思えることではなく、ソース内に事実として・検証可能な形で存在していることに基づく、ということです。
機械学習全般においてグラウンディングとは、モデルの出力を検証可能なエビデンスに結び付けることを指します。モデルは入力を受け取り、予測を出力し、その予測はソースデータに遡ることができなければなりません。グラウンディングなしには、出力を監査・検証する手段がありません。この概念は、測量・地図製作におけるグラウンドトゥルース(ground truth) という古い概念に由来しています。これは実際の地形上で取られた計測値を指します。
グラウンディングと「グラウンドトゥルース」
グラウンドトゥルースとは、ある情報に対する人間が検証した決定的な答えのことです。文書データ抽出においては、文書が何を述べているかの権威ある記録を指します。文脈から妥当に見えることではなく、事実として・検証可能な形で正確なものです。
帰属: https://flipbook.page "グラウンドトゥルースとは何か?"
つまり、ソースをグラウンディングできるようになれば、「グラウンドトゥルース」への道が開かれます。これは、引用された回答を検証するためのバリデーションステップとして機能します。
文書抽出が特に難しい理由
非構造化文書から構造化データを抽出することは、エンタープライズソフトウェアにおける最古の問題のひとつです。何十年もの間、ルールベースのアプローチが試みられてきました。「"日付"という単語から20ピクセル以内に日付らしい文字列があれば抽出する」というようなものです。しかしこれらのシステムは脆弱でした。レイアウトが一つ変わる、珍しいフォントが使われる、スキャン時に傾きが生じる——それだけでルールは破綻しました。
AIはこの状況を一変させました。現代の抽出システムは人間と同様に文書を読むことができます。文脈を理解し、意味を推測し、ばらつきを許容します。精度の上限は劇的に引き上げられました。
しかし、上限が高くなることは、保証とは異なります。そして、モデルが高性能であればあるほど、間違っているときでも自信満々に聞こえます。
文書は、構造化データとは異なる意味で"敵対的"です。曖昧さ、矛盾、修正、手書きの注釈、ページをまたぐ表、他の条項を参照する条項など、複雑な要素が混在しています。モデルは高い確信をもって数値を抽出しながら、実際には誤った数値を抽出しているかもしれません。合計ではなく小計を、現行版ではなく旧版を、単位ではなく千単位の数値を抽出している可能性があります。
グラウンディング——データがどこからどのように取得されたかを確認する手段——なしには、それを知ることができないのです。
グラウンディングとPyMuPDF
先に述べたとおり、グラウンディングとはモデルの出力をソースエビデンスに結び付けること、すなわちモデルが行うすべての主張がソースドキュメント内の検証可能な場所に根付いていることを保証することです。LLMベースの文書処理における問題は、言語モデルがトークン空間で動作することにあります。テキストを受け取り、テキストを生成し、空間的な構造についての本来の認識を持ちません。多くの文書タスクではそれで問題ありませんが、重要なアプリケーションの一群において、根本的な曖昧さが生じます。これはページのどこから来たのか? PyMuPDFはsearch_forメソッドによってこの問いに答え、モデルの出力を読むことと、それがどこから取得されたかを確認することの橋渡し役となります。
Page.search_for(needle, quads=False, flags=..., clip=None) は、PDFページ上でテキスト文字列の出現箇所を検索し、バウンディングレクタングル(quads=Trueの場合は四辺形)のリストを返します。それぞれが、そのテキストがページ上の物理的にどこに存在するかを正確に示します。座標はPDFネイティブのポイント単位の空間にあり、回転なしのページに基づいており、正確です。OCRの推測ではなく、PDFの内部的な文字レベルのジオメトリから直接取得されます。
import pymupdf
doc = pymupdf.open("contract.pdf")
page = doc[0]
# マッチごとにRectオブジェクトのリストを返す
rects = page.search_for("Governing Law")
なぜ空間座標が文書グラウンディングの基盤なのか
PDFの座標系は決定論的です。位置を推定するOCRや、スケーリングやリフローが発生する可能性のある視覚的レンダリングとは異なり、PDFに埋め込まれたテキスト位置は記録の源泉です——それは作成ツールが配置したものです。PyMuPDFのsearch_forがRect(72.0, 144.3, 210.5, 158.7)を返すとき、それは近似ではありません。それは回転なしのページ空間におけるその文字列の正確なバウンディングボックスです。
これはLLMワークフローにおいて、いくつかの理由から非常に重要です。
1. 引用と追跡可能性
LLMは条項・数値・数字を抽出するかもしれません。しかし「4ページ目、第3段落」はあいまいです——数え方やページのレンダリング方法によって変わります。バウンディングボックスは明確です。矩形をPyMuPDFに渡し、ピクスマップから領域を切り抜き、ソースドキュメント内の正確にハイライトされたゾーンをユーザーに示すことができます。これは「モデルによるとペナルティ条項は4ページ目にある」ということと、実際にハイライトされた言葉をユーザーに見せることの違いです。
2. RAGチャンクの検証
検索拡張生成(RAG)パイプラインでは、テキストのチャンクが埋め込まれて取得されます。よくある失敗パターンは、取得されたテキスト自体は正確でも、モデルが誤って帰属させることです——第5条の条項を第2条の文脈に置いてしまうようなケースです。インデックス作成時に各チャンクとともにバウンディング矩形を保存しておけば、モデルの出力が期待されるページ領域にマッピングされているかをプログラム的に検証できます。矩形は空間的正確さのチェックサムとなります。
3. 空間制約を伴う構造化抽出
財務諸表・フォーム・同じ単語(「合計」など)が複数回登場するテーブルから値を抽出する場合を考えてみましょう。search_forはすべての出現箇所を列挙し、その後空間的な論理を適用できます。「この特定のテーブルの最終行に現れる"合計"はどれか?」を、脆弱な正規表現やプロンプトエンジニアリングではなく、座標演算で解決できます。返された矩形をpage.find_tables()から取得したテーブルのバウンディングボックスと交差させることができます。
4. フィードバックループとしてのアノテーション
ドキュメントには標準的なパターンが示されています。文字列を検索し、返されたクアッドを直接page.add_highlight_annot()に渡す。これはLLMレビューの人間参加型ワークフローにおいて強力です。LLMが注目すべき条項を特定し、search_forがその場所を特定し、システムがPDF内でハイライトし、人間のレビュアーが正確な出典を確認します。ハイライトはグラウンドトゥルースに根付いています——プレーンテキストの参照のように位置がずれたり幻覚したりすることはありません。
# LLMが「免責条項」を重要な条項として特定
# 正確なジオメトリですべての出現箇所を検索してハイライト
quads = page.search_for("indemnification", quads=True)
page.add_highlight_annot(quads)
このようにして、LLMが参照している可能性のある箇所を文書にマークアップし、その後のパイプラインで実際のソースエビデンスとのグラウンディングを検証することができます。
5. クロスモーダルグラウンディング
ページをピクスマップにレンダリングしてビジョン対応LLMに渡すとき、モデルはピクセルを見ています。search_forを使えば、ピクセル空間から意味的なテキストに——またその逆に——変換できます。ビジョンモデルが関心領域を特定した場合、クリップされた矩形内(clipパラメータ)で検索して正確なテキストを復元できます。モデルがテキストを生成した場合、その物理的な位置を確認できます。この双方向のグラウンディングこそが、テキストとビジョンを組み合わせたハイブリッド文書パイプラインを信頼できるものにします。
クアッドの詳細は補足ではない
quads=Trueオプションについて少し考えてみましょう。Rectは4つの数値を持ちます: (x0, y0, x1, y1)。Quadは4つの点を持ちます: 左上、右上、右下、左下。水平テキストでは両者は同等です。しかしPDFには、回転した見出し、透かし、任意の角度のテーブルヘッダー、行が軸に揃っていない複数列レイアウトが頻繁に含まれます。このような場合、バウンディングレクタングルは過大近似となり、マッチの一部ではない空白が含まれます。クアッドはよりタイトで幾何学的に正確です。
LLMのコンテキスト構築においてこれが重要なのは、矩形を使ってビジョンモデル用のページ画像を切り抜く場合、過大近似のバウンディングボックスがノイズをもたらすからです——隣のテキストが切り抜きに混入します。クアッドは、マッチしたテキストの周囲に可能な限りタイトな視覚的コンテキストウィンドウを提供します。
実践的なパターン: 座標固定のLLMコンテキスト
以下に、これらのアイデアを組み合わせた方法を示します:
import pymupdf
import json
doc = pymupdf.open("annual_report.pdf")
# インデックス作成時に空間メタデータを含むコーパスを構築
chunks = []
for page_num, page in enumerate(doc):
blocks = page.get_text("blocks") # (x0,y0,x1,y1, テキスト, ...)
for block in blocks:
text = block[4].strip()
if not text:
continue
rect = pymupdf.Rect(block[:4])
chunks.append({
"page": page_num,
"text": text,
"bbox": list(rect), # グラウンドトゥルースの空間アンカー
})
# クエリ時: LLMが「純収益が減少した」を参照する回答を生成
# 空間的に主張を検証
page = doc[3]
hits = page.search_for("net revenue declined")
if hits:
# LLMの主張が実際の場所にマッピングされていることを確認
# ユーザーのためにハイライト
page.add_highlight_annot(hits)
インデックス作成時に保存されたバウンディングボックスは、監査可能な記録となります。「LLMが何を言ったか」だけでなく、「この主張はソースドキュメントのどこに根付いているか」という記録です。それが最も実践的な意味でのグラウンディングです。
まとめ
Page.search_forは一見シンプルなテキスト検索ユーティリティのように見えます。しかしその真の力は、意味空間から幾何空間への変換を行うことにあります。そしてその変換は可逆的で権威あるものです。幻覚と誤帰属が現実のリスクであるLLM文書ワークフローにおいて、あらゆるテキストをページ上の正確な座標に明確にピン止めできるメソッドは、監査可能で検証可能なパイプラインの基盤となります。グラウンディングはLLMの出力ではありません——それはPDFのジオメトリへの接続であり、search_forはそれにアクセスするための手段です。

