深度剖析RAG从朴素实现到生产级演进,介绍标准、混合、GraphRAG等8种架构,附完整决策矩阵。
如果你曾在一个周末里上线了一个“与你的文档对话”原型,恭喜你——你已经构建了 Naive RAG。如果之后你又眼睁睁看着它在多跳问题上产生幻觉、面对表格无从下手,并在生产环境中信心满满地引用了错误的 PDF……也同样恭喜你。你已经发现了为什么“RAG”并不是一种单一架构,而是一片设计空间。
这篇文章就是我希望自己在第四次重建同一套流水线之前能够拥有的那张地图。
Naive RAG(检索 → 填充上下文 → 生成)很快就会暴露问题:分块不合理、语义漂移、无法理解查询,也没有自我纠正能力。
Advanced RAG 通过检索前后的优化(查询重写、HyDE、重排序)提高检索质量。
Modular RAG 将检索视为一条可组合、可路由的流水线,而不是固定链路。
有 8 种值得了解的架构模式:Standard、Hybrid、GraphRAG、CRAG、Self-RAG、Adaptive RAG、Agentic RAG 和 Multi-Modal RAG。
应当根据你的故障模式进行选择,而不是追逐热点。文末附有决策矩阵。
“Hello World”版的 RAG 循环如下所示:
User Query → Embed → Vector Search (top-k) → Stuff into Prompt → LLM → Answer
在只有 20 份 PDF 的演示环境中,它的表现非常出色。可一旦有人提出真正的问题,一切就开始崩塌:
这些问题并不意味着“RAG 已经坏了”。它们只是说明 Naive RAG 是 MVP,而不是终点。下面介绍的所有内容,都是生产团队接下来会采用的方案。
在进入五花八门的架构之前,先拉远视角会更有帮助。大多数 RAG 系统都属于以下三个演进阶段之一。
┌─────────┐ ┌──────────┐ ┌────────────┐ ┌──────────┐
│ Query │ --> │ Embed │ --> │ Vector DB │ --> │ LLM │ --> Answer
└─────────┘ └──────────┘ │ (top-k) │ └──────────┘
└────────────┘
单次嵌入 → 单次检索 → 单次生成。没有反馈循环,不理解查询,也没有纠错机制。这是你的基线,而不是你的产品。
Advanced RAG 保留了线性结构,但增加了两个优化阶段:
检索前:在查询进入索引之前对其进行改进。
查询重写/扩展
HyDE(Hypothetical Document Embeddings,假设文档嵌入)——生成一个虚构的“理想答案”,对其进行嵌入,并用它代替原始问题执行搜索
针对多部分问题的查询分解
检索后:在上下文进入 LLM 之前对其进行改进。
重排序(交叉编码器,例如 Cohere Rerank、BGE-reranker)
上下文压缩/过滤
去除冗余(MMR——Maximal Marginal Relevance,最大边际相关性)
Query --> [Rewrite / HyDE] --> Retrieve --> [Re-rank / Filter] --> LLM --> Answer
在采用任何更复杂的方案之前,这是大多数团队应该优先完成的、投资回报率最高的一项升级。
Modular RAG 不再将流水线视为固定链路,而是将其视为由可互换模块构成的图:检索、路由、记忆、融合、任务适配器——可以根据问题需求以任意方式连接,其中也包括循环。
┌─────────────┐
│ Router │
└──────┬───────┘
┌──────────────┼──────────────┐
v v v
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Vector DB │ │ Graph DB │ │ Web/API │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
└──────────────┼──────────────┘
v
┌───────────────┐
│ Fusion/Rerank │
└───────┬───────┘
v
┌───────────────┐
│ Memory Store │◄──┐ (feedback loop)
└───────┬───────┘ │
v │
┌───────────────┐ │
│ LLM │───┘
└───────────────┘
下一节中的每一种模式,本质上都是对 Modular RAG 构建模块的一种特定配置。
经典方案。纯稠密向量相似度搜索——输入嵌入,通过余弦相似度或点积相似度得到结果。
[Query] --embed--> [Query Vector]
│
v
┌──────────────────┐
│ Vector Index │
│ (HNSW / IVF) │
└─────────┬─────────┘
v
top-k chunks
v
[LLM] --> Answer
适用场景:具有丰富语义的非结构化文本语料库(文档、Wiki、支持文章),且精确关键词匹配并不十分重要。
优点:简单、搭建迅速、工具支持完善(pgvector、Pinecone、Qdrant、Weaviate)。缺点:无法满足精确匹配需求(SKU、错误代码、缩写);不保证相关性;仅执行单次处理。
仅使用稠密搜索时,精确匹配词会导致检索失败(例如 ERR_402、产品代码,以及嵌入模型训练时未学会区分的专有名词)。Hybrid RAG 将稠密向量搜索与稀疏关键词搜索(BM25)融合起来,通常通过 Reciprocal Rank Fusion(RRF,倒数排名融合)合并结果。
┌──────────────┐
┌───────────►│ Dense Search │───────────┐
│ │ (embeddings) │ │
[Query]─┤ └──────────────┘ v
│ ┌───────────┐
│ ┌──────────────┐ │ RRF │──> [LLM] --> Answer
└───────────►│ Sparse Search │─────►│ Fusion │
│ (BM25) │ └───────────┘
└──────────────┘
适用场景:同时需要语义检索和精确匹配检索的混合语料库,例如技术文档、法律文本和电商目录。
优点:兼得两者的召回能力;能够处理嵌入模型遗漏的罕见词和 OOV 词。缺点:需要维护两套索引;融合调优(RRF 常量 k、权重)又增加了需要持续照看的参数。
向量搜索会将每个分块视为一座孤岛。GraphRAG 会在向量索引之外并行构建——或直接用其替代向量索引——一个知识图谱(实体与关系,通常存储于 Neo4j),使检索能够沿关系遍历,而不只是依赖相似度。
[Query] --> [Entity Extraction] --> [Graph Traversal]
│
┌─────────────────┼─────────────────┐
v v v
(Entity A)──relates──(Entity B)──relates──(Entity C)
│ │
└──────────── subgraph ────────────────┘
v
[Context Assembly]
v
[LLM] --> Answer
适用场景:问题需要基于关系进行多跳推理——例如“X 公司依赖的供应商中,哪些还与 Y 地区存在关联?”向量搜索无法回答这个问题,但图遍历可以。
优点:能够捕获关系性和结构性知识;尤其适合合规、组织结构以及依赖关系映射类查询。缺点:构建和维护成本高昂(实体提取及图构建流水线);对于简单查找任务而言过于复杂。
CRAG 在检索后增加了一道质量门:由轻量级评估器对每个检索到的分块进行评级(正确/模糊/错误)。如果置信度较低,它就会触发外部回退方案——例如通过 Tavily 或 DuckDuckGo 进行 Web 搜索——而不是让 LLM 根据垃圾上下文生成答案。
[Query] --> Retrieve --> [Relevance Grader]
│
┌─────────────────┼─────────────────┐
v v v
CORRECT AMBIGUOUS INCORRECT
│ (refine + web) │
│ │ (discard, web search)
└────────┬────────┴────────┬─────────┘
v v
[Knowledge Refinement / External Search]
v
[LLM] --> Answer
适用场景:你的语料库存在覆盖缺口,并且你希望系统能够优雅降级,而不是自信地产生幻觉。
优点:大幅减少因检索结果不相关而导致的幻觉;具备自我修复能力。缺点:会增加额外延迟(评级步骤和潜在的外部调用);评估器的质量会成为一个新的待调优依赖项。
Self-RAG 将反思机制放到了生成端。模型经过训练或提示,会生成用于评估自身输出的反思 token:是否真的需要检索?生成的答案是否得到了检索段落的支持?答案是否有用?
[Query] --> [Retrieve?] --yes--> Retrieve --> Generate --> [Self-Critique]
│no │
v ┌──────────────────┼──────────────────┐
Generate directly v v v
"Supported" "Partially" "Not Supported"
│ │ │
v v v
Return Regenerate Re-retrieve
w/ more context
使用场景:需要内置的幻觉检测,而不必额外部署一个独立验证服务。
优点:更严格的保真度保证;当不需要检索时可直接跳过(节省延迟和成本)。缺点:最佳效果需要微调模型或精心设计的评判步骤;用现成的通用模型实现较难。
并非每个查询都需要相同的处理。自适应 RAG 根据复杂度分类决定查询是否需要无检索、单步检索还是完整的多步智能体推理。
┌───────────────────┐
[Query] --> │ Complexity Router │
└──────────┬─────────┘
┌─────────────────────┼─────────────────────┐
v v v
SIMPLE (no RAG) MODERATE (Standard RAG) COMPLEX (Agentic)
│ │ │
[LLM only] [Retrieve → Gen] [Multi-step reasoning
+ tools + iteration]
└─────────────────────┴─────────────────────┘
v
Answer
使用场景:处理多种查询类型混合(闲聊 + FAQ + 深度分析问题),无法承受每个请求都运行完整智能体的开销。
优点:显著降低延迟和成本;按查询复杂度合理分配计算。缺点:路由准确度成为关键瓶颈——分类错误的复杂查询会得不到充分处理。
检索成为众多工具中的一个,由智能体(或一组专门智能体)编排——它进行规划、调用工具、观察结果、迭代,直到满意。这类似 ReAct 风格的循环或多智能体交接。
┌─────────────────────────────────────────┐
│ Orchestrator Agent │
└──────────────────┬──────────────────────┘
v
┌──────────────┼──────────────┐
v v v
[Retrieval Agent] [SQL Agent] [Web Search Agent]
│ │ │
└──────────────┼──────────────┘
v
[Synthesis / Reflection]
│
(loop if answer incomplete)
v
Final Answer
使用场景:问题需要跨多个异构数据源(数据库、API、文档、实时网络)进行多步推理,中间需要规划。
优点:最灵活和最强大的模式;处理真正复杂的多源任务。缺点:延迟和成本最高;难以调试(非确定性循环);需要强护栏防止工具调用失控。
真实文档不是纯文本——包含图表、表格、图表和扫描图像。多模态 RAG 将文本和视觉内容嵌入到共享(或联合索引)的空间中,使检索能够拉取正确的图表,而不仅仅是其附近的段落。
┌─────────────┐ ┌──────────────┐
[Document]-->│ Text Chunks │ │ Images/Tables/ │
│ │ │ Diagrams │
└──────┬──────┘ └───────┬──────┘
v v
[Text Embedder] [Vision Embedder]
│ │
└────────────┬───────────┘
v
┌────────────────────┐
│ Joint Vector Index │
└──────────┬─────────┘
v
[Query] --> Retrieve (text + visual)
v
[Multi-Modal LLM] --> Answer
使用场景:语料库由包含架构图的 PDF、财务表格、工程图纸或扫描表单组成。
优点:解锁纯文本流水线无声丢弃的信息;匹配人类阅读技术文档的方式。缺点:工具生态相对不成熟(相比纯文本 RAG);多模态嵌入模型运行成本更高。
这是一个紧凑、可运行的模式,结合了混合 RAG(密集检索 + 通过 RRF 的 BM25)和检索后重排步骤——可能是你对朴素流水线进行的最高杠杆升级。
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.retrievers import EnsembleRetriever
from langchain.retrievers.document_compressors import CohereRerank
from langchain.retrievers import ContextualCompressionRetriever
docs = [...] # your pre-chunked Document objects
# 1. Sparse retriever (keyword-based)
bm25_retriever = BM25Retriever.from_documents(docs)
bm25_retriever.k = 10
# 2. Dense retriever (semantic)
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())
dense_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
# 3. Fuse both with Reciprocal Rank Fusion
hybrid_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, dense_retriever],
weights=[0.4, 0.6], # tune based on your corpus
)
# 4. Post-retrieval re-ranking (cross-encoder)
reranker = CohereRerank(model="rerank-english-v3.0", top_n=4)
compression_retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=hybrid_retriever,
)
query = "What caused the Q3 latency regression in the payments service?"
final_docs = compression_retriever.invoke(query)
for doc in final_docs:
print(doc.page_content[:200], "\n---")
为什么这很重要:集合步骤捕捉纯嵌入会遗漏的内容(精确错误代码、服务名),重排器丢弃 top-k 直接送入提示词的噪声。这一个改变通常比交换嵌入模型带来的检索精度提升更大。
一个最小化的 CRAG 风格相关性门,用于对比:
def grade_relevance(query: str, doc: str, llm) -> str:
prompt = f"""Query: {query}
Retrieved passage: {doc}
Is this passage relevant and sufficient to answer the query?
Respond with exactly one word: CORRECT, AMBIGUOUS, or INCORRECT."""
return llm.invoke(prompt).content.strip().upper()
def corrective_retrieve(query, retriever, web_search_fn, llm):
docs = retriever.invoke(query)
grades = [grade_relevance(query, d.page_content, llm) for d in docs]
if all(g == "INCORRECT" for g in grades):
return web_search_fn(query) # fallback to external search
return [d for d, g in zip(docs, grades) if g != "INCORRECT"]
从简单开始。标准密集 RAG 对于狭隘、同质的语料库来说是合法的生产架构——不要仅因为 GraphRAG 流行就急着用。
先修复检索再修复模型。混合搜索 + 重排解决的真实故障比更换 LLM 更多。
当幻觉是业务风险时再加入修正循环(CRAG/Self-RAG),而不是默认加入——它们会增加真实延迟。
一旦流量组合变得多样化,就立即按复杂度路由(自适应 RAG)——这是大规模的最便宜胜利。
最后才考虑智能体 RAG。这是最强大也最昂贵的模式——当任务确实需要多步工具使用时才用,不要因为"智能体"是今年的流行词。
别忘了文档的形态。如果你的语料库充满图表和表格,多模态 RAG 不是可选项——这是阻止无声信息丢失的唯一方式。
这里的真正技能不在于死记八种架构。而在于诊断你实际面对的失败模式,并选用最小化模式来修复它。