☰
RAG技术演进中段战事:从能检索到检索准的工程调优实战
2026/10/13 12:59:15 网站建设 项目流程

1. RAG 技术演进的中场战事:从“能用”到“好用”的分水岭

如果你在过去一年里搭过任何一个基于大模型的问答系统,大概率绕不开 RAG 这个词。检索增强生成,Retrieval-Augmented Generation,说白了就是给大模型外挂一个“资料库”,让它回答之前先去翻资料,而不是全靠脑子里那点预训练时记住的东西。这个思路最早在 2020 年前后被系统性地提出来,但真正让它从论文走进工程实践的,是 2023 年之后大模型应用爆发的那一波浪潮。

我大概是从前年开始密集接触 RAG 相关项目的,从最早的“向量库加个 prompt 模板”的玩具级 demo,到后来要处理几十万份文档、上百个字段过滤条件、还要保证响应延迟在几百毫秒以内的生产系统,中间踩的坑可以说能写一本小册子。这个系列我打算分上中下三篇来聊,上篇讲的是 RAG 的基本盘和早期形态,也就是“能跑通”的阶段;这一篇“中”,我想重点聊聊 RAG 技术演进过程中那个最关键的分水岭——从“能检索到”到“检索得准、生成得好”的过渡阶段。

为什么说这个“中段”特别重要?因为大部分团队做 RAG,第一版 demo 往往一两天就能跑起来,但真正上线之后发现效果不行,回答要么答非所问,要么漏掉关键信息,要么把不相关的段落也塞进上下文里导致模型被干扰。这个时候你要做的不是推翻重来,而是要在检索和生成这两个环节之间做大量的精细化调优。这一篇就是讲这些调优的思路、方法和实操细节。

这篇文章适合谁看?如果你已经搭过一个最基础的 RAG 流程,知道什么是向量数据库、什么是 embedding、什么是 chunk,但效果总是不尽如人意,那这篇就是写给你的。如果你还没接触过 RAG,建议先去看上篇补一下基础概念,不然中篇里很多取舍逻辑你可能会觉得跳跃。

2. 检索环节的精细化:从“一刀切”到“分层策略”

2.1 为什么朴素的向量检索不够用

最基础的 RAG 检索就是:把文档切成固定长度的 chunk,全部做 embedding 存进向量库,用户提问时把问题也做 embedding,然后算余弦相似度,取 top-k 个 chunk 塞给大模型。这个流程跑通没问题,但实际效果往往很粗糙。

我拿一个实际场景举例。假设你有一个内部技术文档库,用户问“XX 接口的超时时间怎么配置”。朴素向量检索可能会返回三段内容:一段讲接口鉴权、一段讲超时配置、一段讲错误码。为什么?因为这三段里都出现了“接口”这个词,embedding 模型在语义空间里把它们拉得比较近。但真正有用的只有第二段,第一段和第三段塞进去反而会干扰模型生成。

这个问题的根源在于:固定长度的 chunk 切分方式,天然会破坏文档的语义完整性。一个完整的配置说明可能横跨两个 chunk,而一个不相关的段落可能因为恰好包含关键词而被召回。更麻烦的是,向量相似度是一个“全局”指标,它衡量的是两段文本在语义空间里的整体接近程度,但用户的问题往往只关心文档中的某一个具体方面。

所以从“中段”开始,RAG 的检索环节要做的事情就不再是“找一个向量库、调一个 top-k”那么简单了,而是要引入分层检索策略。

2.2 分层检索的核心思路与实操拆解

所谓分层检索,我的理解是:不要指望一次向量检索就能搞定所有事情,而是把检索拆成多个阶段,每个阶段用不同的策略和粒度。

第一层:粗召回。这一层的目标只有一个——别漏。用向量检索也好,用关键词检索也好,甚至用全文索引也好,先把可能相关的候选集扩大到几十甚至上百条。这一层不追求精度,追求的是召回率。我通常会把 top-k 设到 50 甚至 100,后面再慢慢筛。

第二层:精排。拿到粗召回的候选集之后,用一个更精细的模型来打分。这里最常用的就是 Cross-Encoder 类的重排序模型。它和向量检索的区别在于:向量检索是分别把 query 和 document 编码成向量再算距离,而 Cross-Encoder 是把 query 和 document 拼在一起送进模型,直接输出一个相关性分数。后者的精度明显更高,但计算量也大得多,所以只能用在候选集比较小的阶段。

第三层:过滤与去重。精排之后,还要根据业务规则做过滤。比如时间范围过滤、权限过滤、来源可信度过滤。同时要做去重,因为相邻 chunk 之间往往有大量重叠内容,如果不去重,模型会看到大量重复信息,既浪费上下文窗口,又可能让模型过度关注某个局部。

这三层下来,最终送给模型的 chunk 可能只有三到五条,但每一条都是精挑细选的。我实测下来,同样的向量库和同样的生成模型,加上分层检索之后,回答准确率能从大概六成提升到八成以上。这个提升幅度在 RAG 项目里已经非常可观了。

2.3 Chunk 策略的进阶玩法

聊完检索分层,必须回头说一下 chunk 策略,因为这是整个检索环节的地基。固定长度切分是最简单的,但也是最粗糙的。进阶的做法有这么几种:

按语义切分。不是按字符数切,而是按段落、按标题层级、按句子边界来切。比如 Markdown 文档可以按标题层级切,每个二级标题下的内容作为一个 chunk。这样切出来的 chunk 语义完整性更好,但长度不均匀,有的可能只有几十个字,有的可能上千字。

重叠切分。在相邻 chunk 之间保留一定的重叠区域,通常是 chunk 长度的 10% 到 20%。这样做的好处是避免一个完整的语义单元被切断。比如一个配置说明横跨两个 chunk,重叠之后至少有一个 chunk 包含完整说明。

父子文档策略。这个稍微复杂一点:把文档切成小块用于检索,但检索到之后,返回给模型的不是这个小块本身,而是它所属的更大的父文档段落。这样做的好处是检索粒度细、定位准,但生成时上下文足够完整。我试过在一个技术文档项目里用这个策略,效果比单纯的重叠切分还要好一截。

混合切分。实际项目里我很少只用一种切分方式,通常是组合使用。比如先用标题层级做一级切分,再在每段内部按句子边界做二级切分,同时保留一定的重叠。这样既保证了语义完整性,又控制了单块的长度。

注意:chunk 长度没有万能值。我见过有人直接抄别人的 512 token 配置,结果在自己的文档上效果很差。正确的做法是拿一批真实用户问题做测试,对比不同 chunk 长度下的召回效果,选一个最适合自己文档特点的值。一般来说,技术文档适合短一些的 chunk,叙事类文档适合长一些的。

3. 生成环节的调优:让模型“说人话”且“说实话”

3.1 上下文组装的学问

检索做完之后,下一步就是把检索到的内容组装成 prompt 送给大模型。这一步看起来简单,其实有很多细节会影响最终效果。

首先是顺序。检索到的多个 chunk 应该按什么顺序排列?按相关性分数从高到低?还是按文档原始顺序?我的经验是:如果 chunk 之间有逻辑上的先后关系,比如一个流程的步骤一和步骤二,那就按原始顺序排;如果彼此独立,那就按相关性分数排。但有一个例外:最相关的 chunk 不要放在最前面,也不要放在最后面,而是放在中间偏前的位置。因为大模型对上下文的首尾部分注意力更集中,中间部分容易被忽略。把最重要的信息放在中间偏前,可以平衡注意力和逻辑连贯性。

其次是分隔符。不同 chunk 之间要用清晰的分隔符隔开,比如用三个短横线或者用 XML 标签包裹。这样做是为了让模型明确知道每个 chunk 的边界在哪里,避免它把不同 chunk 的内容混在一起理解。我习惯用类似<doc id="1">...</doc>这样的标签,实测下来模型对边界的识别更准确。

最后是元信息注入。每个 chunk 除了正文内容,还可以带上一些元信息,比如来源文档标题、更新时间、可信度评分。这些信息可以帮助模型判断内容的时效性和权威性。比如用户问一个最新的配置参数,模型看到某个 chunk 的更新时间是两年前,另一个是上个月,它就应该优先采信后者。

3.2 Prompt 模板的设计原则

Prompt 模板是 RAG 生成环节的核心。一个好的模板应该做到三件事:约束模型只基于给定上下文回答、引导模型引用来源、处理上下文不足的情况。

我见过很多失败的 RAG 案例,问题都出在 prompt 太随意。比如只写一句“根据以下内容回答问题”,模型很可能把上下文和自己的预训练知识混在一起,甚至编造出上下文中根本没有的信息。正确的做法是在 prompt 里明确写清楚:如果上下文中没有相关信息,就回答“根据现有资料无法回答”,不要自己发挥。

引用来源也很重要。让模型在回答时标注信息来自哪个 chunk,一方面方便用户核实,另一方面也能倒逼模型更认真地阅读上下文。我通常会在 prompt 里要求模型用[1][2]这样的角标来标注引用,然后在展示层把角标渲染成可点击的来源链接。

还有一个容易被忽略的点:上下文长度控制。不是塞给模型的 chunk 越多越好。我做过对比测试,同样的问题,塞 10 个 chunk 和塞 3 个 chunk,后者的回答准确率反而更高。原因是过多的上下文会稀释关键信息,模型在长上下文中容易“迷失”。所以检索阶段宁缺毋滥,精排之后只保留最相关的几条就够了。

3.3 生成参数的实际影响

大模型的生成参数对 RAG 效果也有直接影响。最关键的几个是:

temperature。这个参数控制输出的随机性。RAG 场景下我通常会把 temperature 设得很低,0.1 到 0.3 之间。因为 RAG 要的是准确、忠实的回答,不是创意写作。temperature 太高,模型容易自由发挥,偏离上下文。

top_p。和 temperature 类似,控制采样范围。RAG 场景下也建议设低一些,0.8 到 0.9 之间比较稳妥。

max_tokens。控制输出长度。这个要根据业务场景来定。如果是客服问答,回答要简短,设 200 到 300 就够了;如果是技术文档解读,可能需要 800 到 1000。

frequency_penalty 和 presence_penalty。这两个参数用来抑制重复输出。RAG 场景下有时候模型会反复引用同一段上下文,适当调高这两个参数可以缓解。

这些参数没有绝对的最优值,需要根据你的具体场景做 A/B 测试。我的建议是先把 temperature 和 top_p 固定在一个保守值上,然后重点调 max_tokens 和两个 penalty 参数。

4. 评估体系的搭建:没有度量就没有优化

4.1 为什么 RAG 评估这么难

RAG 系统的评估比传统检索系统难得多。传统检索系统只看召回率和准确率,但 RAG 的最终输出是一段自然语言回答,它的好坏很难用一个简单的数值来衡量。一段回答可能事实正确但表述啰嗦,可能表述简洁但漏掉了关键细节,可能引用了正确来源但推理过程有误。

更麻烦的是,RAG 的错误可能发生在检索环节,也可能发生在生成环节,还可能两个环节都有问题。如果不把这两个环节分开评估,你根本不知道问题出在哪里。

所以从“中段”开始,RAG 项目必须建立一套分层的评估体系。

4.2 检索环节的评估指标

检索环节的评估相对客观,核心指标有这么几个:

指标含义目标值参考
Recall@K前 K 个结果中包含正确答案的比例粗召回阶段 > 0.9
Precision@K前 K 个结果中相关结果的比例精排后 > 0.7
MRR第一个相关结果排名的倒数均值越接近 1 越好
NDCG考虑排序位置的相关性加权指标越接近 1 越好

搭建评估集的方法:从真实用户问题中采样一批,然后人工标注每个问题对应的正确 chunk。这个标注工作很枯燥,但非常值得做。我通常建议至少标注 100 到 200 个问题,才能得到比较稳定的评估结果。

有了评估集之后,每次调整 chunk 策略、换 embedding 模型、改检索参数,都可以跑一遍评估,看指标是升是降。这样你的优化就不是凭感觉,而是有数据支撑的。

4.3 生成环节的评估方法

生成环节的评估更复杂,目前业界常用的方法有这么几种:

人工评估。最可靠但最贵。让标注人员对回答的准确性、完整性、流畅性打分。我通常用 1 到 5 分的量表,每个维度单独打分。

模型评估。用一个更强的模型来给回答打分。比如让 GPT-4 来判断回答是否忠实于上下文、是否回答了用户问题。这种方法成本低、速度快,但和人工评估的一致性需要校准。

自动化指标。比如 ROUGE、BLEU 这些传统指标,在 RAG 场景下参考价值有限,因为 RAG 的回答往往不是对原文的复述,而是综合多段内容后的重新组织。不过有一些专门为 RAG 设计的指标,比如 faithfulness(忠实度)和 answer relevance(回答相关性),可以用模型来计算。

我的实际做法是:日常迭代用模型评估快速筛选,重要版本发布前用人工评估做最终确认。两者结合,既保证了效率,又保证了质量。

4.4 评估驱动的迭代闭环

评估体系建好之后,最重要的是把它嵌入到日常迭代流程里。我习惯的做法是:

  1. 每次改动之前,先跑一遍基线评估,记录当前指标。
  2. 改动之后,再跑一遍评估,对比指标变化。
  3. 如果指标提升,保留改动;如果下降,回滚或者调整。
  4. 定期(比如每周)做一次全量评估,检查是否有指标退化。

这个闭环看起来简单,但坚持做下来,RAG 系统的效果会稳步提升。我见过太多团队做 RAG 是“改一改、试一试、感觉差不多就行”,没有量化反馈,优化就变成了玄学。

5. 常见问题与排查技巧实录

5.1 检索到了正确内容但模型没用好

这是最常见的问题之一。检索环节明明返回了包含正确答案的 chunk,但模型生成时要么忽略了它,要么把它和其他不相关内容混在一起。排查思路:

  • 检查 prompt 模板是否明确要求模型基于上下文回答。
  • 检查 chunk 的排列顺序,最重要的内容是否被放在了中间偏前的位置。
  • 检查是否有太多不相关的 chunk 干扰了模型注意力,尝试减少 top-k。
  • 检查 temperature 是否过高,导致模型自由发挥。

我遇到过一次典型情况:检索返回了 8 个 chunk,其中只有第 3 个是真正相关的,但模型在生成时把第 1 个和第 5 个 chunk 的内容也揉进去了,导致回答里出现了错误信息。后来把 top-k 降到 3,并且加了重排序,问题就解决了。

5.2 回答过于笼统或过于细节

有时候模型生成的回答太泛,没有落到具体细节;有时候又太琐碎,把上下文中所有细节都罗列出来。这两种情况都和 prompt 设计有关。

回答太泛,通常是因为 prompt 里没有明确要求“具体”。可以在 prompt 里加一句“请给出具体的配置参数或操作步骤,不要只给概括性描述”。回答太琐碎,通常是因为上下文里塞了太多细节,模型不知道哪些是重点。可以在 prompt 里要求“只回答用户问题直接相关的内容,不要罗列无关细节”。

5.3 多轮对话中的上下文管理

RAG 系统如果支持多轮对话,上下文管理会变得更复杂。用户第二轮提问时,往往省略了第一轮的一些信息,比如第一轮问“XX 接口怎么配置”,第二轮问“那超时时间呢”。如果直接把第二轮问题拿去做检索,很可能检索不到正确内容,因为“那超时时间呢”这个 query 太短、信息量太少。

解决办法是查询改写:把多轮对话的历史和当前问题一起送给模型,让模型生成一个完整的、独立的查询语句,再用这个查询去检索。比如上面那个例子,改写后的查询可能是“XX 接口的超时时间怎么配置”。这样检索准确率会大幅提升。

5.4 常见问题速查表

问题现象可能原因排查方向
回答答非所问检索结果不相关检查 chunk 策略、embedding 模型、top-k
回答遗漏关键信息相关 chunk 未被召回提高召回数量、增加关键词检索兜底
回答包含错误信息模型自由发挥降低 temperature、强化 prompt 约束
回答过于笼统prompt 缺少具体性要求修改 prompt 模板
多轮对话效果差查询信息不完整引入查询改写
响应延迟高检索或生成环节耗时分别计时,定位瓶颈

实操心得:排查 RAG 问题时,一定要把检索结果和生成结果分开看。我习惯在调试模式下把检索到的 chunk 和最终回答并排展示,这样一眼就能看出是检索的问题还是生成的问题。很多团队把这两步混在一起调,效率很低。

6. 工具选型与架构取舍的一些经验

6.1 向量数据库怎么选

向量数据库的选择主要看几个维度:数据规模、查询延迟要求、过滤条件复杂度、运维成本。

小规模场景(几万到几十万条向量),用 FAISS 或者 SQLite 加向量扩展就够了,部署简单,不需要额外运维。中等规模(百万到千万级),可以考虑 Milvus、Qdrant 这类专门的向量数据库,支持分布式和复杂的过滤条件。大规模(亿级以上),基本就要上分布式方案了,同时要考虑索引类型和分片策略。

我个人的经验是:不要一上来就追求“大而全”的方案。很多项目的数据量其实并不大,用轻量级方案反而更稳定、更好维护。等到数据量真的上来了再迁移也不迟。

6.2 Embedding 模型的选择

Embedding 模型直接决定了检索质量。选择时主要看:语言支持、领域适配、维度大小、推理速度。

通用场景下,一些开源的 multilingual 模型表现已经不错。但如果你的文档是特定领域的,比如法律、医疗、技术文档,通用模型可能不够。这时候可以考虑用领域数据做微调,或者选用在相关领域预训练过的模型。

维度大小也是一个取舍点。高维度(比如 1024 或 1536)通常效果更好,但存储和计算成本也更高。低维度(比如 256 或 384)成本低,但可能损失一些精度。我的建议是先用高维度跑通,如果成本压力大再考虑降维。

6.3 重排序模型的部署

重排序模型是提升精度的关键,但它的推理成本比向量检索高得多。部署时要注意:

  • 重排序模型通常只处理几十到几百个候选,不要把它用在粗召回阶段。
  • 可以用 GPU 加速,也可以用 ONNX 或 TensorRT 做推理优化。
  • 如果延迟要求很严格,可以考虑用蒸馏后的小模型,牺牲一点精度换速度。

我试过在一个延迟要求 500 毫秒以内的项目里,把重排序模型从 BERT-base 换成蒸馏后的小模型,精度只掉了不到两个百分点,但延迟降了一半以上。这个取舍是值得的。

7. 中段之后:下一步往哪走

写到这里,RAG 技术演进中段的核心内容基本覆盖了。从检索分层到生成调优,从评估体系到问题排查,这些都是在“能跑通”之后必须面对的工程问题。我自己的体会是,RAG 项目里最花时间的从来不是搭第一版 demo,而是后面这些精细化的调优工作。一个 RAG 系统从六十分做到八十分,可能只需要两周;但从八十分做到九十分,可能需要两个月。

这个系列的下篇,我打算聊一聊 RAG 的进阶形态,比如多模态 RAG、Agentic RAG、以及和微调的结合。那些内容更偏前沿探索,适合已经在中段把基础打扎实的团队去尝试。

最后分享一个小技巧:如果你现在正在做 RAG 调优,不妨先停下来,花半天时间搭一个最小化的评估集。不用多,五十个问题就够。有了这个评估集,你后面所有的优化都会变得有方向。我踩过的最大的坑,就是在没有评估集的情况下盲目调参,改了半天不知道是变好了还是变坏了。这个教训希望你不要重复。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询