RAG 核心原理详解:从 Embedding 到 HNSW 再到完整检索链路
1. 为什么需要 RAG——LLM 的先天局限
大语言模型(LLM)存在三个核心缺陷:
- 知识截止日期:训练数据有截止时间,无法知晓之后发生的新内容
- 幻觉:遇到知识盲区不会如实回复"我不知道",而是强行编造
- 无法识别私有知识:内部文档、代码库、业务规则不会出现在公开训练数据中
RAG(Retrieval-Augmented Generation,检索增强生成)的思路是:让 LLM 先检索外部信息,再结合检索内容给出回答。流程如下:
用户提问 → 检索相关外部信息 → 信息注入 prompt → LLM 基于信息回答
RAG 的完整流水线分为两段:
- 离线阶段:文档 → 切段(Chunking)→ Embedding(向量化)→ 索引写入(存入向量库)
- 在线阶段:用户查询 → Query Rewrite → 元数据过滤 → 两路召回(ANN + BM25)→ RRF 融合 → Rerank 精排 → LLM 生成答案
RAG 好不好用,关键不在 LLM,而在于检索质量。检索回来的内容不对,LLM 再强也是垃圾进垃圾出。
2. Embedding:文本向量化
2.1 核心思想
传统搜索靠字面匹配,SQL 的 LIKE 只能命中包含相同文字的结果,无法理解语义等价。Embedding 解决的是"把文本变成可计算的数据"——将文本映射到向量空间,语义相似度转化为向量距离计算。
2.2 向量
向量是一组有序的浮点数,主流 Embedding 模型输出维度为 768、1024 或 1536。两个向量在空间中的距离越近,代表它们对应的文本语义越相似。
2.3 Embedding 模型训练
Embedding 模型通过对比学习训练:给定一个查询文本,拉近它与正例(语义相关的文本)的距离,推远它与负例(不相关的文本)的距离。训练数据来自搜索引擎点击日志、问答社区采纳记录、平行语料等。
Embedding 模型与生成式 LLM 的区别:Embedding 模型做的是压缩——将语义浓缩进一个向量;LLM 做的是生成——根据上下文输出文字。两者在 RAG 中分工明确:Embedding 模型负责向量化,LLM 负责最终答案生成。
2.4 Dense vs Sparse 向量
- Dense(稠密向量):每个维度都有值,擅长捕捉语义相似,但对专有名词和编码不敏感。例如搜"数据库连接池"能命中"DB connection pool 配置"。
- Sparse(稀疏向量):只有少数维度有值,对应具体词项,擅长精确匹配,但换词就搜不到。例如搜"SLB-20250101"能精确命中,但搜"数据库"无法命中"DB"。
两者是互补关系,不是替代关系。一个完整的检索系统需要两者配合。
3. Chunking:知识切块策略
3.1 为什么要切
- Embedding 模型有输入长度上限(主流 512-8192 Token)
- 超长文本的语义稀释:一篇涵盖多个主题的文档,其向量是各主题的"平均值",对任何一个具体主题都不够接近
- LLM 上下文窗口有限,需要精准段落而非全文
3.2 三种策略
固定长度切块 + 滑动窗口
每 500 Token 一个 Chunk,相邻 Chunk 之间重叠 200 Token。重叠区域让跨边界的句子完整出现在至少一个 Chunk 中,大幅减少信息丢失。
文档: [0..500] [300..800] [600..1100] …
语义切块
按文档的自然结构(标题、段落、小节)来切。每个 Chunk 保持语义完整性,不会出现句子被腰斩的情况。需要文档本身有结构(Markdown 标题、HTML 标签等)。
Parent-Child Chunk
- Parent Chunk:大块,保留完整上下文
- Child Chunk:小块,用于检索(召回率高)
- 检索时用 Child 匹配,返回时将对应的 Parent 送入 LLM
兼顾了召回率和上下文完整性。
3.3 核心权衡
切太小导致上下文断裂,答案被腰斩;切太大导致语义稀释,precision 下降。固定长度 + 滑动窗口是性价比最高的起点,语义切块和 Parent-Child 按需叠加。
4. 相似度度量
给定两个向量,需要用度量算法确定相似程度。
余弦相似度:衡量两个向量方向的接近程度。值域 [-1, 1],1 表示方向一致。Embedding 模型训练时即用此度量,是绝对主流的选择。
cos(θ) = (A · B) / (|A| × |B|)
欧氏距离:衡量两个点在空间中的直线距离。受向量长度影响大,两个意思相同但长度不同的向量,欧氏距离可能很大但余弦相似度很高。不优先选用。
点积:当向量已做 L2 归一化(长度为 1)时,点积等于余弦相似度。如果向量已归一化,用点积效率更高。
建议:不确定用哪个,就用余弦相似度。
5. HNSW:高效近似最近邻搜索
5.1 精确 KNN 不可行
精确 KNN 需要逐条遍历所有向量计算相似度,复杂度 O(N×D)。百万级数据量下,一次查询需要百万次高维向量计算,性能无法接受。
ANN(近似 KNN)路线:用索引结构快速定位候选区域,只对少数候选向量做精确计算。用可控的召回损失,换取数量级的性能提升。
5.2 核心原理
HNSW(Hierarchical Navigable Small World)融合了两种数据结构的思想:
- 跳表的分层思想:在多层结构中,上层节点少、跨度大,逐层缩小范围。查找时从顶层跳过大量元素,复杂度从 O(n) 降到 O(log n)。
- 可导航小世界图的贪心搜索:每层图中,每个节点连接最近的 M 个邻居。搜索时从当前节点出发,选择离目标最近的邻居,重复直到收敛。
两者结合:分层提供快速通道,贪心搜索在每层导航。
5.3 分层图结构
- 高层:节点数量少,边跨度大
- 底层:包含全部节点,边密集,能精确定位
层级分布服从指数衰减:每往上一层,节点数约除以 M(M 默认 16)。100 万节点时,最高层约 5-6 层。
5.4 插入流程
5.5 搜索流程
5.6 三个关键参数
| M | 每节点每层最多连边数 | 越大搜索越精确,但索引更大、构建更慢 |
| efConstruction | 索引构建时的搜索宽度 | 越大召回越高,但构建时间越长 |
| efSearch | 查询时的搜索宽度 | 越大召回越高,但查询延迟越高 |
6. 完整检索链路
6.1 Query Rewrite
用户原始查询可能含混、不完整或不规范。改写策略包括:扩展关键词、修正拼写错误、补充上下文信息。改写后的查询更有利于后续检索。
6.2 元数据过滤
在检索前,按时间范围、文档类型、权限等级等字段过滤,缩小搜索空间。这是提高检索效率的第一道过滤。
6.3 两路互补检索
- ANN(向量检索):基于语义,召回意思相近的结果
- BM25(关键词检索):基于字面,召回精确匹配的结果
两路各自有盲区——ANN 对专有名词不敏感,BM25 无法理解语义等价。需要融合。
6.4 RRF(Reciprocal Rank Fusion)
各路检索结果的分数尺度不同,不能直接相加。RRF 的核心理念:不拼分数拼排名。每个结果在各自排序中的排名决定最终得分:
score = Σ 1 / (k + rank_i)
其中 rank_i 是结果在第 i 路检索中的排名,k 是常数(通常 60)。
6.5 Rerank(精排)
粗召回阶段取 Top-K 候选后,用交叉编码器(Cross-Encoder)对每个候选与查询做精细的语义匹配打分,重排后取 Top-N 送入 LLM。两阶段检索:先快后准。
7. 总结
RAG 的完整检索链路:
Query Rewrite → 元数据过滤 → ANN + BM25 两路召回 → RRF 融合 → Rerank 精排 → LLM 生成
RAG 效果的好坏取决于检索质量。排查 RAG 问题时,按链路逐层定位:
网硕互联帮助中心





评论前必须登录!
注册