RAG(Retrieval-Augmented Generation)は、大規模言語モデル(LLM)に外部知識を取り込み、より正確で文脈に沿った回答を生成するための手法です。
ここでは、代表的な8種類のRAGアーキテクチャを 概要 → 実例 → 実装サンプル の順で紹介します。
前提として、以下の依存パッケージを使用します。
pip install langchain langchain-openai faiss-cpu chromadb duckduckgo-search neo4j networkx
共通セットアップ:
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain.docstore.document import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter
llm = ChatOpenAI(model="gpt-4o")
emb = OpenAIEmbeddings()
docs = [
Document(page_content="返品ポリシー: 未開封なら30日以内に返金可。"),
Document(page_content="海外発送は一部地域のみ。関税は購入者負担。"),
Document(page_content="製品AはIP67防水。バッテリーは3000mAh。")
]
splitter = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=30)
chunks = splitter.split_documents(docs)
1. Naive RAG
概要
もっとも基本的なRAG。クエリを埋め込みベクトル化し、ベクトルDBから関連文書を検索してLLMへ渡します。
実例
- 社内FAQ Bot(Slack経由で社内Wikiを検索)
実装サンプル
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
vs = FAISS.from_documents(chunks, emb)
retriever = vs.as_retriever(k=3)
qa = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
print(qa.run("海外発送の条件を教えて"))
2. Multimodal RAG
概要
テキストだけでなく、画像・音声など複数モーダルの情報を統合検索します。
実例
- 製造業のトラブルシュート(写真+マニュアル+FAQ)
実装サンプル
from langchain_community.vectorstores import Chroma
img_doc = Document(page_content="製品Aの背面図。USB-Cポートは下部中央。")
multi_chunks = splitter.split_documents(docs + [img_doc])
vs_mm = Chroma.from_documents(multi_chunks, emb)
retriever_mm = vs_mm.as_retriever(k=4)
ctx = retriever_mm.get_relevant_documents("USB-Cポートはどこ?")
print(llm.invoke(f"{[d.page_content for d in ctx]} を参考に回答してください。").content)
3. HyDE(Hypothetical Document Embeddings)
概要
クエリから仮想的な回答文をLLMで作成し、それを埋め込み検索に利用して精度を上げます。
実例
- 契約書検索(曖昧な法務用語を含む検索)
実装サンプル
from langchain.prompts import PromptTemplate
from langchain.schema import StrOutputParser
hyde_prompt = PromptTemplate.from_template("質問に対する模範解答を簡潔に作成: {q}")
def hyde_search(question):
hypo = (hyde_prompt | llm | StrOutputParser()).invoke({"q": question})
vs = FAISS.from_documents(chunks, emb)
hits = vs.similarity_search_by_vector(emb.embed_query(hypo), k=3)
ctx = "\n".join([h.page_content for h in hits])
return llm.invoke(f"{ctx} を参考に回答: {question}").content
print(hyde_search("賠償条項の一般的な例を教えて"))
4. Corrective RAG
概要
初回のRAG結果を自己検証し、不足や誤りがあれば追加検索して修正します。
実例
- 医療相談AI(正確性の高い情報提供)
実装サンプル
from langchain_community.vectorstores import Chroma
vs_corr = Chroma.from_documents(chunks, emb)
retriever_corr = vs_corr.as_retriever(k=3)
def corrective_rag(q):
ctx1 = retriever_corr.get_relevant_documents(q)
ans1 = llm.invoke(f"{[d.page_content for d in ctx1]} を参考に: {q}").content
grade = llm.invoke(f"この回答の正確性を0-1で評価。不足あれば'不足'と出力:\n{ans1}").content
if "不足" in grade:
ctx2 = retriever_corr.get_relevant_documents(q + " 詳細")
ctx = ctx1 + ctx2
return llm.invoke(f"{[d.page_content for d in ctx]} を参考に正確に回答: {q}").content
return ans1
print(corrective_rag("海外発送の条件をまとめて"))
5. Graph RAG
概要
データをノードと関係で構造化して検索します。
実例
- 脅威インテリジェンス分析(攻撃者→手法→脆弱性)
実装サンプル
import networkx as nx
G = nx.MultiDiGraph()
G.add_edge("製品A", "特性", relation="IP67防水")
G.add_edge("製品A", "バッテリー", relation="3000mAh")
def graph_retrieve(q):
facts = [f"{u}-{d['relation']}->{v}" for u,v,d in G.edges(data=True)]
return "\n".join(facts)
print(llm.invoke(f"以下の関係から質問に答えて:\n{graph_retrieve('製品A')}\n製品Aの特性は?").content)
6. Hybrid RAG
概要
ベクトル検索とグラフ検索を組み合わせます。
実例
- 新薬研究(論文類似検索+化合物関係探索)
実装サンプル
vs_hybrid = FAISS.from_documents(chunks, emb)
retriever_hybrid = vs_hybrid.as_retriever(k=3)
def hybrid_rag(q):
v_hits = retriever_hybrid.get_relevant_documents(q)
graph_ctx = graph_retrieve(q)
ctx = "\n".join([d.page_content for d in v_hits]) + "\n" + graph_ctx
return llm.invoke(f"{ctx} を参考に: {q}").content
print(hybrid_rag("製品Aの仕様を教えて"))
7. Adaptive RAG
概要
クエリの難易度やタイプに応じて検索戦略を切り替えます。
実例
- EC顧客サポート(FAQ直回答/詳細検索切替)
実装サンプル
from langchain_community.vectorstores import FAISS
def classify(q):
return llm.invoke(f"質問を0=簡単,1=通常,2=複雑で分類: {q}").content[0]
def adaptive_rag(q):
t = classify(q)
if t == "0":
return "FAQから即回答"
elif t == "2":
return "質問を分解して複数回RAG実行"
else:
return qa.run(q)
print(adaptive_rag("送料はいくら?"))
8. Agentic RAG
概要
複数エージェントや外部ツールを組み合わせ、計画・実行を分担します。
実例
- マーケット調査(Web検索+社内DB+分析)
実装サンプル
from langchain.agents import initialize_agent, AgentType, Tool
from langchain_community.tools import DuckDuckGoSearchRun
def rag_tool_run(q:str)->str:
docs = retriever.get_relevant_documents(q)
return "\n".join([d.page_content for d in docs])
tools = [
Tool(name="RAG", func=rag_tool_run, description="社内ドキュメント検索"),
Tool(name="WebSearch", func=DuckDuckGoSearchRun().run, description="ウェブ検索")
]
agent = initialize_agent(tools=tools, llm=llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION)
print(agent.run("海外発送ルールと一般的な国際配送条件をまとめて"))
まとめ
- Naive RAG: 最初の一歩に最適
- Multimodal RAG: 図面・画像込みの検索
- HyDE: 曖昧な質問に強い
- Corrective RAG: 正確性最優先
- Graph/Hybrid RAG: 関係性を活用
- Adaptive RAG: 問合せ難易度に応じて戦略切替
- Agentic RAG: 外部APIや複数タスク統合