RAGは「検索(Retrieval)」と「生成(Generation)」を組み合わせ、LLMが外部知識を根拠に回答できるようにする手法です。本ドキュメントでは、設計から運用までの実践的なベストプラクティスをフェーズごとに整理します。
目次
- 全体アーキテクチャ
- データ準備・前処理
- チャンキング戦略
- 埋め込み(Embedding)
- インデックスとベクトルDB
- 検索(Retrieval)
- リランキング
- プロンプト設計と生成
- 評価
- 運用・監視
- セキュリティとガバナンス
- 発展的手法
- よくあるアンチパターン
- チェックリスト
1. 全体アーキテクチャ
[ドキュメント] → 前処理 → チャンキング → 埋め込み → [インデックス]
│
[ユーザー質問] → クエリ変換 → 検索(ハイブリッド) → リランキング → コンテキスト構築 → LLM生成 → [回答+出典]
基本原則
- まずシンプルなベースラインを作る:素朴なRAG(固定長チャンク+ベクトル検索+Top-k)で動くものを作り、評価してから改善する。
- 評価駆動で改善する:改善施策は必ず評価セットで効果を測定してから採用する。
- 検索品質がボトルネック:回答品質の問題の多くは「正しい情報が検索で取れていない」ことに起因する。生成より先に検索を疑う。
- RAGが本当に必要か確認する:ナレッジが小さく(数十万トークン以内)頻繁に変わらないなら、全文をコンテキストに入れる(+プロンプトキャッシュ)方がシンプルで高精度な場合がある。
2. データ準備・前処理
| 項目 | ベストプラクティス |
|---|---|
| パース | PDF・HTML・Office等はレイアウトを考慮したパーサーを使う。表・見出し・リストの構造を保持する |
| クリーニング | ヘッダー/フッター、ナビゲーション、定型文、重複を除去する |
| 表データ | Markdown表やJSONに変換して構造を保つ。必要なら表ごとに要約を付与 |
| 画像・図 | OCRやマルチモーダルLLMでキャプション・説明文を生成して検索可能にする |
| メタデータ付与 | タイトル、セクション、作成日、更新日、著者、ソースURL、アクセス権限、文書種別などを付与 |
| 重複排除 | 完全一致・近似重複(MinHash等)を除去し、検索結果の多様性を確保 |
| バージョン管理 | 古い版と新しい版が混在しないよう、最新版のみをインデックスするか、日付でフィルタ可能にする |
💡 Garbage in, garbage out:前処理の品質がRAG全体の上限を決める。
3. チャンキング戦略
主な手法
| 手法 | 概要 | 向いているケース |
|---|---|---|
| 固定長(オーバーラップ付き) | トークン数で分割、10〜20%重複 | ベースライン、均質なテキスト |
| 再帰的分割 | 段落→文→単語の順で区切りを探す | 汎用的に優秀なデフォルト |
| 構造ベース | 見出し・セクション・Markdown構造で分割 | マニュアル、技術文書、規程類 |
| セマンティック分割 | 埋め込みの類似度変化点で分割 | 話題が連続的に変わる長文 |
| 文書単位 | 分割しない | FAQ、短い記事、商品説明 |
ベストプラクティス
- チャンクサイズの目安は200〜800トークン。小さすぎると文脈不足、大きすぎるとノイズが増え埋め込みが曖昧になる。データと評価で決める。
- 意味的なまとまりを壊さない:文の途中、表の途中、コードブロックの途中で切らない。
- コンテキストを補う:
- 各チャンクに「文書タイトル+見出しパス」をプレフィックスとして付与する(例:
就業規則 > 第3章 休暇 > 年次有給休暇)。 - Contextual Retrieval:LLMで「このチャンクは文書全体の中で何について述べているか」の短い説明を生成しチャンク先頭に付加してから埋め込む。検索失敗率を大きく下げられることが報告されている。
- 各チャンクに「文書タイトル+見出しパス」をプレフィックスとして付与する(例:
- Parent-Child(Small-to-Big):小さなチャンクで検索し、ヒットしたら親(より大きなセクション)をLLMに渡す。検索精度と文脈の豊かさを両立。
- 複数の粒度を併用:要約チャンク+詳細チャンクなど、粒度の異なるインデックスを持つのも有効。
4. 埋め込み(Embedding)
- ドメイン・言語に合ったモデルを選ぶ:日本語データなら多言語/日本語対応モデルを選ぶ。MTEB/JMTEB等のベンチマークは参考にしつつ、自社データで評価して決める。
- クエリとドキュメントの非対称性:
query:/passage:のようなプレフィックスや、入力タイプ指定が必要なモデルは仕様に従う。 - 次元数とコストのトレードオフ:Matryoshka表現対応モデルなら次元削減でストレージ・速度を改善できる。
- 同一モデルで統一:インデックス時と検索時で必ず同じモデル・同じ前処理を使う。モデル変更時は全件再埋め込み。
- ファインチューニング:専門用語が多いドメインでは、合成した質問-文書ペアで埋め込みモデルを微調整すると効果的なことがある。
5. インデックスとベクトルDB
- 規模に応じて選ぶ:
- 小規模・PoC:pgvector、Chroma、FAISS、SQLite拡張など
- 大規模・本番:専用ベクトルDB(Qdrant、Weaviate、Milvus、Pinecone等)や検索エンジン(Elasticsearch/OpenSearch)
- 既存インフラを活かす:PostgreSQLを既に使っているならpgvectorは有力な選択肢。
- ANNインデックスの調整:HNSWの
ef/Mなどのパラメータで再現率と速度のバランスを取る。 - メタデータフィルタリング:日付・カテゴリ・権限などで事前フィルタできる設計にする。
- 差分更新:文書のハッシュで変更検知し、変更分だけ再インデックスする。削除の反映も忘れない。
6. 検索(Retrieval)
ハイブリッド検索(強く推奨)
- ベクトル検索(意味的類似)+キーワード検索(BM25) を組み合わせる。
- ベクトル検索:言い換え・概念的な質問に強い
- BM25:固有名詞、型番、エラーコード、略語、社内用語に強い
- 結果の統合には RRF(Reciprocal Rank Fusion) がシンプルで頑健。
クエリ変換
| 手法 | 内容 |
|---|---|
| クエリ書き換え | 会話履歴を踏まえて独立した検索クエリに書き換える(「それは?」→具体的な質問へ) |
| マルチクエリ | 1つの質問から複数の言い換えクエリを生成して検索し、結果を統合 |
| クエリ分解 | 複合的な質問をサブ質問に分解して個別に検索 |
| HyDE | 仮の回答をLLMに生成させ、その埋め込みで検索 |
| ステップバック | より抽象的・上位の質問を生成して背景知識も取得 |
その他
- Top-kは多めに取ってリランキングで絞る(例:検索で50〜100件 → リランクで5〜10件)。
- メタデータフィルタを活用:「2025年の」「人事部の」などの条件はLLMで抽出してフィルタに変換(Self-Query)。
- ルーティング:質問の種類に応じて検索対象のインデックスやツール(SQL、API等)を振り分ける。
7. リランキング
- Cross-encoder型リランカー(Cohere Rerank、bge-reranker、日本語対応リランカー等)で候補を再スコアリングする。費用対効果の高い改善施策の一つ。
- LLMをリランカーとして使う方法もある(精度は高いがコスト・レイテンシ増)。
- スコア閾値を設け、関連性の低いチャンクはコンテキストに入れない。
- 多様性の確保:MMR(Maximal Marginal Relevance)で似たチャンクばかりにならないようにする。
8. プロンプト設計と生成
コンテキストの構築
- チャンクに出典情報を付ける:ID、文書タイトル、URL、日付をタグで明示する。
<documents>
<document id="1" title="就業規則" section="第3章" updated="2026-04-01">
...本文...
</document>
<document id="2" ...>
...
</document>
</documents>- 順序を意識する:関連度の高いものを先頭(または末尾)に。長いコンテキストの中間は見落とされやすい(Lost in the Middle)。
- 詰め込みすぎない:関連性の低いチャンクはノイズになり精度を下げる。量より質。
プロンプトのポイント
- 「提供された文書のみに基づいて回答する」ことを明示する。
- 「文書に答えがない場合は『わからない』と答える」ことを指示する(ハルシネーション抑制)。
- 出典の引用を求める:
[1]のような参照番号や、根拠となる文の引用を出力させる。 - 文書間で矛盾がある場合の扱い(新しい日付を優先する等)を指示する。
- 回答の形式・長さ・言語を明示する。
- 長いコンテキストでは「先に関連箇所を引用させてから回答させる」と精度が上がることがある。
生成後の処理
- 引用の検証:引用された文が実際にコンテキストに存在するかを機械的にチェックする。
- 根拠性チェック:必要に応じてLLM-as-a-judgeで回答が文書に支持されているか検証する。
9. 評価
評価の分解
RAGは検索と生成を分けて評価する。
| 対象 | 指標 | 内容 |
|---|---|---|
| 検索 | Recall@k / Hit Rate | 正解チャンクが上位k件に含まれる割合 |
| 検索 | MRR / nDCG | 正解がどれだけ上位にあるか |
| 検索 | Context Precision | 取得したコンテキストのうち関連するものの割合 |
| 生成 | Faithfulness(忠実性) | 回答がコンテキストに支持されているか(ハルシネーションの有無) |
| 生成 | Answer Relevance | 回答が質問に適切に答えているか |
| 生成 | Answer Correctness | 正解との一致度 |
| 全体 | レイテンシ、コスト、ユーザー満足度 | 運用面の指標 |
ベストプラクティス
- 評価データセットを早期に作る:実際のユーザー質問+正解+正解根拠チャンクのセットを50〜200件程度から始める。
- 合成データの活用:LLMで文書から質問を生成して評価セットを拡充する(ただし実質問とのズレに注意)。
- 難しいケースを含める:答えが存在しない質問、複数文書の統合が必要な質問、表や数値を問う質問、曖昧な質問。
- LLM-as-a-judgeを使う場合は、人手評価との一致度を確認してから信頼する。
- ツール例:Ragas、DeepEval、TruLens、LangSmith、Phoenix など。
- 回帰テスト:プロンプト・モデル・チャンキング変更のたびに評価を自動実行する。
10. 運用・監視
- トレーシング:クエリ、書き換え後クエリ、取得チャンク、スコア、プロンプト、回答、レイテンシをすべてログに残す。
- ユーザーフィードバック:👍/👎や「役に立たなかった理由」を収集し、評価セットに還元する。
- 失敗分析:回答失敗を「検索失敗」「生成失敗」「データ欠如」に分類して対策を打つ。
- データ鮮度:定期的・イベント駆動でインデックスを更新し、最終更新日を監視する。
- コスト・レイテンシ最適化:
- 頻出質問のセマンティックキャッシュ
- プロンプトキャッシュの活用
- 簡単な質問は小さいモデル、難しい質問は大きいモデルにルーティング
- ストリーミング出力で体感速度を改善
11. セキュリティとガバナンス
- アクセス制御:ユーザーの権限に応じて検索対象をフィルタする(ドキュメントレベルACLをメタデータに保持)。生成段階ではなく検索段階で制御する。
- プロンプトインジェクション対策:取得文書内の指示文に従わないようシステムプロンプトで明示し、文書を明確なタグで囲む。外部由来データは特に注意。
- 個人情報・機密情報:インデックス前にPIIのマスキングや除外を検討する。
- データ削除への対応:元データ削除時にインデックスからも確実に削除する仕組みを持つ。
- 監査ログ:誰が何を質問し、どの文書が参照されたかを記録する。
12. 発展的手法
| 手法 | 概要 |
|---|---|
| Agentic RAG | LLMがツールとして検索を呼び出し、必要に応じて複数回検索・再検索を行う。複雑な質問に強い |
| GraphRAG | 文書からエンティティと関係のナレッジグラフを構築し、全体俯瞰的な質問やマルチホップ推論に対応 |
| Corrective RAG (CRAG) | 検索結果の関連性を評価し、不十分ならクエリ修正やWeb検索にフォールバック |
| Self-RAG | 検索の要否判断や回答の自己評価をモデル自身が行う |
| Contextual Retrieval | チャンクに文書全体の文脈説明を付加してから埋め込み・BM25インデックスを作る |
| Late Chunking / ColBERT | トークンレベルの埋め込みを活用し、より細かな類似度計算を行う |
| マルチモーダルRAG | 画像・図表・スライドを画像のまま埋め込んで検索する(ColPali等) |
| 長コンテキスト併用 | 検索で絞った文書をチャンクではなく文書丸ごと渡す |
発展的手法は複雑さとコストを増やす。ベースラインの評価で課題が明確になってから導入する。
13. よくあるアンチパターン
- ❌ 評価セットなしで感覚的にチューニングする
- ❌ ベクトル検索のみで固有名詞・型番の検索に失敗する
- ❌ チャンクに文脈(タイトル・見出し)がなく、「本規定は〜」のような断片が検索できない
- ❌ Top-kを大きくしてとにかく大量のチャンクを詰め込む
- ❌ 出典を表示せず、ユーザーが回答を検証できない
- ❌ 「わからない」と答える逃げ道を用意せず、ハルシネーションを誘発する
- ❌ 権限制御を生成時のプロンプトだけに頼る
- ❌ 古いバージョンの文書がインデックスに残り続ける
- ❌ 最初から複雑なエージェント構成やGraphRAGを導入する
14. チェックリスト
構築時
- RAGが本当に必要か(全文投入で足りないか)検討した
- ドキュメントのパース品質を目視確認した(表・見出しが壊れていない)
- チャンクにタイトル・見出しパスなどの文脈を付与した
- メタデータ(日付、出典、権限)を付与した
- ハイブリッド検索(ベクトル+BM25)を導入した
- リランカーを導入した
- プロンプトで「文書のみに基づく」「不明時はわからないと答える」「出典を示す」を指示した
評価時
- 実際の質問を含む評価データセットを用意した
- 検索と生成を分けて評価している
- 回答不能な質問・複数文書統合が必要な質問を含めた
- 変更のたびに回帰評価を回している
運用時
- 全リクエストのトレースを記録している
- ユーザーフィードバックを収集し改善に活用している
- インデックスの更新・削除が自動化されている
- アクセス制御が検索段階で効いている
- コスト・レイテンシを監視している
まとめ
- シンプルに始め、評価で改善する
- 検索品質が最重要:ハイブリッド検索+リランキング+文脈付きチャンク
- 根拠と出典を明示し、わからないときはわからないと言わせる
- 評価・監視・フィードバックのループを回し続ける
- セキュリティ(権限・インジェクション対策)は設計段階から組み込む