RAG 全流程(切分/向量检索/召回/生成)
RAG 整体分成知识库构建阶段和在线检索生成阶段
离线知识入库:文档解析 → 清洗 → 切分 Chunk → Embedding 向量化 → 向量库建索引
在线问答:用户 Query → Query 向量化 → 召回 TopK → 重排 Rerank → 上下文组装 → Prompt → LLM 生成
知识库构建时,
首先对 PDF、Word、Markdown 等文件做解析和文本清洗,然后按照固定长度、递归分段或者语义边界把文档切成多个 Chunk,并保留一定 overlap,避免上下文在切分边界处丢失。
每一个 Chunk 会通过 Embedding 模型转成高维向量,同时保存 chunkId、documentId、原文、标题、页码等 Metadata,然后写入向量数据库,通过 HNSW、IVF 等 ANN 索引加速相似度检索。
用户提问时,
同样使用相同的 Embedding 模型把 Query 转成向量,然后通过 cosine similarity、dot product 等方式从向量库召回 TopK 个候选 Chunk。
实际生产环境一般不直接把 TopK 全部交给大模型,而是结合关键词检索、Metadata Filter,甚至 Hybrid Search,再通过 Reranker 对候选结果重新排序。
最后选择相关度最高的几个 Chunk,在控制上下文窗口和 Token 数量的情况下组装 Prompt,把“用户问题 + 检索上下文”一起交给 LLM,让模型基于检索内容生成答案。
同时我们还会保留引用来源,并通过召回率、MRR、NDCG、答案正确率等指标评估整个 RAG 链路。
1.文档为什么一定要切分?
比如一份 100 页的《支付系统设计》很多个语义主题,如果整个文档只生成一个向量,这个向量实际上是所有语义的“平均表示”
用户Query 和整份文档的向量相似度可能并不高
2.Chunk 应该切多大?
Chunk 太小:
优势:检索精准
问题:语义不完整 上下文缺失
Chunk 太大:
优势:上下文完整
问题:噪声多,Embedding 语义被稀释,Token 成本增加
3.为什么 Chunk 之间需要 overlap?
比如原文:
支付宝支付成功以后,
系统首先校验签名,然后判断订单状态,
如果订单已经支付,则直接返回 success。
如果切成:
Chunk1:
支付宝支付成功以后,
系统首先校验签名,然后判断订单状态
Chunk2:
如果订单已经支付,则直接返回 success
两个 Chunk 语义被割裂。
加入 overlap:
Chunk1:
支付宝支付成功以后,
系统首先校验签名,然后判断订单状态
Chunk2:
判断订单状态,
如果订单已经支付,则直接返回 success
语义连续性更好。
代价是:
数据量增加、Embedding 成本增加
可能召回大量重复 Chunk
所以 overlap 不能无限加。
4.文档到底怎么切?
可以分成四种。
① 固定长度切分
例如:
每 500 token 一段 overlap 100 token
优点:
简单、快。
缺点:
可能把一句话、一个代码块、一张表切断。
② Recursive Chunking(递归切分)
实际项目很常见。
本质上不是按某一个固定“维度”拆,而是按一组从粗到细的文本结构层级递归拆分,直到每个 Chunk 满足目标大小。
标题 ↓ 段落 ↓ 换行 ↓ 句号 ↓ 固定字符数
递归切。
比如 LangChain 的:
RecursiveCharacterTextSplitter
核心思想:
尽可能保留自然语义边界。
③ 结构化切分
Markdown:
# 一级标题 ## 二级标题 ### 三级标题
Word:
Heading 标题 Paragraph 段落 Table 表格
代码:
Class Method Function
这种通常比单纯固定字符切分效果好。
④ Semantic Chunking
通过 Embedding 判断相邻句子的语义变化。
例如:
A A A A B B B C C
语义发生明显变化时再切:
[A A A A] [B B B] [C C]
效果可能更好,但:
预处理成本也明显更高。
5. Chunk 切完之后发生什么?
每个 Chunk 一般会形成:
{
"chunkId": "chunk-001",
"documentId": "doc-001",
"content": "支付宝回调必须保证幂等...",
"title": "支付回调",
"page": 21,
"embedding": [...]
}
实际上可以进一步写成:
{
"chunkId": "chunk-001",
"content": "支付宝回调必须保证幂等...",
"embedding": [0.12, -0.31, 0.78, ...],
"metadata": {
"documentId": "doc-001",
"projectId": "10086",
"userId": "u001",
"title": "支付回调",
"page": 21,
"chunkIndex": 15,
"fileName": "支付宝支付接入.pdf",
"fileType": "pdf",
"source": "knowledge-base",
"createdAt": "2026-09-09"
}
}
这里有一个非常重要的东西:
Metadata。
metadata = 这个 Chunk 是谁、从哪来、属于谁、在哪一页、能不能被你搜到
因为实际 RAG 不只是:
Vector Search
还经常:
Vector Search + Metadata Filter
例如:
查询 projectId=10086 的知识库。
不是全公司文档里检索,而是:
WHERE project_id = 10086 AND user_id = xxx
之后再做向量搜索。
在满足这些条件的 Chunk 中,寻找向量最相似的 TopK
6. Embedding 到底是什么?
Embedding 干了什么?
一句话:
Embedding 是把文本映射到一个高维稠密向量空间,使语义相近的文本在向量空间中的距离也比较接近。
例如:
"Java线程池" → [0.12, -0.42, 0.73, ...]
假设是:
1536维
那么就是:
x1 x2 x3 ... x1536
不是:
每一个维度对应一个具体单词。
而是神经网络学习出来的高维语义特征。
7. 为什么 Query 和文档必须使用同一个 Embedding 模型?
比如知识库:
Document ↓ Embedding Model A ↓ vector A
查询:
Query ↓ Embedding Model B ↓ vector B
即使维度碰巧一样,也不能可靠比较。
因为两个模型学习出来的:
向量空间坐标系不同。
就像:
一个使用经纬度 一个使用笛卡尔坐标
直接计算距离没有意义。
所以一般必须保证:
Document Embedding Model = Query Embedding Model
更换 Embedding 模型后通常需要:
全量重新向量化。
8. 什么叫向量检索?
用户问:
RabbitMQ 如何保证消息不丢失?
先做:
Query ↓ Embedding ↓ Query Vector
例如:
Q = [0.1, 0.8, -0.3 ...]
数据库里面:
Chunk A → Vector A Chunk B → Vector B Chunk C → Vector C
然后计算:
Similarity(Q, A) Similarity(Q, B) Similarity(Q, C)
假设:
A = 0.86 B = 0.32 C = 0.91
取 TopK:
C A ...
这就是最基础的向量召回。
9. Cosine Similarity(余弦相似度) 是什么?
公式:
本质:
比较两个向量方向是否相似。
例如:
A → ↗ B → ↗
方向非常接近:
Cosine Similarity ≈ 1 相似度
Embedding 经常使用:
- Cosine Similarity 余弦相似度
- Dot Product 点积
- Euclidean Distance 欧几里得距离
具体要看 Embedding 模型和向量数据库设计。
在 RAG 中,用户 Query 和知识库 Chunk 都会通过 Embedding 模型转成高维向量,然后使用 Cosine Similarity 计算 Query Vector 与 Chunk Vector 的相似度,按照得分排序并获取 TopK Chunk,作为上下文交给 LLM。相比关键词匹配,它能够捕获文字不同但语义相近的内容。
10. 几百万条向量难道每一条都算一次?
1000 万 Chunk,每次 Query 都和 1000 万向量计算 cosine 吗?不会
HNSW 是什么?
HNSW 是一种基于多层邻接图的近似最近邻搜索算法。它会把向量构建成多层图结构,查询时先从高层快速定位大致区域,然后逐层下降,在底层进行更精细的邻居搜索,从而避免全量遍历所有向量。
理解成:
Level 3 A ────── Z
↓
Level 2 A ── H ── Z
↓
Level 1 A-B-C-D-E-F...
↓
找到最接近 Query 的节点
核心:
不是遍历所有向量,而是沿着邻居图快速逼近最近向量。
想象你人在中国,要找:
距离你最近的一家星巴克。
正常会:
中国 ↓ 广东 ↓ 广州 ↓ 天河区 ↓ 附近门店
只不过:
地理空间
换成了:
向量空间
11.为什么只做向量检索不够?
Embedding 关注:
语义。
但对:
- ID、产品型号、错误码、人名、精确版本号、API 名称、专有名词
可能不够精准。
所以:精确关键词匹配+向量检索
12.什么叫倒排索引?
为什么 LIKE 不等于关键词检索?
1,性能低,大数据量需要扫描大量文本。
2,搜索能力弱(相关度排序,同义词。。。
正向:
Doc1 → Java Redis MQ Doc2 → Java MySQL
倒排:
Java → Doc1, Doc2 Redis → Doc1 MQ → Doc1 MySQL → Doc2
用户搜索:
Redis
直接:
Redis → Doc1
不需要扫描所有文档。所以全文检索效率高。
13. 什么是召回?
召回 Retrieval / Recall:
从整个知识库:
100 万 Chunk
里面快速找:
Top 20 / Top 50
候选文档。例如:
1000000 ↓ Vector / BM25 Top 50
这一步最重要的目标不是:
把第一名排得绝对准确。
而是:
尽量不要漏掉真正相关的文档。
所以召回阶段通常:
高 Recall
优先。
14.什么叫 Rerank?重排序
流程:
100000 个 Chunk
↓ Recall
Top 50
↓ Reranker
Top 5
↓
LLM
Recall:
快,但精度相对低。
Reranker:
慢,但是精度高。
所以不能对:
100 万个 Chunk
全部 rerank。
一般:
召回 Top20~100 ↓ Rerank ↓ Top3~10
实际企业 RAG一般是
用户 Query
↓
Metadata Filter
projectId = 10086
tenantId = xxx
permission = xxx
↓
Recall / Retrieval
Vector Search
BM25
Hybrid Search
↓
Top 50
↓
Reranker
↓
Top 5
↓
LLM
15. Embedding 和 Reranker 有什么区别?
Embedding 负责“从海量文档里快速找出可能相关的候选”,Reranker 负责“把这些候选再仔细比较,重新排出最相关的顺序”。
16. TopK 越大越好吗?不是。
TopK 太小:
相关文档可能没召回来
Recall 低。
TopK 太大:
大量无关 Chunk ↓ Prompt 噪声增加 ↓ Token Cost 增加 ↓ LLM 甚至可能被错误上下文干扰
所以:
TopK 本质上是 Recall、Precision、Latency、Token Cost 的权衡。
常见:
Recall TopK = 20~100 Rerank TopK = 3~10
实际通过评测集确定。
17. Context 是怎么组装的?
例如最终 Top3:
Chunk A Chunk B Chunk C
Prompt:
System: 你是一名技术助手。 只能根据下面提供的知识回答。 如果知识库没有答案,请回答不知道。 Context: [文档1] ... [文档2] ... [文档3] ... Question: RabbitMQ 如何保证消息不丢?
然后:
Prompt ↓ LLM ↓ Answer
这就是:
Retrieval-Augmented Generation
Retrieval:找到知识
Augmented:把知识补进 Prompt
Generation:LLM 生成答案
18. RAG 为什么能够降低幻觉?
RAG 可以降低幻觉,但不能完全消除幻觉。
外部知识 ↓ 作为上下文提供给 LLM
减少模型单纯依赖参数记忆。
但仍然可能发生:
召回错
Retrieval Failure
上下文本身错误
Knowledge Error
模型没按照 Context 回答
Generation Hallucination
因此完整方案还可以加:
引用来源 Groundedness 检查 Answer Verification 拒答策略
如何排查?
先拆链路:
Question ↓ Query理解有没有问题? ↓ Retrieval有没有召回来? ↓ Rerank有没有排错? ↓ Context有没有丢失? ↓ Prompt有没有问题? ↓ LLM有没有生成错误?
19. Query Rewrite 是什么?
Query Rewrite 是在 RAG 检索前,将当前 Query 与多轮对话历史交给 LLM,把代词、省略信息和上下文补全为一个 Standalone Question,再使用改写后的 Query 进行向量检索和关键词检索,从而解决多轮对话中 Query 语义不完整导致的召回下降问题;改写只补全用户意图,不应该引入新的事实。
多轮 RAG 经常需要:
Standalone Question Generation / Query Rewrite。
20. RAG 最常见的完整生产架构
离线知识库构建
│
PDF / Word / Markdown / Web
↓
Parser
↓
Text Clean
↓
Chunk
↓
Embedding
↓
┌────────────┴────────────┐
↓ ↓
Vector DB Search Engine
HNSW BM25/倒排索引
│ │
└────────────┬────────────┘
在线 Query
│
↓
Query Rewrite
│
┌───────────┴──────────┐
↓ ↓
Query Embedding Keyword Query
↓ ↓
Vector Recall BM25 Recall
└───────────┬──────────┘
↓
RRF Fusion
↓
Top50 Candidate
↓
Rerank
↓
Top5
↓
Context Assembly
↓
Prompt + Question
↓
LLM
↓
Answer + Citation
这已经不是“Demo RAG”,而是比较标准的:
Production RAG Pipeline。
21.你的知识库更新怎么办?
新增
Document ↓ Chunk ↓ Embedding ↓ INSERT Vector
修改
一般:
根据 documentId ↓ 删除旧 chunks ↓ 重新 Parse / Chunk / Embedding ↓ 写入
删除
documentId ↓ 删除全部 chunk/vector/index
不能只删除:
MySQL 文档记录
却把向量留在向量库里。
否则:
脏向量 / Ghost Retrieval。
22.文档重复上传怎么办?
可以做:
SHA256(file) 或者: contentHash
例如:
fileHash = SHA256(fileContent)
数据库判断:
fileHash 是否已存在
避免重复:
- Parse
- Chunk
- Embedding
- Storage
Chunk 也可以做 hash:
chunkHash
进行增量向量化。
23.Embedding 是不是很贵?
Embedding 通常比 LLM Generation 便宜很多,但是海量数据依然需要优化。
例如:
100万篇文档 × 大量 Chunk
不能每次启动服务重新向量化。
所以:
文档 Embedding
属于:
Offline Precomputation。离线预计算
只有:
Query Embedding
在请求时实时计算。
这是 RAG 能做到低延迟的重要原因。
24.pgvector、Milvus、Elasticsearch 怎么选?
pgvector 可以理解为:给 PostgreSQL 增加“向量存储 + 向量相似度检索”能力的扩展。
适合:
现有系统已经使用 PostgreSQL 数据规模中小 希望业务数据 + 向量数据事务管理简单
优势:系统复杂度低。
Milvus / Qdrant / Weaviate
专门向量数据库。
适合:
千万 / 亿级 Vector 高并发 复杂 ANN
优势:专业向量搜索能力更强。
Elasticsearch / OpenSearch
优势: 既能做“关键词搜索”,又能做“语义搜索”,还能按 Metadata 过滤,所以特别适合 RAG 的 Hybrid Search。
BM25 + Vector Search + Filter
适合: Hybrid Search。
如果你的项目本身要求:
中文关键词全文检索 + 向量检索
ES/OpenSearch 会非常自然。
25.RAG 怎么评估?
可以把 RAG 评估简单理解成检查两件事:
① 有没有把正确资料搜出来?
② 搜出来以后,LLM 有没有根据资料正确回答?
- Retrieval Evaluation:评估“搜得好不好”
HikariCP 为什么连接超时?
正确答案所在 Chunk 应该被 Retriever 搜出来。
- Recall@K:有没有搜到
- Precision@K:搜出来的结果有多少是有用的
- MRR:正确答案排得靠不靠前
- NDCG:整体排序质量怎么样
2. Generation Evaluation:评估“答得好不好”
假设 Retriever 已经把正确资料给 LLM:
Context: HikariCP connection timeout 通常表示等待数据库连接超过 connectionTimeout。
然后检查:
- Faithfulness / Groundedness:回答是不是基于 Context,有没有瞎编。
- Answer Relevance:有没有真正回答用户的问题。
- Correctness:最终结论是否正确。
- Citation Correctness:引用的 Chunk / 文档是不是真的支持这个答案。
26.RAG 性能怎么优化?
文档侧
异步解析 批量 Embedding Embedding Cache 增量更新
Retrieval
ANN HNSW 参数优化 Metadata Filter 合理 TopK
Rerank
不要:
Top1000 → Rerank
而是:
Top30 / Top50
Generation
控制:
Context Token Chunk 数量 模型尺寸 Prompt 长度
完整延迟:
通常真正的大头往往是:
LLM Generation。
用户 Query
↓
Retriever
↓
正确 Chunk 有没有搜出来?
│
├─ 没搜出来 → Retrieval 问题
│
└─ 搜出来了
↓
LLM
↓
仍然答错 → Generation 问题
可以这样理解:
RAG 评估必须把 Retrieval 和 Generation 分开。Retrieval 用 Recall@K、Precision@K、MRR、NDCG 等指标评估召回和排序;Generation 用 Faithfulness、Answer Relevance、Correctness、Citation Correctness 等指标评估答案质量。
一句话记忆:
Retrieval 看“资料找对没有”,Generation 看“拿到资料后回答对没有”。
27.为什么不直接使用大模型超长上下文?
大模型上下文再长,也只是“这一次最多能读多少内容”;RAG 解决的是“先从海量知识里挑出当前最需要的内容再给模型”。
如果只靠超长上下文
相当于:
100GB 公司文档
↓
全部塞给 LLM
↓
让它自己找答案
问题很明显:
- 贵:输入 Token 越多,成本越高
- 慢:模型要先处理大量 Context
- 噪声多:真正有用的可能只有 5 个 Chunk
- 放不下:128K、1M 也装不下几十 GB / TB 知识库
- 权限难控制:不能把用户无权看到的资料先塞给模型
28.简短
你最好把下面这套练熟。
Q:什么是 RAG?
Retrieval-Augmented Generation,先从外部知识库检索与 Query 相关的信息,再把检索结果作为上下文输入 LLM,让模型基于外部知识生成答案。
Q:为什么切 Chunk?
提升检索粒度,避免整篇文档 Embedding 后多个主题的语义被平均掉。
Q:Chunk 越小越好吗?
不是。太小会丢上下文,太大语义容易被稀释,而且增加 Token 和噪声,需要在 Recall、Precision 和 Context Completeness 之间平衡。
Q:Overlap 为什么存在?
避免关键信息刚好跨越 Chunk 边界导致语义断裂。
Q:Embedding 是什么?
把文本编码成高维稠密向量,使语义相近文本在向量空间距离也更接近。
Q:为什么 Query 和文档必须一个 Embedding 模型?
因为必须处于同一个向量空间,否则两个向量的距离没有可靠语义。
Q:怎么找最相似向量?
可以使用 Cosine、Dot Product 等相似度指标,大规模场景一般通过 HNSW 等 ANN 索引近似搜索,而不是全量扫描。
Q:什么是 TopK?
Retriever 返回相似度最高的 K 个候选 Chunk。
Q:TopK 越大越好吗?
不是,会增加噪声、Rerank 成本和 LLM Token 消耗。
Q:召回和向量检索区别?
召回是一个阶段,向量检索只是召回手段之一,还可以通过 BM25、Graph、SQL 等召回。
Q:为什么还要 BM25?
Vector 擅长语义,BM25 擅长错误码、编号、专有名词等精确关键词,二者互补。
Q:怎么融合?
可以使用 RRF 根据多个 Retriever 中的排名进行融合,而不是直接比较不同体系的原始 Score。
Q:Rerank 是什么?
对召回阶段得到的少量候选文档用更精确的模型重新计算 Query-Document 相关度,然后选 TopN。
Q:为什么不直接全部 Rerank?
Cross-Encoder 计算成本高,只适合候选集,Retriever 负责大范围快速筛选。
Q:RAG 可以消灭幻觉吗?
不能,只能降低。检索错误、知识错误、上下文利用错误都仍然会产生幻觉。
Q:回答错误怎么排查?
先看正确 Chunk 有没有召回,再看 Rerank 有没有排掉,最后看正确 Context 已经进入 Prompt 后 LLM 是否仍然生成错误。


正在连接评论服务,请稍候…