RAG 生产级落地的六道分水岭:从文本拆解到 Agentic RAG

发布时间:2026/10/31 4:37:56
RAG 生产级落地的六道分水岭:从文本拆解到 Agentic RAG

每次技术社区一聊 RAG,总能看到“检索增强生成已经烂大街了”这种论调。说这话的人,多半刚用 LangChain 或者 LlamaIndex 跑通了一条“加载 PDF -> 文本切块 -> 向量化 -> 向量检索 -> 丢给大模型生成”的流水线,然后得出一个结论:RAG 不过如此。

我不这么看。烂大街的从来不是 RAG 本身,而是那条被各类 rag 框架封装得越来越廉价的流水线。你随便搜一下“ollama 简易本地 rag 知识库”,零基础复制教程一抓一大把,跟着做确实能跑出一个像模像样的问答机器人,但问题恰恰出在“像模像样”上——它能处理精心挑选的三五篇文档,却应付不了真实场景里的几千份混合格式资料;它能回答“这份合同里违约金是多少”,却回答不了“这两个季度条款变化背后的业务逻辑”。

真正把 RAG 做成生产级系统的团队,和拿着 Demo 到处演示的团队,差距不在是否会用框架,而在六个容易被忽略的分水岭。这六处,才是 RAG 从玩具走向生产力的关键。

1. 先拆掉“流水线 RAG”的底裤:它到底解决了什么,又掩盖了什么

聊六处分水岭之前,得先把“流水线 RAG”的定义说清楚,否则后面所有的批判都是空对空。

一条标准的流水线 RAG 长这样:文档加载(Loader)→ 文本拆解(Splitter)→ 向量化(Embedding)→ 向量入库(Vector Store)→ 检索召回(Retriever)→ 结果重排(Reranker,可选项,多数人直接跳过)→ 注入 Prompt → 大模型生成。这套东西有四个特征:固定顺序、环节解耦、每步都有现成组件、端到端只需几十行代码。

它当然有价值。2019 年 RAG 概念刚提出时,最大的痛点是没有这条流水线——你得自己处理文档解析、自己维护索引、自己设计检索逻辑。如今 LangChain、LlamaIndex、LangChain4j easy rag 这类项目把环节全部封装成了“积木”,搭积木这件事本身确实不值钱了。

但它掩盖了三件要命的事。

第一,它把“检索”简化成了“点一下接口”,可检索才是 RAG 的真正大脑。你写的那个vector_store.similarity_search(query, k=4),背后是无数个被轻描淡写跳过的细节——用哪个嵌入模型、按什么相似度度量、文本块切多大、需不需要混合检索、召回结果怎么去噪。

第二,它把“文本拆解”简化成了“按字符数切”,可切分方式直接决定了大模型最终读到的内容是否完整。整段语义被拦腰截断,是所有 Demo 型 RAG 的通病。

第三,它默认“把文档扔进去就能检索”,可现实中文档是 PDF、表格、扫描件、图片的混合体,还有大量隐含的业务结构。流水线处理不了结构,它只处理文本。

所以接下来要聊的六处,全部是流水线没有覆盖、但生产环境绕不开的地方。

2. 分水岭一:拆解不再是“按字数切”,而是决定记忆颗粒度

文本拆解是最不起眼、但翻车率最高的环节。因为它看起来太简单了——RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=50),一行代码,完事。

2.1 为什么“固定字数切”必然翻车

一个 512 字符(或 token)的窗口,对中文文档来说大概是几百字的段落。问题在于,语义的单位从来不是字数,而是“一个完整的意思”。举个我实际遇到的例子:一份产品说明书写着“本产品不适用于以下场景:1. 高温环境,2. 高湿度环境,3. 强酸碱环境”,如果两三句话刚好被切成两块,第一块的结尾停在“1. 高温环境”,第二块从“2. 高湿度环境”开始,那么大模型在回答“这个产品适合在什么环境下用”时,只会从切出来的碎片里看到半截内容,结论自然荒谬。

更隐蔽的问题是“切小了检索准、切大了上下文碎”的两难。块越小,向量与 query 的匹配粒度越细,检索精度越高,但大模型看到的上下文就越碎片化,生成时缺乏连贯背景;块越大,上下文越完整,但一块里往往包含两三个主题,向量表达的语义被稀释,检索时就容易召回“看起来相关、实际答非所问”的内容。

2.2 能打的拆解策略:标题感知、父子块与滑动窗口

不同场景我会用不同的拆解策略,但都遵循一条原则:让块边界贴合语义边界。

  • 标题感知拆解:先按 Markdown 标题或文档的层级结构切分,确保每个块属于同一个章节或小节。很多 PDF 转出来的文本带有标题样式,先基于标题划分,再对过长的二级标题内容做二次切分,能显著降低“跨主题”的块出现概率。
  • 父子块结构:小块负责检索(提高精度),大块负责生成(提供上下文)。具体做法是,把文档拆成 256 token 的“子块”和 1024 或 2048 token 的“父块”,向量索引只存子块,召回时根据子块所属的父块,把父块内容一并塞给大模型。这对“检索到细节 + 生成时看全貌”的需求非常管用。
  • 滑动窗口重叠:块与块之间保留一定重叠(比如 10%-15%),避免恰好把一句完整的话切开。这是最低成本的兜底方案,但要注意重叠比例太高会导致冗余索引,增加存储和检索开销。

2.3 拆解之后,别忘了埋元数据

文本块本身只是纯文本,但如果能在拆解时顺手记录来源文件名、章节路径、页码、文档类型、更新时间,后续的价值会大得多——过滤(只搜某年的合同)、引用溯源(生成答案时标注出处页码)、排序加权(最新文档优先)都依赖元数据。这是流水线教程里几乎不讲、但生产系统一定会做的细节。

3. 分水岭二:召回质量靠的不是一个向量库,而是一条混合检索链路

多数人做 RAG,召回阶段就是一个向量相似度搜索:把 query 转成向量,算余弦相似度,取 Top-K。这个做法在“语义相近的模糊查询”上表现不错,但在真实业务里会碰到一个尴尬的问题:向量检索天生不擅长精确匹配。

3.1 向量召回的死穴:精确 ID、型号、人名与反直觉搭配

我做过一个内部设备知识库,用户问“TS-200 的额定电压是多少”,向量检索召回了一堆关于 TS-100、TS-300 以及“额定电压”相关的内容,却把真正包含“TS-200”的文档排到了很后面。原因在于,嵌入模型在计算相似度时,更关注整体的语义主题,而不是个别字符的精确匹配——对于“TS-200”这种字母数字混合的精确标识,向量表示里几乎没有区分度。

类似的场景还有:问“去年和今年的退货率分别是多少”时,query 里的“去年”“今年”都是模糊指代,向量检索无法精确算出时间边界;问“哪份合同里出现了‘不可抗力’条款”,关键词精确检索反而比向量更快更准。

3.2 混合检索:BM25 做精确召回,向量做语义召回,再用 RRF 合并

解决思路不是二选一,而是“混合检索”——多条检索通道并行,再合并结果。

  • BM25 关键词检索:对 query 做分词,按词频和逆文档频率打分,擅长精确词、产品型号、人名、编号的召回。
  • 向量语义检索:擅长同义改写、抽象问题、跨语言查询。
  • 合并策略常用 RRF(Reciprocal Rank Fusion):对每个文档在每条通道里的排名取倒数求和,排名越靠前贡献越大,最终按融合分数排序。这种方法不需要调权重,对不同通道的打分尺度不敏感,工程上最省心。

在 LangChain 生态里,这通常体现为EnsembleRetriever同时挂 BM25Retriever 和 VectorStoreRetriever;如果要更精细,也可以用 Elasticsearch 这类搜索引擎,把向量检索和 BM25 在同一个索引里原生支持。

3.3 重排:别让召回结果直接进 Prompt

召回 Top-20 或 Top-50 之后,直接全塞给大模型既不经济,还可能让模型被无关内容干扰。正确做法是在召回和生成之间加一道重排(Rerank):用一个交叉编码器模型(Cross-Encoder)把 query 和每条候选文本拼接后整体计算相关性分数,打散重排,只取前 3-5 条进生成。

交叉编码器的精度远高于双塔式向量检索,因为它在同一模型里同时看到了 query 和文档全文,对“看似相关实则无关”的负样本更敏感。代价是计算量高,所以工业界的标准打法就是:向量检索粗召回几十条,再交给重排序模型精排几条。一步到位追求“检索即答案质量”的人,大多会在真实数据上吃一次亏才明白这层漏斗的价值。

4. 分水岭三:图片、表格、扫描件怎么变成可检索的上下文

很多同学第一次接触 RAG 知识库时都会冒出一个问题:知识库能存储图片吗?或者说,能不能让 RAG 直接检索图片?这是对“存储”和“检索”的误解叠加。向量库存的从来不是原始文件,而是“文本的向量”或者“多模态内容的向量”。所以这个问题要分三层回答。

4.1 第一层:图片本身进不了知识库,但图片的“文本替身”可以

对一张产品故障图,最实用的做法是先让多模态大模型(比如 GPT-4o、Qwen-VL、本地部署的 LLaVA)生成一段图片描述,包含图片里出现的型号、界面文字、故障状态,再把这段描述作为文本块存入知识库。用户问“KM-300 报错 E5 怎么办”,检索到的是这张图片的描述文本,生成答案时模型可以引用图片内容。本质上就是用多模态模型把图片“翻译”成了可检索的文字。

4.2 第二层:表格和扫描件,先做结构还原

PDF 里的表格是 RAG 最大的敌人。按文本流解析出来的表格往往行序错乱、单元格内容断裂,把它切成文本块后,大模型根本看不出“哪一列对应哪一行”。处理思路是表格结构还原:要么用专门工具把表格转成 Markdown,保留表头和行列对应关系;要么在拆解时把“表格”当作特殊块类型,单独用结构化方式抽取,再在生成阶段用表格内容配合提问。

扫描件则要先做 OCR,比较老的扫描版合同、内部规章,不做 OCR 的 RAG 等于让大模型“看天书”。市面上本地可跑的方案有 PaddleOCR、Tesseract,识别后要注意把 OCR 结果按版面顺序拼回文档流,否则识别文字是有了,段落顺序却乱了。

4.3 第三层:图文混排的终局方案是多模态向量化

如果业务场景里图片信息密度高,且不能靠描述文本覆盖,就需要用真正的多模态嵌入模型——把图片和文本映射到同一个向量空间,检索时用户输入文字 query,直接通过向量相似度匹配图片。这是“知识库能存图片”的正解,但工程成本高:需要多模态向量模型、需要 GPU 推理资源、索引和召回链路也要改造。对大多数团队而言,先用“图片转描述文本”的方案过渡,是性价比更高的选择。判断标准很简单:图片是辅助说明,还是承载核心信息?

5. 分水岭四:从平面向量索引走向知识组织,ontology 与图谱不只是“炫技”

大多数 RAG 系统的知识组织方式是“一袋文本块”——所有文档被切碎扔进向量库,彼此之间没有关系。这在 wiki 类、FAQ 类场景够用,因为每个知识条目本来就是相对独立的。但一旦涉及企业内部文档、专家经验、多份合同之间的交叉引用,平面检索就会出现两个硬伤:一是实体歧义(“苹果”到底指水果还是公司),二是多跳问题(“A 项目的负责人所有过的项目”)。

5.1 wiki 类场景为什么不需要图谱

先说说为什么有些场景确实不需要上图谱。维基百科式的静态知识库,条目之间有明确的超链接结构,每个条目自带标题、分类、摘要,语义边界清晰。直接按段落拆、按标题检索,效果已经很稳定。这种场景强行引入图谱,是典型的过度设计——花了大量人力抽取实体和关系,换来的一两个点的准确率提升根本不值。

5.2 ontology 和 GraphRAG 解决的是“关系密集”的问题

真正需要上 ontology 或知识图谱的场景,有几个共同特征:实体频繁跨文档出现、问题需要沿着关系链推理、不同来源对同一实体的表述不一致。

GraphRAG 的思路是,先抽取文档中的实体(人、组织、产品、术语)和关系(“负责”“隶属于”“导致”),构建一张图,再对图做社区检测和摘要生成,最后在问答时结合图结构和原始文本块。ontology 则更进一步,给实体和关系定义了一套共享的语义模型,比如“员工-就职于-部门”“合同-包含-条款”,让知识组织从“相似度匹配”升级为“关系约束下的推理”。

我参与过的一个售后知识库,维修手册和故障记录里反复出现某个设备型号的多种写法(“TS-200”“TS200”“穿石200”),纯向量检索会把它们当不同实体。引入 ontology 后,先做实体归一化,再建立“设备型号-故障现象-解决方案”的关联关系,回答“TS200 报错怎么处理”时,检索会先找到归一化后的实体节点,再沿着关系找出关联文本,准确率从 61% 提到了 83%。

5.3 想清楚你是要“找得快”还是“推得深”

我的个人判断是:如果你的核心痛点是大规模知识库里“找不着、找不准”,优先优化拆解和混合检索,别急着上图谱;如果你的核心痛点是“需要跨文档推理、实体关系密集、多种表述混淆”,ontology 和 GraphRAG 才是该投入的方向。这两者的 ROI 差别巨大。

6. 分水岭五:给 RAG 装上“度量衡”,不然你永远不知道它在退化

不会有人反对“RAG 需要评测”,但现实是绝大多数项目把评测做成了“看几个样例感觉不错”。这是最危险的状态——大模型的回答是生成式的,随机性和漂移都很显著,今天感觉不错,明天换了底模版本可能全面崩坏,而你毫无察觉。

6.1 分三层设计评测体系

我对 RAG 系统的评测分三层,每层关注不同的问题:

  • 检索层:只看召回质量,不管生成。常用指标包括 Recall@K(正确答案是否在召回结果里)、MRR(正确答案排得多靠前)。这层的问题用“正确答案文本在知识库中的位置”来构造评测集。
  • 生成层:基于召回内容,看大模型是否忠实于上下文(Faithfulness 忠实性)、是否覆盖用户问题(Answer Relevance 答案相关性)、是否符合预期格式(格式合规率)。
  • 端到端层:直接在用户真实 Query 上打分,让大模型当裁判(LLM-as-a-Judge),对比参考答案和系统回答的相关性、完整性、有用性,同时兼顾推理成本、端到端延迟。

三层混在一起评测是最常见的错误——回答差了,你分不清是检索没召回,还是模型没用好召回内容。

6.2 评测集不用贪多,但要覆盖“最难的那批问题”

刚开始做评测时我的建议是,从真实用户日志里挑 100-200 条代表性 query,每条标注对应的标准答案文本块(可以是人工翻出来的,也可以参考已有系统),然后按难度分层:简单直接检索、需要跨文档整合、需要精确数值匹配、答案在图片或表格里。每次调整拆解策略、换 embedding 模型、改检索链路,都拿这 200 条做回归,看各层指标的涨跌。这一百多条“够用但不够全”的种子评测集,往往比几千条自动生成的评测更管用,因为每一题你都清楚它卡在哪个环节。

6.3 没有评测体系的 RAG 优化,都是靠感觉调参

我见过太多团队卡在一个怪圈里:换个 chunk 参数,拿三五个问题试一下,“好像还行”就上线,过了两周用户反馈变差,又换回来。没有量化指标,这种“靠感觉调参”永远无法收敛。有了评测体系之后,方向就清晰多了:检索层召回率不达标,优先动 chunk 大小、混合检索权重、重排模型;生成层忠实性不达标,优先动 Prompt 结构、上下文截断策略;端到端不达标,再考虑是否要从单轮 RAG 升级成多轮编排。顺序不能乱,否则你只是在陪大模型掷骰子。

7. 分水岭六:从单跳问答到 Agentic RAG,编排是最后一层分水岭

前面五处解决的都是“一次检索、一次生成”的静态流程。但大量真实问题并不是单跳就能回答的。

7.1 单轮 RAG 的边界:复杂问题一上来就撞墙

“对比今年和去年的退货率,分析差异原因,并给出建议”——这种问题如果直接丢给单轮 RAG,流程会这样:向量检索召回一堆退货相关的碎片,模型拼凑一段口吻像模像样的回答,里面可能既有 2023 年的数据,又有 2025 年的政策,你根本分不清它引用的是哪一年的上下文。

原因在于,这类问题需要先拆解成子问题(今年的退货率是多少、去年的退货率是多少、各自的原因有哪些),再按子问题依次检索、汇总推理。单轮 RAG 没有“拆解”这个心智。

7.2 Agentic RAG:把检索从“一次调用”变成“可规划的行动”

RAG 与智能体结合,业界叫 Agentic RAG。核心区别在于:Agent 拥有工具(检索、查数据库、调用 API)、能记忆中间结果、可做多轮规划,并在每轮行动后观察结果、调整下一步。具体到知识库问答,常见的几种模式:

  • Query 路由:先判断用户问题属于哪个子知识库,再路由到对应的检索链路。比如“合同相关问法律库,设备相关问运维库”,避免所有问题都打到一个混合索引里。
  • Query 改写:把“退货率差异原因”改写成“2024 年退货率”“2025 年退货率”“退货原因数据分析报告”等多个可检索的子查询,分别召回再合并。
  • 多跳检索:回答“A 项目的负责人负责过哪些项目”,先检索出 A 项目的负责人是谁,再用这个名字做第二轮检索。
  • 工具闭环:检索不到答案时,Agent 调用其他工具(查结构化数据库、调外部 API、请求人工补充),而不是硬编一段“未找到相关信息”。

7.3 什么时候值得上 Agentic RAG

Agentic RAG 不是银弹,它引入的是决策链路和额外推理成本。核心判断标准是:你的问题类型里,有多大比例需要拆解、多跳或路由?如果 80% 是单跳事实问题(“这个产品支持哪些协议”),老老实实把前五处分水岭做扎实,性价比更高;如果用户问题本身就带复合意图、需要推理链、需要跨库汇总,Agentic RAG 才能打出明显优势。

我自己的经验是,先维护一个“问题复杂度”的分类统计:直接检索能答的算一类,需要拆解的算一类,需要检索外部工具的算一类,以此决定要不要引入 Agent。没有这个统计就上 Agent,你只会得到一辆造价昂贵但大部分时间在跑空路的高级汽车。

回头看,流水线 RAG 之所以让人觉得烂大街,是因为它把所有环节都“平均化”了——拆解平均化、检索平均化、知识组织平均化、评测平均化。而真正把一套 RAG 做出生产价值的团队,恰恰是在这些平均化的地方较真:拆解时考虑语义边界,检索时不只靠向量,知识库里的图片表格能真正被利用,再用评测体系守住质量底线,最后按需引入智能体编排。这六处才是 RAG 对抗“烂大街”论调的底气,也是你下一步值得花时间的地方。