订单超时自动取消,你真的做对了吗?从定时任务到千万级高并发方案的完整演进

9 种 RAG 架构深度解析:从入门到生产,每个 AI 开发者都该知道的选型指南

今天在掘金热榜看到一篇"9种RAG架构必学"的文章,阅读量涨得很快。正好最近我在几个项目里踩了不少坑,干脆结合自己的实战经验,把这9种架构逐一拆解一遍,希望对你有用。

引言:为什么 RAG 不是"一招鲜"

很多人第一次接触 RAG(Retrieval-Augmented Generation),往往只知道最简单的那种:向量化文档 → 相似度检索 → 塞进 Prompt → 丢给 LLM。这固然没错,但在生产中你会发现:

  • 检索精度上不去,问个细节问题答非所问
  • 上下文超长,Token 费用飙升
  • 多跳推理(Multi-hop)场景完全撑不住
  • 数据库里有图/表,纯文本 Embedding 搞不定

本文按照从简单到复杂的顺序,系统梳理9种主流RAG架构,每种都附上我认为最适合的应用场景和关键代码片段。


架构一:Naive RAG(朴素 RAG)

适合场景:FAQ 问答、入门原型、文档不超过几十篇

最经典的三步走:

python 复制代码
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI

# 1. 构建向量库
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(docs, embeddings)

# 2. 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})

# 3. 组装 QA 链
qa = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-4o"),
    retriever=retriever
)
result = qa.run("什么是向量数据库?")

核心缺陷:检索的是字面相似,不是语义关联。用户问"苹果手机怎么样",可能召回一堆关于苹果公司财报的文档。


架构二:Advanced RAG(高级 RAG)

适合场景:精度要求较高的知识库问答

在 Naive RAG 基础上,增加了两个关键优化:

1. 查询改写(Query Rewriting)

python 复制代码
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain

rewrite_prompt = PromptTemplate(
    input_variables=["question"],
    template="""请将以下用户问题改写为更适合向量检索的形式,
    去除口语化表达,增加关键术语:
    原始问题:{question}
    改写后:"""
)
rewrite_chain = LLMChain(llm=llm, prompt=rewrite_prompt)
better_query = rewrite_chain.run(question=user_question)

2. 重排序(Reranking)

python 复制代码
from sentence_transformers import CrossEncoder

reranker = CrossEncoder("BAAI/bge-reranker-base")

# 先召回多一些候选
candidates = retriever.get_relevant_documents(better_query, k=20)

# 用 CrossEncoder 重排,取 Top 4
scores = reranker.predict([(better_query, doc.page_content) for doc in candidates])
ranked = sorted(zip(scores, candidates), key=lambda x: x[0], reverse=True)
top_docs = [doc for _, doc in ranked[:4]]

我在实际项目中用 BGE-Reranker 后,答案准确率提升了约 25%,强烈建议每个项目都加上这一步。


架构三:Modular RAG(模块化 RAG)

适合场景:复杂业务系统,需要灵活拼装各个组件

把 RAG 流程拆成可插拔的模块:

css 复制代码
用户问题
  ↓
[查询分析模块] → 判断意图、提取实体
  ↓
[路由模块] → 选择知识库(产品文档/技术文档/FAQ)
  ↓
[检索模块] → 向量/关键词/混合检索
  ↓
[融合模块] → 多路结果合并去重
  ↓
[生成模块] → 带引用的答案生成

这种架构的好处是:各模块可以独立迭代,不影响整体流程。生产级系统必备。


架构四:RAG Fusion(融合检索)

适合场景:单一查询命中率低,需要多角度召回

核心思路:用 LLM 生成多个相关查询,分别检索后用 RRF(Reciprocal Rank Fusion)合并排序

python 复制代码
def generate_queries(question: str, n: int = 4) -> list[str]:
    """生成多个角度的查询"""
    prompt = f"""为以下问题生成{n}个不同角度的检索查询,每行一个:
    问题:{question}
    查询列表:"""
    response = llm.predict(prompt)
    return [q.strip() for q in response.split('\n') if q.strip()]

def rrf_score(rankings: list[list], k: int = 60) -> dict:
    """Reciprocal Rank Fusion 打分"""
    scores = {}
    for ranking in rankings:
        for rank, doc_id in enumerate(ranking, 1):
            scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank)
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

# 执行
queries = generate_queries(user_question)
all_results = [retriever.get_relevant_documents(q) for q in queries]
fused_docs = rrf_score([[doc.metadata['id'] for doc in r] for r in all_results])

亲测:在"多义词"和"模糊意图"场景下,RAG Fusion 的召回率比 Naive RAG 高出 40% 左右。


架构五:Self-RAG(自反思 RAG)

适合场景:答案质量要求极高,允许有额外延迟

Self-RAG 让模型在生成时自我评判是否需要检索,以及检索结果是否有用:

python 复制代码
def self_rag_generate(question: str) -> str:
    # Step 1: 判断是否需要检索
    need_retrieval = llm.predict(
        f"问题:{question}\n是否需要检索外部知识才能回答?(是/否)"
    )
    
    if "是" in need_retrieval:
        docs = retriever.get_relevant_documents(question)
        
        # Step 2: 评估每个文档的相关性
        relevant_docs = []
        for doc in docs:
            relevance = llm.predict(
                f"文档:{doc.page_content}\n问题:{question}\n该文档与问题相关吗?(相关/不相关)"
            )
            if "相关" in relevance:
                relevant_docs.append(doc)
        
        # Step 3: 生成答案并自我评估
        context = "\n".join([d.page_content for d in relevant_docs])
        answer = llm.predict(f"基于以下内容回答问题:\n{context}\n\n问题:{question}")
        
        # Step 4: 验证答案是否有幻觉
        is_grounded = llm.predict(
            f"答案:{answer}\n来源:{context}\n答案是否完全基于来源,没有虚构内容?(是/否)"
        )
        return answer if "是" in is_grounded else "无法基于现有知识库回答此问题"
    else:
        return llm.predict(question)

代价:每次查询要多调用 3-5 次 LLM,延迟和成本显著增加。仅在高价值场景(如医疗、法律)中使用。


架构六:CRAG(Corrective RAG,纠错 RAG)

适合场景:文档质量参差不齐,需要动态纠错

CRAG 在 Self-RAG 基础上增加了纠错能力:当检索到的文档相关性低时,自动通过 Web Search 补充信息。

python 复制代码
def crag_pipeline(question: str) -> str:
    docs = retriever.get_relevant_documents(question)
    
    # 评估相关性
    relevance_scores = [evaluate_relevance(doc, question) for doc in docs]
    avg_score = sum(relevance_scores) / len(relevance_scores)
    
    if avg_score > 0.7:
        # 文档质量高,直接用
        context = "\n".join([d.page_content for d in docs])
    elif avg_score > 0.3:
        # 质量中等,混合使用本地+网络
        web_results = web_search(question)
        context = "\n".join([d.page_content for d in docs] + web_results)
    else:
        # 质量太低,完全依赖网络搜索
        context = "\n".join(web_search(question))
    
    return llm.predict(f"基于以下内容回答:\n{context}\n\n问题:{question}")

架构七:Graph RAG(知识图谱 RAG)

适合场景:实体关系推理、企业知识图谱、复杂依赖查询

普通向量检索找的是"相似内容",Graph RAG 找的是"关联实体":

python 复制代码
from neo4j import GraphDatabase

class GraphRAG:
    def __init__(self, uri, user, password):
        self.driver = GraphDatabase.driver(uri, auth=(user, password))
    
    def query_entity_context(self, entity: str, depth: int = 2) -> str:
        """查询实体及其N跳关系的上下文"""
        with self.driver.session() as session:
            result = session.run("""
                MATCH path = (n {name: $entity})-[*1..%d]-(m)
                RETURN path
                LIMIT 50
            """ % depth, entity=entity)
            
            context_parts = []
            for record in result:
                path = record["path"]
                # 将路径转换为自然语言描述
                context_parts.append(path_to_text(path))
            
            return "\n".join(context_parts)
    
    def answer(self, question: str) -> str:
        entities = extract_entities(question)  # NER 提取实体
        context = "\n".join([self.query_entity_context(e) for e in entities])
        return llm.predict(f"已知信息:\n{context}\n\n回答:{question}")

微软 GraphRAG 是这个方向目前最成熟的开源实现,在复杂报告分析场景下比向量 RAG 强很多。


架构八:Agentic RAG(Agent 式 RAG)

适合场景:需要多步推理、工具调用、动态决策

Agentic RAG 不再是"检索 → 生成"的线性流程,而是让 Agent 自主决定何时检索、检索什么、是否需要多次迭代:

python 复制代码
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Tool

# 定义可用工具
tools = [
    Tool(
        name="knowledge_base_search",
        func=lambda q: retriever.get_relevant_documents(q),
        description="搜索内部知识库,适合查找产品文档、技术规范"
    ),
    Tool(
        name="web_search",
        func=lambda q: search_web(q),
        description="搜索互联网,适合获取最新信息"
    ),
    Tool(
        name="calculator",
        func=lambda expr: eval(expr),
        description="计算数学表达式"
    ),
    Tool(
        name="code_executor",
        func=lambda code: exec_python(code),
        description="执行Python代码来验证某些假设"
    )
]

# 创建 ReAct Agent
agent = create_react_agent(llm, tools, react_prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": user_question})

我的实战观察 :Agentic RAG 适合"深度问答",但对于"快速问答"来说太重了。建议设置 max_iterations=5 防止无限循环。


架构九:Multimodal RAG(多模态 RAG)

适合场景:文档包含图表、PDF 表格、流程图

纯文本 Embedding 无法处理图像中的信息,多模态 RAG 的做法是:

python 复制代码
from transformers import CLIPProcessor, CLIPModel
from PIL import Image
import torch

class MultimodalRAG:
    def __init__(self):
        self.clip_model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
        self.clip_processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
    
    def embed_image(self, image_path: str) -> torch.Tensor:
        """生成图片的 CLIP Embedding"""
        image = Image.open(image_path)
        inputs = self.clip_processor(images=image, return_tensors="pt")
        with torch.no_grad():
            features = self.clip_model.get_image_features(**inputs)
        return features / features.norm(dim=-1, keepdim=True)
    
    def embed_text(self, text: str) -> torch.Tensor:
        """生成文本的 CLIP Embedding(与图片在同一语义空间)"""
        inputs = self.clip_processor(text=[text], return_tensors="pt", padding=True)
        with torch.no_grad():
            features = self.clip_model.get_text_features(**inputs)
        return features / features.norm(dim=-1, keepdim=True)
    
    def retrieve(self, question: str, image_pool: list) -> list:
        """用文本查询找相关图片"""
        query_emb = self.embed_text(question)
        scores = []
        for img_path in image_pool:
            img_emb = self.embed_image(img_path)
            score = (query_emb @ img_emb.T).item()
            scores.append((score, img_path))
        return sorted(scores, reverse=True)[:3]

然后用 GPT-4o 或 Claude 3.5 这类视觉模型同时处理文本 + 图片,生成最终答案。


如何选择?一张对比表

架构 复杂度 延迟 成本 推荐场景
Naive RAG 快速原型
Advanced RAG ⭐⭐ 大多数业务场景
Modular RAG ⭐⭐⭐ 复杂生产系统
RAG Fusion ⭐⭐ 中高 多义词/模糊查询
Self-RAG ⭐⭐⭐⭐ 高精度场景
CRAG ⭐⭐⭐ 中高 中高 文档质量不稳定
Graph RAG ⭐⭐⭐⭐ 实体关系推理
Agentic RAG ⭐⭐⭐⭐⭐ 多步复杂推理
Multimodal RAG ⭐⭐⭐ 含图表文档

总结

RAG 不是一个架构,而是一个架构家族。我的选型建议:

  1. 新项目先用 Advanced RAG:基础向量检索 + 查询改写 + BGE-Reranker,80% 的业务场景够用了
  2. 遇到多跳推理才上 Graph RAG:别过早引入知识图谱的维护成本
  3. 高价值场景才用 Self-RAG / CRAG:多余的 LLM 调用成本很高
  4. Agentic RAG 是终态,但不是起点:从简单架构迭代上去,别一上来就全套 Agent

最后说一句实战心得:Reranker 永远值得加。不管用哪种架构,在最后检索结果送入 LLM 之前加一个 BGE-Reranker,几乎对所有场景都有正向收益,投入产出比极高。


如果你在 RAG 实战中踩过坑,或者有其他架构经验,欢迎评论区交流 🙌

相关推荐
程序员cxuan1 小时前
速度太快了!本地可以跑 DeepSeek-V4-Flash 了
人工智能·后端·程序员
阿祖zu2 小时前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
不才不才不不才2 小时前
Spring 源码系列(16): doDispatch 全流程——一次请求的主干链路
java·后端·spring
IT_陈寒2 小时前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端
搜狐技术产品小编20233 小时前
告别“黑盒”与误判:如何用“多智能体对抗辩论”重构内容安全审核系统
后端·多agent
DantyWei3 小时前
controller注册及调用时机
后端
edwarddamon3 小时前
Spring Cloud 配置热更新与 Bean 代理机制梳理
java·后端
码事漫谈4 小时前
我用 Seed Evolving 做了个 AI 小说写作工具
后端
Raas1004 小时前
MAIGateway,魔芋企业级AI网关的FinAPI成本竞争力设计
java·后端·网关·api网关·魔芋ai·finapi·mai gateway
计算机魔术师4 小时前
传统基础架构 - 微服务
大数据·后端·微服务·架构·开发工具·编程语言