AI全栈知识06:RAG实战 - 检索增强生成
写在前面
上一篇我们知道了RAG是"开卷考试",先搜资料再让AI参考回答。但具体怎么"搜"?为什么不能用百度那种关键词搜索?"向量"到底是什么?
这篇文章帮你把RAG的每个环节彻底搞清楚。学完后你能理解FastGPT内部在做什么,也能自己动手搭一个简单的知识库问答。
为什么关键词搜索不行
假设你的知识库里有这样一段文档:
“当容器内存使用超过limit时,K8s会触发OOMKilled终止Pod”
用户问的问题是:“为什么Pod一直重启?”
| 搜索方式 | 能找到这段文档吗 | 原因 |
|---|---|---|
| 关键词搜索 | 找不到 | 用户问题里没有"OOMKilled"“内存”"limit"这些词 |
| 向量检索 | 能找到 | 虽然字面不同,但"Pod重启"和"OOMKilled终止Pod"说的是同一件事 |
核心区别:
- 关键词搜索看"有没有相同的字"
- 向量检索看"说的是不是同一件事"
生活类比
你去图书馆找书:
- 关键词搜索= 在电脑上按书名搜。你输入"Pod重启",系统只找标题里有"Pod重启"这四个字的书。找不到任何结果。
- 向量检索= 你跟图书管理员说"我想了解容器为什么会崩溃"。管理员理解了你的意思,帮你找出了好几本相关的书,虽然标题是"OOMKilled故障处理"“内存管理最佳实践”,字面上跟你说的不一样,但内容都相关。
向量检索就像一个懂你意思的图书管理员。
向量是什么
一句话
向量就是一组数字,用来表示一段文字的"语义位置"。
怎么理解
想象一个巨大的"语义空间",每段文字在里面都有一个"坐标点"。意思相近的文字,坐标点挨得近;意思无关的文字,坐标点离得远。
"Pod一直重启" → [0.12, -0.34, 0.78, 0.56, ...] "OOMKilled导致容器终止" → [0.15, -0.31, 0.75, 0.52, ...] ← 坐标很接近! "今天天气真好" → [0.92, 0.44, -0.61, 0.08, ...] ← 坐标差很远这组数字不是人写的,是Embedding模型(专门的小模型)算出来的。你只需要把文字丢给它,它返回一组数字。
文档切分 - 把大文档变成小段
为什么要切
公司文档可能几十页甚至几百页。不能整篇塞给模型(Token有上限,也太贵),所以要切成小段。
类比:你不会把整本字典塞给别人让他找答案,而是翻到相关的那一页递给他。
切多大合适
| 切分大小 | 优点 | 缺点 |
|---|---|---|
| 太小(100字) | 检索精准 | 上下文不够,模型看不懂 |
| 太大(5000字) | 上下文完整 | 检索不精准,Token浪费多 |
| 适中(500-1000字) | 平衡精准和完整 | 通常最佳选择 |
切分时的"重叠"技巧
最怕什么?关键信息正好被切在两段的交界处,两边各一半,哪边都不完整。
解决方法:相邻的段之间留一些重叠内容。
原文(2500字):AAAAABBBBBCCCCCDDDDDEEEEE 不带重叠(可能丢信息): 段1:AAAAA 段2:BBBBB ← 如果关键信息跨AB边界,两段都不完整 段3:CCCCC 带重叠(overlap=100字): 段1:AAAAA + BBB的前100字 段2:BBBBB + CCC的前100字 ← 关键信息至少在一段里是完整的 段3:CCCCC + DDD的前100字Embedding模型 - 把文字变成向量
它是什么
Embedding模型是一个专门把文字变成数字向量的小模型。
注意:它不是大语言模型。它不会对话,不会生成回答。它只做一件事:输入一段文字,输出一组数字。
| Embedding模型 | LLM(大语言模型) | |
|---|---|---|
| 做什么 | 文字 → 一组数字 | 文字 → 文字回答 |
| 输出 | [0.12, -0.34, 0.78, …] | “Pod Pending通常是因为…” |
| 大小 | 小(几百MB) | 大(几GB到几十GB) |
| 用在RAG哪步 | 建库时+查询时(转向量) | 最后一步(生成回答) |
类比:Embedding模型是"翻译官",把人话翻译成机器能比较的数字。LLM是"答题者",看着参考资料写答案。
常见的Embedding模型
| 模型 | 维度 | 来源 | 费用 |
|---|---|---|---|
| text-embedding-3-small | 1536 | OpenAI | 收费 |
| bge-large-zh | 1024 | 智源 | 免费开源 |
| m3e-base | 768 | 社区 | 免费开源 |
| 通义千问Embedding | 1536 | 阿里 | 有免费额度 |
向量数据库 - 存储和检索向量
为什么需要专门的数据库
| 操作 | 普通数据库(MySQL) | 向量数据库 |
|---|---|---|
| 精确查找 | WHERE name = 'xxx' | 不擅长 |
| 相似度查找 | 做不到 | “找到跟这个向量最接近的前5个” |
| 适合场景 | 结构化数据 | 语义搜索 |
常见向量数据库
| 名称 | 特点 | 适合场景 |
|---|---|---|
| Chroma | 轻量,pip install就能用 | 学习、开发、小规模 |
| Milvus | 高性能,分布式 | 生产环境 |
| Qdrant | Rust写的,性能好 | 中等规模 |
| pgvector | PostgreSQL插件 | 已有PG的团队 |
| FAISS | Facebook的库 | 嵌入Python代码中用 |
学习用Chroma,生产用Milvus。你们公司的FastGPT大概率用的是Milvus或pgvector。
相似度怎么算
两个向量之间用"余弦相似度"计算(最常用):
- 值范围:-1 到 1
- 1 = 语义完全相同
- 0 = 完全无关
- -1 = 语义完全相反
"Pod重启" vs "OOMKilled终止容器" → 相似度 0.92(很相关) "Pod重启" vs "今天天气真好" → 相似度 0.05(无关)你不需要自己算。向量数据库帮你算好,返回按相似度排序的结果。
完整流程串一遍
阶段一:建知识库(一次性做好)
你的运维文档(10000字) ↓ 第1步:切分(chunk_size=500, overlap=100) 20个文档段 ↓ 第2步:每段调Embedding模型 20个向量 ↓ 第3步:存入向量数据库 知识库建好了阶段二:回答问题(每次用户提问都做)
用户:"Pod一直Pending怎么办" ↓ 第1步:问题也转成向量 查询向量 ↓ 第2步:在向量数据库中找最相似的3段 返回:段7(调度问题)、段12(资源不足)、段15(节点亲和性) ↓ 第3步:拼装Prompt "参考以下资料回答:[段7][段12][段15]。用户问:Pod一直Pending怎么办" ↓ 第4步:调LLM生成回答 "Pod Pending通常有以下原因:1.资源不足 2.节点选择器不匹配 3.PVC未绑定..." ↓ 返回给用户RAG的关键参数
| 参数 | 含义 | 典型值 | 影响 |
|---|---|---|---|
| chunk_size | 每段切多大 | 500-1000字 | 太小丢上下文,太大不精准 |
| chunk_overlap | 重叠多少 | 50-200字 | 防止关键信息被切断 |
| top_k | 检索返回几段 | 3-5段 | 太少可能漏信息,太多浪费Token |
| similarity_threshold | 相似度阈值 | 0.7 | 低于此值的不要(不相关) |
面试怎么说
如果被问"RAG是什么?你了解它的原理吗":
"RAG是检索增强生成。核心思路是先从知识库中检索相关文档,再让大模型参考这些文档生成回答。
具体流程:文档先切分成小段,用Embedding模型转成向量存到向量数据库。用户提问时,问题也转成向量,通过余弦相似度在向量库中找到最相关的几段文档,拼到Prompt里让模型参考回答。
关键参数有chunk_size控制切分粒度、top_k控制检索几段、overlap防止信息切断。
我们公司的FastGPT就是RAG架构,我负责它的部署和运维。"
延伸思考
| 问题 | 答案 |
|---|---|
| RAG和微调哪个好? | RAG灵活(文档随时更新),微调效果更好但成本高。大多数企业先用RAG |
| RAG搜到的文档不相关怎么办? | 调高similarity_threshold过滤低质量结果,或优化文档切分策略 |
| 文档更新了怎么办? | 重新切分+重新Embedding+更新向量数据库(增量更新) |
| top_k设多少好? | 3-5段。太多会浪费Token且干扰模型,太少可能漏掉关键信息 |
小结
本篇核心收获:
- 向量检索 > 关键词搜索,因为它理解语义不只是匹配字面
- Embedding模型把文字变成向量(一组数字),语义相近的向量距离近
- 文档切分要带重叠(overlap),防止关键信息被切断
- 向量数据库专门做相似度搜索(学习用Chroma,生产用Milvus)
- 完整流程:切分 → Embedding → 存库 → 查询时检索 → 拼Prompt → LLM回答
下一篇预告
AI全栈知识07:向量数据库 - Milvus/Chroma实战
下一篇我们将动手:
- 用Chroma在本地跑通一个向量检索
- 搭建一个简单的知识库问答Demo
- 理解Milvus在生产中怎么部署
参考链接
- RAG论文(Lewis et al.)
- LangChain RAG教程
- Chroma官方文档
- Milvus官方文档
- 通义千问Embedding API