RAG(検索拡張生成)の設計パターン
自分の資料をLLMに答えさせるための RAG の仕組み、チャンク分割・埋め込み・検索・生成の各工程の設計ポイント、よくある失敗と改善策。
#RAGとは
Retrieval-Augmented Generation。質問に関連する資料を検索して取り出し、それをプロンプトに添えてLLMに回答させる手法。モデルの知識に頼らず、自分の資料に基づいた回答 を得られる。
質問 → [検索] 関連チャンクを取得 → [生成] 質問 + チャンクをLLMへ → 回答(出典付き)
#RAGが向くケース / 向かないケース
| 向く | 向かない |
|---|---|
| 社内文書・マニュアルへのQA | 資料が数万トークン以内(丸ごと渡せばよい) |
| 頻繁に更新される情報 | 資料全体を横断した集計・要約 |
| 出典を示す必要がある | 推論が主で、参照資料が不要 |
ヒント
資料が合計で数十万トークン程度なら、最近のロングコンテキストモデルに 丸ごと渡す + プロンプトキャッシュ の方が単純で精度も高いことが多い。RAGは「渡しきれない量」になってから検討する。
#パイプラインの構成
#1. 取り込み(Ingestion)
- PDF、HTML、Markdown、Word などをテキスト化
- 表・見出し・ページ番号などの 構造情報を保持 する(後で出典表示に使う)
- 重複・ノイズ(ヘッダー/フッター、ナビゲーション)を除去
#2. チャンク分割(Chunking)
資料を検索単位に切る。ここが精度を大きく左右する。
| 方式 | 特徴 |
|---|---|
| 固定長(例: 500トークン、オーバーラップ50) | 実装が簡単。文脈が切れやすい |
| 構造ベース(見出し・段落単位) | 意味のまとまりを保てる。おすすめ |
| セマンティック(意味の変わり目で分割) | 高精度だが処理コスト大 |
各チャンクに メタデータ(文書名、見出し、日付、URL)を付けておく。
#3. 埋め込み(Embedding)
チャンクをベクトルに変換し、ベクトルDBに保存。
- 埋め込みモデルは日本語対応のものを選ぶ(多言語モデル or 日本語特化)
- チャンク先頭に文書タイトルや見出しを付けてから埋め込むと検索精度が上がる(contextual chunk)
#4. 検索(Retrieval)
- ベクトル検索(意味的な近さ)と キーワード検索(BM25) を組み合わせる ハイブリッド検索 が安定
- 上位 k 件(10〜20件)を取得後、リランカー で並び替えて上位3〜5件に絞る
- メタデータでフィルタ(日付、部署、文書種別)
#5. 生成(Generation)
次の <context> 内の資料のみに基づいて質問に答えてください。
資料に答えがない場合は「資料には記載がありません」と答えてください。
回答の根拠となった資料番号を [1] のように示してください。
<context>
[1] (文書名 / 見出し)
...
[2] ...
</context>
質問: {{質問}}
#よくある失敗と対策
| 症状 | 原因 | 対策 |
|---|---|---|
| 関係ないチャンクが返る | チャンクが大きすぎ/小さすぎ、埋め込みモデルが不適 | 構造ベース分割、モデル変更、ハイブリッド検索 |
| 答えがあるのに見つからない | 質問と資料の語彙が違う | クエリ拡張(LLMで言い換え生成)、キーワード検索併用 |
| 出典が正しくない | メタデータ不足 | チャンクに文書名・位置を付与 |
| 複数資料を横断する質問に弱い | 検索は「1つの答え」向き | 質問を分解して複数回検索(multi-hop) |
| 回答が長い・冗長 | 生成プロンプトの制約不足 | 形式・長さを指定 |
#評価
RAGは 検索 と 生成 を分けて評価する。
- 検索: 正解チャンクが上位k件に含まれる割合(Recall@k)
- 生成: 回答の正確性、根拠との整合性(faithfulness)、出典の正しさ
- 評価用に 質問・正解・正解資料 のセットを30〜50件作っておく
#発展
- エージェント型RAG: LLMが検索を繰り返し、必要に応じてクエリを修正する
- GraphRAG: エンティティ間の関係グラフを使って横断的な質問に対応
- ツールとしての検索: 検索をツールとして定義し、モデルに「いつ検索するか」を判断させる
#まとめ
- まず「丸ごと渡す」で足りるか確認。足りなければRAG
- チャンク分割とメタデータが精度の土台
- ハイブリッド検索 + リランクが安定
- 検索と生成を分けて評価する