RAG 系统架构
本章将深入介绍 RAG 系统的完整架构,让你从全局视角理解各个组件如何协作。
整体架构
一个生产级 RAG 系统远不止"检索+生成"那么简单。完整的架构如下:
graph TB
subgraph 数据处理层
D1[文档加载器] --> D2[文档解析器]
D2 --> D3[文本切分器]
D3 --> D4[Embedding 模型]
D4 --> D5[(向量数据库)]
end
subgraph 检索层
R1[查询理解] --> R2[查询改写]
R2 --> R3[向量检索]
R2 --> R4[关键词检索]
R3 --> R5[混合排序]
R4 --> R5
R5 --> R6[重排序 Reranker]
end
subgraph 生成层
G1[上下文组装] --> G2[Prompt 构建]
G2 --> G3[LLM 生成]
G3 --> G4[后处理]
G4 --> G5[引用标注]
end
D5 --> R3
D5 --> R4
R6 --> G1
G5 --> OUT[最终回答]
style D5 fill:#fff3e0,stroke:#f57c00,stroke-width:3px
style OUT fill:#c8e6c9,stroke:#388e3c,stroke-width:3px
核心组件详解
1. 数据处理层
数据处理层负责将原始文档转化为可检索的向量索引。
graph LR
subgraph 输入
A1[PDF]
A2[Word]
A3[Markdown]
A4[HTML]
A5[数据库]
end
subgraph 处理流程
B1[加载] --> B2[解析]
B2 --> B3[清洗]
B3 --> B4[切分]
B4 --> B5[向量化]
end
subgraph 输出
C1[(向量数据库)]
C2[(元数据存储)]
end
A1 --> B1
A2 --> B1
A3 --> B1
A4 --> B1
A5 --> B1
B5 --> C1
B3 --> C2
style C1 fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
style C2 fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
关键设计决策:
| 组件 | 选项 | 推荐 |
|---|---|---|
| 文档加载 | LangChain Loaders, LlamaIndex, Unstructured | Unstructured(复杂格式) |
| 文本切分 | 固定大小, 语义切分, 递归切分 | 递归切分(通用场景) |
| Embedding | OpenAI, Cohere, BGE, E5 | text-embedding-3-small(性价比) |
| 向量数据库 | Pinecone, Qdrant, Milvus, ChromaDB | Qdrant(开源首选) |
2. 检索层
检索层是 RAG 系统的核心,直接决定最终回答的质量。
"""
检索层核心逻辑示例
"""
class RetrievalPipeline:
"""检索管道"""
def __init__(self, vector_store, reranker=None):
self.vector_store = vector_store
self.reranker = reranker
def retrieve(self, query: str, top_k: int = 5) -> list[dict]:
"""完整检索流程"""
# Step 1: 查询理解与改写
enhanced_queries = self.query_expansion(query)
# Step 2: 多路召回
candidates = []
for q in enhanced_queries:
# 向量检索
vector_results = self.vector_store.similarity_search(q, k=top_k)
candidates.extend(vector_results)
# 关键词检索(BM25)
keyword_results = self.vector_store.keyword_search(q, k=top_k)
candidates.extend(keyword_results)
# Step 3: 去重
candidates = self.deduplicate(candidates)
# Step 4: 重排序
if self.reranker:
candidates = self.reranker.rerank(query, candidates)
return candidates[:top_k]
def query_expansion(self, query: str) -> list[str]:
"""查询扩展:生成多个等价查询"""
return [
query,
self.rephrase(query), # 改写
self.decompose(query), # 分解子问题
]
def deduplicate(self, docs: list[dict]) -> list[dict]:
"""基于内容相似度去重"""
seen = set()
unique = []
for doc in docs:
doc_hash = hash(doc["content"][:100])
if doc_hash not in seen:
seen.add(doc_hash)
unique.append(doc)
return unique
3. 生成层
生成层将检索到的文档转化为高质量的回答。
"""
生成层核心逻辑示例
"""
SYSTEM_PROMPT = """你是一个专业的知识助手。
请根据提供的参考资料回答用户问题。
规则:
1. 只基于参考资料回答,不要编造信息
2. 如果资料不足以回答,诚实说明
3. 在回答中标注引用来源 [1][2]
4. 回答要简洁、准确、有条理"""
def build_prompt(query: str, documents: list[dict]) -> str:
"""构建包含检索结果的 Prompt"""
# 格式化参考资料
references = []
for i, doc in enumerate(documents, 1):
ref = f"[{i}] {doc['title']}\n{doc['content']}"
references.append(ref)
context = "\n\n".join(references)
prompt = f"""## 参考资料
{context}
## 用户问题
{query}
请根据以上参考资料回答用户问题,并标注引用来源编号。"""
return prompt
def generate_with_citations(query: str, documents: list[dict]) -> dict:
"""生成带引用的回答"""
from openai import OpenAI
client = OpenAI()
prompt = build_prompt(query, documents)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": prompt}
],
temperature=0.3,
)
answer = response.choices[0].message.content
return {
"answer": answer,
"sources": [
{"title": doc["title"], "url": doc.get("url", "")}
for doc in documents
]
}
架构模式
模式一:Naive RAG(基础 RAG)
最简单的 RAG 实现,适合快速原型。
graph LR
A[用户问题] --> B[Embedding]
B --> C[向量检索]
C --> D[Top-K 文档]
D --> E[拼接 Prompt]
E --> F[LLM 生成]
F --> G[回答]
style A fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
style G fill:#c8e6c9,stroke:#388e3c,stroke-width:2px
优点:实现简单、快速上线 缺点:检索质量不高、无法处理复杂问题
模式二:Advanced RAG(进阶 RAG)
增加预处理和后处理步骤,显著提升质量。
graph LR
A[用户问题] --> B[查询改写]
B --> C[混合检索]
C --> D[重排序]
D --> E[上下文压缩]
E --> F[LLM 生成]
F --> G[事实核查]
G --> H[回答]
style A fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
style H fill:#c8e6c9,stroke:#388e3c,stroke-width:2px
优点:检索质量高、回答更准确 缺点:延迟增加、实现复杂度高
模式三:Modular RAG(模块化 RAG)
像乐高一样组合不同模块,灵活应对各种场景。
graph TB
A[用户问题] --> B{路由器}
B -->|简单问题| C[直接检索]
B -->|复杂问题| D[问题分解]
B -->|对话问题| E[历史感知检索]
C --> F[生成模块]
D --> D1[子问题1]
D --> D2[子问题2]
D1 --> F
D2 --> F
E --> F
F --> G{质量检查}
G -->|通过| H[返回回答]
G -->|不通过| I[重试/降级]
I --> B
style A fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
style H fill:#c8e6c9,stroke:#388e3c,stroke-width:2px
优点:灵活可配置、适应性强 缺点:设计复杂、维护成本高
技术选型指南
向量数据库选型
| 数据库 | 特点 | 适合场景 | 部署方式 |
|---|---|---|---|
| ChromaDB | 轻量、内嵌式 | 原型开发、小项目 | 本地 |
| Qdrant | 高性能、Rust 编写 | 中大型项目 | 自托管/云 |
| Pinecone | 全托管、零运维 | 企业级、快速上线 | 云服务 |
| Milvus | 分布式、高可扩展 | 超大规模数据 | 自托管/云 |
| Weaviate | GraphQL 接口 | 需要复杂查询 | 自托管/云 |
| pgvector | PostgreSQL 扩展 | 已有 PG 基础设施 | 自托管 |
Embedding 模型选型
| 模型 | 维度 | 性价比 | 多语言 | 推荐场景 |
|---|---|---|---|---|
| text-embedding-3-small | 1536 | 高 | 好 | 通用场景首选 |
| text-embedding-3-large | 3072 | 中 | 好 | 高精度需求 |
| BGE-large-zh | 1024 | 高 | 中文 | 中文场景 |
| E5-large-v2 | 1024 | 高 | 英文 | 英文场景 |
| Cohere embed-v3 | 1024 | 中 | 好 | 多语言场景 |
本章小结
- RAG 系统由数据处理层、检索层、生成层三个核心层组成
- 根据复杂度可选择 Naive RAG、Advanced RAG 或 Modular RAG 架构
- 向量数据库和 Embedding 模型的选型直接影响系统性能
- 生产级系统需要考虑查询改写、混合检索、重排序等高级组件
下一章:我们将学习如何处理不同格式的文档,这是 RAG 系统的数据基础。