RAGの精度が劇的向上:ParentDocumentRetrieverで「文脈切れ」を防ぐ技術
はじめに:「断片的な報告」に怒る上司の気持ち、今ならわかる
RAG(検索拡張生成)システムを作っていて、こんな経験はありませんか?
質問に対して、AIが回答はするものの、なんだかピントがずれている。「そこじゃないんだよなぁ」という惜しい回答。
これ、部下からの報告にも似ています。「部長、トラブルです!」と言われても、「前後の経緯を話せ、経緯を!」って思いますよね。
従来のRAGは、文書を細切れ(チャンク)にしすぎて、前後の文脈を失ってしまうのが弱点でした。今回は、その問題を解決する特効薬 ParentDocumentRetriever について解説します。これを入れるだけで、AIの回答が「気が利くベテラン社員」に進化します。
基礎知識:なぜ通常のRAGでは精度が出ないのか
通常、RAGでは文書を500〜1000文字程度の「チャンク」に分割してベクトル化します。検索時はこの小さな断片がヒットするのですが、ここに問題があります。
断片だけをLLMに渡しても、文脈が足りなさすぎて正しく答えられないのです。例えば「契約解除の条件」という章がヒットしても、それが「甲」の話なのか「乙」の話なのか、その前のページを見ないとわからないことがあります。
ParentDocumentRetrieverは、「検索は小さな断片で行い、LLMに渡すときはその親(元の大きな文書全体)を渡す」というアプローチを取ります。検索ヒット率と、回答品質のいいとこ取りができるわけです。
実装・設定:ParentDocumentRetrieverの導入手順
実装はLangChainを使えば驚くほど簡単ですが、保存先が2つ必要になる点に注意してください。「ベクトルストア(検索用)」と「ドキュメントストア(本文保存用)」です。
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain_chroma import Chroma
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 小さなチャンクと大きな親ドキュメントを作る設定
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
# 2. 保存先の用意
vectorstore = Chroma(embedding_function=local_embeddings)
store = InMemoryStore() # 本番ではRedis推奨
# 3. Retrieverの作成
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter,
)
# 4. ドキュメント追加
retriever.add_documents(docs)
これで検索を実行すると、小さいチャンクで検索しつつ、結果としては自動的に親の大きなチャンクが返ってきます。
応用テクニック:チャンクサイズの黄金比を探る
「Childサイズ」と「Parentサイズ」のバランスが肝です。私の経験則ですが、Childは思い切って小さく(200〜400トークン)、ParentはLLMのウィンドウサイズが許す限り大きく(2000〜4000トークン)取るのが効果的でした。
トラブルシューティング:ストレージ圧迫問題
ParentDocumentRetrieverは、元の文書を丸ごと(あるいは大きく分割して)保存するため、ストレージ容量を食います。メモリ上の InMemoryStore
だと、大量のドキュメントを読み込ませた瞬間にサーバーがOOM(メモリ不足)で落ちます。
本番環境では、必ずRedisなどの永続化KVS(Key-Value Store)を使ってください。PoC(概念実証)が終わったら、横着せずにインフラ担当に相談しましょう。
まとめ:木を見て森も見るAIを作ろう
ParentDocumentRetrieverを導入することで、AIは「木(キーワード)」を見つけ出し、「森(文脈)」を理解して回答できるようになります。
RAGの精度向上に悩んでいるなら、プロンプトをいじくり回す前に、まずこの仕組みを試してみてください。きっと「そうそう、こういう回答が欲しかったんだよ!」と、部下(AI)を褒めたくなるはずです。
コメント
コメントを投稿