Skip to content

✍️ 필사 모드: Advanced RAGパイプライン完全ガイド 2025:チャンキング戦略、リランキング、エージェンティックRAG、評価

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

1. RAGの進化(しんか):NaiveからAdvancedへ

1.1 RAGとは何か

RAG(Retrieval-Augmented Generation)は、LLMが回答を生成する前に外部知識ソースから関連情報を検索してコンテキストとして提供する技術です。LLMのハルシネーションを減らし、最新情報を反映し、ドメイン特化知識を活用できるようにします。

ユーザーの質問 → [検索(Retrieval)][関連文書][LLM + 文書コンテキスト] → 回答生成

1.2 RAGアーキテクチャの進化

Naive RAG2023年初)
├── 固定サイズチャンキング
├── 単一エンベディング検索
├── Top-K結果をそのままLLMに渡す
└── 問題: 検索精度が低い、コンテキストノイズ

Advanced RAG2024年)
├── セマンティックチャンキング + メタデータ
├── ハイブリッド検索(ベクトル + キーワード)
├── リランキングで検索結果を精製
├── クエリ変換(HyDE、Multi-Query)
└── コンテキスト圧縮

Modular RAG2025年)
├── エージェンティックRAG(動的ルーティング)
├── Self-RAG(自己反省)
├── CRAG(Corrective RAG├── マルチモーダルRAG
├── Knowledge Graph + RAG
└── モジュール組み合わせ型パイプライン

1.3 各段階のボトルネック

段階Naive RAGの問題Advanced RAGの解決策
インデキシング固定サイズチャンキングセマンティックチャンキング、階層的インデキシング
検索単一ベクトル検索ハイブリッド検索、リランキング
生成ノイズコンテキストコンテキスト圧縮、フィルタリング
クエリ元のクエリそのままクエリ変換、分解
評価手動評価RAGAS、自動評価

2. チャンキング戦略(せんりゃく)

2.1 なぜチャンキングが重要か

チャンキングはRAGパイプラインの最初で最も重要なステップです。不適切なチャンキングは後続のすべての段階のパフォーマンスを低下させます。

悪いチャンキング: 文の途中で切断 → 意味の損失 → 検索失敗 → 誤った回答
良いチャンキング: 意味単位で分離 → 豊富なコンテキスト → 正確な検索 → 正確な回答

2.2 固定サイズチャンキング

最も単純な方式です。テキストを一定のトークン/文字数で分割します。

from langchain.text_splitter import CharacterTextSplitter

splitter = CharacterTextSplitter(
    chunk_size=500,      # チャンクサイズ
    chunk_overlap=50,    # オーバーラップ(境界情報の保存)
    separator="\n\n"     # セパレータ
)

chunks = splitter.split_text(document_text)

利点: 簡単、高速、予測可能なサイズ 欠点: 意味単位を無視、文の途中で切断される可能性

2.3 再帰的(さいきてき)チャンキング(Recursive Character Splitting)

複数のセパレータを階層的に試行します。最も広く使用されている方式です。

from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    separators=["\n\n", "\n", ". ", " ", ""]  # 優先順位
)

chunks = splitter.split_text(document_text)
# まず\n\nで分離を試み、サイズ超過なら\n、次にピリオド...

利点: 段落/文の境界を尊重、汎用的 欠点: 意味的な関連性の保証なし

2.4 セマンティックチャンキング(Semantic Chunking)

文間のエンベディング類似度を測定し、意味が変わるポイントで分割します。

from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

# セマンティックチャンキング
chunker = SemanticChunker(
    embeddings,
    breakpoint_threshold_type="percentile",
    breakpoint_threshold_amount=95  # 類似度が95パーセンタイル以下なら分割
)

chunks = chunker.split_text(document_text)

動作原理(どうさげんり):

1: "ベクトルDBはAIインフラの核心だ。" → エンベディング [0.1, 0.3, ...]
2: "HNSWは最速の検索アルゴリズムだ。" → 類似度 0.85(高い → 同じチャンク)
3: "一方、今日の天気は晴れだ。"      → 類似度 0.15(低い → 新しいチャンク開始!)

利点: 意味単位の分割、高い検索精度 欠点: エンベディング呼び出しが必要(コスト/時間)、チャンクサイズが不均一

2.5 文書ベースチャンキング(Document-Based Chunking)

文書構造(見出し、セクション、表、コードブロック)を活用します。

from langchain.text_splitter import MarkdownHeaderTextSplitter

headers_to_split = [
    ("#", "Header 1"),
    ("##", "Header 2"),
    ("###", "Header 3"),
]

splitter = MarkdownHeaderTextSplitter(headers_to_split)
chunks = splitter.split_text(markdown_text)

# 各チャンクに見出しメタデータが自動的に含まれる
for chunk in chunks:
    print(f"メタデータ: {chunk.metadata}")
    # {'Header 1': 'Vector Database', 'Header 2': 'インデキシングアルゴリズム'}

2.6 エージェンティックチャンキング(Agentic Chunking)

LLMを使用して最適なチャンキングを決定します。

from openai import OpenAI

client = OpenAI()

def agentic_chunk(text, max_chunk_size=1500):
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """与えられたテキストを意味的に独立したチャンクに分割してください。
各チャンクは自己完結的に理解可能でなければなりません。
JSON配列でチャンクテキストを返してください。"""},
            {"role": "user", "content": text}
        ],
        response_format={"type": "json_object"}
    )
    return response.choices[0].message.content

利点: 最高品質、文脈理解 欠点: コスト高、処理時間が長い、大規模では非実用的

2.7 チャンキング戦略比較

戦略品質速度コスト適合ケース
固定サイズ低い非常に速い無料プロトタイピング、単純な文書
再帰的中間速い無料汎用(デフォルト推奨)
セマンティック高い普通エンベディングコスト精度が重要な場合
文書ベース高い速い無料構造化文書(MD、HTML)
エージェンティック非常に高い遅いLLMコスト少量高品質文書

2.8 最適チャンクサイズガイド

一般テキスト: 5001000トークン(オーバーラップ1020%技術文書: 8001500トークン(セクション単位)
法律/医療文書: 300500トークン(精密度重視)
コード: 関数/クラス単位(構造ベース)
会話/QA: 対話ターン単位

3. エンベディングモデル選択

3.1 エンベディングモデル比較

モデル次元最大トークンMTEBスコアコスト推奨ケース
text-embedding-3-large30728,19164.6有料最高性能が必要な時
text-embedding-3-small15368,19162.3低コスト汎用(コスパ最適)
embed-v3.0(Cohere)102451264.5有料多言語、検索特化
BGE-M3(BAAI)10248,19268.2無料セルフホスティング、最高OSS
Jina-embeddings-v310248,19265.5無料多言語、長文書
voyage-3(Voyage AI)102432,00067.1有料コード検索特化

3.2 選択基準(せんたくきじゅん)

コスト重視 + 汎用        → text-embedding-3-small
最高性能 + 無料          → BGE-M3(セルフホスティング)
多言語 + 検索特化        → Cohere embed-v3.0
コード検索              → voyage-code-3
長文書(8K+トークン)    → Jina-embeddings-v3
プライベートデータ + オンプレミス → BGE-M3 or Nomic

3.3 Late Interactionモデル(ColBERT)

トークンレベルのきめ細かいマッチングを実行します。

from ragatouille import RAGPretrainedModel

rag = RAGPretrainedModel.from_pretrained("colbert-ir/colbertv2.0")

# インデキシング
rag.index(
    collection=[doc1, doc2, doc3],
    index_name="my_index"
)

# 検索(トークンレベルマッチング)
results = rag.search(query="ベクトルデータベース性能比較", k=5)

4. クエリ変換(へんかん)(Query Transformation)

4.1 なぜクエリ変換が必要か

ユーザークエリはしばしば曖昧で、短すぎたり、検索に適していません。

元のクエリ: "RAG遅い"(曖昧、短い)
→ 変換後: "RAGパイプライン検索レイテンシ最適化方法"(具体的、検索に適切)

4.2 HyDE(Hypothetical Document Embeddings)

LLMが仮想的な回答文書を生成し、その文書のエンベディングで検索します。

from openai import OpenAI

client = OpenAI()

def hyde_search(query, collection):
    # 1. LLMで仮想回答を生成
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "与えられた質問に対する詳細な回答を作成してください。正確でなくても構いません。"},
            {"role": "user", "content": query}
        ]
    )
    hypothetical_doc = response.choices[0].message.content
    
    # 2. 仮想回答をエンベディングして検索
    embedding = get_embedding(hypothetical_doc)
    results = collection.search(query_vector=embedding, limit=5)
    
    return results

利点: 文書とクエリ間のエンベディングギャップを解消 欠点: LLM呼び出しコスト、仮想回答が誤る可能性

4.3 Multi-Query(マルチクエリ)

1つのクエリを複数の角度から書き換えます。

def multi_query_transform(original_query):
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """与えられた質問を3つの異なる視点から書き換えてください。
各質問は元の意図を維持しつつ、異なるキーワードを使用してください。
改行で区切って3つの質問のみ返してください。"""},
            {"role": "user", "content": original_query}
        ]
    )
    queries = response.choices[0].message.content.strip().split("\n")
    return [original_query] + queries

# 使用例
queries = multi_query_transform("RAGパイプライン性能最適化")
# → ["RAGパイプライン性能最適化",
#    "検索拡張生成システムの応答時間改善方法",
#    "RAGアーキテクチャでの検索精度向上戦略",
#    "LLMベース文書検索システム最適化技法"]

4.4 Step-Back Prompting

具体的な質問をより一般的な質問に変換します。

def step_back_prompt(query):
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """与えられた質問より一段階より一般的で広い質問を生成してください。
この一般的な質問の回答が元の質問に答えるのに役立つ必要があります。"""},
            {"role": "user", "content": query}
        ]
    )
    return response.choices[0].message.content

4.5 Query Decomposition(クエリ分解)

複雑な質問を複数のサブ質問に分解します。

def decompose_query(complex_query):
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """複雑な質問をシンプルなサブ質問に分解してください。
各サブ質問は独立して回答可能である必要があります。
JSON配列で返してください。"""},
            {"role": "user", "content": complex_query}
        ],
        response_format={"type": "json_object"}
    )
    return response.choices[0].message.content

5. 検索最適化(けんさくさいてきか)

5.1 ハイブリッド検索

ベクトル検索とキーワード検索を組み合わせます。

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import Qdrant

# BM25(キーワード)リトリーバー
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 5

# ベクトルリトリーバー
vector_retriever = qdrant_vectorstore.as_retriever(
    search_kwargs={"k": 5}
)

# アンサンブル(ハイブリッド)
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.4, 0.6]  # ベクトルに重み付け
)

results = ensemble_retriever.invoke("RAGパイプライン最適化方法")

5.2 コンテキスト圧縮(Contextual Compression)

検索された文書から関連部分のみを抽出します。

from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

compressor = LLMChainExtractor.from_llm(llm)

compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=vector_retriever
)

compressed_docs = compression_retriever.invoke("HNSWアルゴリズムのMパラメータの役割")
# 文書全体ではなく、質問に関連する段落のみを返却

5.3 Parent Document Retrieval(親文書検索)

小さなチャンクで検索し、大きな親文書を返します。

from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 小さなチャンク: 検索用
child_splitter = RecursiveCharacterTextSplitter(chunk_size=200)

# 大きなチャンク: コンテキスト用
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)

store = InMemoryStore()

retriever = ParentDocumentRetriever(
    vectorstore=vectorstore,
    docstore=store,
    child_splitter=child_splitter,
    parent_splitter=parent_splitter,
)

# 200トークンチャンクで精密検索 → 2000トークン親文書を返却
retriever.add_documents(documents)
results = retriever.invoke("HNSWパラメータチューニング")

6. リランキング(Re-ranking)

6.1 なぜリランキングが必要か

初期検索(bi-encoder)は高速ですが精度が劣ります。リランキング(cross-encoder)はクエリと文書を一緒に処理し、より正確な関連度を判断します。

1段階(Bi-encoder): クエリベクトル vs 文書ベクトル → 高速だが不正確 → Top 20
2段階(Cross-encoder): (クエリ, 文書)ペアを直接比較 → 遅いが正確 → Top 5

6.2 Cross-Encoderリランキング

from sentence_transformers import CrossEncoder

model = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

initial_results = vector_search(query, top_k=20)

pairs = [(query, doc.content) for doc in initial_results]
scores = model.predict(pairs)

reranked = sorted(
    zip(initial_results, scores),
    key=lambda x: x[1],
    reverse=True
)[:5]

6.3 Cohere Rerank

商用リランキングAPIです。高い性能と多言語サポートが利点です。

import cohere

co = cohere.Client("YOUR_API_KEY")

documents = [doc.content for doc in initial_results]

response = co.rerank(
    model="rerank-v3.5",
    query="RAGパイプライン最適化",
    documents=documents,
    top_n=5
)

for result in response.results:
    print(f"Index: {result.index}, Score: {result.relevance_score:.4f}")

6.4 リランキングモデル比較

モデル速度品質コスト多言語推奨
cross-encoder/ms-marco速い良い無料英語英語専用
Cohere Rerank v3.5速い非常に良い有料100+言語本番デフォルト
ColBERT v2普通非常に良い無料英語セルフホスティング
BGE-Reranker-v2速い良い無料多言語OSS多言語
LLMリランキング遅い最高高い全て少量高品質

7. エージェンティックRAG(Agentic RAG)

7.1 エージェンティックRAGとは

LLMエージェントが検索戦略を動的に決定します。単純な「検索後生成」ではなく、検索結果を評価し戦略を調整します。

従来のRAG: 質問 → 検索 → 生成(固定パイプライン)
エージェンティックRAG: 質問 → [エージェントが判断]
              ├── 検索が必要か? → 検索 → 結果は十分か?
              │                        ├── Yes → 生成
              │                        └── No → 別のソースを検索 / クエリ修正
              └── 検索なしで回答可能 → 直接生成

7.2 Self-RAG(自己反省RAG)

モデルが自ら検索の必要性と生成結果の品質を評価します。

def self_rag(query):
    # 1. 検索必要性の判断
    need_retrieval = judge_retrieval_need(query)
    
    if not need_retrieval:
        return generate_without_context(query)
    
    # 2. 検索実行
    documents = retrieve(query)
    
    # 3. 各文書の関連性判断
    relevant_docs = [doc for doc in documents if is_relevant(query, doc)]
    
    if not relevant_docs:
        refined_query = refine_query(query)
        documents = retrieve(refined_query)
        relevant_docs = [d for d in documents if is_relevant(refined_query, d)]
    
    # 4. 回答生成
    answer = generate_with_context(query, relevant_docs)
    
    # 5. 回答品質の自己評価
    if not is_supported(answer, relevant_docs):
        answer = regenerate(query, relevant_docs)
    
    return answer

7.3 CRAG(Corrective RAG)

検索結果の品質に応じて補正措置(ほせいそち)を取ります。

def corrective_rag(query):
    documents = retrieve(query)
    quality = evaluate_retrieval_quality(query, documents)
    
    if quality == "CORRECT":
        refined_knowledge = refine_knowledge(documents)
        return generate(query, refined_knowledge)
    
    elif quality == "AMBIGUOUS":
        web_results = web_search(query)
        combined = documents + web_results
        refined = refine_knowledge(combined)
        return generate(query, refined)
    
    elif quality == "INCORRECT":
        web_results = web_search(query)
        refined = refine_knowledge(web_results)
        return generate(query, refined)

7.4 Adaptive RAG(適応型RAG)

クエリの複雑度に応じて戦略を選択します。

def adaptive_rag(query):
    complexity = classify_query(query)
    
    if complexity == "SIMPLE":
        docs = simple_retrieve(query, top_k=3)
        return generate(query, docs)
    
    elif complexity == "MODERATE":
        queries = multi_query_transform(query)
        docs = hybrid_search(queries)
        reranked = rerank(query, docs)
        return generate(query, reranked)
    
    elif complexity == "COMPLEX":
        sub_queries = decompose_query(query)
        sub_answers = []
        for sq in sub_queries:
            docs = search(sq)
            sub_answers.append(generate(sq, docs))
        return synthesize(query, sub_answers)

7.5 Query Routing(クエリルーティング)

質問タイプに応じて適切なデータソースにルーティングします。

def query_router(query):
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": """クエリを分析して適切なデータソースを選択してください:
- VECTOR_DB: 内部文書検索が必要な場合
- WEB_SEARCH: 最新情報や外部情報が必要な場合
- SQL_DB: 構造化データクエリが必要な場合
- DIRECT: LLMが直接回答可能な場合
一単語のみ返してください。"""},
            {"role": "user", "content": query}
        ]
    )
    route = response.choices[0].message.content.strip()
    
    if route == "VECTOR_DB":
        return vector_db_search(query)
    elif route == "WEB_SEARCH":
        return web_search(query)
    elif route == "SQL_DB":
        return sql_query(query)
    else:
        return direct_answer(query)

8. マルチモーダルRAG

8.1 画像 + テキストRAG

PDFやスライドから画像と表をテキストと一緒に処理します。

from langchain_community.document_loaders import UnstructuredPDFLoader

loader = UnstructuredPDFLoader(
    "document.pdf",
    mode="elements",
    strategy="hi_res"
)
elements = loader.load()

for element in elements:
    if element.metadata.get("type") == "Image":
        description = describe_image_with_vision(element)
        element.page_content = description

8.2 表(テーブル)処理

def process_table(table_element):
    """表を検索可能な形式に変換"""
    md_table = table_element.metadata.get("text_as_html", "")
    
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "次の表の内容を自然言語で要約してください。"},
            {"role": "user", "content": md_table}
        ]
    )
    summary = response.choices[0].message.content
    
    return {
        "content": summary,
        "metadata": {"type": "table", "original_html": md_table}
    }

9. Knowledge Graph + RAG(GraphRAG)

9.1 GraphRAGの概念(がいねん)

知識グラフでエンティティ間の関係を表現し、ベクトル検索と統合します。

通常のRAG: 文書チャンクを独立的に検索
GraphRAG: エンティティの関係を活用して接続された情報まで検索

: "HNSWを使用するベクトルデータベースは?"
通常のRAG: HNSWに関するチャンクのみ返却
GraphRAG: HNSW  (使用される)Qdrant, Weaviate, Milvus
         +DBHNSW設定関連チャンクまで返却

9.2 Neo4j + RAG実装

from langchain_community.graphs import Neo4jGraph
from langchain.chains import GraphCypherQAChain

graph = Neo4jGraph(
    url="bolt://localhost:7687",
    username="neo4j",
    password="password"
)

chain = GraphCypherQAChain.from_llm(
    llm=llm,
    graph=graph,
    verbose=True
)

result = chain.invoke("Qdrantがサポートするインデキシングアルゴリズムは?")

10. RAG評価(ひょうか)

10.1 RAGASフレームワーク

RAGパイプラインを自動評価するフレームワークです。

from ragas import evaluate
from ragas.metrics import (
    faithfulness,
    answer_relevancy,
    context_precision,
    context_recall,
)
from datasets import Dataset

eval_data = {
    "question": ["RAGとは何か?", "HNSWアルゴリズムの原理は?"],
    "answer": ["RAGは検索拡張生成で...", "HNSWは階層的グラフ..."],
    "contexts": [
        ["RAG(Retrieval-Augmented Generation)は...", "検索ベースの生成技術..."],
        ["HNSWはHierarchical Navigable...", "グラフベースのANNアルゴリズム..."]
    ],
    "ground_truth": ["RAGはLLMが外部知識を...", "HNSWは多層グラフ構造の..."]
}

dataset = Dataset.from_dict(eval_data)

results = evaluate(
    dataset,
    metrics=[faithfulness, answer_relevancy, context_precision, context_recall]
)

print(results)
# {'faithfulness': 0.89, 'answer_relevancy': 0.92,
#  'context_precision': 0.85, 'context_recall': 0.78}

10.2 RAGASメトリクス詳細

メトリクス測定対象範囲目標
Faithfulness回答がコンテキストに根拠を持つ度合い0〜10.85+
Answer Relevancy回答が質問に適合する度合い0〜10.90+
Context Precision関連コンテキストのランキング精度0〜10.80+
Context Recall必要な情報が検索された度合い0〜10.75+
Answer Similarity回答と正解の意味的類似度0〜10.80+
Answer Correctness回答の事実的正確性0〜10.85+

10.3 評価方法比較

方法自動化コスト精度使用タイミング
RAGAS完全自動エンベディングコスト良い継続的モニタリング
TruLens自動LLMコスト良い開発中の反復評価
LLM-as-Judge半自動LLMコスト非常に良い詳細分析
Human Eval手動人件費最高最終検証

11. 本番最適化(さいてきか)

11.1 キャッシング戦略

import hashlib
import json

class RAGCache:
    def __init__(self, redis_client):
        self.redis = redis_client
        self.ttl = 3600  # 1時間
    
    def get_cached_response(self, query):
        key = hashlib.md5(query.encode()).hexdigest()
        cached = self.redis.get(f"rag:{key}")
        if cached:
            return json.loads(cached)
        return None

# セマンティックキャッシング: 類似クエリもキャッシュヒット
class SemanticCache:
    def __init__(self, vectorstore, threshold=0.95):
        self.store = vectorstore
        self.threshold = threshold
    
    def get(self, query):
        results = self.store.similarity_search_with_score(query, k=1)
        if results and results[0][1] >= self.threshold:
            return results[0][0].metadata["response"]
        return None

11.2 ストリーミング応答

from openai import OpenAI

client = OpenAI()

def stream_rag_response(query, context):
    stream = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {"role": "system", "content": f"コンテキスト:\n{context}"},
            {"role": "user", "content": query}
        ],
        stream=True
    )
    
    for chunk in stream:
        if chunk.choices[0].delta.content:
            yield chunk.choices[0].delta.content

11.3 フォールバック戦略

def rag_with_fallback(query):
    try:
        docs = vector_search(query)
        
        if not docs or max_relevance_score(docs) < 0.5:
            docs = web_search_fallback(query)
        
        if not docs:
            return direct_llm_answer(query)
        
        return generate_with_context(query, docs)
    
    except Exception as e:
        return {
            "answer": "申し訳ございません。一時的なエラーが発生しました。",
            "error": str(e),
            "fallback": True
        }

11.4 モニタリング

monitoring = {
    "検索レイテンシ": "目標 p99 200ms",
    "生成レイテンシ": "目標 p99 3s(ストリーミングfirst-token 500ms)",
    "検索適合度(Relevance)": "自動評価 0.85+",
    "回答根拠性(Groundedness)": "自動評価 0.90+",
    "キャッシュヒット率": "目標 30%+",
    "ユーザーフィードバック": "肯定 80%+",
    "トークン使用量": "コスト追跡",
    "エラー率": "目標 1%以下",
}

12. よくある失敗と解決策

12.1 問題診断チェックリスト

症状原因解決策
無関係な文書が返されるチャンクサイズ不適切セマンティックチャンキング、サイズ調整
回答がコンテキストを無視コンテキストが長すぎるかノイズコンテキスト圧縮、リランキング
同義語/類義語検索失敗エンベディングモデルの限界ハイブリッド検索、クエリ拡張
最新情報の欠如インデックス未更新増分インデキシング、スケジューラ
回答ハルシネーション関連度閾値なしスコアフィルタリング、Self-RAG
マルチホップ質問失敗単一検索では不十分クエリ分解、反復検索
特定用語検索失敗ベクトルだけでは不十分BM25ハイブリッド追加
遅い応答リランキング/生成遅延キャッシング、ストリーミング、非同期

13. クイズ

Q1. セマンティックチャンキングと再帰的チャンキングの違いは?

再帰的チャンキングは事前定義されたセパレータ(改行、ピリオドなど)を階層的に適用してテキストを分割します。意味は考慮しません。セマンティックチャンキングは文間のエンベディング類似度を測定し、意味が大きく変わるポイントで分割します。セマンティックチャンキングの方が検索精度は高いですが、エンベディング呼び出しコストがかかります。デフォルトは再帰的チャンキング、精度重視ならセマンティックチャンキングを使用します。

Q2. HyDE(Hypothetical Document Embeddings)はどのように検索を改善しますか?

HyDEはユーザークエリに対する仮想的な回答文書をLLMがまず生成します。その仮想文書をエンベディングして検索に使用します。クエリと文書間のエンベディングギャップ(短い質問 vs 長い文書)を解消し、検索精度を向上させます。欠点はLLM呼び出しコストと仮想回答が誤るリスクです。

Q3. Self-RAGとCRAGの違いは?

Self-RAGはモデルが自ら検索の必要性を判断し、生成された回答がコンテキストに根拠を持つか自己評価します。検索が不要なら直接回答します。CRAGは検索は常に実行しますが、検索結果の品質を評価して「正確/曖昧/不適切」に分類します。不適切な場合、Web検索などの代替ソースで補正します。Self-RAGは検索自体を制御し、CRAGは検索結果を補正します。

Q4. RAGASのFaithfulnessとAnswer Relevancyの違いは?

Faithfulnessは回答の各主張が提供されたコンテキストに根拠を持つかを測定します。ハルシネーション検出に重要です。Answer Relevancyは回答が元の質問にどれだけ適合するかを測定します。質問と無関係な内容が回答に含まれるとスコアが下がります。Faithfulnessが高くても質問への答えでなければAnswer Relevancyが低くなる可能性があります。

Q5. 本番RAGでのセマンティックキャッシングの利点は?

通常のキャッシングは完全に同一のクエリのみヒットします。セマンティックキャッシングは意味的に類似したクエリもキャッシュヒットします。「RAG最適化方法」と「RAG性能改善戦略」が同じキャッシュを活用します。これによりキャッシュヒット率を大幅に向上させ、LLM呼び出しコストと応答レイテンシを削減できます。類似度閾値(例: 0.95)でヒット精度を調整します。


14. 参考資料(さんこうしりょう)

  1. LangChain Documentation - https://python.langchain.com/docs/
  2. LlamaIndex Documentation - https://docs.llamaindex.ai/
  3. RAGAS Documentation - https://docs.ragas.io/
  4. TruLens Documentation - https://www.trulens.org/
  5. Cohere Rerank - https://docs.cohere.com/reference/rerank
  6. ColBERT論文 - https://arxiv.org/abs/2004.12832
  7. Self-RAG論文 - https://arxiv.org/abs/2310.11511
  8. CRAG論文 - https://arxiv.org/abs/2401.15884
  9. Adaptive RAG論文 - https://arxiv.org/abs/2403.14403
  10. HyDE論文 - https://arxiv.org/abs/2212.10496
  11. GraphRAG (Microsoft) - https://github.com/microsoft/graphrag
  12. RAG Survey論文 - https://arxiv.org/abs/2312.10997
  13. Chunking Strategies Guide - https://www.pinecone.io/learn/chunking-strategies/
  14. MTEB Leaderboard - https://huggingface.co/spaces/mteb/leaderboard

현재 단락 (1/520)

RAG(Retrieval-Augmented Generation)は、LLMが回答を生成する前に外部知識ソースから関連情報を検索してコンテキストとして提供する技術です。LLMのハルシネーションを減...

작성 글자: 0원문 글자: 18,506작성 단락: 0/520