尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

RAG系统调优的六个分水岭:从切块策略到评估闭环的工程实践

RAG系统调优的六个分水岭:从切块策略到评估闭环的工程实践 1. 那条流水线为什么谁都能搭但谁都用不好RAG 这个词现在确实被说烂了。随便打开一个技术社区满屏都是十分钟搭建你的专属知识库零基础 RAG 实战教程。我去年帮三个团队做过 RAG 系统的调优发现一个特别有意思的现象Demo 跑通的时间越来越短从半天缩短到半小时但真正上线后能用的一个都没有。问题出在哪出在绝大多数人搭的那条流水线本质上是一个文档切块 → 向量化 → 存库 → 检索 Top-K → 塞进 Prompt的固定管道。这条管道本身没有任何问题它是 RAG 的基础骨架。但骨架不等于血肉。你把同样的骨架给一百个人九十九个人搭出来的东西检索准确率都惨不忍睹剩下那一个能用的是因为他在骨架的六个关键节点上做了完全不同的选择。这六个节点才是 RAG 真正的分水岭。它们分别是切块策略的语义完整性、检索阶段的召回质量、上下文组装的信息密度、知识图谱的引入时机、Agent 化的工作流编排、以及评估体系的闭环设计。前三个决定了你的 RAG 能不能查得准后三个决定了它能不能用得久。这篇文章不打算再给你一条流水线。流水线你已经有了网上到处都是。我要做的是把这六个分水岭逐一拆开告诉你每个节点上大多数人怎么做和真正能用的系统怎么做之间的差距在哪里以及为什么会有这个差距。如果你正在做 RAG 项目或者做完了发现效果不行想推倒重来这篇内容应该能帮你省下至少两个月的试错时间。2. 切块不是切菜语义完整性决定了检索的天花板2.1 固定长度切块为什么是灾难的开始几乎所有入门教程教你的第一件事就是把文档按 500 字或者 1000 字切一块重叠 50 到 100 字。这个做法在 Demo 阶段看起来没问题因为你的测试文档可能只有几页内容主题集中怎么切都能检索到。但一旦文档量上到几百上千页问题就暴露了。我拿一个真实的案例来说明。有个团队做的是企业内部制度问答文档是员工手册、报销规范、考勤制度这类。他们用 500 字固定切块结果员工问出差住宿标准是多少检索出来的块是这样的……员工出差期间产生的交通费用按照实际发生金额凭票报销。住宿费用标准按照职级划分具体标准见下表。出差补贴按天计算……然后下一块是……表格内容职级 A一线城市 600 元/晚二线城市 400 元/晚……问题来了检索系统只召回了第一块因为出差住宿标准这几个字在第一块里出现了。但真正的答案在第二块的表格里。大模型拿到第一块只能回答住宿费用标准按照职级划分具体标准见下表——它看不到那个表。这就是固定长度切块最致命的问题它假设语义单元和字符长度是对齐的但现实中这两者几乎从来不对齐。一个完整的制度条款可能只有 200 字也可能有 1500 字。你按 500 字切要么把一个完整语义切碎要么把多个不相关的语义混在一起。2.2 按语义边界切块的三种可落地方法那怎么切才对核心原则只有一个让每一个块都是一个自包含的语义单元。具体落地有三种方法复杂度从低到高。第一种是基于文档结构的切块。如果你的文档是 Markdown、HTML 或者有明确标题层级的格式直接按标题层级切。一个三级标题下的内容就是一个块如果太长再按段落二次切分。这个方法实现成本最低效果提升却最明显。我试过在一个技术文档库上做对比同样的检索模型按标题切块比固定长度切块的召回准确率高了将近 30 个百分点。第二种是基于语义相似度的切块。把文档按句子拆开然后计算相邻句子的 embedding 相似度在相似度骤降的地方切一刀。这个方法的好处是不依赖文档格式纯文本也能用。但要注意一个坑相似度阈值不能设死不同文档的最佳阈值差异很大。我的经验是先用 0.6 试然后人工看 20 个切块结果根据实际情况调整。第三种是基于大模型判断的切块。直接把文档给大模型让它判断在哪里切分最合理。这个方法效果最好但成本也最高。适合文档量不大但对精度要求极高的场景比如法律合同、医疗指南这类。2.3 切块时最容易忽略的元数据附加切完块之后大多数人直接把文本丢进向量库就完事了。但真正好用的系统会在每个块上附加丰富的元数据。这些元数据在检索阶段能发挥的作用远超你的想象。我通常会附加这几类元数据元数据类型具体内容检索时的作用来源信息文件名、章节路径、页码支持按来源过滤回答时可引用出处结构信息块在文档中的位置、前后块 ID支持上下文扩展检索到一块可拉出相邻块语义标签主题分类、实体列表支持按主题预过滤减少无关召回时间信息文档创建/更新时间支持时效性排序旧文档降权尤其是前后块 ID这个设计解决了一个非常实际的问题当检索到的块信息不完整时系统可以自动把它的前后块也拉出来拼成一个更大的上下文。这比单纯增大切块尺寸要精准得多因为它只在需要的时候才扩展不会污染所有检索结果。3. 检索阶段为什么你的 Top-K 里全是垃圾3.1 纯向量检索的盲区在哪里向量检索的本质是语义相似度匹配。你问如何申请年假它能找到年假申请流程相关的块这没问题。但它有两个盲区。第一个盲区是精确匹配失效。用户问报销单编号规则是什么向量检索可能会召回一堆报销流程报销标准的块因为它们在语义上都很接近。但真正包含编号规则的块可能因为表述是单据编码格式为……而排在后面。向量模型对这类精确术语的匹配能力很弱。第二个盲区是否定和条件检索失效。用户问哪些费用不能报销向量检索会召回大量可以报销的费用的块因为报销这个核心词太强了否定的语义在向量空间里几乎被淹没。3.2 混合检索的权重调参实战解决这两个盲区的标准方案是混合检索向量检索 关键词检索通常是 BM25然后做融合排序。但这里有一个关键问题两者的权重怎么定我见过很多团队直接设 0.5 比 0.5然后就不管了。这是典型的配置了但没调优。实际上权重应该根据你的查询类型动态调整。我的做法是引入一个轻量的查询分类器判断用户问题属于哪种类型概念解释型什么是 XX向量检索权重 0.7BM25 权重 0.3精确查找型XX 的编号是多少向量检索权重 0.3BM25 权重 0.7条件筛选型哪些情况不能 XX向量检索权重 0.4BM25 权重 0.6同时启用否定词增强这个分类器不需要很复杂用几个关键词规则就能覆盖 80% 的情况。我实测下来动态权重比固定权重在混合检索上的准确率提升了 15% 到 20%。融合排序的算法也有讲究。最常见的是 RRFReciprocal Rank Fusion它只看排名不看分数对分数尺度不敏感比较稳。但如果你能确保两路检索的分数都做了归一化加权求和的效果会更好因为它保留了分数差异的信息。3.3 重排序模型小成本大收益的典范混合检索之后你通常会拿到 20 到 50 个候选块。这时候直接取 Top-5 塞给大模型是对候选池的极大浪费。重排序模型Reranker是 RAG 流水线里性价比最高的一环没有之一。它的原理很简单用一个交叉编码器Cross-Encoder把查询和每个候选块拼在一起打分而不是像向量检索那样分别编码再算距离。交叉编码器能看到查询和文档之间的细粒度交互所以排序精度远高于向量检索。代价是它不能预计算必须在线推理所以只适合对少量候选做精排。我通常的配置是混合检索召回 30 个候选重排序后取前 5 个。这个配置下重排序带来的准确率提升通常在 20% 到 40% 之间而增加的延迟只有 100 到 300 毫秒。相比它带来的效果提升这个延迟完全可以接受。注意重排序模型的选择要和你的语言匹配。中文场景下用多语言模型或者专门的中文重排序模型效果会比纯英文模型好很多。我试过用英文模型做中文重排序效果还不如不做。4. 上下文组装把正确的信息放在正确的位置4.1 检索到了不等于用上了这是一个非常容易被忽略的环节。很多人以为只要检索到了正确的块大模型就一定能用上。但实际情况是大模型对上下文的利用效率高度依赖于信息的排列方式和呈现形式。我做过一个对比实验。同样的 5 个检索块同样的查询只是改变块在 Prompt 中的排列顺序回答准确率相差了将近 25%。大模型存在明显的位置偏好——它更容易关注上下文开头和结尾的信息中间部分容易被忽略。这就是所谓的迷失在中间现象。所以上下文组装的第一条原则是把最相关的块放在最前面和最后面次相关的放中间。具体操作上重排序后的结果不要按顺序平铺而是做一个三明治排列第 1 名放开头第 2 名放结尾第 3 到 5 名放中间。4.2 上下文压缩少即是多的信息密度优化另一个常见问题是上下文太长。你检索了 10 个块每个块 500 字加起来 5000 字全塞进 Prompt。结果大模型被大量无关信息干扰反而抓不住重点。上下文压缩的思路是对每个检索块只保留和查询相关的部分。实现方式有两种。一种是抽取式压缩用一个小模型判断块中哪些句子和查询相关只保留相关句子。另一种是生成式压缩让大模型把块压缩成和查询相关的摘要。抽取式压缩更安全不会引入幻觉但可能丢失一些隐含信息。生成式压缩信息密度更高但有引入错误的风险。我的建议是对事实性要求高的场景用抽取式对理解性要求高的场景用生成式。如果拿不准就先用抽取式稳定之后再考虑混合方案。4.3 引用标注让回答可追溯的工程实现一个真正能用的 RAG 系统回答必须可追溯。用户看到答案后应该能知道这个信息来自哪个文档的哪个部分。这不仅是信任问题也是排错的基础——当回答错误时你需要快速定位是检索错了还是生成错了。实现引用标注的关键是在组装上下文时给每个块打上明确的编号标记并在 Prompt 中要求大模型在回答时引用编号。比如[1] 员工出差住宿标准一线城市 600 元/晚…… [2] 出差补贴按天计算标准为……然后在 Prompt 里明确要求回答时请在相关句子末尾标注信息来源编号如 [1][2]。这里有个坑大模型有时候会编造编号引用一个不存在的来源。解决办法是在后处理阶段做校验检查回答中出现的所有编号是否都在实际提供的编号范围内。如果有越界的要么重新生成要么把越界的引用标记去掉。5. 知识图谱什么时候该上 GraphRAG什么时候不该5.1 GraphRAG 解决的是什么问题GraphRAG 这两年被讨论得很多但很多人对它有一个误解以为它是 RAG 的升级版上了它效果就会更好。GraphRAG 不是万能药它解决的是一个非常具体的问题多跳推理和全局性查询。什么叫多跳推理举个例子。你问张三负责的项目里有哪些用到了李四团队开发的组件这个问题需要先找到张三负责的项目再找到这些项目用到的组件再找到李四团队开发的组件最后求交集。纯向量检索很难处理这种需要串联多个实体关系的查询因为它每次只能召回和查询语义相似的块无法沿着关系链跳转。GraphRAG 的做法是先从文档中抽取实体和关系构建知识图谱然后在检索时沿着图谱的边做多跳遍历。这样就能把分散在不同文档块中的关联信息串联起来。5.2 构建知识图谱的三个现实成本但 GraphRAG 的代价也很明显主要体现在三个方面。第一是抽取成本。从文档中抽取实体和关系目前最可靠的方法还是用大模型。这意味着你需要对全量文档跑一遍大模型抽取成本可能是普通 RAG 的几十倍。而且抽取质量高度依赖 Prompt 设计抽出来的图谱经常有大量噪声。第二是维护成本。文档更新时图谱也要同步更新。新增一个实体可能要建立十几条边删除一个实体要清理所有相关边。这个维护逻辑比向量库的增删改查复杂得多。第三是查询成本。图谱查询需要专门的图数据库和查询语言多跳遍历的延迟也远高于向量检索。如果你的场景对响应时间敏感GraphRAG 可能会成为瓶颈。5.3 我的判断标准什么场景值得上图谱基于这几个成本我通常用三个标准来判断一个场景是否值得上 GraphRAG查询中多跳推理的占比是否超过 30%如果大部分查询都是单跳的事实查找GraphRAG 的收益覆盖不了成本。实体关系是否密集且明确法律、医疗、金融这类领域实体和关系定义清晰图谱构建质量高。而散文、新闻这类文本实体关系模糊图谱噪声大。是否有持续的维护投入图谱不是建完就完的需要持续维护。如果没有专人负责图谱会很快腐化效果反而不如纯向量检索。如果这三个条件都满足GraphRAG 值得上。如果只满足一两个我建议先用混合检索 重排序把基础打牢等基础 RAG 的效果确实遇到瓶颈了再考虑图谱。6. Agentic RAG让检索从一次性动作变成迭代过程6.1 传统 RAG 的单次检索为什么不够传统 RAG 的检索是一次性的用户提问 → 检索 → 生成 → 结束。这个流程假设一次检索就能拿到所有需要的信息但现实中这个假设经常不成立。比如用户问我们公司和竞争对手在产品定价上的差异是什么这个问题需要先检索自己公司的定价再检索竞争对手的定价然后做对比。单次检索只能召回和整个问题语义相似的块很可能只召回了自己公司的定价信息竞争对手的信息因为表述差异没被召回。Agentic RAG 的核心思想是把检索变成一个由 Agent 控制的迭代过程。Agent 可以先分析问题拆解成子问题逐个检索然后判断信息是否足够不够就换个查询再检索直到信息充分了再生成回答。6.2 用 LangGraph 编排检索工作流的实操结构LangGraph 是目前做 Agentic RAG 比较顺手的框架它的核心概念是状态图——你定义一个状态结构然后定义节点和边节点之间通过状态传递信息。一个典型的 Agentic RAG 工作流包含这几个节点查询分析节点判断问题类型决定是否需要拆解查询改写节点把原始问题改写成更适合检索的形式检索节点执行检索返回候选块充分性判断节点判断检索结果是否足够回答问题补充检索节点如果不够生成新的查询再次检索生成节点信息充分后生成最终回答这个工作流的关键在于充分性判断节点。它决定了什么时候停止迭代。判断逻辑可以用大模型来做给它原始问题和已检索到的信息让它判断这些信息是否足以回答该问题。如果不够还要让它指出缺少什么信息这样补充检索节点才能生成有针对性的新查询。6.3 迭代终止条件与成本控制的平衡Agentic RAG 最大的风险是无限迭代。如果充分性判断一直说不够Agent 就会一直检索下去成本和延迟都会失控。我的做法是设置三重终止条件最大迭代次数通常设 3 到 5 次超过就强制生成信息增量阈值如果新一轮检索没有带来新的有效信息就停止置信度阈值如果充分性判断的置信度超过某个值就认为够了这三重条件同时生效任何一个满足就终止。实测下来大部分查询在 2 到 3 轮内就能收敛只有极少数复杂查询会触发最大迭代限制。提示Agentic RAG 的延迟通常是传统 RAG 的 3 到 5 倍。如果你的场景对响应时间要求很高比如实时客服要慎重使用。它更适合那些对准确性要求高、对延迟容忍度也高的场景比如研究报告生成、复杂问题分析。7. 评估闭环没有度量就没有优化7.1 RAG 评估的三个核心指标RAG 系统的评估和传统模型评估不一样它要同时评估检索质量和生成质量。我通常用三个核心指标检索命中率Hit Rate正确答案所在的块是否出现在检索结果中。这个指标衡量的是检索的召回能力。如果命中率低后面所有环节都是白搭。检索精确率Precision检索结果中有多少是真正相关的。这个指标衡量的是检索的噪声水平。精确率低会导致上下文被无关信息污染。回答忠实度Faithfulness生成的回答是否完全基于检索到的内容没有编造。这个指标衡量的是幻觉程度。忠实度低意味着系统在胡说八道。这三个指标要分开测不能混在一起。因为它们的优化方向不同命中率低要改切块和检索策略精确率低要加重排序和过滤忠实度低要改 Prompt 和生成策略。7.2 构建评估集的低成本方法评估 RAG 系统需要评估集但人工标注评估集成本很高。我的做法是半自动构建先从真实用户查询中采样 100 到 200 条覆盖各种查询类型。然后对每条查询人工标注它对应的正确文档块。这一步是必须人工的但工作量可控。最后用大模型对每条查询生成一个参考答案人工审核修正。这个评估集建好之后每次系统改动都跑一遍看三个指标的变化。没有评估集的 RAG 优化就是盲人摸象你永远不知道改动是变好了还是变差了。7.3 持续监控上线后的效果衰减与应对RAG 系统上线后效果会随着时间衰减。原因有两个一是文档在更新旧的切块和索引可能过时了二是用户的查询分布在变化新的查询类型可能没有被覆盖到。所以上线后的持续监控很重要。我通常会监控这几个信号检索命中率的周环比变化如果持续下降说明文档或查询分布发生了变化用户反馈的负样本率用户点踩的比例是最直接的信号无答案率系统回答根据现有信息无法回答的比例如果升高说明检索覆盖不足当这些信号出现异常时就要触发重新索引或者调整检索策略。我一般建议每个月做一次全量评估每周看一次监控指标。8. 六个分水岭的优先级排序与落地建议8.1 如果只能改一处先改哪里如果你现在的 RAG 系统效果不好但资源有限只能改一处我的建议是先改切块策略。切块是检索的天花板切块不对后面所有优化都是在错误的基础上修修补补。而且切块优化的成本最低不需要额外模型不需要额外算力只需要重新设计切分逻辑。第二优先的是重排序。它的投入产出比最高加一个重排序模型准确率通常能提升 20% 以上而工程改动量很小。第三优先的是混合检索。它解决的是向量检索的盲区问题对精确查找和条件筛选类查询提升明显。8.2 不同规模团队的差异化路线小团队1 到 2 人建议走切块优化 混合检索 重排序的路线把基础打牢先不要碰图谱和 Agent。这三个环节做好大部分场景的效果已经够用了。中等团队3 到 5 人可以在基础之上加 Agentic RAG用 LangGraph 做迭代检索。同时开始建评估集用数据驱动优化。大团队5 人以上可以考虑 GraphRAG但前提是有专人负责图谱的构建和维护。同时要建立完整的评估和监控体系保证系统长期稳定。8.3 我踩过的三个印象最深的坑第一个坑是过度依赖向量检索。早期我做 RAG 只用向量检索觉得 embedding 模型够强就行了。结果在一个法律文档场景上用户问合同法第 52 条规定的无效情形有哪些向量检索完全找不到正确的块因为第 52 条这种精确引用在向量空间里没有区分度。后来加了 BM25 才解决。第二个坑是忽略上下文顺序。有段时间我发现检索明明是对的但回答总是漏掉关键信息。排查了很久才发现关键信息被放在了上下文的中间位置大模型没注意到。调整排列顺序后问题就解决了。第三个坑是没有评估集就盲目调参。我曾经花了两周时间调各种参数感觉效果在变好但上线后用户反馈还是很差。后来建了评估集一测发现我调的参数在评估集上根本没有提升之前的感觉变好完全是错觉。这三个坑的共同点是它们都不是技术难题而是认知盲区。你不知道有这个问题就永远不会去解决它。希望这篇内容能帮你把这些盲区补上。最后分享一个我一直在用的小技巧每次改动 RAG 系统之前先跑一遍评估集记录当前指标。改完之后再跑一遍对比指标变化。如果指标没提升不管你觉得改动多合理都回滚。这个习惯帮我避免了很多次自以为在优化实际在退步的情况。
返回列表