RAG 工程深入:从分块到混合检索的完整链路(附 15 道高频题)
基础 RAG 是「文档切块 → Embedding → 向量检索 → LLM 生成」。但生产级 RAG 远不止这四步——分块策略、混合检索、Rerank、查询改写、防幻觉、知识库维护,每一环都决定最终效果。这篇按工程链路整理 Day03 核心知识点,文末附 15 道面试速答。
一、为什么要分块?四种策略怎么选
RAG 必须切分文档,原因有三:
- 上下文窗口限制:长文本有 Lost in the Middle 问题,中间内容容易被模型忽略
- 检索精度:不切分只能命中整篇文档,无法定位到具体段落
- Embedding 质量:短文本语义更聚焦,长文本编码会被过度压缩
| 策略 | 做法 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| 固定长度 | 按字符/token 硬切 | 简单快速 | 可能断语义 | 快速原型 |
| 分隔符 | 按段落/句号切 | 保留语义边界 | 块大小不均 | Markdown 文档 |
| 递归字符 | 分隔符优先级逐级降级 | 兼顾大小与语义 | — | 工程默认 |
| 语义边界 | 相邻句相似度跌破阈值处切 | 效果最好 | 成本高 | 高质量 RAG |
递归字符分块(LangChainRecursiveCharacterTextSplitter)的「递归」不是递归函数,而是分隔符列表\n\n → \n → 空格 → 字符逐级降级。
参数经验值:
- FAQ/问答:chunk_size 128~384 tokens
- 通用文档:512~768 tokens
- 长文档/论文:1024~1536 tokens
- overlap:chunk_size 的 10%~15%(防止边界信息丢失)
- 硬约束:不能超过 Embedding 模型最大输入长度(如 bge-large-zh 最大 512 tokens)
二、Embedding 模型怎么选
选型看四个维度:
| 维度 | 要点 |
|---|---|
| 语言 | 中文用 BGE-Large-ZH,英文用 text-embedding-3-small,混合用 BGE-M3 |
| 维度 | 768~1024 是性价比最优区间,超 1536 边际递减 |
| 速度 | 看参数量(3M~568M),小模型快、大模型准 |
| MTEB | 看 Retrieval / STS 子任务得分,不是只看总分 |
BGE-M3 三个 M:Multi-Lingual(多语言)、Multi-Functionality(稠密+稀疏+多向量)、Multi-Granularity(句子到长文档)。
注意:Embedding 模型没有 temperature 等生成参数,是「文本进、向量出」的固定权重模型。
三、向量数据库选型
| 方案 | 定位 | 适合 |
|---|---|---|
| Milvus | 云原生分布式专用向量库,HNSW/IVF/DiskANN | 千万~亿级生产环境 |
| Chroma | 轻量嵌入式,pip install 即用 | 原型验证 |
| FAISS | Meta 算法库,不是数据库,无 CRUD | 研究/底层引擎 |
| Elasticsearch | 搜索引擎 + 向量插件 | 已有 ES 集群做混合检索 |
Milvus 三种部署:Lite(嵌入式)/ Standalone(单机服务)/ Distributed(K8s 集群)。
向量库 vs 传统库(互补,不替代):
| 向量库 | 传统库 | |
|---|---|---|
| 索引 | HNSW/IVF 近邻图 | B+ 树 |
| 查询 | 相似度搜索(近似) | 精确匹配 |
| 事务 | 无 ACID | 有 ACID |
| 返回 | Top-K 近似 | 精确结果 |
高维空间有维度灾难——所有点距离趋于相同,B+ 树无法排序,HNSW 用建图绕开。
四、混合检索:向量 + BM25 + RRF
单用向量或 BM25 都有盲区:
- 向量检索:擅长语义(「汽车」→「车辆」),但对精确术语(
ConcurrentHashMap、型号)不敏感 - BM25:擅长精确匹配,但无法理解同义词(「心梗」搜不到「心肌梗死」)
RRF(倒数排名融合)是最主流融合策略:
RRF(d) = Σ 1/(k + rank_i(d))- 输入是排名,不是分数(向量余弦和 BM25 分数量纲不同)
- k=60 是 Google 论文经验值,零调参
- 文档只在一路出现时,另一路 rank=∞,贡献为 0
完整检索链路:
Query → 向量 Top-20 + BM25 Top-20 → RRF 融合 → Cross-Encoder Rerank → Top-5 → LLM五、Rerank:为什么用 Cross-Encoder
双塔模型(Bi-Encoder):Query 和 Document 各自独立编码,算余弦相似度,速度快可预计算,但没有交互,Top-K 有噪声。
Cross-Encoder:把 Query 和 Document 文本拼接[CLS] Query [SEP] Document [SEP],Self-Attention 逐词交互,直接输出相关性分数,精度高但不能预计算。
为什么不对全部文档 Rerank?百万文档每个都要拼接算一次不可接受。先用双塔粗筛到 20 个,再 batch 精排,GPU 上几百毫秒可接受。
推荐模型:bge-reranker-v2-m3(开源,中英双语,Cross-Encoder 架构)。
六、查询改写(Pre-Retrieval)
解决用户口语化表达与文档书面化表达之间的语义鸿沟:
| 方法 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| LLM 改写 | 大模型重写规范查询 | 语义理解深 | 延迟高 |
| 同义词扩展 | 词典/知识图谱替换 | 零延迟 | 维护成本高 |
| HyDE | LLM 生成假设文档,用假答案检索真答案 | 对齐文档分布空间 | 延迟最高 |
HyDE 反直觉但有效:用户 Query 在「问题区」,知识库文档在「陈述区」。LLM 编一个像文档的假答案,向量距离更近。容忍幻觉——只需要「像」,不需要「对」。假设文档仅用于检索,不参与最终生成。
Advanced RAG 四阶段:Pre-Retrieval(查询改写)→ Retrieval(混合检索)→ Post-Retrieval(RRF + Rerank)→ Generation(防幻觉)。
七、RAG 幻觉怎么处理
三个来源:
1. 检索噪音:chunk 含错误/过时信息
2. 过度推理:LLM 脑补缺失环节
3. 指令遵循失败:忽略约束,吐出预训练旧知
五种手段:
- 相似度阈值过滤:低于阈值返回「未找到」,不强行生成
- 交叉认证:多路检索 + 矛盾 chunk 排序
- Chunk 粒度优化:语义分割 / 父子索引
- 约束型 Prompt:「只基于以下材料回答」+ 引用标注
[chunk_id] - 后置校验:NLI 模型 / LLM-as-Judge / 引用一致性检查
核心原则:不确定就说不知道。
八、GraphRAG vs 传统 RAG
传统 RAG 三个局限:
1.无法多跳推理:答案分散在不同文档,向量检索串不成逻辑链
2.缺乏结构感知:向量空间扁平,无法表达层级拓扑
3.聚合统计无能:结构化计算做不了
GraphRAG 流程:
1. LLM 抽取三元组(实体-关系-实体)
2. 入库图数据库(Neo4j)
3. Leiden 社区发现算法分层聚类,LLM 生成社区摘要
4. 查询时:图遍历做关系推理 + 向量召回兜底
缺点:构建成本高、维护难、三元组抽取可能有错。
九、知识库维护
| 方面 | 做法 |
|---|---|
| 增量更新 | MD5/SHA-256 哈希对比,变了才重新 Embedding;先写新再删旧 |
| 删除处理 | 软删除is_deleted=true,定期物理清理超 30 天的 |
| 版本管理 | chunk_id + version,支持回滚 |
| TTL 过期 | 写expire_at,查询时过滤;Milvus 不支持自动 TTL,需应用层 cron |
十、Query 路由(RAG 作为 Agent 工具时)
单一检索策略无法应对多样意图。路由解决三个问题:万金油检索样样不通、重链路成本高、无关上下文污染 LLM。
意图识别三级递进(工程最佳实践):
1. 规则匹配(零延迟,拦截高频)
2. Embedding 相似度(预定义示例 Query 算余弦)
3. LLM 分类(兜底复杂场景)
路由分发:
| 意图 | 链路 |
|---|---|
| 知识问答 | RAG(向量 + BM25) |
| 代码问题 | 代码搜索(语法树 + 符号索引) |
| 关系推理 | GraphRAG |
| 闲聊 | 直接 LLM,不检索 |
| 不确定 | fallback 默认 RAG |
十一、为什么要向量化?直接文本匹配不行吗
文本匹配(BM25/LIKE)无语义理解:「汽车」搜不到「车辆」。
向量化通过 Embedding 编码语义向量,理解同义词、近义词、跨语言。但有三代价:计算成本高、不可解释、精确术语不敏感。
最佳方案是混合检索——向量补语义,BM25 补精确,正交互补,不是二选一。
附录:15 道 RAG 工程高频面试速答
Q1. 文档分块策略?固定/分隔符/递归字符/语义边界;工程默认 RecursiveCharacterTextSplitter,chunk_size 512,overlap 50。
Q2. chunk_size 怎么选?FAQ 128~384,通用 512~768,长文档 1024~1536;overlap 10~15%;太大检索精度降,太小语义不完整。
Q3. Embedding 怎么选?语言+维度(768~1024)+速度+MTEB;中文 BGE-Large-ZH,混合 BGE-M3。
Q4. 向量库对比?Milvus 生产级,Chroma 原型,FAISS 算法库,ES 混合检索;Milvus 有 Lite/Standalone/Distributed。
Q5. 向量库 vs 传统库?HNSW vs B+树,相似度 vs 精确,无ACID vs 有ACID,Top-K近似 vs 精确;互补不替代。
Q6. 混合检索?向量补语义+BM25补精确,RRF融合Σ 1/(60+rank),k=60零调参。
Q7. Rerank 原理?双塔无交互有噪声;Cross-Encoder拼接文本逐词交互;混合Top-20→Rerank→Top-5。
Q8. RRF 公式?RRF(d)=Σ 1/(k+rank_i(d)),输入排名不是分数,k=60防赢家通吃。
Q9. 查询改写?Pre-Retrieval;LLM改写/同义词/HyDE;HyDE用假设文档检索,容忍幻觉。
Q10. 幻觉处理?阈值过滤+交叉认证+Chunk优化+约束Prompt+后置校验(NLI/Judge/引用检查)。
Q11. 相似度计算?余弦(方向,RAG用)、欧氏(绝对距离,聚类用)、点积(方向+模长,推荐用);归一化后点积=余弦。
Q12. GraphRAG vs RAG?传统RAG无法多跳/无结构/无聚合;GraphRAG用三元组+Leiden社区+图遍历。
Q13. 知识库维护?哈希增量更新+软删除+版本管理+TTL;Milvus无自动TTL需应用层实现。
Q14. Query路由?规则→Embedding→LLM三级意图识别;知识→RAG,代码→搜索,关系→GraphRAG,闲聊→LLM。
Q15. 为什么向量化?文本匹配无语义;向量化理解同义词但有成本;最佳是混合检索。
写在最后
生产级 RAG 的核心不是「接个向量库就完事」,而是全链路工程化:分块参数、Embedding 选型、混合检索 + RRF + Rerank、查询改写、防幻觉、知识库维护——每一环都有明确的 trade-off 和调优方法。把这条链路讲清楚,比背单个概念更有面试竞争力。
