RAGとは
RAG(Retrieval-Augmented Generation)は、LLMに外部知識を与えることでハルシネーション(幻覚)を減らし、最新情報に基づいた回答を生成する技術です。
2025年現在、本番AIアプリケーションの60%がRAGを採用しています。
RAGの基本アーキテクチャ
graph LR
Query["ユーザークエリ"] --> Retriever["Retriever<br/>検索"]
Retriever --> LLM["LLM<br/>生成"]
VectorDB["ベクトルDB<br/>知識ベース"] --> Retriever
2025年の主要RAG手法
1. Basic RAG
シンプルな検索 + 生成パイプライン。
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
# ベクトルストアを作成
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(documents, embeddings)
# RAGチェーンを構築
qa_chain = RetrievalQA.from_chain_type(
llm=ChatOpenAI(model="gpt-4"),
retriever=vectorstore.as_retriever(search_kwargs={"k": 5}),
return_source_documents=True
)
result = qa_chain.invoke({"query": "RAGのベストプラクティスは?"})
2. GraphRAG
知識グラフを活用して文脈と論理を検索に組み込む手法。**検索精度99%**を実現。
from langchain_community.graphs import Neo4jGraph
from langchain_experimental.graph_transformers import LLMGraphTransformer
# ドキュメントからグラフを構築
graph = Neo4jGraph()
transformer = LLMGraphTransformer(llm=llm)
graph_documents = transformer.convert_to_graph_documents(documents)
# グラフベースの検索
graph.query("""
MATCH (entity)-[r]->(related)
WHERE entity.name CONTAINS $query
RETURN entity, r, related
LIMIT 10
""", params={"query": user_query})
3. Self-RAG
自己反省メカニズムで検索の妥当性を評価。ハルシネーションを52%削減。
class SelfRAG:
def __init__(self, llm, retriever):
self.llm = llm
self.retriever = retriever
def generate_with_reflection(self, query: str):
# 1. 検索が必要か判断
if self.needs_retrieval(query):
docs = self.retriever.get_relevant_documents(query)
# 2. 各ドキュメントの関連性を評価
relevant_docs = [
doc for doc in docs
if self.is_relevant(doc, query) # ISREL トークン
]
# 3. 生成と批評
response = self.llm.generate(query, relevant_docs)
critique = self.critique_response(response, query)
if not critique.is_supported:
return self.regenerate(query, critique.feedback)
return response
4. Agentic RAG
複雑な推論やツール使用が必要な場合に使用。
from langchain.agents import create_react_agent
# ツールを定義
tools = [
retrieval_tool, # ベクトル検索
sql_tool, # データベースクエリ
calculator_tool, # 計算
web_search_tool # ウェブ検索
]
# エージェントRAG
agent = create_react_agent(
llm=ChatOpenAI(model="gpt-4"),
tools=tools,
prompt=react_prompt
)
チャンキング戦略
セマンティックチャンキング
意味的なまとまりでテキストを分割。
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 基本的なチャンキング
splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "、", " "]
)
# セマンティックチャンキング
from langchain_experimental.text_splitter import SemanticChunker
semantic_splitter = SemanticChunker(
embeddings=OpenAIEmbeddings(),
breakpoint_threshold_type="percentile"
)
チャンクサイズの目安:
| 用途 | チャンクサイズ | オーバーラップ |
|---|---|---|
| Q&A | 256-512 | 50 |
| 要約 | 1000-2000 | 200 |
| コード | 500-1000 | 100 |
クエリ拡張
曖昧なクエリを改善して検索精度を向上。
def expand_query(query: str, llm) -> list[str]:
"""クエリを複数のバリエーションに拡張"""
prompt = f"""
以下のクエリを、同じ意図を持つ3つの異なる表現に言い換えてください:
クエリ: {query}
"""
expanded = llm.invoke(prompt)
return [query] + parse_variations(expanded)
# HyDE (Hypothetical Document Embeddings)
def hyde_expand(query: str, llm):
"""仮想的な回答ドキュメントを生成して検索"""
hypothetical_doc = llm.invoke(
f"以下の質問に対する詳細な回答を書いてください: {query}"
)
return hypothetical_doc
評価指標
from ragas import evaluate
from ragas.metrics import (
faithfulness, # 生成がソースに忠実か
answer_relevancy, # 回答の関連性
context_precision, # 検索精度
context_recall # 検索網羅性
)
result = evaluate(
dataset,
metrics=[faithfulness, answer_relevancy, context_precision]
)
ベストプラクティス
1. 段階的に複雑化
Basic RAG → Query Rewriting → Self-RAG → Agentic RAG
2. モジュラー設計
class ModularRAG:
def __init__(self):
self.retriever = None # 後から交換可能
self.reranker = None
self.generator = None
def swap_retriever(self, new_retriever):
self.retriever = new_retriever
3. 継続的な改善
- ユーザーフィードバックの収集
- 検索結果の品質モニタリング
- A/Bテストによる最適化
まとめ
2025年のRAGは、単純な検索+生成から、グラフベース、自己反省型、エージェント型へと進化しています。用途に応じた手法選択と、継続的な評価・改善が成功の鍵です。
← 一覧に戻る