RAG(Retrieval-Augmented Generation、検索拡張生成)は、LLMに質問する前に関係する資料を検索し、その資料をプロンプトに添えて回答させる手法です。LLMそのものには手を加えず、LLMに渡す入力を工夫する方法です。

名前は、2020年に発表された次の論文(Lewis ほか、NeurIPS 2020)に由来します。

この論文では、Wikipediaから関連する文章を検索して文章生成モデルに渡す構成を提案し、質問応答のベンチマークで当時の最高性能を出しました。

何のために使うのか

LLMは、学習したデータの範囲でしか答えられません。そのため、次のような問題があります。

  • 社内文書のような公開されていない情報は知らない
  • 学習データを集めた時点より後の出来事は知らない
  • 知らないことでも、もっともらしい文章で答えてしまうことがある(ハルシネーション)

RAGを使うと、LLMを学習し直さずに、手元の資料をもとに答えさせることができます。回答の根拠になった資料を利用者に示せるので、内容が正しいかを確認しやすくなります。資料が更新されたときも、検索対象のデータを入れ替えるだけで済みます。

左はLLMだけの場合で、質問に答えられず困っている。右はRAGを使った場合で、資料を見ながら答えている

どう動くのか

RAGの処理の流れ。事前に資料をチャンクに分けて保存し、質問を受けたら関係するチャンクを検索して質問と一緒にLLMに渡し、回答を得る

RAGの処理は、事前に行う準備と、質問を受けたときに行う処理の2つに分かれます。

事前に行うこと

  1. マニュアルやFAQなど、答えの元にしたい資料を集める
  2. 資料を数百文字程度の断片(チャンク)に分ける
  3. 各チャンクを埋め込みモデルでベクトル(意味を表す数値の配列)に変換し、元の文章と一緒に保存する

チャンクに分けるのは、資料をまるごとLLMに渡すと長すぎるためと、質問に関係する部分だけを取り出せるようにするためです。

質問を受けたときに行うこと

  1. 質問も同じ埋め込みモデルでベクトルに変換する
  2. 質問のベクトルと近いチャンクを検索する(ベクトル検索)
  3. 見つかったチャンクと質問をまとめてLLMに渡し、回答させる

LLMに渡すプロンプトは、たとえば次のような形です。

text
次の資料をもとに質問に答えてください。
資料に書かれていない場合は「分かりません」と答えてください。

# 資料
(検索で見つかったチャンク)

# 質問
有給休暇の申請は何日前までに出せばよいですか。

検索方法はベクトル検索だけでなく、キーワードの一致で探す全文検索や、その2つを組み合わせたハイブリッド検索が使われることもあります。

注意点

RAGを使っても、必ず正しく答えられるわけではありません。

  • 検索で必要な資料が見つからなければ答えられない:回答の質は検索の精度に大きく左右されます。チャンクの分け方や検索方法で結果が変わります。
  • 正しい資料を渡しても間違えることがある:ハルシネーションは減りますが、なくなるわけではありません。
  • 渡せる資料の量に上限がある:LLMが一度に読める長さには限りがあるため、検索結果のうち何件を渡すかを決める必要があります。

うまく答えられないときは、まず検索で正しいチャンクが取れているかを確認するのが基本です。このブログでは、チャンクの分け方や検索方法などを今後一つずつ試していきます。