技術 約4分で読めます

PageIndex — ベクトル検索なしでLLM推論だけのツリーRAG

何これ

PageIndexは、ベクトルDBもチャンキングも使わずにLLMの推論だけで文書の階層ツリーインデックスを構築するRAGシステム。VectifyAIが開発・公開している。

普通のRAGは「文書を分割→ベクトル化→類似度検索」という流れだけど、PageIndexは「文書の目次を検出→ツリー構造をJSON化→各ノードにサマリ生成」という、人間が目次から目的のセクションを探すのと同じアプローチを取る。

「類似度が高い ≠ 関連性が高い」という、ベクトル検索RAGの根本的な弱点を回避できるのが売り。

PDF処理パイプライン

PDFの場合、6段階のLLM呼び出しで処理する:

  1. PDFからテキスト抽出
  2. LLMで目次ページを検出
  3. 目次をJSON構造に変換
  4. 各セクションにページ番号を割当
  5. 割当結果を検証・修正
  6. 各ノードのサマリを非同期並列生成

生成されるツリーの各ノードはこういう構造:

{
  "title": "セクション名",
  "node_id": "1.2.3",
  "start_index": 10,
  "end_index": 15,
  "summary": "このセクションは〜について説明している",
  "nodes": []
}

Markdownはもっとシンプル

Markdownの場合はヘッダ階層(#, ##, ###…)から直接ツリーを構築する。目次検出もページ割当も不要で、LLMはサマリ生成にしか使われない。

# PDF
python3 run_pageindex.py --pdf_path tests/pdfs/earthmover.pdf

# Markdown
python3 run_pageindex.py --md_path tests/md/japanese_sample.md

主なオプション:

オプションデフォルト用途
--if-add-node-summaryyes各ノードにサマリ付与
--if-add-doc-descriptionnoドキュメント全体の説明文生成
--if-thinningnoトークン少ないノードを統合(Markdown用)
--modelgpt-4o-2024-11-20使用モデル

段組認識との関係

これ、NDLOCRの段組認識で苦労した話と繋がる。

あのときはヒストグラム解析で縦方向の画素密度の谷を検出して、力技で4段に分割した。やりたいことは「文書のどこからどこまでが1つのまとまりか」を知ることで、PixelレベルのLayout解析でそれをやっていた。

PageIndexは同じ問題を「LLMに文書構造を理解させる」ことで解決する。目次やヘッダ階層からセクション境界を推論するので、ヒストグラムのような画像処理は一切不要。

ただし前提が違う。PageIndexはテキストが入力なので、OCRの前段(画像→テキスト)で段組が崩れていたら意味がない。つまり:

画像 → [OCR(段組認識が必要)] → テキスト → [PageIndex] → ツリー構造

段組認識を省略できるわけではなく、むしろ「OCRでテキストを正しく取れた後のRAG構築」で活きるツール。

OCRパイプラインとの組み合わせ

じゃあ何と組み合わせると面白いか。

PaddleOCR-VL-1.5は0.9Bパラメータで文書解析SOTAを更新したVLMベースOCR。構造化されたMarkdownを出力できる。VLMベースOCRの記事でも書いたけど、VLM-OCRは表や段組を構造化して出力できるのが強み。

こういうパイプラインが考えられる:

PDF/画像

PaddleOCR-VL(VLM-OCR: 段組・表も構造化して出力)

構造化Markdown

PageIndex(ヘッダ階層からツリー構築 + サマリ生成)

ツリーインデックス付きRAG

VLM-OCRが段組やレイアウトを解決した上で構造化テキストを出し、PageIndexがそれをツリーインデックス化する。ヒストグラム解析のような力技が不要になる。

コストとレイテンシの問題

ベクトルRAGと比べて明らかに不利な点がある。

ベクトルRAGはインデックス構築後の検索がほぼ定数時間。一方PageIndexはクエリのたびにツリーを辿りながらLLMを呼ぶので、検索コストがLLM呼び出し回数に比例する。インデックス構築時もPDFだと6段階のLLM呼び出しが必要。

使いどころとしては:

  • 少数の重要文書を精度高く検索したい場合(社内規定、契約書など)
  • ベクトル検索で「関連性の低い結果」が問題になっている場合
  • 文書の構造が明確で、目次やヘッダがしっかりしている場合

大量文書を高速に検索したいなら、素直にベクトルRAGを使った方がいい。

リンク

関連記事