RAGの文書分割とは?検索で見つける単位と、回答に必要な文脈を両立する
RAGで正しい文書を登録していても、質問への答えが抜け落ちることがある。文書を検索用の小さな断片に切る位置が悪く、答えの条件や例外を別の断片へ追いやっている場合だ。文書分割(Chunking)は単なる前処理ではなく、検索できる情報の単位を決める設計である。
例えば、架空の社内規程に「申請は原則3日前まで。ただし緊急時は当日連絡」と書いてあるとする。前半だけを検索して「当日の申請は認められない」と答えるなら、モデルが断片を正確に読んでも、元の規程には忠実ではない。この例は説明用であり、実在の規程やモデルの実測結果ではない。
登録する断片と、回答へ渡す断片
長い文書を丸ごと検索対象にすると、質問に関係する一文が文書全体の中で埋もれやすい。一方、短く切れば狙った箇所を探しやすくても、その箇所を理解するための見出しや前後の条件を失う。検索に使う小さな断片と、検索後にモデルへ渡す前後を含む文脈は、必ずしも同じ長さである必要はない。
LlamaIndexのNode Parserは、元のDocumentから断片のNodeを作り、文書のmetadataなどを引き継ぐ。これはライブラリの実装例だが、元文書との関係を残す意義が分かりやすい。検索で小さな段落を見つけた後、元文書の該当節を参照して回答へ渡す方法なら、見つけやすさと読むための文脈を分けて調整できる。ただし、拡張した範囲も利用者に閲覧権限のある文書に限定する。
文字数だけで切らず、意味の境界を残す
見出し、段落、箇条書き、表の行、コードの関数など、資料ごとのまとまりを先に考える。規程なら「適用対象」と「例外」、技術資料なら手順とその前提条件を同じ検索単位に含めたい場面がある。機械的な長さ制限が必要でも、まず大きな区切りで分け、長すぎる部分だけさらに分ける。LangChainの再帰的テキスト分割の公式資料も、段落や文などの区切りを優先しながら指定サイズへ収める方法を紹介している。
見出しが断片から離れるなら、文書名、節名、版、更新日、参照先をメタデータとして保持する。ただし、古い版を誤って検索するなら、メタデータを保存するだけでは足りない。検索時の版の絞り込みや旧版の除外も設計に含む。表はセルを無造作に切ると列名と値の対応が失われるため、行と見出しの関係を保つ必要がある。
オーバーラップを増やせば解決するわけではない
隣り合う断片の末尾と先頭を重複させる「オーバーラップ」は、切れ目にある文を拾うための手段だ。しかし重複が多いと、似た断片が検索結果を占め、登録量と回答へ渡すトークンも増える。重要な例外が長く離れている場合、数行を重ねても問題は解決しない。元文書の節を復元するなど、境界自体を見直した方がよい。
最適な「何文字・何トークン」は資料と質問によって変わる。異なる文書・検索器・評価対象を用いた研究結果の数字を、すべてのRAGへ共通の推奨値として移すことはできない。小さな断片、大きな断片、少量のオーバーラップなどを候補にし、実際の質問で比較する。
分割の良し悪しをどう測るか
代表的な質問と、その回答に必要な元文書の箇所を先に用意する。同じ質問集合で分割方法だけを変え、必要な箇所が検索上位に入るか、渡された断片だけで条件と例外を読めるか、最終回答が元文書の内容を正しく反映するかを別々に確認する。質問に不要な重複断片が上位を埋めていないかも見る。
分割を変更すれば検索インデックスを作り直す必要がある。文書の更新・削除時には古い断片を取り除き、出典と版の対応を保つ。検索精度だけでなく、閲覧権限、更新の反映、引用先の追跡まで含めて初めて運用できる。まずは一つの「例外を伴う質問」で断片と元文書を見比べる。そこから、どの境界を残すべきかが具体的になる。