RAGの前にドキュメントをクリーニングする

検索拡張生成(RAG)のためにドキュメントをクリーニングするとは、残りのテキストがチャンクに分割され、埋め込まれ、ベクトルインデックスに保存される前に、内容ではないすべてのもの——PDFがすべてのページに抱えるヘッダー、フッター、ページ番号、繰り返しの定型文——を取り除くことです。それはRAGパイプラインで最も地味なステップであり、検索が機能するかどうかを静かに決めるステップです:クリーニングされていないテキストから構築されたインデックスは、同じ家具を何百回も保存し、それを知識であるかのように検索します。この記事では、家具が埋め込みをなぜ毒するのか、チャンキングが実際にどのように機能するのか、重複除去が埋め込みの前に属する理由、何を剥ぎ取り何を残すべきか、そしてクリーニングが役立ったかどうかをどのように評価するかを説明します。クリーニング自体を行うには、ドキュメントクリーナーを使い、このガイドと並べてあなた自身の結果を読んでください。

ページファニチャが埋め込みを毒する理由

埋め込みモデルは、テキストのチャンクを、そのチャンクが何についてのものかを捉えるはずのベクトルに変えます。レポートのタイトル、機密保持フッター、ページ番号が半分を占めるチャンクをそれに与えると、ベクトルはそれも忠実に捉えます——つまり長いドキュメントのすべてのチャンクが同じ家具へ漂い、ベクトル空間では遠く離れているはずのチャンク同士が、ヘッダーを共有するために人為的に近くなります。検索はすると、求められたとおりのことを正確に行います:返金ポリシーのセクションを尋ねると、その最も強い共有信号が実行ヘッド内の会社名である5つのチャンクを返します。誰もモデリングの誤りを犯していません。インデックスには、すべてのページで繰り返されるノイズが全力で詰め込まれており、繰り返されるノイズは、類似度を数えるシステムにとって信号と見分けがつきません。

損害は希釈よりもひどいものです。家具のチャンクは検索にそのまま勝つことがあります:フッターのような言い回しの問題——機密保持、ドキュメント管理、バージョンについて——は、200回埋め込まれたフッターチャンクに、それに本当に答える唯一の段落よりもよく一致します。ページ番号はより微妙な失敗を生み、裸の数字が内容であるとモデルに教えてしまうため、「42」で終わるチャンクが、その数字に意味があるかのように引用され返されることがあります。そして家具のチャンクはそれぞれ、有限なtop-k結果集合の枠を一つ占有し、本当に関連するチャンクを、モデルに与えられる文脈から押し出します。したがってクリーニングは見た目の整理整頓ではありません;それはあなた自身のインデックスの中で、あなた自身の内容に対する体系的な競合者を取り除くことです。

チャンキングの基礎:サイズ、重なり、境界

チャンキングは、どの単位が埋め込まれるかの決定であり、それには三つのノブがあります。サイズは焦点と文脈を交換します:小さいチャンク、数百文字は、一つの考えを鋭く埋め込んで正確に検索しますが、その考えに条件を与える文なしに到着することがあります;大きいチャンク、数千文字は、文脈を伴いますが、複数の考えを一つの平均ベクトルに混ぜてしまうため、どれも強く検索されません。ほとんどのドキュメントコーパスは中間のどこかに落ち着きます——おおよそ500から1,000文字が妥当な開始領域です——そして正しい答えは、フレームワークの既定値から数字をコピーすることではなく、あなた自身の質問をあなた自身のドキュメントに対してテストすることによって決まります。LangChainのテキストスプリッターのドキュメントは、文字スプリッターや再帰スプリッターから構造を意識するものまで、スプリッターファミリーの良い地図です。

重なりは第二のノブである境界に対する保険です。構造に関係なく800文字ごとに切断するスプリッターは、いずれ定義を真っ二つにし、どちらの半分も上手く検索されたり読まれたりしません。境界で分割すること——まず段落、次に文、次に空白、再帰スプリッターが行うように——は、ほとんどの場合単位を丸ごと保ち、10から20パーセントの控えめな重なりは、一つのチャンクの縁を次のチャンクの冒頭に繰り返すため、それでも起こる切断がその文脈を孤児にしません。LlamaIndexのノードパーサーのドキュメントの階層は、ローダー側から同じ点を述べています:ドキュメントを尊重するノードに解析し、それから分割してください。しかし、このどれも家具を救いません:重なりはヘッダーを次のチャンクにも忠実に繰り返すため、クリーニングはチャンキングの前に来るのであって、決して後ではありません。

埋め込む前に重複を取り除く

重複は第二の体系的な汚染物質であり、二種類あります。第一はドキュメント全体の重複です:同じPDFが異なるファイル名で二度インデックスされた、新しいものの隣に古いバージョンが置かれたままである、メールの添付ファイルが共有ドライブのコピーの隣に保存された。第二はドキュメント内部にあります:タイトルページの免責事項が付録に再び現れる、要約が各章の先頭に繰り返される、表が本文と附属書の両方に貼られた。どちらの種類も検索に同じ影響を与えます——重複したテキストは繰り返し埋め込まれるため、繰り返し検索され、ある節のコピーでtop-kを満たし、他の節は決して浮上しません——そしてコストにも同じ影響を与えます。なぜなら、コピーごとに埋め込みと保存の代金を払うからです。

重複除去は、埋め込む前、それがまだ文字列比較であるときに最も安く済みます。完全な重複は正規化で片付きます:空白を潰し、あなたがすでに剥ぎ取ったページファニチャを無視し、結果をハッシュしてコピーを一つだけ保持します。ほぼ重複——日付が変わった、あるいは見出しが振り直された同じ段落——は類似度のパスを必要としますが、粗いものでも、最も害を与える定型文を捕まえます。二つの注意が重複除去を誠実に保ちます。第一に、最初の出現を保持し、コピーがどこにあったかを記録してください;二つの章に繰り返された警告は意図的な安全装置かもしれず、それを記録から完全に移除することは、それをインデックスから取り除くこととは別の決定です。第二に、重複除去はクリーニングの後であって、前ではありません:ページ番号だけが異なる二つのページは、異なる家具に包まれた内容の重複であり、クリーニングされたテキストだけがそれを明らかにします。

何を剥ぎ取り、何を残すか

知らせることなく繰り返されるものを剥ぎ取ってください:実行ヘッドとフット、ページ番号、透かし、機密保持バナー、生成された「印刷日時」行、そしてウェブからPDFへのエクスポートがすべてのページに刻印するナビゲーションのパンくず。構造を与えるものを残してください:本物の見出し、それらはあなたが持つ最も強いチャンク境界信号であり、しばしばチャンクのメタデータに属するからです;キャプション、図のキャプションは図が何を示すかを述べる唯一のテキストであることが多いからです;表の内容、慎重に扱ってください、剥ぎ取られた表はその数字に意味を与える行と列の見出しを失うからです;そしてリスト、その項目は自然な単位です。境界のケースは目次です。チャンクとしては、目次行は家具です——すべてのクエリに漠然と一致し、どれにも答えないタイトルとページ番号のリスト——しかしメタデータとしては、その同じ目次ページはドキュメントの地図です。それを埋め込まれるテキストから剥ぎ取り、コーパスについてのあなたのメモに残してください。

同じ判断はドキュメントクリーナー自体の中にも適用されます:家具とページ番号は、それらを取り除くことがほぼ常に安全であるため既定でチェックされ、重複段落は、繰り返しが時には目的そのものであるため決して既定でチェックされません。ここでは抽出の誠実さも重要です。PDFは構造化された形式です——ISOのPDF標準であるISO 32000は、ページを流れるテキストではなく、描画とテキスト操作のコンテンツストリームとして定義しています——したがって、どの抽出器も読み順を近似するのであり、スキャンされたPDFは、OCRがテキスト層を与えるまでテキスト層をまったく持ちません。元のドキュメントが他の理由でも重要であるなら、あなたのPDFがウェブサイトのアクセシビリティの一部であることについてのコンパニオン記事は、スクリーンリーダーと抽出器の両方を助けるタグ付き構造を扱っています。

クリーニング後に検索を評価する

クリーニングは仮説です——検索が改善するだろう——そして検索品質についての仮説は、恥ずかしいほどわずかな仕組みでテストできます。あなたのユーザーが実際に尋ねる本物の質問を20から50集め、それぞれに答えるはずの節を手で記録してください。同じリトリーバー、同じチャンク設定、同じtop-kで、クリーニングされていないインデックスとクリーニングされたインデックスに対してそれらを実行し、二つのことを比較してください:正しい節が結果にまったく現れる頻度と、現れたときにどれほど上位にランクするか。そのペア——リコールとランク——がスコアボードです。クリーニングが機能していれば、家具のチャンクは結果に現れるのをやめ、正しい節は上がり、フッターが答えを上回ったために以前は失敗していた質問が合格し始めます。

それから失敗を読んでください、数字だけではあなたにお世辞を言うからです。クリーニングされたインデックスはリコールを獲得しながら、あなたが重複除去してしまった繰り返しの要約の中にその答えが本当に住んでいた質問や、各チャンクが必要とした製品名を携えていたヘッダーを失い、質問を一つ落とすことがあります。そうした損失は情報です:それらは、その要素をメタデータとして保持するよう、あるいはドキュメントのタイトルを、200回偶然に埋め込むのではなく、各チャンクの先頭に意図的に付けるよう教えてくれます。コーパス、スプリッター、あるいは埋め込みモデルが変わるたびに評価を再実行し、質問集合をインデックスと並べてバージョン管理してください。RAGの品質はローンチの特性ではありません;それは保守の特性であり、小さな固定したテスト集合こそが、「良くなった気がする」を弁護できるものに変えるものです。

出典とさらに読むもの

よくある質問

クリーニングは実際にどれほど検索を改善しますか?

それはあなたのドキュメントがどれほど家具に重いかによります、そしてそれは測定できます:クリーニングする前に、ページをまたいで繰り返される行を数え、固定した本物の質問の集合をインデックスの前後でテストしてください。家具が各チャンクの10分の1以上を占めることがあるため、強い実行ヘッドを持つ長いレポートが最も利益を得ます;短くてきれいなドキュメントはほとんど利益を得ないかもしれません。誠実な方法は、最後のセクションにある前後評価であり、約束されたパーセンテージではありません。

クリーニングはチャンキングの前と後のどちらで行うべきですか?

常に前です。クリーニングされていないドキュメントをチャンク化すると、家具がすべてのチャンクに埋め込まれ、次のチャンクに重なり、ページ番号がインデックス全体に散らばって、後のどのステップもそれらを確実に除去できなくなります。まず抽出されたテキストをクリーニングし、それから結果をチャンク化してください——ドキュメントクリーナーはまさにこの理由で、その順序でクリーニングされたテキストと出来合いのJSONLチャンクを生成します。

どのチャンクサイズと重なりから始めるべきですか?

段落の境界での分割と控えめな重なりを備えた約800文字から始め、それからあなた自身の質問集合に対して調整してください。小さいチャンクはより正確に検索しますが文脈が少なく、大きいチャンクはその逆を行います。ソースにリンクされたLangChainのテキストスプリッターのドキュメントのようなフレームワークのガイドはスプリッターファミリーを説明しますが、あなたのコーパスにとって正しい数字は、既定値からではなく評価から来ます。