RAG 原理
是什么
RAG(Retrieval-Augmented Generation,检索增强生成)是一种将信息检索与 LLM 生成结合的技术架构。
RAG = 让 AI 先”查资料”,再”写回答”。
一句话理解:RAG 给了 LLM 一双眼睛,让它在回答之前先看看最新的、私有的知识,而不是纯靠记忆。
传统 LLM:用户提问 → 模型凭记忆回答 → 可能幻觉、过时
RAG: 用户提问 → 检索相关文档 → 将文档作为上下文 → 模型基于文档回答
为什么需要 RAG
LLM 单独使用的三大痛点
| 痛点 | 说明 |
|---|---|
| 知识截止 | 预训练数据有时间边界,不知道训练后发生的事 |
| 幻觉 | 对不确定的知识会”编造”一个看似合理的答案 |
| 无法访问私有数据 | 模型不知道你公司的文档、代码库、业务规则 |
RAG 的解法
- 实时性:检索最新的文档/数据,不受训练截止日期限制
- 可追溯:回答基于具体文档,可以标注来源,用户能验证
- 低成本:不需要微调模型(微调成本高、周期长),只需管理好文档库
- 安全:私有数据不进入模型训练,减少数据泄露风险
RAG vs 微调
| 维度 | RAG | 微调(Fine-tuning) |
|---|---|---|
| 知识更新 | 更新文档即可,分钟级 | 需要重新训练,天级 |
| 成本 | 低(只需向量数据库) | 高(GPU 训练 + 数据标注) |
| 可追溯性 | 强(可引用来源) | 弱(知识融入权重) |
| 适用场景 | 事实性问答、文档查询 | 风格/格式调整、专业领域能力 |
| 幻觉控制 | 较好(有参考依据) | 一般(可能产生新幻觉) |
实践中,RAG 和微调常常组合使用:用微调提升模型的领域理解能力,用 RAG 提供实时知识。
核心流程
RAG 系统分为两个阶段:离线索引 和 在线检索生成。
离线阶段:文档索引
原始文档 → 文档加载 → 文本分块 → Embedding → 存入向量数据库
在线阶段:检索与生成
用户提问 → 查询 Embedding → 向量检索 → 取回相关片段 → 拼入 Prompt → LLM 生成回答
完整流程图:
离线阶段
┌─────────────────────┐
│ PDF/网页/代码/文档 │
│ ↓ │
│ 文本分块 │
│ ↓ │
│ Embedding 模型 │
│ ↓ │
│ 向量数据库 │
└─────────────────────┘
在线阶段
用户提问 ──→ Embedding ──→ 向量检索 ──→ Top-K 相关片段
↓
拼入 Prompt 上下文
↓
LLM 生成回答
↓
返回用户
核心环节详解
1. 文档加载(Document Loading)
将各种格式的原始数据转换为纯文本:
| 数据源 | 工具/方法 |
|---|---|
| PyPDF、pdfplumber、Unstructured | |
| 网页 | BeautifulSoup、Crawl4AI |
| Markdown | 直接读取 |
| 代码 | 按文件读取,保留结构信息 |
| 数据库 | SQL 查询导出 |
| API | 调用后转文本 |
2. 文本分块(Chunking)
长文档需要切分为小块(Chunk),因为:
- Embedding 模型有输入长度限制(通常 512-8192 Token)
- 小块检索更精确——返回整篇文档不如返回最相关的段落
- LLM 的上下文窗口有限,不能塞太多内容
分块策略:
| 策略 | 方法 | 适用场景 |
|---|---|---|
| 固定大小 | 每 512 Token 切一块 | 简单通用 |
| 按语义 | 在段落/章节边界切分 | 结构化文档 |
| 递归分割 | 先按段落,再按句子,再按 Token | LangChain 默认 |
| 滑动窗口 | 重叠 N 个 Token,避免边界信息丢失 | 提升召回率 |
关键参数:
- chunk_size:每块大小(通常 256-1024 Token)
- chunk_overlap:相邻块重叠大小(通常 50-200 Token)
原文:A B C D E F G H I J
chunk_size=5, overlap=2:
Chunk 1: A B C D E
Chunk 2: D E F G H
Chunk 3: G H I J
重叠确保跨块的信息不会因为切割而丢失。
3. Embedding
将每个 Chunk 通过 Embedding 模型转换为向量,存入向量数据库。
Chunk: "Docker 使用 namespace 实现进程隔离,
使用 cgroup 限制资源使用..."
↓
Embedding 模型(如 text-embedding-3-small)
↓
向量: [0.023, -0.156, 0.089, ..., 0.045](1536 维)
Embedding 模型的选择直接影响检索质量,详见 03-Embedding 与向量表示。
4. 检索(Retrieval)
用户提问经过同一个 Embedding 模型转为向量,在向量数据库中搜索最相似的 K 个 Chunk:
查询: "Docker 如何隔离进程?"
↓ Embedding
查询向量: [0.019, -0.148, ...]
↓ 向量数据库搜索(余弦相似度)
Top-3 结果:
1. "Docker 使用 namespace 实现进程隔离..."(0.93)
2. "Linux namespace 提供六种隔离机制..."(0.87)
3. "容器与虚拟机的隔离对比..."(0.82)
检索优化策略:
- 混合检索(Hybrid Search):向量检索 + 关键词检索(BM25),取两者的交集/并集
- 重排序(Reranking):用 Cross-Encoder 对检索结果精细排序
- 查询改写(Query Rewriting):用 LLM 重写用户查询,提升检索命中率
- HyDE(Hypothetical Document Embedding):先让 LLM 生成一个假设性回答,再用这个回答去检索
5. 生成(Generation)
将检索到的 Chunk 作为上下文,与用户问题一起构造 Prompt 发给 LLM:
System: 你是一个技术文档助手。请基于以下参考资料回答用户问题。
如果参考资料中没有相关信息,请明确告知。
Context:
[检索到的 Chunk 1]
[检索到的 Chunk 2]
[检索到的 Chunk 3]
User: Docker 如何隔离进程?
生成阶段的关键决策:
- 上下文数量:放入多少个 Chunk?太少信息不够,太多可能引入噪声
- 截断策略:当上下文总长度超出窗口时如何处理
- 引用标注:是否要求模型标注答案来源(
[1]、[2]) - 置信度:是否要求模型在不确定时拒绝回答
评估指标
RAG 系统的评估需要同时考虑检索质量和生成质量:
检索质量
| 指标 | 含义 |
|---|---|
| 召回率(Recall@K) | Top-K 结果中包含正确答案的比例 |
| 精确率(Precision@K) | Top-K 结果中相关文档的比例 |
| MRR(Mean Reciprocal Rank) | 正确答案首次出现的排名的倒数 |
生成质量
| 指标 | 含义 |
|---|---|
| 忠实度(Faithfulness) | 回答是否忠于检索到的上下文,有没有编造 |
| 相关性(Relevance) | 回答是否真正回答了用户的问题 |
| 完整性(Completeness) | 回答是否覆盖了关键信息 |
常用评估框架:RAGAS、TruLens。
常见问题与优化方向
| 问题 | 原因 | 优化方向 |
|---|---|---|
| 检索不到相关内容 | 分块粒度不当 / Embedding 模型不匹配 | 调整 chunk_size、换 Embedding 模型 |
| 检索到了但答案不对 | 上下文噪声太多 / Prompt 设计不好 | 加入 Reranking、优化 Prompt |
| 回答包含幻觉 | 模型忽略上下文自行发挥 | 强化 System Prompt 约束、降低 Temperature |
| 响应太慢 | 向量检索耗时 / LLM 生成耗时 | 优化索引、使用缓存、流式输出 |
| 文档更新后答案过时 | 索引未刷新 | 增量索引、定期重建 |
进阶架构
Agentic RAG
将 RAG 与 Agent 结合,让 Agent 自主决定:
- 是否需要检索
- 检索什么内容
- 是否需要多次检索
- 是否需要从不同数据源获取信息
Graph RAG
在向量检索之外引入知识图谱,利用实体关系提升检索质量,特别适合需要多跳推理的场景。
Corrective RAG(CRAG)
检索后先评估检索质量,如果不够好就触发纠正策略(重写查询、换数据源等)。
延伸阅读
- 01-LLM 原理:理解 LLM 的能力与局限
- 03-Embedding 与向量表示:向量检索的底层机制
- 06-Agent 原理:Agentic RAG 的基础
- 02-MCP 协议:MCP 如何为 AI 提供外部数据访问能力