初めに
大量の資料をLLMに渡したのに、回答に必要な条件が抜けている。
長い資料を扱うときは、全文を一度に読ませる以外の方法も考えたいです。
今回は、質問に必要な根拠を抽出するQuery-focused extractionと、資料を分けて処理し、結果を統合するMap-Reduce QAを組み合わせます。
1. Query-focused extractionは、質問を基準に抽出する
Query-focused extractionは、質問に答えるために必要な情報を、文章から選び出す処理です。ここでは、この説明的な呼び方を使います。
たとえば、質問が「製品Aの無料プランでは、データを何日保存できるか?」なら、抽出したいのは次の情報です。
- 対象プラン
- 保存期間
- 例外や適用条件
- 根拠となる原文と出典
資料全体の概要よりも、今回の質問に必要な情報を残すことを優先します。
検索結果から関連情報を取り出し、質問への回答を合成する構成は、Anthropicの公開デモでも扱われています。
2. Map-Reduce QAは、個別処理と統合を分ける
Map-Reduce QAでは、資料やチャンクをそれぞれ処理するMapと、その結果をまとめるReduceに分けます。
文書を個別に処理してから結果を統合するパターンは、LangChainでも実装されています。
今回の構成では、MapにQuery-focused extractionを使います。
| 段階 | 処理 |
|---|---|
| Map | 各資料から、質問に必要な根拠を抽出する |
| Reduce | 根拠を照合し、出典付きの回答を作る |
Map段階では、各資料だけで最終回答を作る必要はありません。回答の材料を取り出します。
3. プロンプトでは、根拠と条件を残す
Map用のプロンプト例です。
質問に答えるために必要な情報を、資料から抽出してください。
- 根拠となる原文を引用する
- 数値、対象、適用条件、例外を残す
- 資料IDとページ番号を付ける
- 関連情報がなければ空配列を返す
- 資料にない内容を補わない
質問:{question}
資料ID:{document_id}
資料:{text}
Reduceでは、元の質問と抽出結果を渡します。
抽出された根拠を使って、質問に回答してください。
- 資料IDを出典として付ける
- 条件の違いと、同じ条件での矛盾を区別する
- 根拠が足りない場合は、不足している点を明記する
質問:{question}
根拠:{evidence}
実装側でも、引用が原文に存在するか、資料IDが正しいかを検証すると、抽出ミスを見つけやすくなります。
4. 抽出で落とした情報は、Reduceでは戻らない
この方法の注意点は、Map段階で必要な情報を削ると、後段で取り戻せないことです。
たとえば、「保存期間は30日」だけを残し、「有料プランの場合」という条件を落とすと、誤った回答につながります。
また、文書をまたぐmulti-hop質問では、最初の資料で得た名前やIDを使って、追加検索が必要になることがあります。各チャンクを一度処理するだけで解決できるとは限りません。
そのため、実装では次を押さえます。
- 見出しや前後の文脈を付けて抽出する
- 原文を再取得できる出典を残す
- 必要に応じて追加検索する
- 抽出結果も長すぎる場合は、情報を保って段階的に統合する
呼び出し回数は増えるため、時間とコストも評価します。
まずは同じ質問で、全文を渡す方法と比較し、正答率・根拠の漏れ・処理時間を確認すると、採用する価値を判断しやすくなります。
