Day 20:RAG 优化
学习目标
昨天我们跑通了 RAG 问答链路 v1,一个端到端的系统已经能工作了。但你一定发现了不少问题:有些问题检索不到相关内容、有些检索到了但答案质量不高、有些问题的答案引用了错误的来源。
今天是”找问题、改问题”的一天。我们要学习 RAG 系统中最常见的优化手段:Query Rewrite、Multi-query Retrieval、Hybrid Search、Rerank、Context Compression、Answer Grounding、Citation Check,以及检索失败时的回退策略。
这些优化手段不是都要加上的。正确的做法是:先用 v1 跑出基线数据,找出最影响效果的一两个问题,针对性地优化。每次只改一个变量,测量改进效果,然后再改下一个。
学完今天,你应该能诊断 RAG 系统中的常见问题,选择合适的优化手段,并且能量化优化前后的效果差异。
核心概念
一、Query Rewrite(查询改写)
Query Rewrite 是在用户原始问题进入检索之前,对问题进行改写,使其更适合检索。
为什么需要改写。 用户的问题表述方式和文档中的表述方式经常不一致。用户可能问”东西坏了怎么退”,但文档中写的是”产品退换货流程”。两段文字语义相近,但字面重叠很少,纯向量检索可能匹配不上。
用户的问题还可能太简短(“退货?“)或者太模糊(“那个政策怎么说”),缺乏足够的信息来生成有效的检索向量。
改写的方式。
扩展式改写。 将简短的问题扩展成更完整的表述。比如”退货?“扩展为”产品的退货流程和退货条件是什么”。
关键词提取式改写。 从问题中提取核心关键词,用于关键词检索。比如”购买超过 30 天还能退货吗”提取出”购买超过30天”、“退货”等关键词。
同义替换式改写。 将用户用词替换为文档中可能使用的术语。比如”东西坏了”替换为”产品质量问题”或”产品缺陷”。
用大模型做改写。 最灵活的方式是让大模型来改写查询。给模型一个 Prompt:“请将以下用户问题改写为更适合在知识库中检索的查询语句,保留核心意图,使用更正式和完整的表述。“模型通常能生成比原始问题更适合检索的查询。
改写的风险。 改写可能改变用户的原始意图。如果改写后的查询偏离了用户想问的内容,检索结果就会偏。所以改写后需要验证:检索到的 Chunk 是否确实和用户的原始问题相关,而不是只和改写后的查询相关。
二、Multi-query Retrieval(多查询检索)
Multi-query Retrieval 的思路是:与其用一个问题检索一次,不如生成多个不同角度的查询,分别检索,然后合并结果。
为什么需要多查询。 用户的问题只代表了一种表述方式,但同一个意图可以用很多不同的方式表达。一个查询可能检索不到某些相关内容,但另一个查询可以。多查询增加了”命中”的概率。
怎么做。
- 用大模型将用户问题改写为 3-5 个不同角度的查询
- 对每个查询分别做向量检索(每个查询返回 top-k)
- 将所有检索结果合并,去重
- 按相似度重新排序,取最终的 top-k
举个例子。 用户问”退货要多久”:
- 查询 1:“退货处理时间”
- 查询 2:“退货流程需要几天”
- 查询 3:“退款到账周期”
三个查询可能检索到不同的 Chunk(有的讲处理时效,有的讲流程步骤,有的讲退款周期),合并后比单一查询的覆盖面更广。
代价。 每个额外的查询都需要一次 Embedding API 调用和一次向量检索。3 个查询就是 3 倍的延迟和成本。在高并发场景下需要权衡。
适用场景。 当 v1 系统的主要问题是”检索覆盖不全”(答案存在但检索不到)时,Multi-query 是首选的优化手段。
三、Hybrid Search(混合检索)
混合检索同时使用向量检索和关键词检索,把两路结果合并。
为什么需要混合检索。 向量检索擅长语义匹配但不擅长精确匹配,关键词检索擅长精确匹配但不擅长语义理解。两路结合可以互补。
向量检索的优势场景:用户问”怎么退货”,文档写的是”产品退换货流程”。字面不同但语义相近,向量检索能匹配。
关键词检索的优势场景:用户问”产品编号 SN-2024-0518 的保修期”,文档中明确出现了”SN-2024-0518”。关键词检索能精确匹配这个编号,向量检索可能匹配不上(因为编号是一个特殊字符串,没有语义)。
怎么做。
- 对用户问题同时做向量检索和关键词检索
- 向量检索返回按相似度排序的结果集 A
- 关键词检索返回按相关度排序的结果集 B
- 用某种融合策略合并 A 和 B
融合策略。 常用的是 Reciprocal Rank Fusion(RRF,倒数排名融合)。对每个 Chunk,计算它在 A 和 B 中的排名的倒数之和,作为最终的融合分数。排名越靠前(排名数字越小),倒数越大,融合分数越高。
这个公式的好处是:不需要两路检索的分数在同一尺度上(余弦相似度和 BM25 分数的尺度完全不同),只要用排名就够了。
关键词检索的实现。 关键词检索需要全文索引。有些向量数据库(如 Weaviate、Qdrant)内置了全文检索功能。如果没有,可以用 Elasticsearch 或 Meilisearch 作为独立的搜索引擎,和向量数据库并行使用。
效果提升。 混合检索通常比纯向量检索的召回率提升 10%-30%,尤其是当文档中包含大量专有名词、编号、日期等需要精确匹配的内容时。
四、Rerank(重排序)
Rerank 是在初始检索之后,对检索结果做一次精细的重排序。
为什么需要 Rerank。 初始的向量检索是快速的、近似的。它用单一的向量表示来匹配问题和文档片段,不可避免地会丢失细节。Rerank 模型更精细地分析问题和每个候选 Chunk 之间的相关性,给出更准确的排序。
Rerank 模型和 Embedding 模型的区别。
Embedding 模型是把文本独立地映射到向量空间。问题和 Chunk 分别生成向量,然后计算向量距离。这种方式是”双编码器”——问题和文档分别编码,只做一次交互。
Rerank 模型是把问题和 Chunk 一起输入模型,做深度的交叉注意力计算。这种方式是”交叉编码器”——问题和文档在模型内部做多层交互,能捕捉更细致的语义关系。
交叉编码器更准确,但也更慢、更贵。所以不能用它来做全量检索(对数据库中每个 Chunk 都做交叉编码太慢了),只能用它来对初始检索的候选集做重排序。
怎么做。
- 初始检索返回 top-k(比如 k=20)个候选 Chunk
- 对每个候选 Chunk,将问题 + Chunk 一起输入 Rerank 模型
- Rerank 模型输出每个 Chunk 的相关性分数
- 按新分数重新排序
- 取重排序后的 top-n(比如 n=3)作为最终的检索结果
主流 Rerank 模型。
- Cohere Rerank:商用 API,效果好
- BGE-Reranker:开源模型,中文效果好
- Jina Reranker:开源模型,多语言支持
效果提升。 Rerank 通常是 RAG 优化中性价比最高的一步。加了 Rerank 之后,检索的准确率通常能提升 15%-40%。因为它修正了向量检索的排序偏差,把真正相关的 Chunk 提到前面。
五、Context Compression(上下文压缩)
Context Compression 是在检索结果拼接到 Prompt 之前,对内容做精简。
为什么需要压缩。 检索到的 Chunk 可能很长,或者包含大量和问题无关的内容。比如用户问”退货 SLA 是多少”,检索到的 Chunk 有 500 字,包含了退货流程、退货条件、退货SLA、退款方式等各种信息。其中只有”退货SLA”这一句是有用的,其余都是噪声。
如果直接把所有检索到的 Chunk 全部拼接到 Prompt 中,噪声会稀释模型的注意力,导致答案质量下降。
压缩的方式。
截断。 最简单的方式:只保留 Chunk 中和问题最相关的部分。但怎么判断”最相关”?简单做法是找到问题关键词在 Chunk 中的位置,保留关键词前后一定窗口范围内的文本。
摘要。 让模型对每个检索到的 Chunk 生成一个简短摘要,只保留和问题相关的信息。这比截断更智能,但需要额外的模型调用。
抽取式压缩。 用模型从 Chunk 中抽取和问题直接相关的句子,丢弃无关句子。这比摘要更忠实于原文,不会引入模型的改写。
什么时候用压缩。 当检索到的 Chunk 平均长度超过 500 字符、且用户问题通常指向具体知识点(而非理解整段内容)时,压缩效果最好。如果 Chunk 本身就比较短(200 字符以内),压缩的收益不大。
六、Answer Grounding(答案落地)
Answer Grounding 是确保模型的答案严格基于检索到的内容,不自由发挥。
为什么需要 Grounding。 即使 Prompt 中写了”只基于参考资料回答”,模型有时还是会”越界”——用自己训练数据中的知识来补充答案。这些补充内容可能正确,也可能不正确。在 RAG 场景中,我们只想要基于文档的、可验证的答案。
Grounding 的方式。
Prompt 强化。 在 Prompt 中更强烈地约束模型:“你必须且只能基于以上参考资料中的信息来回答。如果参考资料中没有相关信息,你必须回答’根据现有资料未能找到相关信息’。不得使用参考资料以外的任何知识。”
多次重复这个约束(在 Prompt 开头说一次,结尾再说一次),可以提升模型的遵守率。
后处理验证。 模型生成答案后,用一个独立的验证步骤检查答案中的每个关键声明是否能在检索到的 Chunk 中找到依据。如果某个声明没有依据,标记为”无法验证”或直接去掉。
结构化输出。 要求模型以结构化格式输出,每个答案段落都必须标注引用的 Chunk 编号。这样没有引用的段落就是”无依据的”,可以直接过滤掉。
七、Citation Check(引用检查)
Citation Check 是对答案中的引用来源做自动化校验。
为什么需要检查引用。 模型标注的引用不一定准确。它可能标注了引用但实际上那个 Chunk 不包含对应信息,也可能使用了某个 Chunk 的内容但忘了标注。
检查的方式。
自动匹配。 对答案中的每个句子,检查它和引用标注的 Chunk 之间的文本相似度。如果相似度很低(说明答案中的信息和引用的 Chunk 关系不大),标记这个引用可能有问题。
交叉验证。 让另一个模型(或同一个模型在另一个调用中)来判断:答案中的每个引用是否准确?参考资料 X 是否确实支持答案中的说法?
覆盖率检查。 检查检索到的所有 Chunk 是否都被答案引用了。如果某个高相似度的 Chunk 没有被引用,可能模型遗漏了重要信息。
什么时候做检查。 v1 阶段可以不做自动化检查,但需要人工抽查引用准确性。生产系统中,自动化的引用检查是质量保障的重要环节。
八、检索失败回退
检索失败是 RAG 系统的常态,不是异常。用户的问题可能超出知识库范围,或者知识库中确实没有对应信息。系统需要优雅地处理检索失败。
失败的场景。
- 相似度分数全面偏低(所有 top-k 结果的分数都低于阈值)
- 检索结果和问题不相关(分数不低但内容不对)
- 向量数据库服务不可用(技术故障)
回退策略。
诚实回答。 最基本的策略:告诉用户”根据现有知识库,未找到和您问题相关的信息”。这比硬编一个答案好得多。
扩大搜索。 降低相似度阈值,增加 top-k 值,做一次更宽泛的检索。可能在更宽松的条件下找到相关内容。
换检索方式。 如果默认是向量检索,回退时尝试关键词检索。不同的检索方式有不同的盲区,切换方式可能找到原来找不到的内容。
提示用户。 建议用户换一种方式提问,或者提供更多上下文信息。“您能否提供更多细节,或者换一种方式描述您的问题?”
转人工。 在企业客服场景中,如果 RAG 系统检索失败,可以自动转接给人工客服。这保证了用户不会被一个无助的 AI 搁置。
概念关系图
RAG 优化手段全览
=========================================================
[用户问题]
|
v
[Query Rewrite] -------- 改写查询,提升检索匹配率
|
v
[Multi-query] ---------- 生成多个查询,扩大覆盖面
|
v
[Hybrid Search] -------- 向量检索 + 关键词检索,互补
|
v
[Rerank] --------------- 精细重排序,提升准确率
|
v
[Context Compression] --- 压缩检索结果,去除噪声
|
v
[Prompt 组装] ---------- 强化 Grounding 约束
|
v
[答案生成]
|
v
[Citation Check] -------- 验证引用准确性
|
v
[最终答案]
优化手段 vs 解决的问题
=========================================================
问题 优化手段 预期提升
-----------------------------------------------------------------
用户表述和文档不一致 Query Rewrite 检索覆盖 +10-20%
检索不全,答案在别处 Multi-query 召回率 +10-30%
专有名词/编号检索不准 Hybrid Search 精确匹配 +20-40%
检索结果排序不准 Rerank 准确率 +15-40%
检索结果噪声太多 Context Compression 答案质量 +10-20%
模型自由发挥,不基于文档 Answer Grounding 幻觉率 -20-50%
引用标注不准确 Citation Check 引用准确率 +15-30%
检索全面失败 检索失败回退 用户体验改善
优化引入顺序建议
=========================================================
第一步(性价比最高):Rerank
| 解决排序问题,几乎总是有效
|
第二步:Query Rewrite
| 解决表述差异问题,成本增加不多
|
第三步:Hybrid Search
| 解决精确匹配问题,需要额外基础设施
|
第四步:Multi-query
| 解决覆盖不全问题,成本翻倍
|
第五步:Context Compression
| 解决噪声问题,需要额外模型调用
|
第六步:Answer Grounding + Citation Check
| 解决答案可靠性问题,增加后处理链路
实战分析
任务一:加入 Query Rewrite
在用户问题和向量检索之间,加一个查询改写环节。
实现方式。 调用大模型,用 Prompt 将用户问题改写为更适合检索的表述。Prompt 大致如下:
“请将以下用户问题改写为更适合在知识库中检索的查询。要求:保留核心意图,使用更正式和完整的表述,添加可能的关键词。”
测试方法。 对 v1 中检索失败的问题(知识库中有答案但检索不到),用改写后的查询重新检索,看是否能找到正确的 Chunk。
记录对比。 对每个测试问题,记录原始查询的检索结果和改写后查询的检索结果,对比差异。
任务二:加入 Rerank
在初始检索之后加一个 Rerank 步骤。
实现方式。 初始检索返回 top-10,送入 Rerank 模型重新排序,取重排序后的 top-3 作为最终检索结果。
工具选择。 如果用 Cohere Rerank API,直接调用。如果用开源模型(如 BGE-Reranker),需要本地部署模型。
测试方法。 对同一个问题,比较排序前后的检索结果顺序。关注:原来排在第 2-3 位的正确结果,经过 Rerank 后是否被提到了第 1 位。或者原来不在 top-3 的正确结果,经过 Rerank 后是否进入了 top-3。
任务三:对比优化前后结果
这是今天最重要的任务:量化优化效果。
评估指标。
- 准确率。 在 20 个测试问题中,正确回答的比例。
- 引用准确率。 在正确回答的问题中,引用标注准确的比例。
- 检索命中率。 在 20 个测试问题中,正确 Chunk 出现在 top-k 中的比例。
- 平均相似度。 检索结果和问题的平均相似度分数。
对比表格。 分别记录 v1(无优化)、加 Query Rewrite、加 Rerank、加两者组合的四个版本的数据。
分析方法。 如果某个优化手段在某些问题上有效、某些问题上无效甚至变差,分析原因。没有一种优化手段是对所有问题都有效的。
任务四:记录错误案例
对优化后仍然回答错误的问题,做详细的错误分析。
错误分类。
-
检索错误。 正确的 Chunk 没有被检索到。
- 原因 A:文档中确实没有答案(知识库不完整)
- 原因 B:问题表述和文档表述差异太大(需要更好的 Query Rewrite)
- 原因 C:Chunk 切分不当,把答案切散了(需要调整切分策略)
-
生成错误。 检索到了正确的 Chunk,但模型生成的答案不对。
- 原因 A:模型没有严格基于检索内容回答(需要更强的 Grounding)
- 原因 B:检索结果中噪声太多,干扰了模型(需要 Rerank 或压缩)
- 原因 C:Prompt 指令不够清晰(需要优化 Prompt)
-
引用错误。 答案内容正确但引用标注有误。
- 原因 A:模型标注了错误的引用编号
- 原因 B:模型遗漏了引用标注
每个错误案例都应该归入上述某一类,这样才能针对性地优化。
当日产物说明
产物一:《RAG Demo v2》
在 v1 基础上加入了 Query Rewrite 和 Rerank 的优化版本。
应该包含:
- v1 的所有功能
- Query Rewrite 功能(自动改写用户查询)
- Rerank 功能(检索结果重排序)
- 20 个测试问题在 v2 上的回答记录
质量标准: 和 v1 相比,至少在 3 个原来回答错误的问题上有所改善。
产物二:《RAG 优化对比表》
这是一份量化对比文档。
应该包含:
- 评估指标定义(准确率、引用准确率、检索命中率等)
- v1 的基线数据
- 加 Query Rewrite 后的数据
- 加 Rerank 后的数据
- 两者组合的数据
- 每个测试问题在不同版本上的表现对比
- 统计汇总和结论
质量标准: 数据真实、对比公平(同样的测试问题集、同样的评估标准)。结论有数据支撑,不是凭感觉。
产物三:《RAG 错误案例库》
这是一份结构化的错误分析文档。
应该包含:
- 每个错误案例的完整记录(问题、检索结果、答案、正确答案)
- 错误分类(检索错误/生成错误/引用错误)
- 错误原因分析
- 优化建议
质量标准: 每个错误案例都有明确的分类和原因分析。优化建议具体可执行。
常见误区与避坑
误区一:所有优化手段一起上
看到 8 种优化手段就想全部加上,这是常见的冲动。但每种优化手段都有成本(延迟、计算、开发量、维护复杂度),而且它们之间可能相互干扰。
正确的做法是:一次加一种优化,测量效果,确认有效后再加下一种。这样你能清楚知道每种优化的贡献。如果一股脑全加上去,效果好了不知道是哪个的功劳,效果差了不知道是哪个在捣乱。
误区二:只看成功案例
用优化后能回答更好的问题来证明优化有效果,忽略了那些优化后反而变差的问题。任何优化手段都是双刃剑,在某些场景下可能帮倒忙。
比如 Query Rewrite 可能将一个本就精确的问题改写得过于宽泛,导致检索结果从精准变成模糊。Rerank 可能将一个语义匹配但不包含关键词的正确结果排到了后面。
评估优化效果时要看全量数据,不只是挑好的看。
误区三:过度优化检索,忽略生成
检索优化(Query Rewrite、Hybrid Search、Rerank)很容易引起关注,因为它们有明确的指标(检索准确率、召回率)可以量化。但答案质量还受生成环节的影响。
如果检索到了正确的 Chunk,但 Prompt 写得不好、模型能力不够、Temperature 设置不当,答案质量一样会很差。在优化检索的同时,别忘了检查生成环节。
误区四:用少量测试问题得出结论
用 5 个测试问题就判断某种优化”有效”或”无效”,样本量太小,结论不可靠。一个优化可能在某 5 个问题上效果很好,但在另外 50 个问题上没有效果甚至变差。
建议至少用 20 个测试问题来评估。如果时间允许,50 个更好。测试问题要覆盖不同类型和难度,避免选择性偏差。
误区五:把 Rerank 当作万能药
Rerank 确实是性价比很高的优化手段,但它不能解决所有检索问题。如果初始检索的候选集中根本没有正确的 Chunk(因为候选集太小或者向量检索完全跑偏了),Rerank 也无能为力——你不能对不存在的东西做排序。
Rerank 解决的是”正确结果在候选集中但排序不对”的问题,不能解决”正确结果根本不在候选集中”的问题。后者的解决方案是扩大初始检索的 top-k、使用 Multi-query、或者使用 Hybrid Search。
延伸思考
优化是一个持续过程
RAG 系统的优化不是一次性的工作,而是一个持续迭代的过程:
- 收集用户的真实问题和使用反馈
- 分析错误案例,找出系统性的薄弱环节
- 选择合适的优化手段
- 实施优化,测量效果
- 重复
每一轮迭代都会发现新的问题。随着知识库的增长(新文档加入)和用户群体的扩大(新类型的提问出现),系统的表现会动态变化。定期评估和优化是保持系统质量的关键。
RAG 优化和 Eval 体系的关系
今天讲的优化效果评估是手工的:准备测试问题集、运行系统、人工判断答案是否正确。这在 MVP 阶段够用了,但规模化后需要自动化的评估体系。
Week 5 的 Day 31 会学习 Eval 评估体系,其中就包括 RAG 系统的自动化评估:用模型来自动判断答案质量、引用准确性、检索相关性。今天打下的基线数据(20 个测试问题和人工标注)就是未来自动化评估的基础。
从 RAG 优化到 Agent
今天的优化手段都是”固定管线”式的:Query Rewrite → Multi-query → Hybrid Search → Rerank → Compression → Generation → Citation Check。不管用户问什么,都走同样的流程。
但在更高级的系统中,这些优化可以由 Agent 来动态决策。Agent 判断第一次检索结果不够好,主动决定换一种检索方式或者扩大搜索范围。Agent 判断某个问题需要跨文档综合,主动发起多轮检索。这就是”Agentic RAG”的思路,在 Week 4 学完 Agent 之后可以深入探索。
自测问题
-
Query Rewrite 解决什么问题?改写的风险是什么?
-
Multi-query Retrieval 的原理是什么?它的代价在哪里?
-
为什么混合检索比纯向量检索效果好?两者的互补关系是什么?
-
Rerank 模型和 Embedding 模型的核心区别是什么?为什么 Rerank 更准确但更慢?
-
Context Compression 的三种方式是什么?分别适用于什么场景?
-
Answer Grounding 的目的是什么?实现 Grounding 的三种方式分别是什么?
-
如果 RAG 系统的主要问题是”专有名词检索不准”,你会优先选择哪种优化手段?为什么?
-
为什么说”一次加一种优化”是正确的优化策略?一次全加上有什么问题?
-
设计一个 RAG 优化的评估方案:有哪些指标、怎么对比、怎么判断优化是否有效?
-
检索失败的四种回退策略分别是什么?在什么场景下选择哪种策略?
关键词
- Query Rewrite(查询改写):将用户的原始问题改写为更适合检索的表述,提升匹配率
- Multi-query Retrieval(多查询检索):生成多个不同角度的查询分别检索,合并结果以扩大覆盖面
- Hybrid Search(混合检索):同时使用向量检索和关键词检索,融合两路结果
- Rerank(重排序):用交叉编码器对初始检索结果做精细重排序,提升准确率
- Context Compression(上下文压缩):精简检索结果内容,去除和问题无关的噪声
- Answer Grounding(答案落地):确保模型答案严格基于检索内容,不自由发挥
- Citation Check(引用检查):自动校验答案中的引用来源是否准确
- 检索失败回退:当检索不到相关内容时的处理策略,包括诚实回答、扩大搜索、转人工等
- Reciprocal Rank Fusion(RRF):倒数排名融合,一种将多路检索结果合并的算法
- 交叉编码器(Cross-Encoder):将问题和文档一起输入模型做深度交互的编码方式,比双编码器更准确