コンセプト解説

検索拡張生成(RAG)

AIに会社の規程や最近のニュースについて聞くと、もっともらしいのに間違った答えが返ってくることがあります。モデルを学習し直さずに、質問が来るたびに必要な文書を探して一緒に渡してあげる方法がRAGです。AI関連の資格試験でもよく出題されるテーマです。

01

AIが知らないことを聞かれたら

ある会社が、社員の質問に答える社内アシスタントのチャットボットを作りました。ある社員がこう尋ねます。

東京出張のとき、ホテル代は1泊いくらまで出ますか?

会社の出張規程には「宿泊費は1泊12,000円以内。ただし東京・大阪は15,000円」と書かれています。ところがチャットボットは「1泊10,000円までです」と答えました。なぜこんなことが起きるのでしょうか。

チャットボットの中では、大規模言語モデル(LLM)が動いています。LLMはWebページや本など、公開されている大量の文章から学習しています。それでも、知り得ないことが2つあります。1つは、学習が終わったあとに起きた出来事です。モデルはその時点までの文章しか見ていません。もう1つは、そもそも公開されたことのない情報です。この会社の出張規程がまさにそれです。

知らないなら「わかりません」と言ってくれればよいのですが、LLMはそれまでの文章を見て、次に来そうな言葉をつなげて答えを作ります。そのため、知らないことでも、もっともらしい文章ができあがってしまいます。事実でないことを事実のように答えてしまう現象をハルシネーションと呼びます。

解決策は意外とシンプルです。質問と一緒に、規程の該当する条文を渡せばよいのです。教科書を見ながら受けられる「持ち込み可」の試験のようなものです。モデルが規程を暗記している必要はありません。目の前に置かれた資料を読んで答えるだけです。

下の図で確かめてみましょう。左が会社の規程文書、真ん中の枠がモデルに送る文章、右がAIモデルとその回答です。最初は質問だけが送られます。規程の条文も一緒に送るスイッチを入れてみてください。条文が送る文章の中に移り、回答からその条文へ出典の線が伸びます。

送ったチャンク
なし(質問だけ)
回答
1泊10,000円までです。 · 作り話 · 根拠なし

社内アシスタントに質問 —「東京出張のとき、ホテル代は1泊いくらまで出ますか?」

規程文書とつながっていないので、モデルには質問だけが届きます。モデルはこの会社の規程を見たことがありません。それでも何か答えようとして、もっともらしい金額を作ってしまいます。

このように、合う資料を検索(Retrieval)し、それで送る文章を拡張(Augmented)してから、その資料をもとに答えを生成(Generation)する方法を、検索拡張生成(RAG)と呼びます。名前は2020年に発表された研究論文に由来します。

RAGで変わるのは、モデルに送る文章だけです。モデルが学習した内容を保持している数値、つまり重みはそのままです。だから規程が変わっても、文書を差し替えればよく、モデルを学習し直す必要はありません。試験では、正解付きのデータでモデルを追加学習させるファインチューニングとの違いとして、ここがよく問われます。

「該当する条文を探して付ける」と一言でいっても、実はいくつかの段階があります。大きく分けると、質問が来る前にやっておく作業と、質問が来たときにやる作業です。

前もってやっておくこと

インデックス作成の段階

  1. 文書を小さなチャンクに分ける第2章
  2. チャンクの意味を数値に変えて保存する第3章

質問が来たときにやること

検索と生成の段階

  1. 質問も数値に変えて、いちばん近いチャンクを探す第4章
  2. そのチャンクを質問と一緒にモデルへ送り、答えをもらう第5章

最初の段階が「分ける」なのはなぜでしょう。規程集をまるごと付けてしまえばよいのでは? と思うかもしれません。でも、それが数百ページあったらどうでしょうか。

02

文書を小さく分ける(チャンク分割)

モデルが一度に読める文章の量には上限があり、これをコンテキストウィンドウと呼びます。最近のモデルはかなり余裕がありますが、送る文章が長いほど回答は遅くなり、費用も上がります。多くの場合、入力と出力の文章量(トークン数)で料金が決まるからです。ちなみに日本語の文章は、同じ内容の英語よりもトークン数が多くなりがちです。

たくさん送ればきちんと読んでくれる、というわけでもありません。Liuらの2023年の研究では、モデルは長い文章の最初と最後にある情報はよく使えても、真ん中に埋もれた情報は見落としやすいことがわかりました。数百ページの中から1行を探すのは、まさにこの状況です。

そこで、前もって文書を小さく分けておき、質問が来たら関係のある数個だけを送ります。分けた1つひとつをチャンク、文書をこのように分けることをチャンク分割(チャンキング)と呼びます。

ここが引っかかりやすいところで、難しいのはサイズです。下の図でチャンクのサイズを変えてみてください。サイズごとに、質問にいちばん近いチャンクを1つ付けたらどうなるかを示しています。

送ったチャンク
宿泊費は12,000円以内
回答
1泊12,000円までです。 · ただし書きを見落とした回答

チャンクのサイズ:1文ずつ(小さい) — 質問にいちばん近いチャンクを1つ付けた場合

原則(「12,000円以内」)とただし書き(「ただし東京・大阪は15,000円」)が、別々のチャンクに分かれてしまいました。検索は「宿泊費」という言葉が入った前のチャンクだけを持ってきたので、モデルは12,000円と答えます。

1文ずつ分けると、「宿泊費は12,000円以内」と「ただし東京・大阪は15,000円」が別々のチャンクになります。検索は「宿泊費」という言葉が入った前のチャンクだけを持ってきて、モデルは12,000円と答えます。反対に章全体を1つのチャンクにすると、必要な部分は含まれますが、食費や交通費の条文まで一緒に入ってきます。文章が長くなって費用がかさみ、ほかの金額も答えに紛れ込みやすくなります。

この例では、1つの条文を1チャンクにするのがいちばんうまくいきました。原則とただし書きが同じ条文に入っているからです。ちょうどよいサイズは文書によって違いますが、考え方は同じです。1つの質問に答えるのに必要なことがまとめて入る大きさで、関係のないことは入らない小ささにします。

分け方のいろいろ

  • 固定サイズ:一定の文字数やトークン数(モデルが文章を読むときの単位)ごとに区切ります。いちばん簡単ですが、文の途中で切れてしまうことがあります。
  • 文書の構造で分ける:見出し、条、段落など、文書がもともと持っている区切りに沿って分けます。規程やマニュアルのように構造がはっきりした文書に向いています。
  • 意味の変わり目で分ける:前後の文で意味が大きく変わる位置を見つけて、そこで区切ります。これをセマンティックチャンキングと呼びます。

どの方法で分ける場合でも、前のチャンクの最後の数文を次のチャンクの最初にも入れておくと、境目にある内容が失われにくくなります。これをオーバーラップ(重なり)と呼びます。

問題文にこんな表現があれば → これを選ぶ

  • “文書をより小さな単位に分ける”チャンク分割
  • “チャンクが小さすぎて、原則と例外が別々になる”チャンクのサイズを大きくする
  • “関係のない内容が混ざり、費用も高い”チャンクのサイズを小さくする
  • “チャンクの境目で文が途切れる”チャンクのオーバーラップ

チャンクの準備ができました。あとは質問が来たら、数千あるチャンクの中からどれを付けるかを選びます。ところが社員は「ホテル代」と聞き、規程には「宿泊費」と書いてあります。同じ言葉を探す検索では、この条文は見つかりません。

広告

03

意味を座標に変える(埋め込み)

地図を思い浮かべてください。住所を緯度と経度という2つの数字に変えれば、2つの場所がどれくらい近いかを測れます。文章も同じです。文章の意味をいくつかの数字の組に変えれば、座標のように扱えます。

このように文章を数字の並びに変えることを埋め込み(エンベディング)、できあがった数字の並びをベクトルと呼びます。変換を担当するのは埋め込みモデルです。意味の似た文章ほど似た数字になるように学習されています。そのため「ホテル代」と「宿泊費」は言葉こそ違いますが、意味が近いので座標も近くなります。

下の図は、規程のチャンクを埋め込みにして空間に置いたものです。色はテーマを表します。出張のチャンクは出張どうし、休暇のチャンクは休暇どうしで集まっています。誰かがテーマを教えたわけではありません。意味が似ているので自然に集まったのです。黄緑の点が質問です。質問を切り替えてみましょう。

質問

質問:「東京出張のとき、ホテル代は1泊いくらまで出ますか?」

規程には「ホテル代」という言葉はなく、「宿泊費」と書かれています。それでも質問の点は「出張」のかたまりの真ん中、宿泊費のチャンクのすぐそばに落ち着きます。位置を決めるのは言葉そのものではなく、意味だからです。

実際の埋め込みは2つや3つではなく、数百から数千の数字でできています。そんな空間は絵に描けないので、図では3次元に縮めています。数字の数が多いほど、意味の細かな違いまで表せます。

チャンクの埋め込みは、質問が来る前にすべて計算して保存しておきます。ベクトルを保存して、すばやく検索できるようにした保管庫をベクトルデータベース(ベクトルストア)と呼びます。質問が来たときにその場で埋め込みにするのは、質問だけです。

質問と文書は、必ず同じ埋め込みモデルで埋め込みにします。埋め込みモデルごとに座標の決め方が違うので、別々のモデルで作った座標どうしの距離を測っても意味がありません。縮尺も向きも違う2枚の地図の座標を比べるようなものです。同じ理由で、埋め込みモデルを替えたら、保存済みの文書もすべて埋め込みをやり直す必要があります。

もう1つ、試験で引っかかりやすいポイントがあります。埋め込みモデルは文章を生成しません。文章どうしを比べられるように数字に変えるだけです。答えを書くのは、次の段階のLLMの仕事です。

問題文にこんな表現があれば → これを選ぶ

  • “テキストを数値のベクトルに変換する”埋め込み
  • “言葉が違っても意味の近い文章を見つける”埋め込みによるセマンティック検索
  • “質問と文書を別々の埋め込みモデルで変換する”誤った設計 — 同じモデルを使う
  • “埋め込みモデルが回答を書く”誤った選択肢 — 回答を書くのはLLM

これで、すべてのチャンクと質問が同じ空間の点になりました。残るは、質問の点にいちばん近いチャンクの点を見つけることだけです。

Pro限定

ここまでは無料で読めます

残りの5章はPro会員向けです。各章に3D図解と「問題文にこんな表現があれば」の整理が続き、最後の章では実際に解いて確かめられます。

  1. 04ベクトル検索
  2. 05グラウンディング
  3. 06ナレッジベースの管理
  4. 07評価と原因の切り分け
  5. 08RAGとファインチューニングの選び方

PasslyExam

概念をつかんだら、次は試験形式の問題で確かめましょう

PasslyExamは、各資格の出題範囲に合わせて作成したオリジナルの練習問題・解説・本番形式の模擬試験を提供しています。正解の選択肢がなぜ正しく、似た選択肢がなぜ誤りなのかまで解説します。登録すると毎日無料で練習問題に取り組めます。