9月3日、Angela ShiおよびKezhan Shiが「Tables in PDFs for RAG: Don't Flatten the Grid」と題した記事を公開した。Angela ShiはMLエンジニアリングおよびRAGシステム設計を専門とし、Kezhan Shiはドキュメント解析と非構造化データ処理を専門とする研究者・エンジニアだ。この記事では、RAGパイプラインでPDF内のテーブルを「テキストに平坦化」せず構造を保ったまま処理するための診断手法と5つの操作について詳しく紹介されている。
テーブルをテキストに潰すと何が起きるか
RAGの標準的なパイプラインは、PDFを読み込んでテキストにチャンク化し、埋め込みで検索する。箇条書きや段落はこれで十分機能するが、答えがテーブルのセル内にある瞬間、パイプラインは数値を幻覚し始める。そして誰も気づかないまま、監査人がソース文書を開いて初めて発覚する、というのが典型的な失敗パターンだ。
PDF内のテーブルを扱う難しさはRAGに限った問題ではなく、LlamaParseやAzure Document Intelligenceといったドキュメント解析ツールが専用の構造復元ロジックを備えるほど、業界全体で認識されている根本課題だ。その理由はPDFというフォーマットの性質にある。PDF内のテーブルは、データ構造としてのテーブルではない。ページ上に描画された矩形の集合であり、パーサーは空間的な位置関係からグリッドを復元しなければならない。これが失敗すると3つの問題が同時に発生する。
- 行・列の構造が失われ、LLMは関係性のない値の羅列を見ることになる
- 複数ページにまたがるテーブルでは、ヘッダーが最初のページにしかなく、2ページ目以降が数値ノイズになる
- 行が復元されていない以上、「47行目」を引用・参照できない
根本原因は同一だ。テーブルは元々データだったものを、配布フォーマットの都合でレイアウトに変換したものに過ぎない。正しいアプローチは「テキストとしてうまく扱う」ことではなく、早期に構造化データへ復元し、以後はデータとして処理することである。
4段階の表現レベル
記事では、同一のテーブルをパイプライン内で4つの構造レベルで表現できるとしている。テーブルのサイズ、スキーマの安定性、質問の形式に応じて適切なレベルを選ぶのが最初の設計判断だ。
- A.
line_df内の行として保持:デフォルト。Markdownのパイプ記法(| col1 | col2 |)で1行として扱う。混在コンテンツ文書のテーブルの大多数はここで止まる - **B. 独立した
table_df**:複数ページにまたがる連結、特定列への射影、行フィルタリングが必要な場合に昇格させる - C. 名前付き・型付きの列ストア:同一スキーマのテーブルが複数文書にわたって繰り返し登場する場合(保険契約の保険料テーブル、財務諸表の収益サマリーなど)。SQLで集計・結合できる状態にする
- D. 異種混在の列ストア:Cを目指したがスキーマを正規化できなかった場合のフォールバック
大半のテーブルはAで止まる。 一部がBに昇格し、繰り返し登場するものがCへ昇格する。
診断:5つの直交するプロパティ
ディスパッチャーが表現レベルを決定するために、各テーブルについて以下の5項目を記録したtable_df_metaを構築する。
| プロパティ | 値の例 |
|---|---|
| パース品質 | Perfect / Partial / Failed |
| サイズ | (n_rows, n_cols) |
| ヘッダー有無 | Present / Absent / Continuation |
| 複数ページ連続性 | Autonomous / Continued-from-N / Continues-to-M |
| 文書レベルのテーブル比率 | テーブル面積 / テキスト面積(例: 6%, 13%, 26%) |
特に「文書レベルのテーブル比率」は重要な指標だ。文書の本文の半分近くをテーブルが占める場合、アーキテクチャそのものを「テキストRAG+テーブル例外処理」から「SQLによるテーブル検索+テキストはアノテーション」へ切り替えることを検討すべきだと記事は指摘する。
5つの操作:最も重要な2つを深掘りする
O1. 位置情報からの構造再構築
パース品質が「Partial」で、単語のバウンディングボックスが利用可能な場合に適用する。x座標のヒストグラムピークで列バンドを、y座標のギャップで行バンドをクラスタリングし、グリッドを再構築する。コストは1ページあたりの幾何学的な1パスのみで、ほぼゼロ。ただし、行をまたいでセルが結合されているような不規則なテーブルはO1では対処できず、O5に引き継ぐ。
O5. Vision-LLMフォールバック
O1が失敗した場合、またはパース品質が「Failed」の場合に適用する。テーブル周辺のページ領域を画像としてレンダリングし、Vision対応のLLMにJSON形式での出力を求める。コストはO1の少なくとも10倍以上であるため、必ずフォールバックとして位置づけなければならない。デフォルトにすると長大な文書でコストが急膨張する。
その他3つの操作
- O2. 複数ページ連結とヘッダー伝播:同一列構造のテーブルが複数ページに分断されている場合、ヘッダーを各ページの行へコピーして単一の
table_dfに連結する。source_page列で出典ページを保持する - O3. 質問駆動の射影:テーブルがコンテキストウィンドウを超える場合に適用する。元記事が定義する
scope_filters(対象範囲を絞り込む条件、例:特定の年度や地域)とconcept_keywords(注目すべき概念・用語のリスト)に基づいて列を射影し、行をフィルタリングしてからLLMに渡す - O4. 列ストアへの昇格(B→C または B→D):テーブルが複数文書にわたって繰り返す場合、SQLエージェントが処理できる列ストアへ昇格させる
操作の組み合わせ
これらは合成可能だ。「Partial品質 + 3ページ目から継続 + 大型テーブル + フィルタリングが必要」なケースなら O1 → O2 → O3 を順に適用する。各操作はべき等(preconditionを満たさない操作は何もせずスキップされる性質)なので、安全に合成できる。
実装コードはdoc-intel/notebooks-vol1にRunnable Notebookとして公開されている。
詳細はTables in PDFs for RAG: Don't Flatten the Gridを参照していただきたい。




