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

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 实战中踩过坑,或者有其他架构经验,欢迎评论区交流 🙌

相关推荐
ServBay2 小时前
2026年重新定义 Python 开发工作流的8个现代化工具
后端·python
Java内核笔记2 小时前
Spring Security 过滤器链的构建过程:从 HttpSecurity 到 DefaultSecurityFilterChain
后端
自进化Agent智能体2 小时前
Hermes 自进化Skill:让AI能力自己长出来
后端
宇宙之一粟3 小时前
如何判断是时候离开了
后端·程序员
武子康4 小时前
Java-16 深入浅出MyBatis 架构设计与源码剖析:从初始化到 SQL 执行全流程
java·后端
逍遥运德4 小时前
Java编程高频的“技术点”-03:“下划线命名”参数,后端用"驼峰命名"接收
java·后端·架构
To_OC4 小时前
阿里云多模态图片生成!抛弃SDK手写Fetch请求,我终于搞懂了大模型调用底层
javascript·后端·aigc
西安邮电大学4 小时前
binlog/redolog/undolog三者对比
java·后端·其他·面试