从零理解 RAG:检索增强生成完整指南

为什么需要 RAG?

大语言模型(LLM)虽然强大,但有三个致命问题:

  1. 知识有截止日期 — 训练数据是历史快照,不知道最新信息
  2. 无法访问私有数据 — 你公司的文档、个人笔记,它从没见过
  3. 会”幻觉” — 没见过的东西也能一本正经地编出来

RAG(Retrieval-Augmented Generation,检索增强生成)的解决方案很简单:先查资料,再回答问题

1
2
3
4
5
6
7
没有 RAG:  你问"我们公司的报销流程是什么?"
→ 大模型:瞎编一段看似合理的流程 💀

有 RAG: 你问"我们公司的报销流程是什么?"
→ 先去知识库搜到《报销管理办法》
→ 把相关内容喂给大模型
→ 大模型:根据你们公司的规定,报销流程是...

RAG 完整流程

RAG 不是单一步骤,而是一条完整的流水线,包含五个核心环节:

1
2
3
4
5
离线阶段(建索引):
📄 文档 → ✂️ 分块 → 🔢 向量化 → 💾 存入向量库

在线阶段(问答):
❓ 问题 → 🔢 向量化 → 🎣 召回 → 🎯 精排 → 🤖 生成回答

接下来逐一拆解。

1. 分块(Chunking)

大模型的上下文窗口有限(比如 GPT-3.5 只有 4K token),不能把整个文档塞进去。所以需要把长文档切成小块。

为什么要分块?

  • 精确检索:块越小,检索越精准
  • 不超限:每块控制在 200-500 字符
  • 保持语义:每块要有完整的意思

常见分块策略

策略 原理 适用场景
固定长度 按字符数硬切 简单快速,学习用
递归分块 先段落→再句子→再字符 生产环境常用
语义分块 用 Embedding 检测语义断点 最智能但最慢
结构化分块 按 Markdown 标题、HTML 标签切 结构化文档

overlap(重叠)是什么?

相邻块之间重叠一部分文字,防止一句话被切断导致两头都不完整:

1
2
3
4
5
6
7
8
9
无 overlap:
块1: "Spring Boot 是"
块2: "一个快速开发框架"
→ 两块都不完整

有 overlap(overlap=5):
块1: "Spring Boot 是"
块2: "是 一个快速开发框架"
→ 至少块2有完整语义

2. 向量化(Embedding)

把文本变成一串数字(向量),让计算机能算”两个文本有多像”。

原理

Embedding 模型把文本映射到高维空间。在这个空间中,语义相近的文本,向量距离也近

1
2
3
"猫是一种可爱的动物" → [0.12, 0.34, -0.56, ...](1536维)
"小猫好萌" → [0.11, 0.35, -0.55, ...](非常接近!)
"今天天气不错" → [-0.45, 0.23, 0.67, ...](距离较远)

两种主流方案

TF-IDF(传统方案)

  • 原理:词频 × 逆文档频率
  • 优点:简单、快速、不需要 GPU
  • 缺点:不理解语义(”猫”和”小猫”不认为是相似的)

Neural Embedding(神经网络方案)

  • 原理:用深度学习模型编码语义
  • 代表:OpenAI text-embedding-3-small、BGE、M3E
  • 优点:理解语义,效果好
  • 缺点:需要 API 或 GPU

TF-IDF 原理详解

TF-IDF = Term Frequency × Inverse Document Frequency

  • TF(词频):一个词在当前文档中出现越多,越重要
  • IDF(逆文档频率):一个词在所有文档中都出现(如”的”、”是”),就不那么重要;只在少数文档中出现,说明有区分度
1
2
3
4
5
6
7
8
文档1: "Spring Boot 快速开发"
文档2: "Java 基础语法"

"Spring" 在文档1出现频率高(TF高),只在1个文档中出现(IDF高)
→ TF-IDF 高 → 是文档1的特征词

"Java" 在文档2出现(TF中等),只在1个文档中出现(IDF高)
→ TF-IDF 中等 → 是文档2的特征词

余弦相似度

计算两个向量有多”像”的常用方法:

$$\cos(A, B) = \frac{A \cdot B}{|A| \times |B|}$$

  • 值为 1 → 完全相同方向(最相似)
  • 值为 0 → 正交(无关)
  • 值为 -1 → 完全相反

归一化后,余弦相似度 = 向量点积,计算更快。

3. 召回(Retrieval / Recall)

从所有文档块中快速筛选出可能相关的候选集

类比

你是警察,要从 100 万人里找嫌疑人:

1
2
3
4
5
6
7
8
9
第一步「召回」:
→ 用粗筛条件(年龄、性别、地区)缩小范围
→ 100万 → 500个嫌疑人
→ 要求:宁可多抓,不能漏掉(高召回率)

第二步「精排」:
→ 对 500 人仔细调查
→ 最终锁定 3 个真正的嫌疑人
→ 要求:精准,不要冤枉好人(高精确率)

在 RAG 中

1
2
3
4
5
用户问:"怎么配数据库?"

召回阶段:从 1000 个文档块中快速筛出 50 个可能相关的
→ 要求:尽量不漏(高召回率)
→ 实现:向量近似搜索(ANN),如 HNSW、IVF 算法

关键指标

召回率 = 找到的相关文档 / 所有相关文档

  • 知识库里有 10 篇相关文档,你召回了 8 篇 → 召回率 80%

精确率 = 找到的相关文档 / 召回的所有文档

  • 你召回了 20 篇,其中 8 篇是相关的 → 精确率 40%

两者通常矛盾:召回率高 → 可能混进不相关的;精确率高 → 可能漏掉相关的。所以需要两阶段策略。

4. 精排(Reranking)

对召回的候选用更精确的模型重新打分排序

1
2
3
4
5
6
7
召回返回 50 个候选

用 Cross-Encoder 精确打分

取最好的 3-5 个

喂给大模型

为什么需要精排?

召回追求速度(毫秒级),用的是近似算法,结果不一定最准。精排追求准确性,用更重的模型(如 Cross-Encoder)对候选重新排序。

Cross-Encoder vs Bi-Encoder

维度 Bi-Encoder(召回用) Cross-Encoder(精排用)
速度 快(毫秒级) 慢(秒级)
准确度 中等
用法 文本单独编码,算向量距离 两段文本一起输入,直接输出相关性分数
适用 召回(大规模筛选) 精排(小规模精选)

5. 生成(Generation)

把精排后的文档块 + 用户问题拼成 Prompt,发给大模型。

1
2
3
4
5
6
7
8
9
10
11
=== 参考资料 ===
【rag-tutorial.md】
RAG(Retrieval-Augmented Generation)即检索增强生成...

【spring-boot-guide.md】
Spring Boot 是基于 Spring 框架的快速开发脚手架...

=== 用户问题 ===
什么是 RAG?

请基于以上参考资料回答:

Prompt Engineering 要点

  • 明确告诉大模型”只根据参考资料回答”
  • 如果资料中没有相关信息,要求诚实说”不知道”
  • 控制上下文长度,太多会超 token 限制,太少信息不够

优化技巧

Hybrid Search(混合搜索)

关键词搜索 + 向量搜索融合,既不漏掉语义相关的,也不丢掉精确匹配的:

1
2
3
4
5
6
用户搜:"数据库连接超时怎么办"

关键词搜索:找到包含这些字的文档
向量搜索:找到语义相关的文档

两者结果融合排序(RRF / 加权)

Query Rewriting(查询改写)

用 LLM 优化用户的问题,提高召回质量:

1
2
3
原始问题:"那个啥 就是数据库那个超时"
↓ LLM 改写
优化问题:"MySQL 数据库连接超时的排查和解决方案"

Multi-query(多角度查询)

一个问题拆成多个角度去搜,提高覆盖率:

1
2
3
4
5
6
"怎么配数据库?"
→ 拆成:
- "数据库连接配置"
- "数据源设置"
- "JDBC 配置"
→ 三个角度分别搜索,合并结果

HyDE(假设性文档嵌入)

先让 LLM 生成一个假设性答案,用答案去搜(因为答案的语义更接近目标文档):

1
2
3
4
5
问题:"Spring Boot 怎么配数据库?"
↓ LLM 生成假设答案
"Spring Boot 通过 application.yml 中的 spring.datasource 配置数据源..."
↓ 用这个答案去搜
找到最相关的文档

评估指标

指标 含义 目标
召回率 相关文档里找到了多少 越高越好
精确率 找到的文档里有多少相关 越高越好
F1 Score 召回率和精确率的调和平均 综合评估
Faithfulness 回答是否忠实于检索资料 不胡编
Answer Relevancy 回答是否切题 越相关越好

生产环境选型

向量数据库

数据库 特点
Milvus 开源、性能强、国内用得多
Chroma 轻量、Python 友好、适合原型
Pinecone 全托管云服务、开箱即用
Weaviate 支持混合搜索
pgvector PostgreSQL 扩展、已有 PG 的直接用

Embedding 模型

模型 维度 特点
text-embedding-3-small 1536 OpenAI,便宜够用
text-embedding-3-large 3072 OpenAI,更精准
BGE-large-zh 1024 智源,中文优化
M3E 768 面壁智能,中文效果好

总结

1
2
3
4
5
RAG = 分块 + 向量化 + 召回 + 精排 + 生成

核心思想:先查资料,再回答问题
关键优势:让大模型基于真实数据回答,减少幻觉
适用场景:企业知识库问答、文档搜索、客服系统

RAG 不是什么高不可攀的技术,它就是给大模型装了个搜索引擎。理解了分块、向量化、召回、精排、生成这五个环节,你就掌握了 RAG 的全部核心。


本文配套 Spring Boot 实战项目见 GitHub,代码中有详细中文注释。