超越朴素 RAG

朴素 RAG 的流程是:用户提问 -> 检索 top-K 文档 -> 拼接到 Prompt -> LLM 生成。这对简单问题够用,但面对复杂问题力不从心。本文介绍 6 种高级 RAG 架构模式。

模式一览

模式核心思想适用场景复杂度
多跳检索分步检索,每步基于前步结果多跳推理问题
递归检索先粗后细,分层检索层级结构文档
自适应检索LLM 决定是否检索/检索什么不确定是否需要检索
Self-RAGLLM 自我反思检索质量高质量要求
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论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。