叶小钗

你们用过复杂RAG吗,知道什么是Agentic RAG吗?

AI训练营7期,1月下旬开班,欢迎咨询

最近因为学员在Agent和RAG这块老是犯迷糊,所以写了较多相关文章:

  1. 《万字:Agent概述》
  2. 《万字:RAG实战技巧,包教包会》

就我这边学员反馈的情况来说,多数公司依旧还在Coze、Dify,连个知识库都玩不明白的状态,所以只要做到上述2篇任何一种,找工作是肯定没问题的。

只不过如果进入了“真AI应用”团队,或者是遇到需要装逼的面试官,上述单篇内容就稍显不足了,需要将两者合并一下:Agentic RAG 应运而生,这一下智能度就够够了!

Agentic RAG 从出生开始,就属于地主家的还在,并且会伴随一种常见的论调RAG已经过时了。

并且昨天一次AI闭门会,这个观点又出现了:一个资深投资大佬在吹嘘Agent,不自主的在贬低RAG。

虽然你真问他做了什么深度RAG项目,又大概率拿不到你要的答案。

但我们还是必须先理清楚,现阶段所谓的RAG过时了到底是什么,毕竟模型只有一个输入输出,只要在输入前对问题进行干涉都能被称为RAG,按理说这东西是不可能过时的。

过时的“RAG”

不好用的东西过时了,这个还是很能达成一致的:之前我们把一整段文档直接丢给向量库,效果奇差,这也是最近两三年前兴起的“朴素RAG”模式:

一次向量检索、Top-K chunks 直接塞进 prompt、最终垃圾进垃圾出。

这种“朴素RAG”最常见的问题是:上下文割裂,文档分块的时候对原文的完整性进行了破坏,比如表格阶段、论证逻辑切断,最终结果是信息丢失。

所以,结论是:分块导致问题,而现在模型上下文这么大了,百万上下文即将来临,是不是全部丢给模型就好,不需要分块了?

可能也不是这么回事,因为长上下文虽然可以缓解分段割裂的问题,但背后的检索效率和精度问题依旧还在,所以还是必须分块,具体来说有以下原因:

主流的文本Embedding模型有其最佳编码长度(中度长度)。

将一本数万token的书编码成一个向量,就像用一句话概括整本书,大量细节会丢失,导致检索精度暴跌。这里有些同学可能不太理解,我做下解释:

每个基座模型都具备Embedding的接口,他不关注你输入量有多大,无论是200字还是2万字,最终他都会给你压缩成一个向量,这里的结果是:输入越长,信息越多,压缩越狠,结果往往更“平均化”,检索分辨率下降。

所有的信息在传递过程中都具有扩散和压缩的特性,并不是越多越好,可参考此图:

Image

也就是因为这个原因出了很多工程层面的技术做“迁就”,比如:《树搜索RAG系统:PageIndex》

Image

只不过,如果都做到这种程度的结构化了,我完成可以给每个子文档先做一个大类,再给具体文档一段摘要描述(description);

每次问题来了穷举,先进具体类型,再用模型去判断description就好了,这里用小模型的话效率挺高的,向量库就可以不用了。

所以,真实情况下,向量库也不是必须的,很多时候都在混用。

然后随着Agent的需求激增,模型侧对Agent的基础支持做了大量优化,包括MCP、Skills等的提出,可以说工具侧最烦的问题处理的差不多了,明年很可能模型会在记忆侧发力,给出更有的工程策略;

举个例子,理想情况的知识数据就是我把文档全量喂给某个智能库,而后我在做知识检索的时候,这个智能库能够给我正确的回答。

之前大家是用向量库在做语义检索这块,很显然他不好用,需要我们叠加很多工程技术才能勉强实现,后面大家就发现一个情况,小模型配合结构化知识库也能做语义检索啊,干嘛非要用向量库,于是整个工程范式有很大的变化。

如何把这种复杂的工程技术做内化包装,如何将向量技术内置到模型黑盒里面,应该是下个阶段模型技术突破的命题之一。

好了,在大概解释清楚什么是过时RAG后(因为其实我也不知道他们在说什么过时了...),我们再回归到Agentic RAG。

Agentic RAG

为了更好的AI体验,我们做了很多工程层面的优化,包括:多源知识整合、更动态的上下文验证以及与外部工具的深度融合等。

而后Agent概念火了后,大家发现这东西可以用Token去换架构,用不停的循环增加的成本去解决Workflow的泛化工程问题。

于是就有好事者在想,是不是可以引入Agentic RAG的概念,进行精细的计划、多步骤推理,并充分利用外部工具去处理复杂问题。

总而言之,都是所有Agent字样的出现,都是想去偷工程复杂性的懒,是一种时间换架构的范式

Agentic RAG的工作是:在多个文档和数据源间比对信息、提炼总结,从而产出全面且准确的答案。

换言之,Agentic RAG实现了从被动检索到主动推理的转变,将静态问答过程升级为动态、智能的知识探索过程......

PS:可以看到反正沾了Agent字样的就很玄妙

这里来个传统RAG(上)与Agentic RAG(下)流程对比:

Image

Agentic RAG使用循环迭代流程:引入Agent对查询进行分析和决策,如选择查询内部知识库还是进行网络搜索,然后再对结果相关性进行评分(Grade)。

如果结果不理想,Agent会改写查询重新检索。如此反复迭代,直到收集到足够有用的上下文,再由LLM生成可靠答案。

换句话说:Agentic RAG 是一种泛化能力很强的Workflow架构,能够让模型自己拿到更好的数据

我知道大家依旧有点迷糊,来个之前的案例吧:

粗暴RAG的问题

成都某大型律所之前有个小需求:

在审阅一份800页的跨境并购协议时,需要快速定位数十个关键条款(赔偿、终止、担保、知识产权转移等),并对每个条款的风险点进行初步分析。一个资深律师完成全面审阅需要40-50小时。

于是乎他们老板问我10万AI能不能搞定,我说能搞定、并且去做了,也“搞定了”。只不过可扩展性不高,毕竟10万你不可能搞个Harvey出来吧?

初期我也是想空手套白狼,派了个本地(成都)学员去搞,一套基于Dify的标准打法:

  1. 文档处理:将PDF合同文本化,按固定长度(如512字符)进行重叠分块;
  2. 向量化:使用Dify知识库功能自动分块;
  3. 检索:用户提问时,召回Top-5最相似分块;
  4. 生成:将分块与问题拼接,交给GPT-4生成答案;

实际效果堪称灾难:

一、关键条款丢失

一些"条款"可能跨越3-5页,包含定义、范围、限额、除外情形等,固定分块将其切成5-6段后,每段语义都不完整。

二、表格数据丢失

合同附录中会有很多表格,一般是需要Markdown化的,如果不处理、或者处理不对也会被切碎了,模型可能只看到表头或零散数据。

三、引用混乱

模型经常自信地引用"第523页第2段",但实际上该页讨论的是完全不同的议题,甚至有引用页码超出了文档总页数,这个就很屌了...

四、图片问题

这个就不用说了,图片没特殊处理(Markdown + 简单描述),几乎丢了。

五、一致性问题

同一问题在不同时间提问,得到的答案和引用完全不同,完全无法用于正式法律意见,只要错一个律师就会不信所有。

......


上述问题都有成熟的工程解法,因为导致其问题的最主要原因一定是粗暴的插入过程:

原始文档(800页PDF)
    ↓
文本提取(800页纯文本)
    ↓
机械分块(每512字符切一块,共约1500个chunk)
    ↓
向量化(1500个向量存入向量数据库)
    ↓
完。

Agentic RAG

Agentic RAG 效果要好,就一定要在输入侧做文章,比如不再把文档当成"一堆文字",而是当成"有结构的对象":

# Agentic RAG's data storage is effectively hierarchical and multimodal
document_structure = {
"metadata": {
"doc_id": "contract_001",
"title": "并购协议",
"total_pages": 800,
"version": "1.0"
  },

# Layer 1: Table of Contents (stored in a relational database)
"toc": [
    {"chapter": 1, "title": "定义", "pages": "1-5"},
    {"chapter": 8, "title": "赔偿条款", "pages": "45-62"},
    {"chapter": 8.2, "title": "赔偿范围", "pages": "47-52"},
    {"chapter": 8.2.2, "title": "间接损失", "pages": "48-50"},
    {"chapter": 8.3, "title": "赔偿限额", "pages": "53-58"}
  ],

# Layer 2: Chapter summaries (hybrid vector + text storage)
"chapter_summaries": {
"8.2.2": {
"vector": [0.12, 0.34, ...],  # embedding for the summary
"summary": "本节规定间接损失的赔偿条件:需可合理预见且在30日内书面通知。",
"key_entities": ["间接损失", "合理预见", "30日"],
"relevance_score": None  # computed at runtime
    }
  },

# Layer 3: Detailed content (vectorized on-demand)
"detailed_chunks": {
"8.2.2_para1": {
"vector": [0.45, 0.67, ...],  # only vectorize when queried
"text": "8.2.2 间接损失赔偿。尽管有第8.2.1条规定...",
"page": 48,
"chunk_type": "正文"
    },
"8.3_table1": {
"vector": None,  # tables are not vectorized; handled specially
"type": "table",
"data": [["损失类型", "上限比例"], ["间接损失", "50%"], ...],
"page": 56
    }
  },

# Layer 4: Cross-reference graph (stored in a graph database)
"references": {
"8.2.2": ["8.1.6", "8.3", "8.4.3"],  # references to other clauses
"8.3": ["8.2.2", "附录D"]
  }
}

大家可以看到,这里的数据处理更前面的PageIndex是否类似,只不过这套东西维护成本奇高:

说白了,不管什么RAG效果要好都得处理数据,甚至80%的工作量都在数据处理,Agentic RAG 也没有多么神奇

换句话说,Agentic RAG 如果最终不解决数据处理成本过高问题,那么他也是花架子

这里再补一句:Agentic RAG的核心在于数据已经处理好的情况下,利用得更好。如果理解这个点后,大家会更Agentic RAG的意义,在相同数据质量的情况下,会呈现出更优的表现,但基础的数据建设依旧要跟上,不然效果一定不会很好。

在基本数据得到保证的情况下,就可以真正进入Agentic RAG了:模拟真人律师的实际工作的SOP(Workflow)。

SOP → Agentic RAG

先强调一句:Agentic RAG 不是“再检索一次”这么简单,它是把“检索”做成一个可控的流程。你只要把这个 SOP 跑通,也就基本学会了,所以重点是真人怎么做,然后用代码做实现。

一个资深律师拿到问题,他会做这几步:

澄清问题边界 → 先定位章节: → 逐层下钻: → 处理交叉引用: → 拿原文做证据链: → 写之前先核对 → 如果证据不足就继续找,不硬写,回到第2步。

Agentic RAG 要做的,就是把上面这套 SOP 变成代码。比如把系统拆成五个“角色”(也可以叫 Skills):

  1. 路由Agent Router:决定先看哪些章节/数据源(只做决策,不回答);
  2. 导航Agent Navigator:按“章节 → 条款 → 段落”逐层下钻,把范围缩小;
  3. 证据Agent Collector:抽取“可引用锚点”的证据片段(page/span);
  4. 引用Agent Verifier:检查“引用是否存在、结论是否被证据支持”;
  5. 写作Agent Writer:把证据链变成“律师能看的”结论与风险提示;

来一个案例:本协议对间接损失(indirect damages)是否赔偿?如果赔偿,条件是什么?是否有 cap/basket?请给可引用页码。

一、输入理解

先把问题拆成 3 个子问题(这一步非常关键,否则后面永远找不全):

  • Q1:间接损失是否被排除/允许?
  • Q2:如果允许,有哪些条件?
  • Q3:上限/门槛是多少?

二、第一轮路由

Router 不读正文,只读你结构化存的 toc 和 summary 卡片,输出一个非常简单的结构化决策(示意):

{
"route": [
    {"node": "8.2.2", "why": "直接命中间接损失规则", "confidence": 0.92},
    {"node": "8.3", "why": "cap/basket通常在限额条款或表格", "confidence": 0.88},
    {"node": "LoL", "why": "间接损失常被责任限制排除", "confidence": 0.65}
  ],
"stop_condition": "证据必须覆盖 Q1-Q3,且每条结论可引用"
}

这一步没有向量 Top-K 的随机性,因为是在“章节树”上路由,搜索空间天然被压小了。

三、信息下钻

进入 8.2.2,把范围从“章节”缩小到“可读段落”。

  1. 如果 8.2.2 很短:直接拉全文
  2. 如果 8.2.2 仍然很长:继续按段落/子条款拆

这时系统才会触发在 detailed_chunks 里的 on-demand 向量化:

  1. 只对 8.2.2 的段落做 embedding(而不是 800 页全量)
  2. 同时把页码锚点带上(page=48–50)

得到候选证据片段:

  1. p48_s03:解释间接损失范围;
  2. p49_s01:条件(合理预见、30日书面通知);
  3. p50_s02:例外/除外(如果有);

这里就是前面说的在输入侧做文章的收益:证据天然带锚点,后面引用不会乱飞。

四、补齐证据

Q3是 上限/门槛,这类信息在合同里很爱到处藏,要么在正文写死,要么就在某个表格附件,所以证据Agent需要明确的指令:对于数字信息优先查表格附件,如果没有则查询正文。

对于传统RAG来说,这里也会是个难点,他很难稳定把表格里某个单元格召回进 Top-K。

五、关系链

这里是最为关键一步,他意味着拿出来的数据是不是全面,就是Agent需要判断原文里面的 references 引用的相关内容是不是需要被包含。

六、数据组装

最后就是数据组装了,他大概长这样:

{
"evidence": [
    {"id":"E1","node":"8.2.2","page":48,"span":"p48_s03","text":"...间接损失..."},
    {"id":"E2","node":"8.2.2","page":49,"span":"p49_s01","text":"...合理预见...30日内书面通知..."},
    {"id":"E3","node":"8.3","page":56,"span":"8.3_table1_row2","text":"间接损失 上限比例 50%"},
    {"id":"E4","node":"8.3","page":53,"span":"p53_s02","text":"...aggregate cap..."}
  ],
"coverage": {"Q1": true, "Q2": true, "Q3": true}
}

数据已经充足情况下就是输出问题,我们这里就不展开了......

结语

其实这篇文章真的挺难写的,因为我们当时做的时候确实没有用什么Agentic RAG,而是用了非常多、也非常常规的工程手法去解决这一切。

事实上我也翻阅了很多资料,什么是Agentic RAG,该有的案例是什么?

结果无一例外的没有发现特别合适的,然后又与很多业内人员做了交流,这个图应该是比较好的说明:

Image

整个Agentic RAG 的工程发展方向是:把数据接口做细 → 封装成工具/Agent → 用 ReAct 让模型决定是否调用。

这里的关键是将复杂的RAG流程拆解成一系列定义明确的 Skills (或 Tools、Agent),然后通过一个 ReAct (Reasoning + Acting) 框架,让模型自己决定何时、以何种顺序调用这些技能,从而完成查询。

这里可能也是Agentic RAG最大的难点或者问题所在了,这里的Skills (或 Tools、Agent)他是一个黑盒,比如现在有个医疗、法律Agent现在要给我提供API,这里复杂度是很高的。

也就是,这个数据Agent需要提供各种证据链,也要解决复核性等问题。比如医疗/法律这类 Data Tool 的复杂度高,根因不在工具数量,而在工具必须提供可追溯、可校验的证据服务,

现阶段Skills是个非常经典的实现,解决了很多工程问题,大家可以多关注下。

点击上方卡片关注叶小钗公众号,查看下方二维码,添加我个人微信:

Image

往期推荐

《系统性:如何进入AI行业?》

《万字:Agent概述》

《万字:个人IP,包教包会》

《万字:RAG实战技巧,包教包会》

《万字:聊聊微调》


《简单聊聊GEO》

《AI团队组织结构该如何设计?》

《AI学习路线图2.0》

《生产级别的RAG系统》

《LangChain、 Dify、 n8n、 Coze:四大AI框架怎么选?》