RAG
外部知識を検索して LLM の回答精度を向上させるアーキテクチャ
RAG とは
RAG (Retrieval-Augmented Generation) は、LLM にプロンプトを送る前に外部の知識ベースから関連情報を検索し、その情報をコンテキストとして付与することで回答精度を向上させるアーキテクチャである。2020 年 5 月に公開された論文「Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks」(arXiv:2005.11401) で提案され、Facebook AI (現 Meta) の研究チームが発表した。
ただし論文が指していた RAG と、現在実務で RAG と呼ばれているものは中身が違う。論文の構成は検索する部分と文章を作る部分をひとつのモデルとしてまとめて学習できるものだったが、今よく使われているのは学習を伴わず、検索した文章をプロンプトに差し込むだけの構成である。原典を読むときはこの差を踏まえておきたい。
LLM 単体では学習データに含まれない最新情報や社内ドキュメントに回答できないが、RAG を使えばモデルを再学習せずに知識を拡張できる。
RAG のアーキテクチャ
RAG はユーザーの質問を埋め込みベクトルに変換し、ベクトル DB から関連ドキュメントを検索する。検索結果をプロンプトに付与して LLM に渡すため、モデルの重みは一切変わらない。回答の質を決めているのは検索で拾えた文章であり、根拠となる文章が拾えていなければ、LLM は手元にない知識を埋めようとしてもっともらしい誤りを書く。RAG がうまく動かないという相談の多くは、生成の問題ではなく検索の問題として現れる。
[ユーザーの質問]
↓
[1. 埋め込み] 質問をベクトルに変換
↓
[2. 検索] ベクトル DB から類似ドキュメントを取得
↓
[3. 拡張] 検索結果をプロンプトに付与
↓
[4. 生成] LLM が検索結果を参照して回答
↓
[回答]
AWS での実装
AWS で組む場合は、次の役割にサービスを割り当てる形になる。
| コンポーネント | AWS サービス |
|---|---|
| 埋め込みモデル | Bedrock (Titan Embeddings) |
| ベクトル DB | OpenSearch Serverless / Aurora pgvector |
| LLM | Bedrock (Nova, Claude) |
| オーケストレーション | Bedrock Knowledge Bases |
| ドキュメント格納 | S3 |
Bedrock Knowledge Bases を使えば、S3 にドキュメントを置くだけで埋め込み生成、インデックス作成、検索、回答生成までを自動化できる。
分割方法を指定しない場合は 300 トークン・重なり 20 % の固定長分割で取り込まれる (2026 年 8 月時点)。固定長のほかに階層分割・意味単位の分割・分割なしも選べるが、いったんデータソースを接続した後は分割方法を変更できない。扱う文書の構造に合う切り方を最初に決めておく必要がある。
RAG vs ファインチューニング
知識を足す手段としてファインチューニングと比べられるが、書き換える対象が違う。RAG は入力に足すだけで、ファインチューニングはモデルそのものを更新する。
| 観点 | RAG | ファインチューニング |
|---|---|---|
| 知識の更新 | ドキュメント追加で即時反映 | 再学習が必要 |
| コスト | 検索インフラ + API 呼び出し | 学習コスト (GPU 時間) |
| 精度 | 検索品質に依存 | タスク特化で高精度 |
| 誤りの扱い | 参照した文書を提示できるが検索が外れれば誤る | 軽減されるが残る |
| 適用場面 | FAQ、社内文書検索 | 文体の統一、専門用語の生成 |
まず RAG を試し、検索の精度を上げても届かない場合にファインチューニングを検討するのが実務的な順序である。足りないものが知識なら RAG、出力の形式や口調ならプロンプトの作り込みで足りることが多く、業務固有の判断基準まで覚えさせたい場合に初めてファインチューニングが正当化される。
検索精度を上げるコツ
- チャンク分割: 200〜500 トークン程度を目安に分割する (Bedrock Knowledge Bases の既定は 300 トークン)。大きすぎると 1 つのチャンクに無関係な話題が同居して類似度が薄まり、小さすぎると指示語の指す先が別のチャンクへ切れて文脈が失われる。段落や見出しの境界で切れているかが効くため、文字数だけで機械的に切らない
- メタデータフィルタ: カテゴリ、日付、ソースでフィルタリングし、検索対象を絞る
- ハイブリッド検索: ベクトル検索 (意味的類似度) とキーワード検索 (BM25) を組み合わせる
- リランキング: 検索結果を LLM で再評価し、関連度の高い順に並べ替える
答えが外れたときの切り分け
回答が的を外したときは、生成より前の段階で止まっていないかを先に見る。検索で返ってきたチャンクを実際に目で確かめ、答えの根拠になる文章が入っていなければ検索側の問題で、プロンプトをいくら書き直しても直らない。入っているのに答えが違うなら、指示の書き方か渡し方の問題である。この 2 つを分けずに直そうとすると、手当てが空回りする。
検索側が原因なら、分割の見直し、キーワード検索の併用、フィルタの追加の順に効く。利用者は略語で尋ね、文書には正式名称しか書かれていないような場合は、埋め込み による類似検索だけでは拾いきれないため、語そのものを突き合わせる検索を併用する。
渡すチャンクは多いほどよいわけではない。無関係なものが混ざると、モデルはそれも根拠として扱おうとする。関連度で並べ替えて上位だけを渡し、どの文書を根拠にしたかを回答に添えさせておくと、誤りに気づける形になる。
この記事は役に立ちましたか?