RAG と知識検索

RAG(Retrieval-Augmented Generation、検索拡張生成)は、現在最も主流な LLM 実装アーキテクチャの一つです。

RAG の核となる考え方は:LLM が質問に答える際、まず外部知識ベースから関連内容を検索し、その検索結果に基づいて回答を生成させるのであって、モデルがトレーニング時に記憶した知識だけに依存するのではありません。

これにより、LLM の二つの核心的な課題が解決されます:知識のカットオフ日(モデルはトレーニング後に起きたことを知らない)と幻覚問題(モデルが不確かなときに答えをでっち上げること)です。


RAGの基本原理

完全な RAG システムは、2つのパイプラインで構成されます:オフライン索引パイプライン(ドキュメントを前処理してベクトルデータベースに格納する)とオンライン検索パイプライン(ユーザーの質問を受け取り、検索し、生成する)。

オフライン段階では、元のドキュメントを小さなチャンクに分割し、Embedding モデルでベクトルに変換して、ベクトルデータベースに格納します。

オンライン段階では、ユーザーの質問も同様にベクトルに変換し、データベースから最も類似したドキュメントチャンクを見つけ、コンテキストとして連結して LLM に渡し、回答を生成させます。

次の図は RAG の完全なリクエストフローを示しています:

RAG 基本フローチャート RAG の完全なリクエストフロー:ユーザーの質問は Embedding モデルでクエリベクトルに変換され、ベクトルデータベースで類似ドキュメントチャンクを検索し、質問と検索結果を Prompt として連結し、LLM に入力して最終回答を生成します。 ユーザーの質問 Embedding クエリベクトルに変換 ベクトルデータベース 類似度検索 Top-K Prompt の連結 質問 + ドキュメントチャンク LLM 生成 検索結果に基づいて回答 オフライン索引(一回限りの前処理) 元のドキュメント 分割 / クリーニング Embedding ドキュメントベクトルに変換 書き込み ベクトルデータベース オンライン検索フロー(毎回のリクエストで経由)

データ前処理とドキュメント分割(Chunking)

前段の課題:複雑なドキュメント解析

分割を行う前に、RAG はしばしば直面するのはフォーマット解析という課題です。特に PDF、Word、スキャン文書内の表、画像、多段組みでは、通常のテキスト抽出では意味が大きく乱れやすくなります。

現在、業界の主流な解決策は、ドキュメント解析エンジン(LlamaParse、Unstructured など)またはマルチモーダル大規模モデルを導入し、複雑な画像やテキストを構造化された Markdown に変換して、後続の高品質な分割の基盤を築くことです。

ドキュメント分割戦略

ドキュメント分割は RAG の効果の基盤であり、分割の粒度は検索品質に直接影響します。チャンクが大きすぎるとノイズが入り、小さすぎるとコンテキストが失われます。一般的な戦略は以下の通りです:

分割戦略 適用シーン 長所 短所
固定サイズ分割 一般的なテキスト 実装が簡単、高速 意味的に完全な文を途中で切る可能性がある
再帰的文字分割 構造化テキスト(Markdown、コード) 段落や文などの意味的な境界を優先して分割 実装がやや複雑で、適切な区切り文字リストの設定が必要
セマンティック分割(Semantic) 長文ドキュメント、書籍 Embedding を用いて隣接文の類似度を計算し、意味の転換点を自動的に見つけて分割 計算コストが高く、前処理速度が遅い
親子ドキュメント検索
(Small-to-Big)
あらゆるシーンをカバー 「小さなチャンク」で高精度なベクトル検索を行い、ヒット後に対応する「大きなチャンク」(親ドキュメント)を LLM に返すことで、検索精度とコンテキストの完全性を両立します。 データベースの設計・保守コストが2倍になる

実践では、分割時にオーバーラップ(overlap)を加えることがよくあります。つまり、隣接するチャンク間でいくつかの文字を共有させ、重要な情報が境界で途切れるのを防ぎます。典型的な設定:チャンクサイズ 512 tokens、オーバーラップ 50〜100 tokens。

実例:LangChain を使った再帰的分割

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,        # 各チャンクの最大トークン数
    chunk_overlap=50,      # 隣接チャンクのオーバーラップトークン数。境界で情報が失われるのを防ぐ
    separators=["\n\n", "\n", "。", ".", " ", ""]  # 段落や文を優先して分割
)

chunks = splitter.split_text(document_text)
print(f"{len(chunks)} 個のドキュメントチャンクに分割しました")

ベクトル検索

Embedding モデル

Embedding モデルは、テキストを稠密ベクトル(通常は 768 次元または 1536 次元の浮動小数点数配列)に変換する役割を持ちます。意味的に近いテキストはベクトル空間内で距離が近くなり、これが類似度検索の数学的基盤です。

一般的な Embedding モデルの比較:

モデル 次元 対応言語 特徴
text-embedding-3-small(OpenAI) 1536 多言語 コストパフォーマンスが高く、大規模な索引に適している
text-embedding-3-large(OpenAI) 3072 多言語 精度が最も高く、コストが比較的高い
BAAI/bge-m3 1024 中国語と英語 オープンソース、中国語の性能が優秀、多言語対応
sentence-transformers/all-MiniLM-L6-v2 384 英語 サイズが小さく、高速、ローカルでの超軽量デプロイに適している

類似度計算と ANN アルゴリズム

検索の核心は距離の測定です。最も一般的に使われるのはコサイン類似度(Cosine Similarity)、これは2つのベクトルのなす角のコサイン値を計算し、値域は [-1, 1] で、1 に近いほど類似しています。他にもドット積(Dot Product)やユークリッド距離(L2 Distance)があります。

100万レベルのベクトルでミリ秒単位の検索を実現するため、データベースは通常近似最近傍(ANN)アルゴリズム(例:HNSWHNSW、IVF)。HNSW は現在最も主流なアルゴリズムで、多層スキップグラフネットワークを構築することで、わずかな精度を犠牲にして桁違いの検索速度向上を実現します。


Advanced RAG(高度なアーキテクチャ)

基本アーキテクチャ(Naive RAG)は、検索の不正確さや冗長な情報が多いことによる「コンテキストの埋没」などの問題に直面することがよくあります。Advanced RAG は、検索前最適化 → 検索融合 → 検索後最適化という三段階のアーキテクチャでこれを解決します。

1、検索前処理:クエリ最適化

ユーザーの元の質問は、表現が十分に正確でないことがよくあります:

  • クエリ書き換え(Query Rewriting):LLM を使って口語的な質問を規範化された検索語に書き換えます。
  • HyDE(Hypothetical Document Embedding):LLM にまず「当て推量」で仮の回答を生成させます。生成された回答は通常、元の質問よりも多くの業界用語を含むため、この仮回答のベクトルを使って検索すると、より高品質なドキュメントを再取得できることが多いです。

2、ハイブリッド検索(Hybrid Search)

将ベクトル検索(意味を理解し、エラー耐性が高い)とキーワード検索(BM25、マッチング精度が高い)の結果を重み付けで融合します。これは固有名詞、製品型番、コード断片を扱う際に特に重要です。従来のベクトル検索は特定の固有名詞で「失敗」しやすいからです。

3、検索後最適化:リランキング(Reranking)

これは粗いランキング → 精密なランキングという二段階設計です。ベクトル検索は高速ですが、スコアリングが十分に正確ではありません。リランキング(Reranking)では、Cross-Encoder モデルを導入します。(例:`bge-reranker`)、「質問」と「ドキュメント」をペアでモデルに入力し、共同推論でスコアリングを行います。計算量が大きいため、Top-20 から Top-5 への精選のみを担当します。

実例:リランキング処理の擬似コード

from sentence_transformers import CrossEncoder

reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")

# 1. 粗選別:ベクトル検索で超高速に Top-50 をリコール
candidates = vector_store.similarity_search(query, k=50)

# 2. 精選:「問題、ドキュメント」のペアを構築して正確にスコアリング
pairs = [[query, doc.page_content] for doc in candidates]
scores = reranker.predict(pairs)

# 3. 最終的に LLM に渡す Top-5 をフィルタリング
ranked_docs = sorted(zip(scores, candidates), reverse=True)
final_docs = [doc for _, doc in ranked_docs[:5]]

4、Self-RAG と CRAG(修正型 RAG)

自己反省メカニズムを追加します。例えば CRAG(Corrective RAG)は、検索結果を取得した後、まず LLM が「審査員」としてスコアリングします。ローカル知識ベースに対象の文書が存在しない、または品質が極めて低い場合、システムは自動的に Web Search(Google API など)をトリガーして補完し、幻覚(ハルシネーション)を大幅に低減します。


GraphRAG:知識グラフ + 検索融合

従来の RAG は知識ベースを独立したテキスト断片として扱うため、「現 CEO が創業し、かつ時価総額が千億を超える企業をすべて見つける」のような、ドキュメント横断・多段階推論(マルチホップ推論)を必要とする複雑な問題には答えられません。GraphRAG知識グラフ(Knowledge Graph)を導入し、エンティティと関係を明示的にモデル化します。

GraphRAG アーキテクチャ概略図 GraphRAG はベクトル検索と知識グラフを融合します。ユーザーの質問はベクトル検索とグラフ検索を同時にトリガーし、2 つの経路の結果を融合して LLM に入力し、回答を生成します。 ユーザーの質問 ベクトル検索 関連ドキュメントブロック グラフ検索 エンティティ関係サブグラフ コンテキスト融合 ドキュメントブロック + グラフパス エンティティ A → 関係 → エンティティ B エンティティ B → 関係 → エンティティ C

GraphRAG の中核ステップ

  1. 知識構築:オフライン段階で LLM を使用してドキュメントからトリプル(主語、述語、目的語)を抽出し、Neo4j などのグラフデータベースに書き込みます。
  2. 二経路検索:質問内のエンティティに対して、従来のベクトル検索を行うだけでなく、グラフ内でグラフトラバーサル(Graph Traversal)をトリガーし、多段階の関係チェーンを抽出します。
  3. テキストとグラフの融合生成:ベクトル検索で取得した「断片」とグラフ検索で取得した「パス構造」を Prompt に組み込むことで、LLM がグローバルな視点と具体的な詳細の両方を備えるようにします。

GraphRAG 参考コンテンツ:https://www.example.com/ai-agent/graphrag-usage.html


技術とデータベース選定の推奨

データベース/ツールの選定 タイプ 推奨される導入シナリオ
Pinecone / Zilliz Cloud フルマネージドクラウドサービス すぐに使え、インフラを維持管理する必要がありません。Cohere Rerank + GPT-4o と組み合わせるのが最速で商用化できる方法です。
Qdrant オープンソース + マネージド Rust で記述されており、メモリ管理に優れ、性能が極めて高い。エンタープライズ向けのプライベートデプロイに適しています。
Weaviate / Elasticsearch オープンソース + マネージド 非常に成熟した BM25 + ベクトルハイブリッド検索(Hybrid Search)を内蔵しており、固有名詞が多いシナリオで最優先の選択肢です。
Milvus オープンソース分散型 10億〜100億レベルの超大規模エンタープライズ検索プラットフォームに適しています。
Chroma / FAISS ローカルライブラリ/組み込み型 非常に軽量で、独立したサービスのデプロイが不要。ローカル開発や個人知識ベースプロジェクトの検証に非常に適しています。

RAG 評価指標(RAGAS フレームワーク)

RAG システムの評価は直感だけに頼ることはできず、主流ではRAGASフレームワークを使用し、「検索」と「生成」の 2 つの側面から自動化された定量的テストを行います:

  • Context Recall(検索リコール率):正解中の情報がどの程度の割合で検索できるか。
  • Context Precision(検索適合率):検索されたドキュメントのうち、どの程度の割合が実際に関連しているか。
  • Faithfulness(忠実度/幻覚指標):生成された回答が、検索されたドキュメントによってすべて裏付けられているか。
  • Answer Relevance(回答関連性):生成された回答がユーザーの質問に本当に答えているか。的外れな回答を避ける。
その他の拡張