RAG 检索优化报告

从 RAG 的六个环节讲起,比较切块、嵌入模型、查询改写、重排与拒答,给出最终方案和效果。

1. 结果

这套系统要回答的问题很简单:用户问一句投资相关的话,系统能不能从资料里找到对的段落,并且只依据这些段落回答。

经过四组对比实验,最终方案在 40 条有答案的测试题上,前 5 条命中正确段落的比例从 0.675 提升到 0.850;前 5 条里命中正确书目的比例达到 95%;8 条知识库里没有答案的问题全部正确拒答,没有一条编造。

环节选择效果
切块512 字平铺在效果和成本之间最平衡
嵌入模型bge-m3(1024 维)中文、英文、跨语言都靠前
查询处理多 query 改写 + RRF召回提升的主要来源
排序可选 cross-encoder 重排把最相关的证据推到第一位
拒答分数门控 + LLM 审核不该答的题不乱答

2. RAG 是怎么工作的

RAG(检索增强生成)不是“把文档丢给大模型”,而是一条流水线。每一环都有不同的做法,选错了,后面再强的模型也救不回来。

文档:切块 → 向量化 → 索引
问题:改写 → 检索(向量 + 关键词)→ 重排 → 生成 → 带引用的回答

下面按这条链路,逐个说明有哪些选择、各自的取舍。

2.1 文档怎么切

模型一次能读的文字有限,长文档必须先切成块(chunk)。切法直接决定检索能不能命中:

块越小,定位越准,但上下文越碎;块越大,上下文越完整,但容易混入无关内容。这是切块的核心矛盾。

2.2 文本怎么变成向量

检索依赖嵌入模型(embedding model)把文字变成向量。向量越能表达语义,找得越准。这次比较了四类模型:

模型维度特点
bge-small-zh-v1.5512本地 ONNX,轻量,中文够用,英文和跨语言较弱
multilingual-e5-small384更小,英文表现好,跨语言一般
bge-m31024本地 ONNX,多语言,长文本,跨语言最强
text-embedding-v41024云端 API,中文强,不占本地算力

维度不是越高越好:维度高通常更准,但索引更慢、存储更大。选模型要看语料是中文、英文,还是中英混合。

2.3 怎么检索

有了向量,检索有三种基本方式:

混合检索的关键不是“都开”,而是权重。权重偏向量,同义改写更容易命中;偏关键词,精确术语更稳。

2.4 问题怎么改写

用户的一句话往往不是最好的检索词。查询改写让模型把问题变成多条 query:

每条 query 各检索一次,再用 RRF(Reciprocal Rank Fusion)按排名融合。RRF 只看“排第几”,不看分数绝对值,所以不同 query 的结果可以直接合并。

2.5 找到后怎么排序

向量检索返回的是“大致相关”的候选。重排模型(reranker)把问题和每个候选放在一起做一次精细判断,重新打分。它通常能把最相关的证据推到第一位,但计算量比向量检索大,适合作为可选的第二阶段。

2.6 没有答案怎么办

知识库里没有答案时,系统应该明确说“资料中没有足够信息”,而不是硬凑。两种做法:

3. 实验怎么做的

3.1 语料

两套语料回答的是不同问题:经典书籍考“概念和推理”,年报考“数字、表格和具体公司”。

3.2 测试题

48 条问题:40 条有答案、8 条无答案;有答案里 9 条是“中文提问、答案在英文书里”,用来考察跨语言检索。后来做拒答实验时,又补了 20 条知识库外的问题(公司财报、行情、宏观),合计 28 条无答案。

3.3 指标

指标含义
Recall@5前 5 条里有没有正确答案
MRR第一条正确答案排得多靠前
nDCG@5相关结果有没有排在前面
Top-1第一条是不是相关
文档级召回前 5 条有没有命中正确的书

所有对比都在同一套题上做,一次只改一个变量。

4. 实验一:切块方式

先固定嵌入模型和检索参数,只改切块。

切块方式块数Recall@5MRRTop-1
PDF 512 平铺3,9480.6250.5880.550
TXT 512 平铺3,1890.6750.6330.600
TXT 512 父子块33,1690.6750.6190.575
TXT 1024 平铺1,6480.7000.6460.625
TXT 1024 父子块33,1550.6750.6500.625

(PDF 与 TXT 的解析方式不同,两者不是严格对照;切块结论只看 TXT 内部。)

三个观察:

  1. 512 到 1024 有小幅提升:Recall +1 条、Top-1 +1 条,因为块更大,上下文更完整。
  2. 父子块与同尺寸平铺持平:512 父子块和 512 平铺同分,1024 父子块的排序优势在平铺 1024 里也能拿到。收益来自“块变大”,不是父子机制本身。
  3. 成本差距很大:父子块有 33,000 多个子块,平铺 1024 只有 1,648 块。

最终选 512 平铺:效果接近最优,索引和检索成本最低,后续换模型、改参数也最容易。

5. 实验二:嵌入模型

5.1 纯向量对比

先排除关键词检索的干扰,只用向量做 top-5 检索:

模型维度Recall@5中文英文跨语言MRR
bge-small-zh-v1.55120.4750.7270.3330.0000.433
multilingual-e5-small3840.6500.7730.8890.1110.602
bge-m310240.8000.7730.8890.7780.714
text-embedding-v410240.7500.8640.7780.4440.695

结论很清晰:

没有“全面碾压”的模型,只有适合语料的模型。这也是为什么先做纯向量对比:混合检索会掩盖模型之间的差距。

5.2 接入混合检索后

把 bge-small 换成 bge-m3,切块和其他参数不变:

方案Recall@5MRRTop-1
bge-small 直接检索0.6750.6330.600
bge-m3 直接检索0.7250.6960.675
bge-small + 多 query0.8500.7080.625
bge-m3 + 多 query0.8500.7400.650

直接检索时,bge-m3 多命中 2 条、MRR 提升 6.3 个百分点;叠加查询改写后,召回都到 0.850,bge-m3 继续在排序上领先。原因是混合检索的关键词权重已经补掉了部分语义差距,模型的优势主要体现在“把对的排得更前”。

最终选 bge-m3:多语言能力和排序质量都更好,索引成本可以接受。

6. 实验三:查询改写 + 多 query + RRF

这是提升最大的一环。做法是让模型把一个问题改写成 3–5 条 query,各检索一次,再融合。

模式Recall@5MRR跨语言 Recall
直接检索0.6750.6330.000
只用英文翻译——0.667
多 query(不含英文)0.8000.6760.222–0.556
多 query + RRF0.8500.7080.667

多 query 的代价是检索次数变成 3–5 倍。实测可以通过缓存和并发把延迟压到可接受范围。

7. 实验四:重排

在多 query 的候选池上再加一层 cross-encoder 重排,只比较排序质量:

排序方式MRRTop-1
多 query + RRF0.6900.625
每路分别重排后融合0.7150.675
并集候选 + 原问题重排0.7500.725

重排不改变“能找到什么”,但明显改变“先看到什么”:Top-1 从 0.625 提到 0.725,MRR 从 0.690 提到 0.750。对于生成式问答,第一位往往就是被引用的证据,所以这个提升很直接。

由于重排计算量较大,最终把它定位为可选层:对延迟不敏感的场景开启,交互场景可以先用多 query 的结果。

8. 最终架构

四组实验的结论合成一条链路:

离线索引
文档入库6 本投资经典 + 30 份年报,共 8,205 页
解析切块PDF / TXT 解析为纯文本,按 512 字平铺
双索引bge-m3 向量(1024 维,本地 ONNX)+ BM25 关键词索引
在线问答
查询改写LLM 生成 3–5 条 query,覆盖原问、术语、英文与子问题
多路混合检索每条 query 各检索一次,向量 0.3 / 关键词 0.7
RRF 融合按排名融合各路结果,取 top 5
重排(可选)bge-reranker-base int8,用原问题对并集候选重排
拒答判定Top-1 分数 ≥ 0.45 直接放行;低于 0.45 交给 LLM 审核 top 5
生成只依据 top 5 作答,正文 [n] 与来源清单闭合;材料不足则明确拒答
层最终选择参数
解析PDF / TXT版面解析后统一为纯文本
切块固定长度平铺512 字
嵌入bge-m31024 维,本地 ONNX
关键词BM25与向量按 0.3 / 0.7 加权
改写LLM 多 query3–5 条
融合RRFk = 60,取 top 5
重排bge-reranker-base int8可选
拒答分数门控 + LLM 审核0.45
生成LLM仅用 top 5,[n] 引用

8.1 效果

检索侧(默认不开重排):

指标结果
Recall@5(段落级)0.850
文档级 Recall@50.950
MRR0.740
跨语言 Recall0.778

生成侧(32 题:24 有答案 + 8 无答案):

指标结果
支撑度(0–2)1.96
相关性(0–2)2.00
引用质量(0–2)1.96
无答案题正确拒答8/8
编造事实0

也就是说:材料足够时,回答基本都能在原文找到依据,引用对得上;材料不足时,系统会明确说“资料中没有足够信息”,而不是猜一个答案。

9. 一句话总结

RAG 的效果不取决于“用了多大的模型”,而取决于每个环节有没有选对:切块要匹配语料,嵌入模型要匹配语言,查询改写负责召回,重排负责排序,拒答负责边界。这四件事做对,检索召回可以从 0.675 提到 0.850,并且让系统在该说“不知道”的时候真的说“不知道”。