初めに
RAG(Retrieval-A環境のRAGは次のような複数の工程で構成されています。
文書解析
↓
チャンク分割
↓
Embedding・インデックス作成
↓
Query理解・Query改写
↓
検索・Rerank
↓
コンテキスト構築
↓
回答生成
↓
評価・フィードバック
この中のどこか一つで情報を失うと、後段のモデルを強化しても精度は上がりません。
たとえば、PDF解析時に表や画像内の数値を落とした場合、その情報はEmbeddingにも入らず、検索もできず、最終回答の根拠にもなりません。
逆に、必要な文書を正しく検索できても、生成モデルが検索結果を無視すれば幻覚が発生します。
本記事では、RAGの最適化を次の観点から整理します。
- 文書解析とデータ入庫
- チャンク設計
- Embeddingとベクトルデータベース
- Query改写
- 混合検索とRerank
- GraphRAGとAgentic Search
- Long Contextとの組み合わせ
- 評価指標と継続改善
- Agentを含む本番運用設計
先に結論
RAGの精度改善で優先すべきなのは、単一の高度な手法を導入することではありません。
重要なのは、次の閉ループを構築することです。
構造を壊さず文書を解析する
↓
検索に適した粒度でチャンクを作る
↓
Queryの意図を補完する
↓
複数方式で候補を検索する
↓
Rerankで候補を絞る
↓
根拠付きで回答する
↓
検索層と生成層を分けて評価する
↓
Bad Caseを入庫・検索・生成へ戻す
特に効果が大きいのは、次の組み合わせです。
- 動的な意味チャンクと10~20%のOverlap
- Small-to-Bigの親子チャンク
- Query改写とQuery driftの検証
- ベクトル検索とBM25の混合検索
- Rerankによる再順位付け
- メタデータによる検索前フィルタリング
- Context RecallとFaithfulnessの分離評価
- Bad Caseを利用したフィードバックループ
GraphRAG、Agentic Search、Long Contextは、これらの基本設計を置き換えるものではありません。
質問やデータの性質に応じて使い分ける追加ルートです。
1. RAGの精度は文書解析から決まる
複雑なPDFを単純にテキスト化してはいけない
本番環境では、PDFを単純にテキストへ変換し、一定文字数で分割してベクトルデータベースへ登録するだけでは不十分です。
PDFにはさまざまな形式があります。
- テキスト層を持つPDF
- スキャンされたPDF
- 複雑な段組みを持つ文書
- 表が中心の文書
- 画像や図が中心の文書
- 複数ページにまたがる内容を持つ文書
最初にPDFの種類を判定し、それぞれに適した解析方法を選ぶ必要があります。
ネイティブテキストを持つPDF
テキスト層が存在する場合は、直接テキストを抽出します。
ただし、文字列だけを取得するのではなく、次の構造も保持します。
- ページ番号
- 章
- 見出し階層
- 段落
- 箇条書き
- 表
- 画像説明
- ヘッダー
- フッター
スキャンPDFや複雑なレイアウト
スキャン文書や複雑なレイアウトでは、マルチモーダルモデルによる認識を利用します。
ページ単位でEmbeddingを作成すれば、テキスト検索だけでなく、画像検索やページをまたぐ検索にも対応しやすくなります。
重要なのは、すべてを無理にプレーンテキストへ変換しないことです。
表、画像、本文は、それぞれ異なる形式で処理します。
文書の構造を復元する
RAGでは、文章そのものだけでなく、その文章が文書内のどこに存在するかが重要です。
たとえば、次の二つのChunkを考えます。
申請後、3営業日以内に承認されます。
第4章 経費申請
第4.2節 国内出張費
申請後、3営業日以内に承認されます。
同じ本文でも、後者の方がモデルは意味を判断しやすくなります。
各Chunkには、本文に加えて次のような情報を持たせます。
文書名
章
節
ページ番号
文書バージョン
作成部署
発行日時
機密レベル
前後の文脈
特に「このChunkが文書全体のどこに位置しているか」を示す短い説明を付けると、生成時の解釈が安定します。
表と画像を本文とは別に処理する
表を通常の文章と同じ方法で分割すると、行と列の関係が壊れる可能性があります。
そのため、表は独立した構造データとして扱います。
画像についても、画像そのものだけでなく、画像の要約や説明を保持します。
本文 → 意味単位でチャンク化
表 → 構造化して保存
画像 → 画像+要約を保存
ページ → ページ番号と原文位置を保存
この構造を維持することで、回答時に根拠となるページや表を提示できます。
PDFをAgent用のツールとして公開する
複雑なPDFを一度にモデルへ渡すのではなく、複数のツールとして公開する方法も有効です。
たとえば、次のツールを用意します。
search_document(query)
read_page(page_number)
extract_table(page_number)
inspect_image(page_number)
Agentは質問に応じて検索し、必要なページだけを読み、必要であれば表や画像を追加確認します。
この方法では、モデルが自分で読解経路を計画できます。
質問を理解する
↓
文書を検索する
↓
候補ページを読む
↓
表または画像を確認する
↓
根拠を付けて回答する
PDF回答における幻覚防止
複雑なPDFを扱う場合は、最低限、次の三つを徹底します。
- 回答にページ番号または原文Chunkを付ける
- 引用内容を検索結果の範囲内に限定する
- 回答品質だけでなく、検索命中率と数値の正確性も評価する
回答が自然であっても、引用元のページが間違っていれば、RAGとしては正しい回答ではありません。
2. チャンク設計を最適化する
固定Token分割の問題
固定Token数で機械的に分割すると、文章の途中でChunkが切れる可能性があります。
Chunk 1:
このサービスを利用する場合、管理者は申請を
Chunk 2:
承認しなければなりません。
この状態では、それぞれのChunkだけを取得したときに意味が欠落します。
そのため、文や段落の境界を認識した動的な意味分割を利用します。
動的な意味分割
NLPを利用して、次の境界を考慮します。
- 文の終わり
- 段落
- 見出し
- 箇条書き
- 章や節
- 表や画像の境界
Chunkのサイズを完全に均一にすることよりも、意味を壊さないことを優先します。
Overlapを設定する
Chunk間には10~20%、または100~200 Token程度のOverlapを持たせます。
Chunk A:
認証に3回失敗すると、アカウントはロックされます。
ロック解除には管理者の承認が必要です。
Chunk B:
ロック解除には管理者の承認が必要です。
承認後、利用者はパスワードを再設定します。
Overlapによって、Chunk境界付近の情報が失われにくくなります。
ただし、Overlapを大きくしすぎると重複した検索結果が増えるため、検索ノイズとのバランスが必要です。
Small-to-Bigの親子チャンク
検索精度と回答に必要な文脈量は、同じではありません。
小さいChunkは検索しやすい一方で、生成時に必要な情報が不足しやすくなります。
大きいChunkは文脈を保持できますが、複数の話題を含むためEmbeddingが曖昧になります。
この問題を解決するのが親子チャンクです。
親Chunk
├── 子Chunk 1
├── 子Chunk 2
├── 子Chunk 3
└── 子Chunk 4
ベクトルデータベースには、焦点が明確な子Chunkを検索対象として登録します。
検索で子Chunkがヒットした後、生成モデルには対応する親Chunkを返します。
検索:
小さい子Chunkで高精度に検索
生成:
子Chunkに対応する大きい親Chunkを使用
これにより、「検索は細かく、回答は広く」という構成を実現できます。
3. Embeddingとベクトルデータベースを設計する
Embeddingの役割
Embeddingは、人間の言葉を機械が比較できる高次元の意味座標へ変換する処理です。
意味が近い文章は、ベクトル空間上でも近くなります。
たとえば、次の二つは単語が一致していなくても、意味的には関連しています。
キャッシュが存在しないリクエストが大量に届く
データベースへのアクセス負荷が急増する
従来のキーワード検索では一致しにくい関係も、Embeddingによって検索できる可能性があります。
類似度の計算方法
質問とChunkをEmbeddingへ変換し、次のような距離指標で比較します。
- コサイン類似度
- 内積
- ユークリッド距離
基本的な処理は次のとおりです。
質問
↓ Embedding
Query Vector
文書Chunk
↓ Embedding
Document Vector
Query VectorとDocument Vectorを比較
↓
近いChunkを検索
Embeddingモデルの選び方
Embeddingモデルは、用途に合わせて選択します。
- 一般文書向け
- 特定業界向け
- 多言語向け
- コード向け
モデルの性能だけでなく、実際のデータや質問との相性が重要です。
垂直領域の文書を扱う場合は、その領域向けに調整されたモデルを利用します。
メタデータによる事前フィルタリング
Embedding検索の前に、メタデータで対象を絞ると精度を上げられます。
たとえば、次の条件を検索前に適用します。
部署 = 人事部
文書バージョン = 最新
公開範囲 = 社内
発行日時 >= 指定日
機密レベル <= 利用者の権限
これにより、意味的には近いものの、古い文書や権限外の文書が検索されることを防げます。
HNSWとバッチ登録
数千万件規模のベクトルを総当たりで検索することは現実的ではありません。
大規模データでは、HNSWなどのグラフベースのインデックスを利用します。
また、データ登録時には1件ずつ処理するのではなく、バッチ挿入と並列処理を利用してスループットを高めます。
データ清洗
↓
チャンク分割
↓
Embeddingを並列生成
↓
バッチ挿入
↓
HNSWインデックス構築
MilvusやPineconeなど、ハイブリッド検索に対応するベクトルデータベースを利用し、ベクトルだけでなく次の情報も保存します。
- 原文
- 親Chunk ID
- メタデータ
- 文書バージョン
- ページ番号
- 更新日時
継続更新と知識競合の管理
企業文書は継続的に更新されます。
一度登録して終わりではなく、増分同期を設計します。
また、古い規程と新しい規程が同時に検索されると、回答が不安定になります。
入庫時に次の処理が必要です。
- 新規文書の追加
- 更新文書の差し替え
- 古い文書の無効化
- 重複文書の削除
- 競合する知識の整理
検索命中率が低下した場合は、Embeddingモデルだけでなく、データ更新やメタデータの状態も確認します。
4. Query改写でユーザーと文書の言葉をつなぐ
Query改写が必要な理由
ユーザーの質問と業務文書では、表現が異なることがあります。
ユーザー:
PCをなくした。どうすればいい?
文書:
情報端末紛失時のインシデント報告手順
質問をそのまま検索すると、必要な文書に到達できない可能性があります。
Query改写には、主に三つの目的があります。
- 口語と専門用語のギャップを埋める
- 省略された背景情報を補う
- 多輪対話の代名詞や指示対象を解決する
5種類のQuery最適化
1. Query Rewrite
口語的な質問を、検索しやすい書面表現へ変換します。
元の質問:
アカウント入れない
改写後:
アカウントにログインできない場合の復旧手順
2. Multi-Query Generation
同じ質問から複数の検索表現を生成します。
ログインできない
認証に失敗する
アカウントアクセスを復旧したい
パスワード認証エラー
一つの表現だけでは取得できない文書を、複数ルートから検索します。
3. Sub-Query Decomposition
複雑な質問を、複数の小さな質問へ分解します。
元の質問:
海外出張の申請方法と利用可能な交通費、承認者を教えてください。
分解後:
1. 海外出張の申請方法は何か
2. 利用可能な交通費は何か
3. 誰が承認するのか
各質問を個別に検索した後、結果を統合します。
4. HyDE
質問に対する仮想的な回答文書を生成し、その文書のEmbeddingを使って実際の文書を検索します。
短く曖昧な質問では、質問そのものよりも、仮想回答の方が実際の文書に近い表現を含む可能性があります。
短い質問
↓
仮想的な回答文書を生成
↓
仮想文書をEmbedding
↓
実文書を検索
5. Step-back Prompting
具体的な質問から一度後退し、より上位の概念や背景を検索します。
具体的な質問:
この申請が却下された理由は何ですか
Step-back:
この申請に適用される承認条件と却下条件は何ですか
個別事象だけでなく、その事象を判断するためのルールを取得します。
Query driftを防ぐ
Query改写には、検索意図を変えてしまう危険があります。
元の質問:
退職した社員のアカウントはいつ停止されますか
誤った改写:
社員アカウントを停止する方法
元の質問は「停止時期」を聞いていますが、改写後は「操作方法」へ変わっています。
これを防ぐため、改写前後のQueryについてコサイン類似度を計算します。
similarity(original_query, rewritten_query)
たとえば、類似度の閾値を0.8に設定します。
類似度 >= 0.8:
改写Queryを利用
類似度 < 0.8:
改写を破棄し、元のQueryへ戻す
Query改写の三つの課題
レイテンシ
Query改写のために大きなモデルを毎回呼び出すと、回答時間が増加します。
対策として、専用に調整した小型モデルや並列パイプラインを利用します。
コスト
すべての質問で改写する必要はありません。
意図ルーターを配置し、単純な質問はそのまま検索し、複雑または曖昧な質問だけを改写します。
意図の変化
類似度検証を行い、改写によって意図が変わった場合は元のQueryへフォールバックします。
5. ベクトル検索だけに依存しない
ベクトル検索の弱点
ベクトル検索は意味的な類似に強い一方、完全一致が重要な検索では弱くなることがあります。
たとえば、次のような情報です。
- 製品番号
- エラーコード
- 人名
- API名
- バージョン
- 固有の社内用語
また、「有効化」と「無効化」、「登録」と「削除」のように、同じ話題に属する反対の操作を混同する可能性もあります。
BM25との混合検索
ベクトル検索とBM25を組み合わせます。
Query
├── ベクトル検索
└── BM25キーワード検索
↓
候補を統合
↓
Rerank
役割は次のように分かれます。
ベクトル検索:
意味が近い文書を見つける
BM25:
同じ単語や固有名詞を含む文書を見つける
これにより、意味検索と完全一致検索の両方を利用できます。
スコアをそのまま比較しない
ベクトル検索とBM25では、スコアの意味や範囲が異なります。
そのまま加算すると、一方の検索方式が過度に優先される可能性があります。
そこで、Rerankerモデルを利用し、検索方式に依存しない共通の関連度で候補を再評価します。
Rerankは「海選の後の精選」
最初の検索では候補を広めに取得します。
その後、Rerankで質問との関連度を再計算し、上位だけを生成モデルへ渡します。
Hybrid Retrieval:
広く候補を集める
Rerank:
質問に直接答える候補を選ぶ
Generation:
選ばれた根拠から回答を作る
Rerankによって、検索結果に含まれるノイズを削減できます。
高並行時のルーティング
Rerankは精度向上に有効ですが、追加の計算コストとレイテンシが発生します。
そのため、すべての質問に同じ検索経路を適用する必要はありません。
単純な質問:
ベクトル検索のみ
固有名詞を含む質問:
混合検索
曖昧または複雑な質問:
Query改写+混合検索+Rerank
ルーターによって検索経路を切り替えることで、精度と応答速度を両立します。
6. GraphRAGと通常のRAGを使い分ける
通常のRAGが得意なこと
通常のRAGは、一つの質問と一つまたは少数の文書を対応させる検索に向いています。
この制度の申請期限はいつですか
この製品の保証期間は何年ですか
単純な事実検索では、通常のRAGやESで十分です。
多段推論で起きる問題
複数の条件をまたぐ質問では、通常のRAGは何度も検索を繰り返すことがあります。
たとえば、次のような質問です。
バッテリー持続時間が長く、利用者の評価も高いスマートフォンはどれですか
この質問に答えるには、少なくとも次の情報が必要です。
- スマートフォンの一覧
- 各製品のバッテリー持続時間
- 各製品の利用者評価
- 条件を満たす製品の絞り込み
通常のRAGで補召回を繰り返すと、ノイズとToken消費が増加します。
GraphRAGの特徴
GraphRAGでは、インデックス作成時に文書からエンティティと関係を抽出し、知識グラフを構築します。
製品
├── バッテリー持続時間
├── 評価
├── メーカー
└── 関連モデル
一つのエンティティを起点として、複数の属性や関連情報を取得できます。
そのため、次のような用途に向いています。
- 複数文書をまたぐ質問
- 多段推論
- エンティティ間の関係探索
- 暗黙的な関係の発見
GraphRAGのコスト
GraphRAGは、インデックス作成前にエンティティと関係を抽出する必要があります。
そのため、通常のRAGより前処理コストが高くなります。
すべての質問をGraphRAGへ送るのではなく、Query Routerで使い分けます。
単純な事実検索
→ ESまたは通常のRAG
意味的な文書検索
→ ベクトル検索+BM25
多段推論・関係探索
→ GraphRAG
7. コードやログではAgentic Searchを検討する
コードにEmbeddingが使えないわけではない
Embeddingはコードの意味も表現できます。
しかし、コード検索では従来型RAGに三つの問題があります。
不可診断性
検索結果が悪い場合、原因が次のどこにあるのか判断しにくくなります。
- インデックスが古い
- チャンク設計が悪い
- Embeddingが合っていない
- 検索条件が悪い
- 生成モデルが誤解した
誤差の乗算
RAGは複数の工程から構成されています。
解析精度
× チャンク精度
× 検索精度
× Rerank精度
× 生成精度
各工程の小さな誤差が積み重なると、最終精度が大きく低下します。
インデックスの鮮度
コードは頻繁に更新されます。
変更のたびにインデックスが古くなるため、最新状態との不一致が発生しやすくなります。
Agentic Search
Agentic Searchでは、モデルがリアルタイムに検索ツールを操作します。
たとえば、コード検索ではgrepを直接利用します。
質問を理解
↓
検索語を決定
↓
grepで最新コードを検索
↓
対象ファイルを読む
↓
追加検索
↓
回答
モデルが検索経路を制御するため、隠れた検索パイプラインを減らせます。
使い分けは次のとおりです。
コード・ログ・完全一致が重要な情報
→ Agentic Search
概念・制度・意味的に関連する文書
→ RAG
重要なのは、「検索結果がモデルを駆動する」のではなく、「モデルが検索を駆動する」ことです。
8. Long ContextとRAGは競合しない
Long Contextだけでは解決できない
長いContext Windowを持つモデルへ大量の文書をそのまま渡す方法には、次の問題があります。
- Tokenコストが高い
- 最初の回答が出るまでの時間が長い
- 不要な情報が多くなる
- Lost in the middleが発生する
モデルが長い文章を入力できることと、その中から必要な情報を安定して利用できることは同じではありません。
RAG + Long Contextの漏斗構造
RAGとLong Contextは、次のように組み合わせます。
大量の文書
↓
RAGで粗く検索
↓
ノイズを削除
↓
関連性の高い文書群
↓
Long Contextで精読
↓
回答
役割は明確に分かれます。
RAGは広さを担当する
大量の文書から、低コストかつ低レイテンシで候補を絞ります。
コンテキスト構築は密度を担当する
重複や無関係な情報を除き、回答に必要な根拠だけを残します。
Long Contextは深さを担当する
絞り込まれた文書をまとめて読み、複数箇所の関係や前後の文脈を分析します。
Long ContextはRAGを置き換えるのではなく、RAGが取得した範囲を深く読むために利用します。
9. RAGを評価する
最初に基準データセットを作る
RAGを改善するには、比較可能な評価データが必要です。
評価データは次の二つから作成します。
- 実際の利用ログから抽出した質問
- 文書からLLMで逆生成し、人間が確認した質問
各サンプルには、最低限、次の情報を持たせます。
ユーザー質問
標準回答
期待される文書
期待されるChunk
標準回答だけでは、検索が正しく動いたか評価できません。
期待されるChunkも定義することで、検索層と生成層を分けて評価できます。
検索層の評価
Context Precision
検索されたChunkのうち、回答に必要なものがどれだけ含まれているかを評価します。
低い場合、検索結果にノイズが多いことを意味します。
Context Recall
回答に必要な情報のうち、どれだけ検索できたかを評価します。
低い場合は、次の部分を見直します。
- チャンク分割
- Embedding
- Query改写
- 検索件数
- メタデータフィルター
- Hybrid Retrieval
Hit Rate
期待していた文書またはChunkが、検索結果に含まれているかを評価します。
Recall@K
上位K件の検索結果に正解Chunkが含まれている割合です。
たとえば、Recall@5では、上位5件以内に期待Chunkが存在するかを確認します。
MRR
最初の正解Chunkが、検索順位のどこに現れたかを評価します。
正解Chunkが上位にあるほど高くなります。
生成層の評価
Faithfulness
回答が検索された文書に基づいているかを評価します。
検索結果に存在しない情報をモデルが追加している場合、Faithfulnessが低くなります。
Answer Relevance
最終回答が、ユーザーの質問へ直接答えているかを評価します。
根拠が正しくても、質問に答えていなければ良い回答とは言えません。
指標から原因を特定する
評価値を一つの総合スコアだけで見ると、改善箇所が分かりません。
Context Recallが低い
→ 検索前の問題
→ Query、Chunk、Embedding、検索方式を確認
Context Precisionが低い
→ 検索ノイズが多い
→ フィルターやRerankを確認
Recallは高いがFaithfulnessが低い
→ 必要な情報は取得できている
→ 生成モデルまたはPromptを確認
Faithfulnessは高いがAnswer Relevanceが低い
→ 根拠は使っている
→ 質問に対する回答構成を確認
このように、検索と生成を分離して診断します。
Ragasを利用した評価
Ragasを利用する場合、主に次の三つを確認します。
- Context Relevance
- Faithfulness
- Answer Relevance
日常的な回帰テストでは、ローカルに配置した小型モデルを評価役として利用し、コストを抑えます。
リリース前には、一部のサンプルをGPT-4o級のモデルでも評価し、小型モデルとの一致度を確認します。
CI/CDへ組み込む
評価スクリプトは手動実行だけでなく、CI/CDへ組み込みます。
コード変更
↓
評価データセットを実行
↓
検索・生成指標を計算
↓
基準値と比較
↓
許容範囲内:
マージ可能
許容範囲を超えて低下:
マージを停止
完全一致のスコアを要求するのではなく、許容範囲を設定します。
スコアが一定以上低下した場合だけ、コードのマージを止めます。
最終的には業務指標を見る
オフライン評価だけでは、実際の利用価値を完全には判断できません。
本番環境では、次の指標も確認します。
- ユーザー満足度
- 問題解決率
- Bad Case率
- 転人工率
- ユーザーからの高評価・低評価
技術指標と業務指標の両方を追跡します。
10. RAG精度を60%から85%へ上げる改善順序
RAGの精度が低い場合、すべてを同時に変更すると原因を追跡できません。
次の順序で改善します。
Step 1:評価データを固定する
まず、ユーザー質問、標準回答、期待Chunkを含む基準データセットを作ります。
評価条件を固定しなければ、改善前後を比較できません。
Step 2:文書解析を見直す
PDF、表、画像、見出し、ページ番号が正しく取得できているか確認します。
解析段階で情報が欠けている場合、検索手法を改善しても取得できません。
Step 3:固定分割を動的分割へ変更する
文や段落の境界を認識し、意味単位でChunkを作ります。
Chunk間には10~20%、または100~200 Token程度のOverlapを設定します。
Step 4:親子チャンクを導入する
検索には小さい子Chunkを使い、生成には対応する親Chunkを返します。
検索精度と文脈量を両立します。
Step 5:メタデータフィルターを追加する
部署、日時、バージョン、機密レベルなどで検索対象を事前に絞ります。
特に、古い文書と新しい文書が混在する環境では重要です。
Step 6:Query改写を追加する
短い質問、口語表現、代名詞を含む質問を検索向けに補完します。
ただし、元Queryとの類似度を確認し、閾値を下回った場合は元のQueryへ戻します。
Step 7:Hybrid Retrievalを導入する
ベクトル検索とBM25を組み合わせます。
意味検索だけでは取得しにくい固有名詞やエラーコードを、キーワード検索で補完します。
Step 8:Rerankを導入する
複数の検索経路から取得した候補を、統一された関連度で再評価します。
上位候補だけを生成モデルへ渡し、ノイズを削減します。
Step 9:検索と生成を分けて評価する
Context Recallが低い場合は検索を改善します。
Faithfulnessが低い場合は生成とPromptを改善します。
原因に対応した層だけを変更します。
Step 10:Bad Caseを継続的に戻す
ユーザー評価やAI巡回検査からBad Caseを収集します。
分流Agentで原因別に分類します。
解析失敗
チャンク失敗
Query理解失敗
検索漏れ
検索ノイズ
Rerank失敗
生成時の幻覚
知識の期限切れ
分類したBad Caseを評価データセットへ追加し、継続的に再発を確認します。
11. 企業向けRAGの全体構成
企業向けRAGは、次のような構成になります。
[データソース]
PDF / 表 / 画像 / 文書
↓
[解析]
OCR / マルチモーダル解析 / 構造復元
↓
[清洗]
ノイズ除去 / 重複削除 / 期限切れ知識の整理
↓
[チャンク]
意味分割 / Overlap / 親子チャンク
↓
[インデックス]
Embedding / BM25 / HNSW / メタデータ
↓
[Query処理]
補完 / 指示語解決 / Rewrite / Multi-Query / HyDE
↓
[Router]
通常RAG / GraphRAG / Agentic Search
↓
[検索]
ベクトル検索 + BM25
↓
[Rerank]
関連度再評価 / 業務上の重み付け
↓
[Context構築]
重複除去 / 親Chunk取得 / 引用情報付与
↓
[生成]
根拠に基づく回答
↓
[評価]
Recall / Precision / Faithfulness / Relevance
↓
[Feedback]
Bad Case収集 / 原因分類 / 改善
業務要件に応じて、特定の情報源を優先する重み付けも追加します。
たとえば、最新の正式文書や高優先度の情報源を上位へ配置します。
12. RAGとAgentを組み合わせる場合の運用設計
RAGをAgentから利用する場合は、検索精度だけでなく、ツール実行、状態管理、障害回復も設計する必要があります。
ツールのSchemaを明確にする
Agentへ提供するツールには、明確なSchemaを定義します。
- パラメータ型
- 必須項目
- 許容値
- 戻り値
- エラー形式
入力値を厳格に検証し、データ注入を防ぎます。
ツール実行はサンドボックス内で行い、実行環境への破壊的操作を防止します。
ツール呼び出し方式
Agentのツール実行には、複数の方式があります。
直接呼び出し
単純な質問に対し、必要なツールを一回呼び出します。
ReAct
推論とツール実行を交互に行います。
考える
↓
ツールを呼ぶ
↓
結果を確認
↓
再度考える
DAG
複雑なタスクを依存関係のある処理へ分解します。
並列実行可能な処理と、前段の結果を待つ処理を分離します。
イベントバス
高並行環境では、ツール実行をイベントバス経由で非同期化します。
失敗したメッセージはデッドレターキューへ送り、再処理や原因調査を可能にします。
MCPによるツール接続
MCPは、さまざまなツールを接続するための共通仕様を提供します。
リクエストとレスポンスをJSON Schemaで記述することで、ツールを交換可能な形で接続できます。
これにより、Agent側がツールごとの独自接続方式を持つ必要を減らせます。
Contextが大きくなった場合
会話履歴や検索結果をすべてContextへ入れ続けると、Tokenを消費します。
次の方法を組み合わせます。
- Sliding Window
- 古い会話の要約
- 過去履歴のEmbedding検索
直近の重要な会話はそのまま保持し、古い履歴は要約または検索可能な形で保存します。
短期記憶と長期記憶を分ける
短期記憶や作業記憶は、メモリまたはRedisへ保存します。
長期記憶はベクトルデータベースへ保存します。
短期・作業記憶:
現在のタスク状態
直近の会話
中間結果
長期記憶:
過去の重要な情報
継続的に参照する知識
過去のユーザー履歴
保存量が増え続けないように、LRUまたは重要度スコアで削除・更新します。
Multi-Agentの状態管理
複数Agentが協調する場合、状態を各Agentのローカルメモリだけに置くと、途中で失われる可能性があります。
グローバル状態をRedisやETCDへ保存し、Checkpointを作成します。
障害発生時には、最後のCheckpointから処理を再開します。
また、メッセージにTrace IDを付与し、どのAgentがどのツールを呼び、どの結果を受け取ったか追跡できるようにします。
まとめ
RAGの精度は、Embeddingモデルやプロンプトだけでは決まりません。
重要なのは、入庫から評価までを一つのシステムとして設計することです。
- PDFは種類を判定し、テキスト、表、画像を分けて処理する
- ページ番号、章、節、バージョンなどの構造とメタデータを保持する
- 固定Token分割ではなく、意味単位の動的チャンクを利用する
- Chunk間に10~20%程度のOverlapを持たせる
- Small-to-Bigの親子チャンクで、検索精度と文脈量を両立する
- Embeddingモデルは言語と業務領域に合わせて選択する
- ベクトル検索とBM25を組み合わせ、Rerankで候補を絞る
- Query改写にはRewrite、Multi-Query、Sub-Query、HyDE、Step-backを使い分ける
- Query driftを類似度で検出し、問題があれば元Queryへ戻す
- 単純検索は通常RAG、多段推論はGraphRAG、コードやログはAgentic Searchへ分岐する
- RAGで範囲を絞り、Long Contextで深く読む
- Context RecallとFaithfulnessを分けて評価する
- 評価をCI/CDへ組み込み、精度低下を検出する
- ユーザー評価とBad Caseを改善ループへ戻す
RAGを本番で安定させるために必要なのは、単発の最適化ではありません。
正しく取り込む
↓
正しく検索する
↓
正しく根拠を渡す
↓
正しく回答する
↓
正しく評価する
↓
失敗を次の改善へ戻す
この閉ループを継続的に回すことが、RAGの精度を60%から85%へ引き上げるための中心になります。