論文概要(Abstract)
ARAGOG(Advanced RAG Output Grading)は、RAGパイプラインの構成要素を体系的に比較する評価フレームワークです。Sentence Window Retrieval(SWR)、Auto-Merging Retrieval(AMR)、Document Summary Index(DSI)、Hypothetical Document Embedding(HyDE)、Contextual Chunk Headers(CCH)の5つの高度な検索手法を15構成で評価し、Context Precision・Answer Similarity・Answer Relevanceの3軸で比較しています。HyDE + CCHの組み合わせがContext Precisionをベースラインから9.3%改善する結果を得ました。
この記事は Zenn記事: LangGraph Agentic RAGの本番運用設計:マルチソースルーティングと評価駆動リランキング の深掘りです。
情報源
- arXiv ID: 2404.16130
- URL: https://arxiv.org/abs/2404.16130
- 著者: Matej Blagaj, Klemen Kotar et al.
- 発表年: 2024
- 分野: cs.CL, cs.AI
- コード: https://github.com/predlico/ARAGOG(Apache 2.0)
背景と動機(Background & Motivation)
RAGパイプラインには多数の構成要素(チャンキング戦略、埋め込みモデル、検索アルゴリズム、生成モデル)があり、その組み合わせが性能に大きく影響します。しかし、どの組み合わせが最適かを体系的に比較する手段がありませんでした。
Zenn記事では、リランカー選択にRAGASメトリクスを用いたA/B評価パイプラインを紹介しましたが、リランカー以前の検索手法そのものの選択も品質に大きく影響します。ARAGOGは、この「検索手法の選択問題」に対して、RAGAS指標を用いた体系的な比較フレームワークを提供します。
主要な貢献(Key Contributions)
- 5つの高度検索手法の統一条件比較: SWR, AMR, DSI, HyDE, CCHを同一データセット・同一バックボーンLLMで評価
- HyDE + CCHの優位性を実証: Context Precisionが0.657→0.718(+9.3%)、追加学習不要
- RAGAS 3軸評価の実践的適用: Context Precision, Answer Similarity, Answer Relevanceの組み合わせ評価
- 埋め込みモデル・チャンクサイズの最適値を特定: mxbai-embed-large-v1 × 512トークンが最良
- Gradio UIを含むオープンソースフレームワーク: 非専門家でもRAG構成を対話的に比較可能
技術的詳細(Technical Details)
5つの高度検索手法
1. Sentence Window Retrieval(SWR)
固定サイズチャンキングでは文の途中で分割され、文脈が失われます。SWRは文単位で索引を構築し、検索時に周辺文を含むウィンドウを返します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def sentence_window_retrieval(
query: str,
sentence_index: VectorIndex,
window_size: int = 3,
top_k: int = 5
) -> list[str]:
"""文単位で検索し、周辺ウィンドウを返す
Args:
query: 検索クエリ
sentence_index: 文単位の埋め込みインデックス
window_size: 返す周辺文の数(前後合計)
top_k: 検索する文の数
Returns:
ウィンドウを結合したコンテキスト文字列のリスト
"""
matched_sentences = sentence_index.similarity_search(query, k=top_k)
contexts = []
for sent in matched_sentences:
pos = sent.metadata["position"]
all_sents = sent.metadata["document_sentences"]
start = max(0, pos - window_size // 2)
end = min(len(all_sents), pos + window_size // 2 + 1)
window = " ".join(all_sents[start:end])
contexts.append(window)
return contexts
最適ウィンドウサイズ: 3(1では文脈不足、5では無関係な情報が混入)
2. Auto-Merging Retrieval(AMR)
文書の階層構造(セクション→段落→文)を保持する手法です。子ノード(文)で検索し、親ノードの子の50%以上が検索された場合、子を親ノードに統合します。
\[\text{Merge}(P) = \begin{cases} \text{True} & \text{if } \dfrac{|\mathcal{R} \cap \text{children}(P)|}{|\text{children}(P)|} > \theta \\ \text{False} & \text{otherwise} \end{cases}\]ここで、$P$は親ノード、$\mathcal{R}$は検索された子ノードの集合、$\theta = 0.5$(デフォルト閾値)です。
注意: 階層構造が明確な文書(法律文書、マニュアル等)では有効ですが、フラットな構造の文書では逆効果になります。本論文のLlama2テクニカルレポートでは、AMRがベースラインを下回る結果となりました。
3. Document Summary Index(DSI)
2段階検索手法です。まずLLMで生成した文書要約で文書を絞り込み、次にチャンクレベルで検索します。
Stage 1: $D^* = \arg\text{top-}k_{D \in \mathcal{D}} \text{sim}(\text{embed}(q), \text{embed}(\text{summary}(D)))$
Stage 2: $C^* = \arg\text{top-}k_{c \in D^*} \text{sim}(\text{embed}(q), \text{embed}(c))$
トレードオフ: インデキシング時にLLM呼び出しが必要(コスト増加)。検索時コストはNaive RAGと同等。
4. Hypothetical Document Embedding(HyDE)
クエリを直接埋め込む代わりに、LLMで仮想的な回答を生成し、その回答を埋め込みに使用します。
\[\hat{d} = \text{LLM}(\text{"Write a passage answering: "} + q)\] \[e_{\text{query}} = \text{embed}(\hat{d}) \quad \text{(}e_q = \text{embed}(q)\text{ の代わり)}\]直感: 仮想回答は実文書と同じ意味空間に存在するため、クエリ-文書間の分布ギャップを解消します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def hyde_retrieval(
query: str,
llm: ChatModel,
embedding_model: EmbeddingModel,
vector_store: VectorStore,
top_k: int = 5
) -> list[Document]:
"""HyDEによる検索: 仮想回答を生成→埋め込み→検索"""
hypothetical_doc = llm.generate(
f"Write a passage that answers: {query}",
max_tokens=128
)
query_embedding = embedding_model.encode(hypothetical_doc)
return vector_store.similarity_search(query_embedding, k=top_k)
コスト: クエリごとに1回のLLM推論追加(レイテンシ200-500ms増加)
5. Contextual Chunk Headers(CCH)
チャンクに文書メタデータとセクション見出しを付加してから埋め込みを作成します。
1
2
3
4
5
6
7
def add_contextual_header(
chunk_text: str,
doc_title: str,
section_title: str
) -> str:
"""チャンクにコンテキストヘッダーを付加"""
return f"[Document: {doc_title}, Section: {section_title}]\n{chunk_text}"
コスト: インデキシング時のみ。検索時の追加コストはゼロ。
RAGAS評価メトリクス
ARAGOGは3つのRAGAS指標で評価しています。
Context Precision(CP): 検索結果の関連度の精度
\[CP = \frac{1}{K} \sum_{k=1}^{K} P@k \times \text{rel}_k\]- $P@k$: 上位$k$件までの精度
- $\text{rel}_k$: $k$番目のチャンクが関連する場合1、そうでなければ0
Answer Similarity(AS): 生成回答と正解の意味的類似度
\[AS = \cos(\text{embed}(a_{\text{gen}}), \text{embed}(a_{\text{ref}}))\]Answer Relevance(AR): 生成回答が質問に対して的確か(逆生成で評価)
\[AR = \frac{1}{N} \sum_{i=1}^{N} \cos(\text{embed}(q^{(i)}_{\text{gen}}), \text{embed}(q_{\text{orig}}))\]回答から$N=3$個の質問を逆生成し、元の質問との類似度を測定します。
実装のポイント(Implementation)
最適構成の選択指針
以下のフローチャートで構成を選択できます。
1
2
3
4
5
6
7
8
9
10
11
文書に明確な階層構造があるか?
├─ YES → AMR を検討(閾値θ=0.5から調整)
└─ NO → HyDE + CCH を推奨
クエリ-文書の分布ギャップが大きいか?
├─ YES → HyDE を導入(レイテンシ許容時)
└─ NO → CCH のみで十分
文書が大量か?
├─ YES → DSI を導入(要約による2段階検索)
└─ NO → 直接検索で十分
Zenn記事のA/B評価パイプラインとの統合
Zenn記事で紹介したリランカーA/B評価パイプラインに、ARAGOGの検索手法比較を追加できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from ragas import evaluate
from ragas.metrics import context_precision, faithfulness, answer_relevancy
from ragas.dataset_schema import SingleTurnSample
from ragas import EvaluationDataset
def compare_retrieval_configs(
configs: dict[str, callable],
eval_dataset: list[dict],
llm: ChatModel
) -> dict[str, dict]:
"""検索構成をRAGAS指標で比較"""
results = {}
for name, retriever in configs.items():
samples = []
for item in eval_dataset:
docs = retriever(item["query"])
context = "\n".join([d.page_content for d in docs])
response = llm.invoke(f"Context:\n{context}\n\nQ: {item['query']}")
samples.append(SingleTurnSample(
user_input=item["query"],
response=response.content,
retrieved_contexts=[d.page_content for d in docs],
reference=item["ground_truth"],
))
dataset = EvaluationDataset(samples=samples)
result = evaluate(
dataset=dataset,
metrics=[context_precision, faithfulness, answer_relevancy],
)
results[name] = result
return results
よくある落とし穴
- HyDEの幻覚リスク: 仮想回答がまったく的外れな場合、検索精度が悪化する。
temperature=0を設定し、プロンプトで具体性を強制 - CCHのトークン消費: ヘッダーが長すぎると埋め込みの有効容量が減少。ヘッダーは50トークン以内に抑える
- AMRの閾値チューニング: $\theta$が低すぎると不要な統合が発生。データセットに応じて0.3-0.7の範囲で調整
実験結果(Results)
主要結果
| システム | Context Precision | Answer Similarity | Answer Relevance |
|---|---|---|---|
| Naive RAG(ベースライン) | 0.657 | 0.886 | 0.919 |
| + SWR(window=3) | 0.662 (+0.8%) | 0.887 | 0.921 |
| + AMR | 0.649 (-1.2%) | 0.884 | 0.917 |
| + DSI | 0.671 (+2.1%) | 0.888 | 0.920 |
| + HyDE | 0.701 (+6.7%) | 0.893 | 0.924 |
| + CCH | 0.694 (+5.6%) | 0.891 | 0.922 |
| + HyDE + CCH | 0.718 (+9.3%) | 0.897 | 0.928 |
HyDE + CCHが全指標で最高スコア。特にContext Precisionでの改善が顕著です。
埋め込みモデル比較
| モデル | 次元 | Context Precision |
|---|---|---|
| mxbai-embed-large-v1 | 1024 | 0.694 |
| bge-large-en-v1.5 | 1024 | 0.688 |
| text-embedding-ada-002 | 1536 | 0.681 |
| e5-large-v2 | 1024 | 0.678 |
差は小さい(~2%以内)。mxbai-embed-large-v1がオープンソースで最良です。
チャンクサイズの影響
| チャンクサイズ | Context Precision |
|---|---|
| 128トークン | 0.641 |
| 256トークン | 0.662 |
| 512トークン | 0.694 |
| 1024トークン | 0.681 |
512トークンが最適。1024では無関係な情報が混入し、精度が低下します。
実運用への応用(Practical Applications)
評価駆動のRAG最適化サイクル
ARAGOGの手法は、Zenn記事で解説した評価駆動リランキングを検索層にまで拡張します。
- ベースライン測定: Naive RAGでContext Precision等を計測
- 手法導入: HyDE + CCHを追加
- A/B評価: RAGASで定量比較
- 本番適用: 改善が確認された構成をデプロイ
- 継続監視: LangSmithで指標を追跡
コスト-品質トレードオフ
- CCHのみ(追加コスト0): CP +5.6%。まず試すべき手法
- HyDE + CCH(+1 LLM call/query): CP +9.3%。レイテンシ許容時に推奨
- DSI(+1 LLM call/doc at indexing): CP +2.1%。大規模文書コレクション向け
関連研究(Related Work)
- HyDE (Gao et al., 2022): ARAGOGが評価した5手法の1つ。ゼロショット密検索のためのクエリ拡張
- RAGAS (Es et al., 2023): ARAGOGが採用した評価フレームワーク。LLM-as-judgeによる自動評価
- ColBERT v2 (Santhanam et al., 2022): トークンレベル遅延相互作用検索。ARAGOGでは評価対象外だが、リランキング段階で有用
まとめと今後の展望
ARAGOGは、RAG構成の体系的比較フレームワークとして、実務者にデータドリブンな検索手法選択を可能にしました。HyDE + CCHの組み合わせがContext Precisionを9.3%改善するという知見は、Zenn記事の評価駆動リランキングの前段階として直接応用可能です。
制限として、100件のQAペア(Llama2レポート)のみでの評価であり、ドメイン横断的な検証が今後の課題です。
参考文献
- arXiv: https://arxiv.org/abs/2404.16130
- Code: https://github.com/predlico/ARAGOG
- Related Zenn article: https://zenn.dev/0h_n0/articles/f15c5b29dc16ed