8月23日、Towards Data Science(著者名は記事内で非公開)が「Multi-Document RAG: A Folder of Unrelated PDFs Is One Long Document with a Nested Outline」と題した記事を公開した。共通フィールドを持たない異種PDF群をマルチドキュメントRAGで扱う際、「ネガティブ情報こそが62ファイルを開かずに捨てることを可能にする」——この一文がこの設計の核心だ。インデックステーブルもスキーマも不要で、63行のサマリーと2,422行のアウトラインだけで成立するアーキテクチャを詳しく解説している。
「共通フィールドがない」は欠落ではなく、設計の前提だ
RAGシステムをスケールさせる際の定石は「文書ごとにフィールドを持つインデックスを構築し、検索前にフィルタリングする」というものだ。しかしこのアドバイスは、文書間に共通フィールドが存在することを前提としている。
実際の業務フォルダはそうなっていないことが多い。たとえば以下のような構成を考えてみる:
- NIST SP 800-53セキュリティ統制カタログ(492ページ)※1
- ゼロトラストアーキテクチャ仕様書※2
- AIリスクフレームワーク
- 機械学習論文31本
- 商品市場レポート7本
これらに共通するフィールドは何か。クライアント名も、有効日も、金額も、すべての文書に同じ意味で存在するものは何もない。
記事の核心はここにある。共通フィールドがない場合、インデックステーブルを構築しようとすること自体が誤りだ。 むしろ準備ステップは2つのアーティファクトに集約され、そのうち1つはパーサーが最初から返してくれる。
記事ではこの考え方を一言で表している:
共通フィールドを持たない文書フォルダは、ネストされたアウトラインを持つ1つの長文書である。
各ファイルがチャプター、各セクションがサブセクションに対応する。長文書を読む方法は既知だ。目次を読めばよい。
※1 NIST SP 800-53:米国国立標準技術研究所(NIST)が定める連邦情報システム向けのセキュリティ・プライバシー統制カタログ。AC-2(アカウント管理)、GV.OC-01(ガバナンス・組織コンテキスト)などのコード体系で統制項目が管理されている。公式ドキュメントを参照。
※2 ゼロトラストアーキテクチャ:「内部ネットワークは安全」という前提を排し、すべてのアクセスを継続的に検証するセキュリティモデル。NISTによる定義はSP 800-207にまとめられている。
「自分がどのフォルダにいるか」を判断する2つの問い
設計に入る前に、以下の2つの問いで状況を判定する。
問い1:フォルダ内の文書が互いを参照しているか?
改訂版が原文を参照する、更新契約が前年の契約を参照する、といった場合は文書間の構造をモデリングする必要があり、この手法は適用できない。
問い2:ビジネスユーザーが「全文書に共通するフィールド」を即座に答えられるか?
「クライアント名」「有効日」「保険料」といった答えが素早く返ってくるなら、そのフォルダはまだ誰もデータベース化していない構造化データだ。この場合はスキーマを定義してSQLベースの検索を構築するのが正解になる(記事シリーズの別記事が扱うアーキテクチャ)。
両方ともNOなら、この記事のアーキテクチャが適用できる。
なお「混在フォルダ」も現実には多い。5,000件の契約書と300件の雑多なファイルが同じドライブに混在するケースでは、無理に統一しようとせず2つのコーパスとして分割し、それぞれに適したアーキテクチャを適用するのが正解だ。
準備はたった2つのアーティファクト
インジェスト時に一度だけ構築するものは2つだけだ。
- Level 0:ファイルリスト。1ファイル1行、そのファイルが何について書かれているかを記述
- Level 1:各ファイル固有の目次(パーサーが返す
toc_dfをそのまま利用)
分類パスも、フィールド抽出も、スキーマも、オントロジーも不要だ。
サマリー行は「読者向け」ではなく「ルーター向け」に書く
ここが品質の大半を決める部分だと記事は強調している。サマリー行はドキュメンテーションではない。読むのはルーティングコールのみであり、63行の中からどのファイルが回答を含む可能性があるかを判断するための入力だ。
良いサマリー行と悪いサマリー行の差を生む3要素:
ユーザーの言葉と文書固有の語彙の両方を含める
「account management」という質問に対して、行中に「account management」と「AC-2」(NIST SP 800-53におけるAccount Managementコントロールのコード)の両方が存在しないと、ルーターはマッチングできない。ファイルが答えられる「形状」を示す
「1セクション1コントロール」と「ナラティブレポート」では、答えがセクション単位かチャプター単位かが変わる。ルーターが第2レベルの検索をどう設計するかに直結する。何についてのファイルでないかを明記する
これが最も見落とされがちな点だ。「実装ガイドではない(Not an implementation guide)」の一文で、how-to系の質問すべてからそのファイルを除外できる。ネガティブ情報こそが62ファイルを開かずに捨てることを可能にする。
サマリー行の生成コストは安い。文書の冒頭数ページと目次を入力に1コール生成し、あとは人手でレビューする。コストはファイル変更時にのみ再発生する。
Level 1はコスト不要
パーサーが返すtoc_df(見出しとページ範囲が1行ずつ入ったテーブル)をそのまま使う。63ファイル中47本はPDFネイティブのアウトラインを持っており、1パースで完結する。残り16本はネイティブアウトラインを持たないが、短ければ「リーフ」として全文を読む、長ければアウトラインを再構築するという2択で対処する。
結果として63行のサマリーと2,422行のアウトラインが生成される。モデルが毎回の質問で読むのは63行だけ。2,422行はファイルごとに必要なときだけ参照される。
クエリ時のルーティング:2段階で下降する
例として「_account management controlは何を要求するか?_」という質問を63ファイルに投げるケースを見る。答えはNIST SP 800-53 Rev. 5のコントロールAC-2(46〜50ページ)にある。残り62ファイルは開かれない。
Level 0:ファイルを選ぶ
1コール。モデルは63行を読み、回答を含む可能性のあるファイルIDをリターンする。通常1〜3ファイル。
補助的にキーワードタリー(質問のキーワードがサマリーや目次タイトルに何回出現するか)も並列実行する。AC-2やGV.OC-01のような正確なコードを文章のサマリーが省略している場合に補完する役割を果たす。なおGV.OC-01はNISTサイバーセキュリティフレームワーク(CSF)のガバナンス領域における組織コンテキスト定義に関するコードであり、こうした体系固有の識別子をサマリーに含めておくことがルーター精度の鍵となる。
このコールには2つの特性がある。bounded(ファイルサイズに関係なく常に63行)とauditable(なぜそのファイルを残したかの理由文字列が出力されるため、誤答を類似スコアではなくルーティング決定に遡れる)。
Level 1:サバイバーの内部に下降する
ここからは単一文書のケースと同一だ。そのファイルの目次をルーターに渡し、枝を選択し、子セクションがあればさらに繰り返す。このループは以下のコードで表現されている:
# フォルダのファイルリストは1つの目次のトップレベル
level = corpus_toc[corpus_toc.level == 0] # 63行、1ファイル1行
files = reason_on_toc(question, level, # 同じルーターコール
section_signals=keyword_hits(question, level))
sections = []
for file_id in files.section_ids: # 通常1〜3ファイル
level = corpus_toc[(corpus_toc.file_id == file_id)
& (corpus_toc.level == 1)]
# ここから単一文書と同じループ
2レベルは同じ呼び出しパターンだ。フォルダのファイルリストは、巨大な1文書の目次の最上位レベルに過ぎない。
設計が破綻する4つのパターン
記事は正直にスケール限界も列挙している:
- ファイル数が増えすぎた場合:63行は1プロンプトに収まるが、フラットなファイルリストにはスケール上限がある。この記事ではその閾値の具体値は示されていない
- アウトラインを持たない長い文書:タイポグラフィからアウトラインを再構築する処理が必要になる
- クロスファイルの質問:「セキュリティ統制とゼロトラストフレームワークの対応関係は?」のような質問は、Level 0で複数ファイルが残り、合成レイヤーが必要になる
- サマリー行の品質不足:ルーターの精度はサマリー行の品質に直結するため、コピーライティングではなくスキーマ定義として扱う必要がある
コンパニオンノートブックはdoc-intel/notebooks-vol1で公開されており、63ファイルへのルーティングが1ページも読む前に1ファイルに絞り込まれる様子を実際に確認できる。
詳細はMulti-Document RAG: A Folder of Unrelated PDFs Is One Long Document with a Nested Outlineを参照していただきたい。