超越朴素 RAG
朴素 RAG 的流程是:用户提问 -> 检索 top-K 文档 -> 拼接到 Prompt -> LLM 生成。这对简单问题够用,但面对复杂问题力不从心。本文介绍 6 种高级 RAG 架构模式。
模式一览
| 模式 | 核心思想 | 适用场景 | 复杂度 |
|---|---|---|---|
| 多跳检索 | 分步检索,每步基于前步结果 | 多跳推理问题 | 中 |
| 递归检索 | 先粗后细,分层检索 | 层级结构文档 | 中 |
| 自适应检索 | LLM 决定是否检索/检索什么 | 不确定是否需要检索 | 高 |
| Self-RAG | LLM 自我反思检索质量 | 高质量要求 | 高 |
| CRAG | 检索质量评估+Web兜底 | 知识库覆盖不全 | 高 |
| 模块化 RAG | 可插拔模块组合 | 生产环境灵活部署 | 高 |
1. 多跳检索(Multi-Hop Retrieval)
面对"张三所在公司的CEO毕业于哪所大学?“这种问题,单次检索无法回答。需要:
Hop 1: 检索"张三" -> 得到所在公司"ABC公司"
Hop 2: 检索"ABC公司 CEO" -> 得到"李四"
Hop 3: 检索"李四 教育背景" -> 得到"清华大学"
class MultiHopRetriever:
def __init__(self, llm_client, vector_store):
self.llm = llm_client
self.store = vector_store
self.max_hops = 4
async def retrieve(self, query: str) -> list[dict]:
all_docs = []
current_query = query
for hop in range(self.max_hops):
docs = await self.store.search(current_query, top_k=3)
all_docs.extend(docs)
prompt = f"""问题: {query}
已知信息: {self._format_docs(all_docs)}
如果已有足够信息回答问题,回复"SUFFICIENT"。
如果需要更多信息,生成下一个检索查询(只输出查询)。"""
resp = await self.llm.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0
)
next_action = resp.choices[0].message.content.strip()
if next_action == "SUFFICIENT":
break
current_query = next_action
return all_docs
def _format_docs(self, docs):
return "\n".join(f"[{i}] {d['content']}" for i, d in enumerate(docs))
2. 递归检索(Recursive Retrieval)
适用于层级结构文档。先检索章节级别(粗粒度),再在选中章节内检索段落级别(细粒度):
class RecursiveRetriever:
def __init__(self, store):
self.store = store
async def retrieve(self, query: str, top_k: int = 5):
# 第一层:检索相关章节摘要
chapter_hits = await self.store.search(
collection="chapter_summaries",
query=query, top_k=3
)
# 第二层:在相关章节内检索详细段落
all_results = []
for chapter in chapter_hits:
chapter_id = chapter["metadata"]["chapter_id"]
detail_hits = await self.store.search(
collection="details",
query=query, top_k=top_k,
filter={"chapter_id": chapter_id}
)
all_results.extend(detail_hits)
return self._dedup_and_rank(all_results)[:top_k]
3. 自适应检索(Adaptive Retrieval)
不是所有问题都需要检索。让 LLM 先判断是否需要检索:
class AdaptiveRAG:
def __init__(self, llm, retriever):
self.llm = llm
self.retriever = retriever
async def answer(self, query: str):
route = await self._route(query)
if route == "no_retrieval":
return await self._generate(query, [])
elif route == "single_retrieval":
docs = await self.retriever.search(query, top_k=5)
return await self._generate(query, docs)
elif route == "multi_hop":
docs = await self._multi_hop(query)
return await self._generate(query, docs)
async def _route(self, query: str) -> str:
prompt = f"""判断以下问题需要哪种检索策略:
- no_retrieval: 常识问题、计算题、闲聊
- single_retrieval: 单次检索可回答的事实性问题
- multi_hop: 需要多步推理的复杂问题
问题: {query}
只输出策略名称。"""
resp = await self.llm.chat.completions.create(
model="gpt-4o-mini", # 用小模型路由,省钱
messages=[{"role": "user", "content": prompt}],
temperature=0
)
return resp.choices[0].message.content.strip()
4. Self-RAG
LLM 在生成过程中自我评估检索结果质量,决定是否重新检索:
class SelfRAG:
async def generate(self, query, docs):
prompt = f"""问题: {query}
上下文: {docs}
回答问题。然后在最后加一行:
[RELEVANT: yes/no] - 检索结果是否相关
[SUPPORTED: yes/no] - 回答是否有上下文支持"""
resp = await self.llm.generate(prompt)
if "[RELEVANT: no]" in resp:
new_query = await self._reformulate_query(query)
new_docs = await self.retriever.search(new_query)
return await self.generate(query, new_docs)
return resp
5. CRAG(Corrective RAG)
评估检索质量,不好就用 Web 搜索兜底:
检索 -> 质量评估 ->
高质量 -> 直接用
低质量 -> Web 搜索补充 -> 重新组合
模糊 -> 检索 + Web 搜索混合
6. 模块化 RAG
把 RAG 拆成可插拔模块:Router -> Retriever -> Reranker -> Filter -> Generator -> Post-Processor。每个模块可独立替换。
选型决策树
问题简单(单跳事实查询)?
-> 朴素 RAG + 重排序
问题需要多步推理?
-> 多跳检索
文档有清晰层级结构?
-> 递归检索
不确定是否需要检索?
-> 自适应检索
质量要求极高?
-> Self-RAG / CRAG
需要生产级灵活部署?
-> 模块化 RAG
实战建议
- 从朴素 RAG 开始:80% 的场景朴素 RAG + 好的重排序就够了
- 重排序是性价比最高的优化:用 bge-reranker-v2-m3 对检索结果重排,效果提升 15-30%
- 多跳检索要控制深度:超过 3 跳后 LLM 容易"跑偏”,且延迟成倍增加
- 自适应路由用小模型:路由判断不需要大模型,用 GPT-4o-mini 或 Qwen-7B 即可—
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
