资讯动态

RAG进阶实战:从检索质量到评估闭环的完整工程体系

发布时间:2026/10/20 2:35:18 来源:尧图企业网站定制
1. 先说清楚当RAG从Demo走向可用时你会撞上什么墙这几年搭过RAG系统的朋友应该有一个共同的感受第一天用LangChain加一个向量库几百行代码就能跑通上传文档→切片→embedding→检索→大模型回答的完整链路demo演示时效果惊艳得不行。但一旦把数据量从几篇PDF涨到几千篇、把问题从文档里写了什么换成结合文档内容分析一下XX方案的风险整个系统就开始露馅了——答非所问、检索不到关键段落、明明库里有的信息却编造答案甚至一段话里面前一半对后一半错。很多人都把这口锅甩给大模型本身说我用的模型不行、上下文不够长。但我在实际项目中花了大量时间排查后发现绝大多数进阶场景下问题出在RAG的R上——检索环节没有真正把用户意图和文档内容对齐召回结果是错的生成端再强也无非是在错误材料上做精装修。所以这篇文章要聊的不是怎么用现成框架三步搭一个RAG demo而是当你真正要把它做成一个能回答复杂问题、能在业务里扛住真实流量的系统时必须想清楚的几件事检索质量怎么提、切片策略怎么设计、生成端怎么约束、以及最容易被忽视的评估闭环。整个过程我会按我实际做项目时的推进顺序来讲从问题定义到模块拆解再到踩坑记录尽量把为什么这么做也一并交代清楚。适合谁来读正在做RAG落地但发现效果不稳定的开发者或者想从调用API写Prompt往设计一套检索问答系统再走一步的同学。如果只是玩过几下demo建议先补齐向量检索和LangChain基础再来看否则部分内容会觉得跳跃。2. 进阶和入门的本质区别检索不再是查关键词2.1 向量检索的天然短板你得心里有数入门教程通常教你的做法是文档切片后用embedding模型转成向量用户提问时也转成向量然后算余弦相似度挑TopK个片段丢给大模型。这套流程在问题表述和文档原文高度接近时确实好用比如文档里写着退款政策是7天无理由用户问退款政策是什么检索结果自然精准。但真实业务的问题根本不是这个形态。我做模拟项目时遇到过几类典型检索失败改写型问题。文档里写本产品支持128位AES加密用户问咱们的数据传输安全吗。语义上两者强相关但字面上几乎没有一个词重叠。如果embedding模型本身能力一般或者文档在这个语境下还有大量其它安全相关的内容向量相似度可能把加密相关段落排到几十名开外。多条件约束问题。上个月华东区的退货率同比变化趋势——这句话至少要命中三个维度时间上个月、地域华东区、指标退货率、同比。单靠向量检索经常只命中其中一两个维度因为相似度计算是全局的不会替你去拆解条件。答案分散在多处的问题。这个项目的风险点有哪些答案可能藏在第一段的背景介绍、第五段的执行方案、第十二段的附录备注里。TopK4可能只捞到其中两处剩下两处在上下文窗口之外模型自然答不全。这类问题的根源在于向量相似度本质是一个全局的、模糊的文本匹配信号它不感知用户问题里的结构化约束也不处理信息分散与合并的问题。入门demo之所以看起来没问题是因为测试样本太少、问题太简单掩盖了检索信号的粗糙。2.2 所谓进阶其实是在检索链路里加入多层信号我理解的进阶不是在某个环节换一个更贵的模型而是把一次向量检索升级成多层信号组合的检索管线。大概是这样一条链路先对用户问题进行意图识别和关键词/实体抽取把问题里的关键约束变成可检索的条件做混合检索向量召回 关键词召回 结构化条件过滤如果有元数据然后把结果做融合重排在融合结果上跑一个rerank模型对候选段落做精细的语义相关性打分再根据上下文判断是否需要多轮检索、是否需要查数据库或知识图谱。这个链路不是每个场景都要全套上但你必须知道每一层在解决什么问题才能按需取舍。比如我之前做的项目X一个面向企业内部制度文档的问答系统最初只做了向量检索准确率卡在60%多加了关键词召回和元数据过滤之后直接跳到80%以上后面再上rerank又涨了几个点。每一步的收益不一样但组合起来才是进阶和入门的分水岭。啰嗦一句不要一上来就追求全链路堆模块。检索管线的每一层都有额外延迟和运维成本先把最痛的那一环补上再考虑下一层。3. 决定性的一步把用户问题拆成可检索的检索条件3.1 问题拆解的两种做法轻量正则与模型抽取很多教程跳过了问题理解这一步默认用户怎么问就直接拿整句话去检索。这在简单问答里没问题但一旦问题里有多条件约束整句检索的效果会急剧下降。我建议至少做一个轻量级的问题拆解模块把问题里的时间、地域、对象、指标、动作等要素抽取出来转成结构化的检索条件。这里有两种典型做法按项目资源可以选第一种是规则 正则。比如上个月近30天2024年Q3这类时间表达用正则就能覆盖大部分场景华东区华南区这类地域词直接用字典匹配。优点是零成本、快、可解释适合问题模式比较固定的业务。缺点是碰到复杂表述容易漏抽例如用户说去年同期到现在简单正则就会一头雾水。第二种是用大模型做轻量抽取。让模型输出一段JSON把用户问题里的条件字段填好我一般会把这步和主问答的Prompt分开写。这样做的鲁棒性更好能处理各种口语化表达但会增加一次模型调用大概多100~300毫秒延迟。部分用云端大模型API的场景还要注意成本毕竟每个问题都多一次调用。我自己的习惯是先用正则和字典把能抽的硬条件抽掉只把正则抽不干净的部分交给模型比如业务影响风险点这类没有固定表达但语义上很重要的要素用模型抽取效果更稳。经文再说一遍这个环节的实际收益非常大。我在模拟项目中做过一个统计单条硬性条件时间、地域、品类抽准后检索命中率平均能提升10个百分点以上。原因很简单——检索条件是把模糊的整句问题翻译成了明确的查询语句向量和关键词检索的效率都变高了。3.2 查询改写用户问法太口语你的库不一定接得住问题拆解解决的是把条件拎出来但还有一个常见故障用户的表述和文档表述完全不在一个体系里。比如用户问咱们的东西坏了找谁文档里对应的是售后支持联系方式用户问申请报销最多多少天到账文档里写的是财务处理时效为3个工作日。这时候需要的是查询改写query rewriting本质上就是把口语化的用户问题转换成更接近文档表达习惯的检索语句。常用做法有这么几类同义替换把口语词替换成业务术语或文档高频词比如坏了→故障报修补充主语/宾语把缺省部分补全比如这个怎么操作→XX功能的操作方法扩充同义表达一条问题改写成多个候选查询再分别检索合并结果。改写这步可以固定规则做也可以用大模型做。用大模型时我习惯让模型返回多个改写版本而不是一个——比如退款怎么弄改写为退款流程申请退款的方式退款条件三条分别去检索再合并去重召回覆盖面会宽很多。代价是检索次数变多、延迟变高我一般会限制最多3条改写、只对复杂问题启用。查改写是很多RAG项目漏掉的环节也是进阶味道最浓的一步。为什么这么说因为它解决的不是检索算法的问题而是用户和你系统之间语言不一致的问题——这类问题靠换embedding模型解决不了靠加数据也低效但你只要在链路里多一个小步骤效果立刻不一样。4. 混合检索与Rerank召回质量的两个核心抓手4.1 为什么一定要加关键词召回前面说了向量检索擅长语义相似但它在精确匹配上有个天然缺陷embedding压缩信息时会丢掉一些细节。比如一个产品序号PT-2301-A、一组精确的报错码、一个人名向量召回很容易把包含这些关键字的段落排到后面原因是这些词在向量空间里的位置受上下文影响太大。混合检索 向量召回 关键词召回BM25或ES的倒排索引是业界最主流的解法。关键词召回负责精确命中向量召回负责语义扩展两者结果做融合既抓住确定性信息又不漏掉语义相关的内容。我做某个周报问答模块时有个特别直观的体验文档里有大量周报模板请假流程这类强业务名词用户提问也会直接带这些词但Embedding之后向量相似度排序经常把准确段落排在第五六位。后来加了ES的BM25召回把两路结果用RRFReciprocal Rank Fusion倒数排名融合合并准确率提升非常明显——原因不复杂精确命中的段落被保底捞回来了。融合的方式有好几种RRF、加权平均、或者用一个简单的模型打分。RRF最省事效果也稳定我推荐作为第一选择——它不看各路的原始得分只按排名先后计算避免了向量分数和BM25分数量纲不同没法直接加权的问题。4.2 Rerank把TopK从过得去变成精而准混合检索的两路召回TopK一般会拿到二三十条候选但最终能塞进大模型上下文的可能只有5~8条。这么一截断排序的精准度就是命门——排在前面的差错一条模型看到的内容就偏一分。Rerank的作用就是对这些候选做一次更精细的语义相关性排序。和向量检索不同rerank模型通常是交叉编码器cross-encoder结构它把问题和候选段落同时喂给模型做深度的交互式计算精细程度远高于各自转向量再算距离的双塔式结构。代价是计算量大、速度慢所以一般只用来对几十条候选做重排而不是对全库检索。选型上中文场景我推荐从国产开源rerank模型入手比如BGE-Reranker系列效果在大部分业务场景下都够用。部署方式就是起一个独立的模型服务检索流程里把混合召回的候选列表丢给它按输出分数重新排序再截断TopK。实测下来利用质量好的rerank模型Top5精确率能再提升5~15个百分点。不过要提醒一句Rerank不是万能药。如果召回阶段已经漏掉了正确答案rerank只能在挑出来的篮子里排序篮子外的东西它救不回来。所以流程一定是先保住召回率多路召回再做精排rerank顺序错了等于白做。4.3 元数据过滤很多人到这一步才意识到索引结构的重要性还有一个低成本高收益的手段元数据过滤。如果在建立索引时就把文档的时间、来源、所属业务线、文档类型等字段单独存下来检索时就能直接用结构化条件过滤掉大量无关内容。举个例子用户问2024年华东区的销售政策是什么如果先按时间字段过滤掉2025年之后的新版政策再按地域字段过滤掉华北、华南的文档剩下的候选集合已经小了一两个数量级后面无论做向量召回还是rerank效率和精度都会更理想。这一步极其容易在初期被忽略因为搭建demo时往往只是一堆stored文档向量没有考虑元数据。等数据量上来、问题变复杂后再回头补索引结构迁移成本会很高。所以我的建议是哪怕是demo也从第一天就规划好元数据字段。宁可暂时用不上也别等到要用了才后悔。5. 文档切片策略检索质量的地基工程5.1 固定长度切片的坑语义断层与跨段信息丢失如果说检索链路是RAG的发动机切片策略就是发动机的底盘——出了问题后面的模块再努力也白搭。入门项目最常见的做法就是按照固定token数比如500 token带一点重叠硬切这个做法做demo没问题但放到真实文档里有两个高频事故。第一个事故是语义断层。一段话在512 token处被拦腰截断前半段讲方案的背景后半段讲方案的执行检索时只命中了前半段大模型看到的材料是不完整的回答自然不完整。重叠窗口能缓解一部分问题但治标不治本。第二个事故是跨段信息组合困难。比如一份制度文档里审批流程的表头说以下流程适用于单笔金额超过10万元的采购但具体步骤列表在后面的段落里。固定长度切片可能把这些步骤拆到不同的chunk里检索时只召回步骤chunk而丢了适用范围chunk模型笨一点就会把特殊流程当成通用流程讲。所以进阶项目中切片策略不能是用一个函数自动切而是要根据文档结构来做有语义边界的切分。5.2 按文档层级切片 父子块结构我目前觉得最稳的方案我目前在实际项目里最依赖的组合是按文档层级结构切片再加父子块结构来兜底。按层级切片的做法是解析出文档的标题层级H1、H2、H3、段落以标题为边界每个章节作为一个大块如果章节太长再按段落、按句子切小块。这样切出来的每个块都有完整的上下文边界——大模型收到的材料至少是一个完整的章节段落而不是断在半空中的半截话。父子块结构解决的是检索粒度 vs 上下文完整度的矛盾子块比如一个段落或几句话用于精确的向量匹配因为粒度小、语义聚焦更容易和问题对齐父块子块所在的完整章节或完整文档块用于喂给大模型因为上下文更全模型不容易被断章取义误导。检索时先用子块向量匹配到TopK段落再通过索引映射到它们对应的父块把父块整体内容送进大模型。这样设计的原因很直观精确检索需要小颗粒度完整理解需要大上下文两者天然有冲突父子块结构就是同时满足两侧需求的折中方案。实践中配合元数据过滤使用效果特别好——比如先按元数据过滤文档再在剩余的小块里做向量匹配最后取父块做生成整条链路既快又准。5.3 表格与PDF两类文档的切片特判这里必须单独提一句表格和PDF因为这是实际项目中非常高频的场景也是最容易翻车的地方。表格。普通切片把表格一行行切散检索出来的经常是残缺的几行模型根本读不懂表头对应关系。我的做法是对表格做特殊处理把表格整体作为一个chunk存入同时把表格内容转成结构化描述文本比如这是一个产品销售记录表列包括日期、产品名、销售额其中2024年1月A产品销售额为100万这比直接塞原始表格更容易被embedding模型理解。PDF。很多PDF解析工具会把双栏版面、页眉页脚、图表混排弄乱导致切出来的文本顺序错乱或夹带杂质。进阶项目里PDF的解析质量决定了切片质量的上限。我一般会先做版面分析layout analysis识别出标题、正文、页眉、表格等区域过滤掉页眉页脚再按阅读顺序重组正文之后才做切片。这块可以用一些开源版面分析模型也可以退一步用带阅读顺序输出的PDF解析工具省心不少。之前我在某公司做合同文档问答时吃过一次大亏合同里的表格条款被切片切散了模型把甲方权利义务和乙方权利义务混在一起讲还讲得头头是道。后来排查了半天才发现是解析切片的锅不是模型的问题。从那以后我对文档预处理这三个字格外敬畏——切片之前的所有步骤都在决定你检索的上限。6. 生成端的约束策略别让模型自由发挥6.1 提示词里的三条硬规则进阶RAG和入门RAG在生成端的差异不在模型选得多强而在约束是否足够硬。很多入门教程喜欢在Prompt里写请根据以下资料回答问题这太弱了——模型会把资料和自己训练时记住的知识混在一起讲你根本分不清哪些是检索来的、哪些是它编的。我实际使用的Prompt里至少有三条硬性规则只能使用提供的资料回答问题资料中不存在的信息必须明确回答说资料中未提及回答中需要标注信息出处至少标到来自哪份文档的哪个章节不做推测性回答不基于资料内容做额外联想式扩展。这三条规则的意图很明确把大模型从一个爱表现的聊天者约束成一个忠于资料的分析助手。模型天生倾向于讨好用户、编一个更像样的答案你需要用强指令把它拽回来。但光在Prompt里写还不够因为模型偶尔还是会越界。所以我还会在输出检查上加一道保险生成完答案后用一个轻量级的校验环节判断回答里的关键句子是否能在检索到的资料片段里找到依据找不到就标记为存疑回答或直接触发重新检索。这道校验可以用大模型自己做也可以用答案中的实体/关键词是否出现在资料中这种简单规则做。我的经验是简单的关键词级校验在大多数场景下已经能拦掉一半以上的幻觉输出。6.2 多轮对话中的上下文管理真正的进阶分水岭另一个很多人忽略的地方是多轮对话场景下的上下文策略。RAG不是每次都要拿着用户最新问题去检索有些问题依赖之前几轮的语境。比如用户先问我们公司去年的营收是多少模型回答1.2亿用户接着问那今年呢。如果拿那今年呢这四个字去做检索召回结果大概率是乱的。正确做法是把多轮对话压缩成一个独立的检索问题——我们公司今年的营收是多少——再去检索。这部分我习惯用一个上下文改写模块先把最近几轮对话和用户的当前问题一起交给大模型让它改写成一个不依赖上下文的完整查询然后再进检索链路。为什么需要专门做而不是直接在生成时把全部对话历史都塞进去因为检索是独立的环节它需要的是清晰、完整、不含冗余的查询语句而把全部历史都塞进向量检索反而会把检索条件搞浑浊。改写后既可以检索也可以拼进生成上下文。还有个细节不要把无限长的对话历史全塞进生成Prompt。大模型的注意力是有限的历史越长重点信息越容易被摊薄。我一般只保留最近3~5轮的核心信息加上改写后的当前问题足够支撑大部分问答场景。6.3 生成时引用来源不只是显示个来源更是可追溯进阶项目里我强烈建议在最终答案里保留引用来源的信息——不仅仅为了让用户信服更重要的是让你自己能够排查问题。当用户反馈答案不对时如果你能看到这个答案是依据文档A的第3章第2节生成的排查链条会清晰得多。实现方式上我会在检索阶段给每段候选保留一个doc_id和chunk_id生成时要求模型输出答案时带上对应的标记。后端组装最终回复时把这些标记映射成用户可读的文档名和章节位置。这个方法还有一个附带好处用户如果对答案有疑问可以直接点击来源去看原文整个问答系统的可信度会高一个台阶。7. 质量评估与回归测试没有评估体系的RAG项目走不远7.1 你至少需要一套百问百测的评估集很多RAG项目在demo阶段效果不错一上生产就各种被吐槽原因多半是没有评估集。你可能在几个精心挑选的问题上调试得很开心却不知道在另外一百个真实问题上系统表现如何。所以进阶项目的第一任务就是建一套评估集。我的做法是从真实业务场景里整理出100~200个有代表性的问题每个问题配好标准答案或至少配好答案里必须覆盖的要点。这两百个问题就是你的考卷每次改完检索或生成逻辑跑一遍考卷分数涨没涨一目了然。评估指标的选取也要分两个维度检索质量看召回片段里是否包含能支撑正确答案的材料常用指标是RecallK和MRR倒数排名均值生成质量看最终答案是否准确、完整、可依据资料支撑。生成质量主观性强可以人工打分也可以用大模型做自动评估让一个裁判模型对比标准答案和生成答案的语义一致性和完整性。我见过很多团队只盯着回答得好不好这一个主观感受没建立客观指标结果优化方向完全靠感觉。建立评估集这件事是最不性感但最值得投入的部分——没有尺子你永远不知道自己改进了多少。7.2 线上反馈回收评估集之外的另一个信息源评估集只能覆盖已知问题真实线上用户的问题永远会超出你的想象。所以一个进阶RAG系统一定要有反馈回收机制。至少要做到两点用户可以对答案点有用/没用这个信号能直接告诉你哪些类型的问题没答好把模型回答不够有把握或校验环节判定为存疑的问答对自动存下来定期人工抽查。我在项目里发现这个存疑收集箱价值极高。因为大模型的错误是有规律的把一段时间内的失败案例归一下类常常能发现检索链路里某个具体环节的系统性缺陷——比如某个文档结构没处理好、某种问法没有覆盖到、某个元数据漏标了。修好这一类问题往往不是修一个点而是修一大片。7.3 一个可复用的调优循环最后分享一个我自己反复使用的调优循环基本能覆盖日常80%的优化需求先随机抽取一批线上失败案例人工判断问题出在检索没召回还是召回但生成错。如果检索没召回去检查重现检索过程看是查询改写的问题、切片的问题还是融合排序的问题定位后针对那一环节修。如果召回正确但生成错再去查Prompt约束、上下文截断和校验环节。修完之后跑一遍已有的评估集看是否回退再上线观察反馈。这个循环的核心思想就是先定位环节再做修改最后用数据验证。大部分RAG项目优化效果差不是因为缺想法而是因为改哪了都不知道。8. 一条实际踩坑的完整复盘检索链路加了一堆还是没效果这个部分我想完整复盘一次真实的排错经历对理解整条链路很有价值。当时我在做某企业内部的制度问答系统客户反馈一个典型的失败案例用户问员工出差住宿标准是多少系统答得模棱两可引用了差旅管理办法文档里的一段文字但那段文字根本没写明具体金额。一开始我的第一反应是切片切太碎了于是我把切片粒度调大加了父子块结构——折腾一圈问题还是存在。接着我怀疑是rerank排序不好换了更强的rerank模型效果依旧没有明显改善。最后静下心把整条链路完整走了一遍才发现问题出在查询改写环节。原始问题员工出差住宿标准是多少被改写成差旅住宿费报销标准关键词里多了报销少了员工和出差。而文档里的关键标题是员工出差住宿费标准embedding模型判断报销标准和住宿费标准语义接近但和原文员工出差住宿费这组词的实际语义匹配度并不高——结果关键段落被排到了第十九位而TopK只取了5。这个案例暴露出来几个连环问题我的查询改写环节改写太多没保持和原文术语的一致性TopK取值太小即便存在相关的低排名段落也压根没进候选。这两件事在隔离状态下都很难发现因为分开看每一步都挺合理的——改写模型没犯错检索流程也没报错但组合起来就是失败。修法说起来也不复杂改写Prompt里加了一条约束——优先使用原文中出现过的术语进行改写不做过度意译同时把TopK从5调到10再加一道rerank把关。改完评估集上直接涨了好几分。我讲这个案例的核心用意是RAG排错时永远不要假设某一步没问题。排查顺序应该从查询入口一路查到生成出口分环节定位别怕浪费时间——在这个系统里90%的失败其实都能定位到某一个环节上而不是模型不行。9. 关于选型与成本的几句经验之谈到这已经写了很多了最后说几个我认为RAG进阶项目中最关键的选型判断。Embedding模型的选择是一个够用就好和越强越好的平衡。我不建议一上来就追最新最强的embedding模型因为它的收益通常在复杂语义上但对于很多业务场景你真正的瓶颈是在查询改写、元数据过滤和切片上换模型属于锦上添花。先把检索链路补齐再评估embedding模型的边际收益。大模型本身的选择要考虑该不该上更大参数的模型。在我做过的项目里RAG系统的问题很少是模型聪不聪明导致的更多是模型看到的信息对不对。把信息搞对了中小参数的模型往往也能给出不错的回答信息不对再大的模型也只是错得更流畅。所以我的优先级永远是先修检索再调提示词最后才考虑换更大的模型。成本和延迟的控制核心是分层。不是每个问题都需要最强的模型和最全的链路。简单问题可以走轻量改写关键词检索直接返回复杂问题才走多路召回rerank大模型生成。在入口处做一个意图分级能够明显降低平均成本。你甚至可以把问题分为知识查询型命中知识库即返回答案和综合分析型需要多段材料推理两类分别走不同链路——这是进阶系统常见的架构选择。向量数据库的选择上不要被特性多迷了眼。我建议优先考虑你团队熟悉、运维成本低、和现有技术栈能融合的方案。很多场景不需要分布式、不需要超大规模一个跑得稳、支持元数据过滤的开源向量库就够用。系统的可靠性往往比一两个花哨功能重要得多。10. 收尾RAG项目的尽头不是模型是工程体系说了这么多如果只提炼一件事我愿意说做RAG进阶本质上是做工程不是做模型。模型在里面的角色不过是一个靠谱的零件真正决定系统上限的是查询改写、混合检索、rerank排序、切片结构、元数据设计、评估反馈闭环这一整套工程体系。我见过不少团队和我早期一样一有问题就往换个更大的模型上想。但完整走完几轮调优循环之后我的体会是绝大多数失败都有具体的工程原因——改写过度、切片断层、过滤不足、TopK太小、缺少校验。每解决一个系统就扎扎实实往前走一步而且这一步是稳定、可复现、能沉淀的。如果你正在做一个RAG项目并遇到了瓶颈我真心建议你先别急着调模型回到工程链路上把上面提到的每一个环节盘一遍再决定动哪里。亲手把系统从一个有时候准、有时候不准的状态调到一个稳定、可解释、有可追溯性的状态那个成就感远不是跑通一个demo能比的。现阶段我碰到不少人在往Agent方向做RAG的延展比如让AI自行决定查哪个库、调什么接口、怎么多步推理。这块我自己还在实践等跑出一些有说服力的结论了再来分享。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑