最近ローカルLLMで何かできないかと情報収集をはじめたところ、RAG(Retrieval-Augmented Generation)が気になったので、仕組みを図にして整理してみました。図にしないと頭に入ってこない派なので、、
RAG の処理の流れ
図1 RAG の処理の流れ(質問から回答まで)
| 番号 | やりとり | 内容 |
|---|---|---|
| ① | 利用者 ➔ 司令塔 | 質問を投げる |
| ②③ | 司令塔 ⇄ テキスト生成モデル | 質問を検索しやすい言い方に書き換えてもらう(クエリ拡張)。任意なので点線 |
| ④⑤ | 司令塔 ⇄ Embeddingモデル | 検索用の質問をベクトル(数字の並び)に変換してもらう |
| ⑥⑦ | 司令塔 ⇄ ナレッジ(ベクトルDB) | 質問ベクトルに意味が近い文章(チャンク)を検索して受け取る |
| ⑧ | 司令塔 | 元の質問(①)+関連する文章(⑦)+指示 でプロンプトを組み立てる |
| ⑨⑩ | 司令塔 ⇄ テキスト生成モデル | プロンプトを渡して、回答を生成してもらう |
| ⑪ | 司令塔 ➔ 利用者 | 回答に出典を添えて返す |
司令塔はオーケストレーターとも呼ばれ、Open WebUI などがこの役割をしています。
R・A・G との対応
| 文字 | 意味 | 図の番号 |
|---|---|---|
| R(Retrieval:検索) | 関連する文章を探す | ④〜⑦ |
| A(Augmented:拡張) | 質問に文章を足してプロンプトにする | ⑧⑨ |
| G(Generation:生成) | 回答を作る | ⑩ |
冒頭の「検索の力で拡張された生成」が、そのまま図の流れになっています。
プロンプトを組み立てるのは司令塔
ここが一番大事なポイントだと思いました。テキスト生成モデルは自分では検索しないし、ナレッジのことも知りません。見ているのは司令塔から渡されたプロンプトの中身だけです。司令塔は、例えば以下のようなテンプレートに質問と検索結果を当てはめています。
以下の「参考情報」だけを使って、質問に答えてください。 参考情報に答えがない場合は「わかりません」と答えてください。 回答の中で、根拠にした参考情報の番号を [1] のように示してください。 ### 参考情報 [1] (ベクトルDBから取得した文章 その1) [2] (ベクトルDBから取得した文章 その2) [3] (ベクトルDBから取得した文章 その3) ### 質問 (利用者の元の質問)
- 参考情報だけを使って:もっともらしい嘘(ハルシネーション)を抑える
- ないときは「わかりません」:ベクトル検索は「0件」にならず、近いものを必ず返してくるので、この指示が必要
- [1] [2] の番号:どの資料を根拠にしたかを回答に示させる(出典につながる)
つまり、RAG の回答のよさは、司令塔がプロンプトに何をどう入れるかでほぼ決まります。
クエリ拡張の結果はプロンプトには入らない
②③で書き換えた「検索用の質問」は、検索で当たりやすくするための使い捨てです。プロンプトに入れるのは、利用者が本当に聞きたかったニュアンスが残っている元の質問(①)です。図の⑧に「①+⑦」と書いているのはこのためです。
また、②③(テキスト生成モデル)と④⑤(Embeddingモデル)は別物です。前者は「文章 ➔ 文章」、後者は「文章 ➔ 数字」の変換をしています。
回答には出典がつく
⑩で返ってきた回答は、基本はそのまま利用者に返しますが、司令塔は出典を添えます。プロンプトの [1] [2] が、どの文書のどこなのかを司令塔が覚えているので、回答の下に資料名やリンクを表示できます。
ふつうのチャットAIと違って「どの資料をもとに答えたか」を示せるのが RAG のよいところで、人が「本当にそう書いてあるか」を確かめられます。
イメージは「持ち込み可の試験」
| 試験 | RAG |
|---|---|
| 問題用紙 | 利用者の質問 |
| 持ち込んだ資料 | 検索で集めた文章(チャンク) |
| 答案 | 回答 |
試験に強い人が資料をそのまま書き写さず、関係のある部分を見つけて自分の言葉でまとめるように、テキスト生成モデルも渡された資料から答えをまとめています。だからこそ、資料の読み間違いや、資料にないことを作り話で埋めることもあるので、出典が大事になります。
次回
この図では「ナレッジ(ベクトルDB)」は最初からあるものとして描きましたが、実際には元の資料を事前にチャンクに分けてベクトル化し、ベクトルDBを作っておく必要があります。次回はその「ナレッジの作り方と検索のしくみ」をまとめる予定です。
