RAG 检索质量优化清单:chunking、MMR、混合检索、Rerank 与调试
RAG 检索质量优化清单:chunking、MMR、混合检索、Rerank 与调试
适用人群:RAG 已经能跑,但「答案总是差点意思」的开发者
检索质量差时先看哪里?
RAG 项目调试有一个铁律:先看检索质量,再看生成质量;不要把所有问题都归因于模型。建议开启 tracing(LangSmith 等),按顺序排查:loader → splitter → embedding → retriever → LLM。
一、调 chunk 参数(最基础也最见效)
| 参数 | 影响 | 建议 |
|---|---|---|
| chunk_size | 块越大上下文越完整,但检索精度下降 | 默认 512,问答场景可试 256-1024 |
| chunk_overlap | 保留边界上下文,防止切在语义中间 | 块大小的 10-20%(如 512 → 64) |
| retrieval k | 取回多少条 | 第一版 4-8;加 rerank 后可放大到 20-50 |
chunk 策略升级路线:recursive 512(默认)→ semantic / parent-child → Contextual Retrieval / Late Chunking。每一步都比上一步贵,按需取用。
二、MMR:减少重复结果
普通 top-k 检索经常返回高度相似的内容(冗余)。MMR(最大边际相关性)在「相关性」和「多样性」之间取平衡:
retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={"k": 6, "fetch_k": 20, "lambda_mult": 0.7},
)
fetch_k:先取多少候选lambda_mult:越高越重相关性,越低越重多样性(默认 0.5)
三、Metadata Filter:按范围检索
企业知识库往往需要带条件检索(时间、类别、部门):
retriever = vectorstore.as_retriever(
search_kwargs={
"k": 4,
"filter": {"category": "运维手册", "updated_at": {"$gte": "2026-01-01"}},
}
)
选型提醒:Chroma 的过滤能力较弱,复杂过滤场景选 Qdrant / Milvus。
四、混合检索:关键词 + 向量
向量检索对精确词(型号、人名、报错信息)很弱,BM25 关键词召回 + 向量召回并行,再用 RRF(基于排名的融合) 合并结果,是修复 naive RAG 最有效的手段:
召回阶段: BM25 关键词召回 ∪ 向量语义召回
融合阶段: 对两者按排名做 RRF 融合 → top-N
| 阶段 | 做什么 | 典型延迟 |
|---|---|---|
| 第一版 | 纯向量检索 | 最低 |
| 第二版 | 向量 + MMR / filter | 低 |
| 第三版 | 向量 + BM25 + rerank | 50-200ms 额外 |
五、Rerank 重排序:精排质量的关键
两阶段检索架构:
- Retrieve(粗排):bi-encoder embedding 快速取 top 50-100
- Rerank(精排):cross-encoder 对 (问题, chunk) 联合打分,收窄到 3-5 条
常用 reranker:Cohere Rerank 3.5、Voyage rerank-2.5、BGE reranker-v2、Jina Reranker v2(后两者开源可自部署)。
Rerank 会增加约 50-200ms 延迟与成本,但传给 LLM 的上下文质量显著提升,复杂知识库收益明显。要在召回规模、成本和延迟之间权衡。
六、答案质量优化:回答前先判断上下文是否足够
检索到的内容不足时,模型容易「硬编」答案。建议:
- 让模型输出
cited_source_indexes,逐句引用 - 做 answer grounding 校验:答案必须有检索依据
- 无依据时回答「不确定」,而不是编造
七、安全:Prompt Injection 不可忽视
检索内容来自不可信来源时,可能包含恶意指令。RAG 的上下文不是天然可信,检索内容必须被当作数据,而不是指令。生产系统建议:提示词声明「检索内容仅供参考」、内容脱敏、权限隔离。
八、调试清单(LangSmith / tracing)
RAG 项目强烈建议开启 tracing,调试步骤:
- 先看 Retrieve 环节:检索到的 top-k 和问题相关吗?→ 相关则问题在生成,不相关则问题在检索
- 再看 chunk 内容:边界上下文是否丢失?→ 丢失则调 overlap 或 parent-child
- 最后看 LLM 生成:模型有没有遵循引用要求?
升级路线总览
第一版 纯向量检索(2-step RAG)
↓ 检索不准
第二版 向量 + MMR / metadata filter
↓ 精确词召回差
第三版 向量 + BM25 混合检索 + RRF
↓ 精排质量不够
第四版 加上 rerank(top 50-100 → 3-5)
↓ 上下文丢失
第五版 Contextual Retrieval / Late Chunking
每升一级解决一类问题,不要一开始就上全套——先定位瓶颈,再针对性优化。