做RAG的人这两年越来越多了多到我都快看不过来了。打开各种教程清一色的流程加载文档、切块、embedding、怼进向量库、接大模型、问几个问题、完事。这套流水线跑通确实不难半天时间就能搭个demo。但真正的问题是——你把这个demo丢到真实业务里它能不能扛得住我见过太多人和我说“我们RAG做完了”结果一问细节PDF表格全碎、检索出来的段落文不对题、多轮对话一问就懵、答不上来的时候还硬编答案。这些都不是流水线的问题流水线人人都会搭。真正拉开差距的是流水线之外的六处细节。我把这一年多在真实项目里踩过的坑、验证过有效的做法收敛成六个分水岭。你要是能把这几处思考到位你的RAG系统就能从“能跑”变成“能打”。1. RAG 不是流水线是一套系统工程1.1 为什么你的 RAG 跑起来像个玩具先聊一个我观察了很久的现象。同样的技术栈有人用 LangChain 加一个开源向量库搭出来的东西能直接给客户演示有人照着教程一步步敲最后得到的只是一个“看起来会回答问题”的玩具。差别在哪很大程度上在于对 RAG 的理解深度。萌新看 RAG是“检索生成”两个模块按字面意思拆把文档切了存起来用户提问时去搜一下把搜到的内容丢给大模型回答。有经验的人会往上拆一层理解问题、查询构造、索引匹配、信息融合、答案生成、引用溯源。这六个环节里任何一个成为短板整个系统的体验就会塌方。举个例子你就明白了。一个企业内部知识库系统用户问“上个月的报销流程变了没有”知识库里存的是“2024年11月财务流程更新公告”这种书面标题。你直接拿用户口语去匹配向量相似度再高也排不到前面。这不是向量模型不行是你的查询处理环节缺了一环。所以我说RAG烂大街烂的不是技术本身而是那条人人都会搭的流水线。把pipeline跑通只是起点真正决定系统质量的是你在这六个环节里做了什么决策、有没有把细节补全。1.2 六处分水岭先看清差距在哪这六处分水岭我按“从数据进来到答案出去”的顺序理一下分水岭对应的环节回答的核心问题文档解析与切分入口质量数据进屋之前洗没洗干净检索层混合策略召回质量能不能把该找的东西找出来查询处理问题理解用户的话适不适合拿来检索索引结构设计内容组织知识库里存的是文本还是知识Agentic 编排任务形态系统是问答机还是任务执行器评测体系调优闭环改得好不好用尺子说话你注意看这六个环节没有一个是“炫技型”的全是脏活、累活、细活。但恰恰是这些不显眼的环节决定了两个团队做出来的RAG系统是天上地下。2. 分水岭之一文档解析——入口数据的“最后一公里”2.1 PDF 表格与扫描件最容易被低估的坑真实业务环境里PDF是绝对的主流格式但PDF本身只是版式容器内容提取质量全看解析器。我见过太多项目直接把常见的PDF加载器拉出来就用结果三个经典翻车现场第一是表格全碎。一份财务报告里写着“华南区Q3营收1.2亿”表格被切成两个chunk后一个只留了“华南区Q3”另一个只剩“营收1.2亿”。用户问华南区营收多少检索回来的是半截信息模型拼都拼不回来。第二是多栏文本乱序。很多论文和杂志是双栏排版解析器如果没做版面分析会把左栏下半截和右栏上半截读成连续文本句子完全驴唇不对马嘴。第三是扫描件直接白给。真实知识库里有大量扫描存档这些文件不经过OCR你灌进向量库的就是一堆空白文本。有一次我帮朋友排查一个知识库top检索结果全是空文档原因就是扫描PDF没做OCR处理。我自己现在的做法是PDF这类复杂格式走“OCR 版面分析 表格结构还原”的组合管线输出成Markdown格式再入库。像PP-Structure这类开源工具链就能做表格还原识别出表头、表体和单元格结构把表格变成一个结构化的Markdown表格再按行切块每一行配上表头作为metadata。这样检索“华南区Q3营收”返回的就是一个完整的行级数据。2.2 切分策略别把标题、段落和表格腰斩切块chunking是纯工程问题但对召回质量的影响极其直接。固定字符窗口切分是万恶之源。按512个字符一刀切它的好处是实现简单坏处是会把标题和正文切断、把表格从中间腰斩、把一段完整逻辑拆成两半。加多少重叠overlap都治标不治本因为重叠只能补上下文补不了逻辑完整性。更稳的思路是结构感知切分按标题、段落、列表、表格、代码块这些自然边界来切。一本书先按章节拆章节内再按小节拆小节里遇到表格就单独切成行级块。这样每个chunk都有相对完整的语义检索召回时更精准。另外一个关键细节是metadata。每个chunk都要记录文档来源、页码、章节路径、更新时间、权限级别。这些字段是你后期做权限隔离、按时间过滤、按来源追溯的关键。很多项目一开始觉得麻烦不存metadata等真要按部门隔离权限的时候后悔莫及只能重新解析一遍数据。2.3 实操建议不同文件类型分开处理我现在的处理策略是“分类型走专线”不搞一刀切。PDF复杂版式走OCR加版面分析加表格还原转Markdown后再切。Word文档直接解析结构标题、段落、表格天然分离不需要OCR。HTML页面按语义标签切分顺手把导航栏、页脚这些噪音过滤掉。Excel和CSV按行切块表头作为公共metadata这样检索“某产品某季度销量”时能直接命中具体的行。Markdown和代码文档优先保留代码块和注释结构不要拆散。切完以后务必做一轮人工抽检。每个文件类型抽10条切块结果肉眼过一遍标题有没有跟着正文走表格有没有还原多栏文本有没有乱序。这一步花一个下午能帮你发现解析管线里80%的问题。3. 分水岭之二检索层策略——从向量TopK到混合检索3.1 单路向量检索的局限性很多人以为向量检索是最先进的方式所以只用向量检索。但向量检索有一个天然的硬伤它对精确匹配和关键词场景非常不敏感。举个例子。用户问“A100-80G 的显存是多少”如果你的embedding模型对数字和字母组合不够敏感它可能把“A100-80G”和“A100”当成高度相似的文本召回的段落全是错的。还有内部项目代号、法律条文编号、产品型号这些上下文无关的精确字符串向量表示往往区分度不够。另一个问题是长文本稀释。你把一篇完整报告平均成一个向量这个向量会把各个主题的信息“平均”掉检索时撞命的概率很大。文档越长单一向量的语义越模糊。所以单路向量检索的本质是在语义相似和精确匹配之间做了一次赌博赌你的query恰好和文档语义相近。但真实用户的问题往往不那么合拍。3.2 混合检索BM25 与向量双路并行工程上更靠谱的姿势是混合检索BM25关键词检索 和 向量语义检索 双路并行再把结果融合。BM25管精确匹配向量管语义相似两者互补。融合算法我常用的是RRFReciprocal Rank Fusion它不关心两个结果集的分数分布只关心排名。每个文档的融合分是所有检索列表中“排名倒数之和”最后按融合分排序。比如一个文档在向量检索里排第3在BM25里排第5那它的融合分就是1/3加1/5。RRF的好处是鲁棒不受两个检索器分数量纲不一致的影响。实际效果怎么样我做过对比在同一个知识库上只用向量检索的Top5命中率不到60%加上BM25之后直接提升到80%左右。特别是用户喜欢用“项目编号”“合同号”“文件名”提问的场景BM25几乎是救命的。3.3 Rerank把“像”变成“是”混合检索之后你拿到的还是一个“粗排”结果。粗排的目标是别漏掉相关内容但排在第一名的答案往往只是“语义相近”而不是“直接回答问题”。这时候需要加一个重排Rerank环节。重排模型通常基于cross-encoder架构能把query和doc拼接起来精细打分比双塔结构的向量模型精度高一大截。现在也有直接用LLM做rerank的方案把query和候选文档放进prompt里让模型判断哪个更相关效果确实好但成本高。我的建议是分层来做先用混合检索粗排从几万条里捞出Top 50再用轻量级rerank模型精排到Top 5如果预算允许再用LLM对Top 5做最终筛选。这是成本与效果的平衡点。加不加rerank用户体验差别有多大我自己实测同一个知识库问答不加rerank的时候用户总抱怨“答案相关但不精准”加了之后直观感受就是“回答靠谱多了”。延迟会多个一两百毫秒但这个代价换来的准确性提升绝对值。4. 分水岭之三查询处理——别拿用户原话直接检索4.1 用户的提问方式不适合直接检索这条经验我几乎在每次分享都会提用户说出来的问题天然不适合直接拿去做检索。原因很简单用户不会按照知识库的收录方式来提问。内部系统里用户会问“那个项目现在什么情况”而知识库里存的是“XX项目于2024年3月立项当前处于联调阶段”。这两者之间在语义空间里的距离比你想象的要远。不处理就直接召回的结果是query和文档的表达方式错位向量检索即使再准也找不着。还有个常见场景是缩写和术语不一致。用户说“ERP”和“企业资源管理系统”全称、缩写、口语称呼在知识库里混着出现。如果查询处理环节不把用户的问题和知识库的表达方式做一次“对齐”检索质量就会大打折扣。4.2 查询改写、查询分解与 HyDE解决这个问题我有三个常用手段按成本和收益排序一是查询改写Query Rewriting。让LLM把用户口语转化为知识库更可能收录的表述方式。比如“那个项目现在什么情况”改写成“XX项目当前进展状态”补全指代、还原缩写、补充上下文。这个操作成本很低收益却非常明显。二是查询分解Query Decomposition。用户的问题往往是复合问题“帮我对比A方案和B方案的成本和实施周期”。这种问题直接拿去检索可能在A方案相关的文档里找到了一些内容B方案相关的文档里也找到了一些但都是零散的。正确做法是先拆成“A方案的成本”“A方案的实施周期”“B方案的成本”“B方案的实施周期”四路检索各自召回后再合并。三是HyDEHypothetical Document Embeddings。这个方法有意思的地方在于它让LLM先根据问题生成一个“假设答案草稿”再用这个草稿的向量去检索。原理是直接拿问题去检索可能与文档表达方式不匹配但假设答案的用词和知识库文本更接近检索命中率更高。实测下来对“开放式问题”效果很好对“事实型问题”效果一般所以我会跟查询改写配合使用。4.3 改写Prompt的一个实测相对稳的写法我平时用的查询改写Prompt很简单核心就三句话你是一个知识库检索助手。请把用户的问题改写为更适合检索的查询。 要求 1. 补全指代把“它”“那个项目”还原为具体名称。 2. 使用知识库文档中可能出现的书面化表达。 3. 不要添加问题之外的新信息不要猜测。 4. 只输出改写后的查询不要解释。这里有一个很重要的坑要提醒改写的时候不要“过度脑补”。我见过一个案例用户问“报销额度是多少”查询改写模块自作主张加上了“差旅报销额度”结果把检索范围带偏了。改写只做形式转换不做内容扩展这是底线。另外多轮对话场景还要处理指代问题。用户上一句问“A项目延期了”下一句问“它影响后续排期吗”这里的“它”必须用对话历史补全为“A项目延期对后续排期的影响”。每一轮都要先做“对话历史整备”再进检索否则连续性一塌糊涂。5. 分水岭之四索引结构——向量库里存的是文本还是知识5.1 父子分块把“召回粒度”和“生成粒度”分开刚开始做RAG的时候我一直在纠结一个问题chunk到底切大还是切小切小了检索命中精确但上下文不够模型回答的时候信息不足切大了上下文完整但chunk内部信息太杂vector表示被稀释检索召回率下降。这两头都难受直到我用了父子分块Parent-Child Chunking的思路才解开。思路很简单小的子块用于召回大的父块用于生成。子块按256个字符左右的小窗口切负责跟query精确匹配每个子块记录它的父块ID。检索阶段命中的是子块但喂给大模型生成的是它对应的父块全文。举个例子你就明白了。一个操作手册里有一段1500字的“故障排查流程”其中“重启路由器的步骤”在第800字的位置。如果你只切小chunk模型只看到重启步骤如果你只切大chunk检索时“路由器”这个词可能匹配不精准。用父子分块用户问“怎么重启路由器”命中小chunk“重启路由器操作”然后把这1500字的完整排查流程全部喂给模型。这样模型既不缺上下文检索又足够精准。工程实现上也很直接建两张表子块表和父块表子块字段里挂parent_id检索时子块命中、父块回传。很多向量库天然支持这种结构不用额外写复杂逻辑。5.2 多级摘要索引让向量库里存“知识”而不是“文本”纯文本索引只能解决“这句话在哪”的问题解决不了“这个主题的结论是什么”的问题。用户如果问“这个项目全年一共完成了哪些里程碑”你把项目周报的几十个chunk全部灌给模型它大概率答不好。多级摘要索引的思路是先对一批文本块做摘要再对摘要做摘要形成一棵“摘要金字塔”。底层是原始文本中层是段落摘要顶层是整篇文档的一页结论。查询时先在顶层摘要里找方向再逐级下钻到具体文本块。这样系统相当于从“给你找原文”升级成了“给你提炼结论”。这个方案的成本比普通RAG高毕竟摘要需要调用模型而且摘要本身也是token消耗。我一般在文档价值高、时效性强、用户需要“结论型答案”的场景下用比如战略研究报告、技术方案评审、竞品分析材料。顺带提一个相关但不太一样的方向本体约束的RAGOntology RAG。如果知识库结构非常清晰可以在抽取阶段给LLM加一层本体约束让实体和关系按照预定义的类型去抽取和链接。这样索引组织会更规范关系型问题也好回答但前期需要做好领域建模成本也不低。5.3 知识图谱与 GraphRAG跨文档关联问题的一剂猛药传统RAG最大的软肋是回答不了需要“跨文档推理”的问题。多份文档放在一起A材料里说了“华东子公司营收下滑”B材料里说了“华东子公司主营产品是工业传感器”C材料里说了“工业传感器市场整体萎缩”。用户问“华东子公司为什么下滑”传统RAG靠向量相似度很难把这三点关联起来。GraphRAG的思路是把实体、事件、关系抽取出来组成图结构再用社区检测生成社区摘要。它天然适合回答“全局性问题”和“关系型问题”。但代价也很明显构建成本高、抽取质量依赖模型能力、图谱更新维护麻烦。我的建议是不是所有RAG都要上GraphRAG。先用父子分块加多级摘要打底如果发现用户问题里大量涉及“比较、关联、趋势、原因”再考虑上图谱。一上来就堆技术往往是给自己挖坑。6. 分水岭之五Agentic RAG——把检索变成一种能力而非一步操作6.1 从“一问一答”到“任务编排”传统RAG的形态是用户问一句系统检索一次模型答一次。但真实业务里的需求往往不是这种“单轮QA”而是“帮我整理一下”“帮我对比一下”“帮我出一份报告”。这时候RAG不能再是一条固定的“检索-生成”管道它得变成一个能拆解任务、能决定下一步调什么工具的智能体。所谓Agentic RAG本质上是把检索能力作为工具之一挂到Agent上跟计算工具、数据库查询工具、Web搜索工具并列。Agent根据用户意图决定用哪个工具、按什么顺序用、用几轮。这跟“一遍检索一遍生成”的管道式RAG是完全不同的两种东西。另外这两年也流行把RAG服务化RAG as a Service把检索、记忆、工具调用封装成统一服务层上层Agent直接调用。这个思路我觉得是对的检索能力不应该跟具体业务逻辑耦合在一起做成服务之后多个Agent共享一套检索能力维护成本会低很多。6.2 路由、工具与自我反思三个落地关键点Agentic RAG看起来很美落地的时候有三个关键点必须处理好。第一个是意图路由。Agent进来后不是直接检索而是先判断用户意图这是闲聊、是知识问答、是要数据分析、还是要一个多步骤任务不同的意图走不同的链路。比如闲聊就直接对话知识问答走RAG数据分析则调SQL工具加RAG混合。这一步判断错了后面全错。第二个是工具封装。不同数据源要封装成不同检索工具并且给LLM友好的工具描述。比如“company_policy_search检索公司制度文档”“product_manual_search检索产品手册”“order_db_query查询订单数据库”。LLM看到这些描述以后才能自主决定该调哪个。工具描述写得模糊LLM就会胡乱调工具这是Agentic RAG最常见的失败原因。第三个是自我反思Self-Reflection。让Agent在给出答案之前先自我检查一轮“我召回的内容够不够回答这个问题”“这个结论有没有引用支撑”“有没有更合适的工具我还没用”。如果发现问题就重新检索、重新生成。这个反思循环是效果好坏的胜负手也是成本控制的最大变数——不加限制的反思循环会把token消耗搞到爆炸。6.3 一个典型工作流多数据源对比汇报举个例子你就有画面了。用户说“帮我对比A方案和B方案的优劣并整理一页PPT要点。”传统RAG会怎么做它拿整句话去检索可能召回一堆杂乱内容然后硬生成一段泛泛的对比。Agentic RAG会怎么做先拆任务对比A方案、对比B方案、找实施难点、整理PPT要点。然后分别调用产品文档库检索两个方案再调项目复盘库查实施难点再调模板库查PPT格式最后统一组织输出。这种任务固定pipeline完全做不到。但是Agent做到了因为它有“计划、执行、检查、再执行”的闭环。这也是为什么我认为RAG的下一个分水岭就是做Agentic化。7. 分水岭之六评测体系——没有尺子调优就是玄学7.1 分层评测检索层指标与生成层指标做RAG调优最怕的就是“凭感觉”。你改了chunk大小、换了embedding模型、加了rerank到底有没有变好没有评测体系你只能靠一两个案例来主观判断这是进阶的大忌。我习惯把RAG评测拆成两层检索层和生成层。检索层主要看三个指标Hit Rate正确答案是否出现在召回结果里。比如你召回Top 5正确答案在里面就算命中。RecallK正确答案占所有应召回内容的比例它衡量的是“该找的有没有找全”。MRR第一个正确答案排在第几位。它衡量的是“找到之后是不是排在前面”。生成层主要看两个指标忠实度Faithfulness答案里的每个论断能不能在原始文档里找到依据。这是知识库敢不敢上线的生死线。相关性Relevance答案是不是用户问的东西有没有答非所问。这两个指标都需要人工或LLM Judge打分。我自己在项目初期倾向人工评测找三五个人把评测集跑一遍打分虽然累但你会对系统边界有极其清晰的感觉。等系统稳定了再用LLM Judge做回归。7.2 评测集构建从真实用户日志里找问题评测集从哪里来很多人问这个问题。最好的来源是真实用户日志——把过去三个月用户问过的问题按类型聚类挑出有代表性的人工写好期望答案和引用段落形成一个200到500条的评测集。写期望答案的时候要保证每一条都能在原文里找到依据否则标出来的分数没有业务意义。另一个要特意做的是“负样本注入”故意问知识库里没有的内容比如“公司上个月有发布过XX政策吗”实际上没有系统必须回答“未找到相关信息”不能硬编。这个测试很关键因为RAG系统最大的风险不是答不好而是幻觉——明明没有的东西大模型会一本正经地编出来。7.3 调优路线图从下往上修避免瞎试有了评测集调优就有章法了。我的路线图是从下往上逐层排查第一步检查文档解析层。抽出20条切块结果人工看如果切块本身质量就差后面全白搭。第二步检查检索层看Hit Rate和RecallK如果召回率低调chunk大小、加混合检索、加rerank每一轮调整后都在评测集上跑一遍。第三步检查查询层看看是不是query改写不够好、指代没补全。第四步才检查生成层调提示词、调引用策略、调上下文拼接方式。这个顺序很重要因为每一层的问题会传导到下一层。如果你答案不准确先别急着调提示词先看召回结果对不对。召回没问题再谈生成。很多团队调Prompt调了半天没有进展回头发现是文档解析阶段就出了问题。最后提醒一个成本控制的点RAG的token消耗大头往往在于把太多不相关内容塞进上下文。上下文一长成本高模型注意力还容易被稀释。加一个上下文选择性压缩机制只保留和query最相关的几个段落能省不少钱效果反而更好。我个人的体会是做RAG越久越觉得这个领域最花时间的地方不在花哨的模型选型而在那些“不值得炫耀”的环节。文档解析和切分是脏活评测集构建是累活查询改写和重排是细活。但恰恰是这些环节决定了你的系统是玩具还是生产工具。每次有人问我“RAG怎么做”我都会先反问一句你的评测集建了吗你的PDF表格解析过关了吗。如果这两样都没做好那换再强的模型、再先进的框架也没用。分水岭一直都不在流水线上在流水线的每一个接口处。