11a - RAG 概念与架构
本文是《AI Agent 实战手册》第 11 章第 1 节。 上一节:10e-多Agent实战案例 | 下一节:11b-RAG流水线详解
概述
检索增强生成(Retrieval-Augmented Generation,RAG)是当前 AI 应用中最重要的架构模式之一。它通过将大语言模型(LLM)与外部知识检索系统相结合,让 AI 能够基于最新、可验证的事实生成回答,而非仅依赖模型训练时的静态知识。本节将系统讲解 RAG 的核心概念、动机、端到端架构,以及从 Naive RAG 到 Advanced RAG 再到 Modular RAG 的演进历程。
1. 什么是 RAG?
核心概念
RAG(Retrieval-Augmented Generation)是一种混合 AI 架构范式,将信息检索与文本生成两个能力组合在一起。其核心思想可以用一个类比来理解:
- 传统 LLM = 闭卷考试:模型只能依赖训练时记住的知识
- RAG = 开卷考试:模型可以在回答时查阅外部资料库,获取最新、准确的信息
RAG 的基本工作流程:
- 用户提问:用户输入一个查询(Query)
- 检索相关文档:系统从外部知识库中检索与查询最相关的文档片段
- 增强上下文:将检索到的文档片段与原始查询一起组装成增强的 Prompt
- 生成回答:LLM 基于增强后的上下文生成有据可查的回答
关键术语
| 术语 | 英文 | 说明 |
|---|---|---|
| 检索器 | Retriever | 负责从知识库中找到相关文档的组件 |
| 生成器 | Generator | 负责基于检索结果生成回答的 LLM |
| 知识库 | Knowledge Base | 存储文档、数据的外部数据源 |
| 向量数据库 | Vector Database | 存储文档嵌入向量的专用数据库 |
| 嵌入模型 | Embedding Model | 将文本转换为数值向量的模型 |
| 分块 | Chunking | 将长文档切分为适合检索的小片段 |
| 重排序 | Re-ranking | 对检索结果进行二次排序以提高相关性 |
2. 为什么需要 RAG?
LLM 的固有局限
大语言模型虽然强大,但存在几个根本性问题:
| 问题 | 说明 | 影响 |
|---|---|---|
| 知识截止 | 模型训练数据有时间截止点,无法获知最新信息 | 回答过时问题时给出错误答案 |
| 幻觉 | 模型可能自信地编造不存在的事实 | 生成看似合理但完全错误的内容 |
| 缺乏私有知识 | 模型不了解企业内部文档、代码库等私有数据 | 无法回答组织特定的问题 |
| 不可溯源 | 模型无法说明回答的信息来源 | 难以验证回答的准确性 |
| 更新成本高 | 重新训练或微调模型成本极高 | 知识更新周期长、费用大 |
RAG vs 微调(Fine-tuning):何时选择哪个?
| 维度 | RAG | 微调(Fine-tuning) |
|---|---|---|
| 知识更新 | ✅ 实时更新,修改知识库即可 | ❌ 需要重新训练,周期长 |
| 前期成本 | 中等(需要检索基础设施) | 高(需要训练数据和 GPU 资源) |
| 运行成本 | 每次查询有检索开销 | 推理成本与普通模型相同 |
| 可溯源性 | ✅ 可以引用具体来源文档 | ❌ 知识融入模型权重,不可追溯 |
| 适用场景 | 知识频繁变化、需要引用来源 | 风格/格式固定、领域术语适配 |
| 幻觉控制 | ✅ 基于检索事实,幻觉率低 | 中等,仍可能产生幻觉 |
| 数据隐私 | ✅ 数据留在本地知识库 | ⚠️ 训练数据可能泄露到模型中 |
选择建议:
- 选 RAG:当你的回答依赖于频繁变化的文档、需要引用来源、或涉及私有数据时
- 选微调:当你需要一致的输出风格、特定领域的术语适配、或模式固定的结构化输出时
- 两者结合:在生产环境中,RAG + 微调的组合往往能获得最佳效果——微调让模型更好地理解领域语言,RAG 提供最新的事实依据
3. RAG 端到端架构
架构总览图
┌─────────────────────────────────────────────────────────────────────┐
│ RAG 端到端架构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ 离线阶段(Indexing Pipeline) │
│ │ │ │
│ │ 原始文档 │ ┌──────┐ ┌──────┐ ┌──────┐ ┌────────┐ │
│ │ PDF/MD/HTML │───▶│ 解析 │──▶│ 分块 │──▶│ 嵌入 │──▶│向量数据库│ │
│ │ 代码/数据库 │ │Parser│ │Chunk │ │Embed │ │VectorDB│ │
│ │ │ └──────┘ └──────┘ └──────┘ └────────┘ │
│ └──────────────┘ │ │
│ │ │
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤ │
│ │ │
│ 在线阶段(Query Pipeline) │ │
│ ▼ │
│ ┌──────┐ ┌────────┐ ┌──────┐ ┌──────┐ ┌──────────────┐ │
│ │ 用户 │──▶│查询转换 │──▶│ 检索 │──▶│ 重排序│──▶│ Prompt 组装 │ │
│ │Query │ │Rewrite │ │Search│ │Rerank│ │ + LLM 生成 │ │
│ └──────┘ └────────┘ └──────┘ └──────┘ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ 回答+来源 │ │
│ │ Response │ │
│ └──────────┘ │
└─────────────────────────────────────────────────────────────────────┘两大阶段详解
阶段一:离线索引(Indexing Pipeline)
这是数据准备阶段,将原始文档转化为可检索的向量索引:
- 文档解析(Parsing):从 PDF、Markdown、HTML、数据库等多种来源提取文本内容
- 文档分块(Chunking):将长文档切分为语义完整的小片段(通常 256-1024 tokens)
- 向量嵌入(Embedding):使用嵌入模型将每个文本片段转换为高维数值向量
- 向量存储(Storage):将向量及其元数据存入向量数据库,建立索引
阶段二:在线查询(Query Pipeline)
这是用户交互阶段,处理查询并生成回答:
- 查询转换(Query Transformation):优化用户原始查询(如查询扩展、HyDE 等)
- 向量检索(Retrieval):在向量数据库中搜索与查询最相似的文档片段
- 重排序(Re-ranking):使用交叉编码器等模型对检索结果进行精排
- Prompt 组装与生成:将检索到的上下文与查询组装成 Prompt,送入 LLM 生成回答
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| LlamaIndex | RAG 专用框架,数据索引与检索优化 | 免费(MIT 开源) | 文档密集型 RAG 应用,快速原型 |
| LangChain | 通用 LLM 编排框架,支持完整 RAG 生命周期 | 免费(MIT 开源) | 复杂多步骤工作流,Agent + RAG |
| Haystack | 生产级 NLP 管线框架,混合搜索 | 免费(Apache 2.0 开源) | 企业级生产部署,混合搜索场景 |
| Pinecone | 托管向量数据库 | 免费层可用;标准版 $70/月起 | 零运维需求的云端向量存储 |
| Weaviate | 开源向量数据库,支持混合搜索 | 免费(自托管);云版 $25/月起 | 需要混合搜索(向量+关键词)的场景 |
| ChromaDB | 轻量级开源向量数据库 | 免费(开源) | 本地开发、原型验证、小规模应用 |
| Qdrant | 高性能开源向量搜索引擎 | 免费(自托管);云版 $25/月起 | 高性能检索需求,Rust 实现 |
| OpenAI Embeddings | 文本嵌入 API | text-embedding-3-small: $0.02/百万 tokens | 快速集成,高质量通用嵌入 |
| Cohere Embed | 多语言嵌入模型 | 免费层 100 次/分钟;生产版按量计费 | 多语言 RAG 场景 |
| Unstructured | 文档解析与预处理 | 免费(开源);API 版 $0.01/页起 | 复杂文档格式(PDF、PPT、图片)解析 |
4. RAG 的演进:从 Naive 到 Advanced 到 Modular
RAG 架构经历了三代演进,每一代都在解决前一代的核心痛点。
4.1 Naive RAG(朴素 RAG)
最基础的 RAG 实现,遵循简单的”检索-读取-生成”流程:
用户查询 ──▶ 向量相似度搜索 ──▶ Top-K 文档 ──▶ 拼接到 Prompt ──▶ LLM 生成特点:
- 实现简单,适合快速验证概念
- 使用单一的向量相似度检索
- 直接将检索结果拼接到 Prompt 中
局限:
- 检索精度低:语义相似不等于真正相关
- 冗余和噪声:Top-K 结果可能包含大量无关内容
- 缺乏查询理解:不对用户查询做任何优化
- 上下文窗口浪费:无关内容占用宝贵的上下文空间
4.2 Advanced RAG(高级 RAG)
在 Naive RAG 基础上,在检索前和检索后增加优化环节:
用户查询 ──▶ 查询优化 ──▶ 混合检索 ──▶ 重排序 ──▶ 上下文压缩 ──▶ LLM 生成
(Pre-retrieval) (Post-retrieval)关键改进:
| 阶段 | 技术 | 作用 |
|---|---|---|
| 检索前 | 查询重写(Query Rewriting) | 优化查询表述,提高检索命中率 |
| 检索前 | HyDE(假设文档嵌入) | 先让 LLM 生成假设答案,用假设答案做检索 |
| 检索前 | 查询分解(Query Decomposition) | 将复杂查询拆分为多个子查询 |
| 检索中 | 混合搜索(Hybrid Search) | 结合向量搜索和关键词搜索(BM25) |
| 检索中 | 多路召回(Multi-path Retrieval) | 从多个索引或数据源并行检索 |
| 检索后 | 交叉编码器重排序(Cross-encoder Reranking) | 用更精确的模型对结果重新排序 |
| 检索后 | 上下文压缩(Context Compression) | 去除冗余,只保留最相关的片段 |
| 检索后 | 去重与融合(Dedup & Fusion) | 合并多路召回结果,去除重复 |
4.3 Modular RAG(模块化 RAG)
2025 年的主流趋势,将 RAG 系统拆解为可独立替换和组合的模块:
┌─────────────────────────────────────────────────────┐
│ Modular RAG 架构 │
├─────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 路由模块 │ │ 检索模块 │ │ 生成模块 │ │
│ │ Router │ │Retriever│ │Generator│ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │
│ │查询分析 │ │向量检索 │ │Prompt │ │
│ │意图识别 │ │关键词检索│ │模板引擎 │ │
│ │路由决策 │ │图谱检索 │ │输出格式化│ │
│ └─────────┘ │SQL 检索 │ │引用标注 │ │
│ └─────────┘ └─────────┘ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 评估模块 │ │ 记忆模块 │ │ 编排模块 │ │
│ │Evaluator│ │ Memory │ │Orchestra│ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────────────────┘核心特征:
- 条件检索:不是每次都检索,而是根据查询类型智能决定是否需要检索、从哪里检索
- 模块可插拔:每个模块可以独立替换(如更换向量数据库、切换嵌入模型)
- 自适应流程:根据查询复杂度动态调整处理流程
- 多数据源融合:可以同时从向量库、知识图谱、SQL 数据库等多种来源检索
三代 RAG 对比
| 维度 | Naive RAG | Advanced RAG | Modular RAG |
|---|---|---|---|
| 检索策略 | 单一向量搜索 | 混合搜索 + 重排序 | 多源自适应检索 |
| 查询处理 | 无 | 查询重写/分解 | 意图识别 + 智能路由 |
| 后处理 | 无 | 重排序 + 压缩 | 评估 + 自我修正 |
| 架构灵活性 | 固定流程 | 增强流程 | 模块可插拔 |
| 实现复杂度 | 低 | 中 | 高 |
| 适用场景 | 原型验证、简单问答 | 生产级应用 | 企业级复杂系统 |
| 检索精度 | 一般 | 较高 | 最高 |
| 2025 推荐度 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
5. RAG 核心组件详解
5.1 嵌入模型(Embedding Model)
嵌入模型是 RAG 的基石,负责将文本转换为数值向量,使得语义相似的文本在向量空间中距离更近。
主流嵌入模型对比:
| 模型 | 维度 | 最大 Tokens | 价格 | 特点 |
|---|---|---|---|---|
| OpenAI text-embedding-3-large | 3072 | 8191 | $0.13/百万 tokens | 高质量通用嵌入 |
| OpenAI text-embedding-3-small | 1536 | 8191 | $0.02/百万 tokens | 性价比之选 |
| Cohere embed-v4 | 1024 | 512 | 免费层可用 | 多语言支持优秀 |
| Voyage AI voyage-3 | 1024 | 32000 | $0.06/百万 tokens | 代码和技术文档优化 |
| BGE-M3(开源) | 1024 | 8192 | 免费 | 多语言、多粒度、多功能 |
| Jina Embeddings v3(开源) | 1024 | 8192 | 免费(自托管) | 任务自适应嵌入 |
5.2 向量数据库(Vector Database)
向量数据库是 RAG 系统的存储核心,负责高效存储和检索向量。详细对比见 11c-向量数据库对比。
5.3 检索策略
| 策略 | 原理 | 优势 | 劣势 |
|---|---|---|---|
| 稠密检索(Dense) | 基于向量相似度(余弦/点积) | 语义理解强 | 对精确匹配弱 |
| 稀疏检索(Sparse) | 基于关键词匹配(BM25/TF-IDF) | 精确匹配强 | 缺乏语义理解 |
| 混合检索(Hybrid) | 结合稠密和稀疏检索 | 兼顾语义和精确匹配 | 需要调权重 |
| 知识图谱检索 | 基于实体关系图的结构化检索 | 关系推理强 | 构建成本高 |
6. Agentic RAG:RAG 的未来方向
2025 年,RAG 正在与 Agent 架构深度融合,形成 Agentic RAG——让 AI Agent 自主决定何时检索、从哪里检索、如何验证检索结果。
┌──────────────────────────────────────────────┐
│ Agentic RAG 架构 │
├──────────────────────────────────────────────┤
│ │
│ 用户查询 │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Agent 大脑│◀─── 规划、推理、自我修正 │
│ └────┬─────┘ │
│ │ │
│ ├──▶ 需要检索?──▶ 选择数据源 │
│ │ │ │ │
│ │ ▼ ▼ │
│ │ 向量库 知识图谱 SQL 数据库 │
│ │ │ │ │
│ │ └──────┬───────┘ │
│ │ ▼ │
│ │ 评估检索质量 │
│ │ │ │
│ │ ├── 质量不足 ──▶ 重新检索/换策略 │
│ │ │ │
│ │ └── 质量足够 ──▶ 生成回答 │
│ │ │
│ └──▶ 不需要检索?──▶ 直接回答 │
│ │
└──────────────────────────────────────────────┘Agentic RAG 的关键能力:
- 自主决策:Agent 判断是否需要检索,避免不必要的检索开销
- 多源编排:根据查询类型选择最合适的数据源
- 质量自评:评估检索结果是否足够回答问题,不够则重试
- 迭代优化:通过多轮检索-评估循环逐步逼近最佳答案
操作步骤:5 分钟搭建你的第一个 RAG 系统
步骤 1:安装依赖
pip install llama-index openai chromadb步骤 2:准备文档
将你的文档(PDF、Markdown、TXT 等)放入一个目录:
mkdir -p ./data
# 将文档复制到 ./data 目录步骤 3:构建索引并查询
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
# 1. 加载文档
documents = SimpleDirectoryReader("./data").load_data()
# 2. 构建向量索引(自动分块 + 嵌入 + 存储)
index = VectorStoreIndex.from_documents(documents)
# 3. 创建查询引擎
query_engine = index.as_query_engine()
# 4. 提问
response = query_engine.query("这个项目的主要功能是什么?")
print(response)步骤 4:验证结果
# 查看检索到的来源文档
for node in response.source_nodes:
print(f"来源: {node.metadata.get('file_name', 'unknown')}")
print(f"相关度: {node.score:.4f}")
print(f"内容片段: {node.text[:200]}...")
print("---")提示词模板
RAG 系统 Prompt 模板
你是一个基于知识库的问答助手。请严格根据以下检索到的上下文信息回答用户问题。
## 规则
1. 只使用提供的上下文信息回答问题
2. 如果上下文中没有相关信息,明确说"根据现有知识库,我无法找到相关信息"
3. 在回答中标注信息来源(如 [来源: 文档名])
4. 不要编造上下文中不存在的信息
## 上下文信息
[检索到的文档片段]
## 用户问题
[用户的查询]
## 回答要求
- 简洁准确,直接回答问题
- 标注信息来源
- 如有不确定之处,明确说明RAG 查询优化 Prompt 模板
请将以下用户查询优化为更适合向量检索的形式。
原始查询:[用户原始问题]
优化要求:
1. 保持原始意图不变
2. 扩展关键术语(添加同义词)
3. 如果查询模糊,生成 2-3 个更具体的子查询
4. 去除口语化表达,使用专业术语
输出格式:
- 优化后的主查询:...
- 子查询 1:...
- 子查询 2:...实战案例:为代码仓库构建 RAG 问答系统
场景
为一个大型开源项目构建内部问答系统,让新成员能快速了解项目架构和代码逻辑。
实现方案
from llama_index.core import (
VectorStoreIndex,
SimpleDirectoryReader,
Settings,
StorageContext,
)
from llama_index.core.node_parser import CodeSplitter
from llama_index.vector_stores.chroma import ChromaVectorStore
import chromadb
# 1. 配置代码专用分块器
code_splitter = CodeSplitter(
language="python",
chunk_lines=40, # 每块 40 行
chunk_lines_overlap=5, # 重叠 5 行
max_chars=1500,
)
# 2. 加载代码文件
documents = SimpleDirectoryReader(
input_dir="./my-project/src",
recursive=True,
required_exts=[".py", ".ts", ".md"],
).load_data()
# 3. 使用 ChromaDB 持久化存储
chroma_client = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = chroma_client.get_or_create_collection("codebase")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
# 4. 构建索引
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context,
transformations=[code_splitter],
)
# 5. 查询
query_engine = index.as_query_engine(similarity_top_k=5)
response = query_engine.query("用户认证模块是如何实现的?")
print(response)案例分析
- 分块策略:代码文件使用
CodeSplitter按语法结构分块,而非简单按字符数切分,保证每个块是语义完整的代码单元 - 持久化存储:使用 ChromaDB 持久化,避免每次启动都重新构建索引
- 多格式支持:同时索引代码文件(.py、.ts)和文档文件(.md),提供全面的知识覆盖
- Top-K 调优:设置
similarity_top_k=5,在召回率和精度之间取得平衡
避坑指南
❌ 常见错误
-
分块策略不当导致语义断裂
- 问题:使用固定字符数分块,导致句子或代码块被截断,检索到的片段缺乏完整语义
- 正确做法:根据内容类型选择合适的分块策略——文本用语义分块(按段落/章节),代码用语法感知分块(按函数/类)。设置适当的重叠(overlap)以保持上下文连贯
-
嵌入模型与查询语言不匹配
- 问题:使用英文优化的嵌入模型处理中文文档,导致检索质量严重下降
- 正确做法:选择支持目标语言的嵌入模型(如 BGE-M3 支持多语言),或使用针对特定语言优化的模型。在部署前用目标语言的测试集验证检索质量
-
忽略检索后处理,直接将 Top-K 结果塞入 Prompt
- 问题:Top-K 结果中可能包含冗余、矛盾或不相关的内容,浪费上下文窗口并干扰生成质量
- 正确做法:添加重排序(Reranking)步骤过滤低质量结果,使用上下文压缩去除冗余信息。生产系统中,重排序通常能将回答准确率提升 10-20%
-
过度依赖向量相似度,忽略关键词精确匹配
- 问题:用户查询包含专有名词、产品编号等精确信息时,纯向量搜索可能找不到精确匹配
- 正确做法:使用混合搜索(Hybrid Search),结合向量检索和 BM25 关键词检索,通过权重调节平衡两者
-
没有评估体系就上线生产
- 问题:无法量化 RAG 系统的回答质量,上线后出现问题难以定位是检索问题还是生成问题
- 正确做法:在上线前建立评估体系,使用 RAGAS 等框架测量 faithfulness(忠实度)、relevance(相关性)、context precision(上下文精度)等指标。详见 11f-RAG评估与优化
✅ 最佳实践
- 从 Naive RAG 开始,逐步迭代到 Advanced RAG——先验证业务价值,再优化技术细节
- 建立端到端的评估管线——每次修改分块策略、嵌入模型或检索参数后,都用标准测试集验证效果
- 元数据是被低估的利器——为文档添加丰富的元数据(来源、日期、类别、作者),支持过滤检索
- 监控检索质量指标——追踪检索命中率、平均相关度分数、用户满意度等运行时指标
- 定期更新知识库——建立文档更新管线,确保知识库与源数据保持同步
相关资源与延伸阅读
- LlamaIndex 官方文档 — RAG 入门教程 :最全面的 RAG 框架文档,包含从入门到高级的完整教程
- LangChain RAG 教程 :LangChain 官方 RAG 实现指南,适合已有 LangChain 经验的开发者
- Pinecone — RAG 学习中心 :Pinecone 出品的 RAG 概念和实践系列文章
- RAGAS 评估框架文档 :RAG 系统评估的事实标准框架,提供自动化评估指标
- Haystack 官方文档 :生产级 RAG 管线框架,适合企业部署场景
- Weaviate — RAG 架构指南 :从向量数据库视角解读 RAG 架构
- Anthropic — RAG 最佳实践 :Claude 官方推荐的 RAG 集成方式
- OpenAI Cookbook — RAG 示例 :OpenAI 官方 RAG 代码示例集合
参考来源
- Retrieval-Augmented Generation (RAG) in 2025: Innovations, Architecture, Adoption, and Frameworks (2025-05)
- Optimizing Retrieval-Augmented Generation: Architecture, Retrieval Strategies, and Reliability Patterns (2025-12)
- RAG is Dead, Long Live RAG: Retrieval in the Age of Agents (2025-06)
- Naive RAG, Advanced RAG, and Modular RAG Architectures (2025-01)
- Native RAG vs. Advanced RAG vs. Modular RAG — Zilliz (2025-03)
- How to Implement Naive RAG, Advanced RAG, and Modular RAG (2025-12)
- RAG vs Fine-tuning in 2025: A Practical Playbook for Teams (2025-10)
- Best RAG Frameworks 2025: LangChain vs LlamaIndex vs Haystack (2025-11)
- RAG Framework Comparison — Athenic Blog (2025-09)
📖 返回 总览与导航 | 上一节:10e-多Agent实战案例 | 下一节:11b-RAG流水线详解