Agentic RAG 到底强在哪里?从一个电梯责任案例看传统 RAG 与 Agentic RAG
事情从一桩维修争议说起:
小区一户业主正在装修,装修工人曾经进入电梯搬运材料。之后物业发现电梯出现故障,维修报价几千元,于是要求业主承担维修费用。
业主认为:监控只能证明装修工人进入过电梯;没有拍到工人撞击或损坏电梯;这个电梯之前也出现过故障;维修报价也不能证明就是装修造成的。
那么,这个维修费用到底应该由谁承担?
它看起来只是在问“谁负责”,但真要回答,得同时判断几个不同的问题:
装修行为和损坏有没有因果关系?
监控能证明到什么程度?
电梯以前出现过故障,会不会影响这次认定?
维修报价单能不能直接当作责任依据?
责任不清时,费用又该怎么分摊?
为了看不同的检索方式能不能把这些分散依据找齐,我简单搭了一个电梯损坏责任咨询系统,有三种可切换的检索模式:纯 BM25、BM25+向量重排、Agentic 多轮检索。三种模式共用同一套知识库语料、同一个模型。模型用 GLM-4.6(开启思考模式),向量用 embedding-3。每道题三种模式各跑一遍,比较检索命中、回复里的信息点、token 消耗和耗时。
一、确保知识库里没有一篇现成答案
知识库是自建的模拟语料,而不是真实法规:11 个部分、68 个段落,包括 63 条模拟条例和 5 个处理案例。和开篇问题相关的部分有:
第二部分:装修管理 → 装修期间发生损坏,并不代表业主自动承担责任
第四部分:监控与证据 → 监控只能证明人员进入,不能单独证明实施了损坏
第五部分:电梯故障 → 电梯有历史故障时,应结合历史维修记录判断
第六部分:物业收费与费用承担 → 费用承担要看损坏原因和责任主体,报价单≠责任认定
第八部分:装修人员管理 → 施工人员登记、出入管理义务
第十部分:案例记录 → 五个真实形态的处理案例(监控缺失、报价争议等)
相关信息分散在不同部分,单看任何一段都不够下结论,这样才能测出检索方式的差异。
进行几轮问答后发现一个问题:三种模式的回复总是差不多。原因是语料里大部分条例和常识同向,比如“监控只能证明进入”本来就是常识;就算检索漏了,生成模型凭常识也能把话说圆。于是我在三个部分末尾各加了几条常识猜不出的“硬规定”,都带具体期限或程序:
第六十一条(监控与证据):公共区域视频监控资料的保存期限一般不少于三十日。发生设施损坏争议的,业主或物业服务人应当在争议发生之日起七日内提出监控调取申请,逾期资料可能因循环覆盖而无法恢复。
第六十二条(搬运与公共区域):搬运大件物品确需使用电梯的,物业服务人不得以保护电梯为由一律拒绝,但可以要求搬运方签署设施保护承诺书,并安排工作人员到场陪同。经陪同搬运仍发生损坏的,陪同记录可作为认定事实的资料。
第六十三条(装修人员管理):装修施工人员未按规定办理登记即进入小区的,物业服务人应当记录在案。此类人员造成公共设施损坏且无法查明具体责任人的,物业服务人因未履行出入管理义务,应当承担相应的补充责任。
问这三条规则相关的问题,可以快速从回复中看出是否检索到了。
二、先看 BM25
BM25 可以简单理解为关键词检索,流程如下:
用户问题 → BM25 → Top 5 段落 → 拼进提示词 → LLM → 答案
实现上没什么花哨的,中文分词用 Python 库 jieba 的搜索引擎模式,然后用标准的 BM25Okapi 打分:
def _tokenize(text):
return [t for t in jieba.cut_for_search(text.lower()) if t.strip()]
# 索引时把文档标题拼进段落文本,这样“监控与证据”这类只出现在标题里的主题词也能命中段落
bm25 = BM25Okapi([_tokenize(p.text + " " + p.doc_id) for p in paras])
scores = bm25.get_scores(_tokenize(question))
hits = sorted(zip(paras, scores), key=lambda x: x[1], reverse=True)[:5]
检索结果暴露出的问题
直接问“业主装修前需要办理什么手续?”,纯 BM25 模式能又快又准地拿到装修登记语料并回复。但是问开篇那道电梯争议题时,引用 top 5 如图所示,没有第四部分(监控与证据),也没有第五部分的第二十八条(电梯反复故障应结合历史维修记录判断)。问题里明明白白说“这个电梯之前也出现过故障”,但第二十八条的 BM25 全库排名是第 26,没挤进前五。
图 1:纯 BM25 模式的最终引用区。
当问题里的说法和知识库原文差别比较大时,BM25 很容易把真正相关的内容排到后面。比如这个问题:
“监控拍到装修的人进去,但是没拍到他碰坏东西,这能直接算他的责任吗?”
对应知识库原文是第十九条:“监控画面仅能证明人员出现在某一地点时,不宜直接据此认定该人员实施了造成设备损坏的具体行为”。问题里的“没拍到他碰坏东西”和原文的表述差别比较大,BM25 很难判断两者其实是在说同一件事。结果第十九条只排到了第 11 名,没能进入最终的 top 5。
三、加入向量重排,提升检索相关度
BM25 对关键词比较敏感,但用户的表达和知识库里的表述往往不一致。一个常见的做法是把两者结合起来:先用 BM25 做召回,再用向量相似度重新排序,让语义上更接近的内容排得更靠前。这里的“向量”,可以简单理解为把文本转换成一串数字,再通过余弦相似度判断两段文本在语义上有多接近。
流程如下:
用户问题 → BM25 召回 20 段 → embedding 重排 → Top 5 → LLM → 答案
所有语料的向量提前计算好并缓存起来,每次查询时只需要把用户的问题转换成向量,再用它来做相似度排序。重排的核心就几行 Python:
def rerank(self, embedder, query, hits, top_k):
q = embedder.embed([query])[0] # 每问只向量化问题本身
idx = [pos_of(h) for h in hits] # 候选段落的向量下标
sims = self.vectors[idx] @ q # 归一化后点积=余弦相似度
order = np.argsort(-sims)
return [hits[i] for i in order[:top_k]]
向量重排 仍然属于传统 RAG,只是把检索这一步做得更准确,整体流程依然是“一次检索 → 一次生成”。
它确实把相关内容找出来了
先看几个比较典型的例子。为了测试词面不一致的情况,我特意把问题换成了和知识库不同的说法,比如用“录像”代替“监控”,用“大衣柜”代替“大件物品”,用“没打招呼”代替“未登记”。
结果比较明显:向量重排把 BM25 原本排在第 11、18、8 名的三条内容,都提到了第 1 名。
| 题目(问法摘录) | 目标条文 BM25 排名 | 向量重排后 | 相似度 |
|---|---|---|---|
| “这录像他们能留多长时间?” | 第六十一条:第 11 | 第 1 | 0.585 |
| “物业说怕撞坏电梯不让走电梯,有这个权力吗?” | 第六十二条:第 18 | 第 1 | 0.531 |
| “师傅没跟物业打招呼就直接进来干活了” | 第六十三条:第 8 | 第 1 | 0.56 |
也就是说,这三条内容原本都在 BM25 的 top 5 之外,单靠 BM25 根本不会进入最终上下文;加入向量重排后,全部被提到了第一位。
检索结果的变化也会直接影响最终回答。拿“录像能保存多久”这个问题来看:
- 纯 BM25:回复说录像“一般在 15 天到 30 天左右”,但知识库里的“7 日内申请”没有被检索出来,因此回答里也没有这条依据。这个时间范围属于提示词允许的常识补充,并不算胡编,但和知识库中的具体规定对不上。
- 向量重排:回复变成“录像一般至少保存 30 天;……最好在 7 天内正式提出申请,否则可能被新录像覆盖丢失。”这里的两个数字都能对应到第六十一条。
从这个结果来看,向量重排的价值在于当用户的说法和知识库的表述不一致时,更容易把语义相关的内容提到前面。
图 2:纯 BM25 答监控期限题。回复只能给常识性区间;引用 5 段里没有第六十一条。
图 3:同一道题,向量重排模式。回复给出“至少 30 天 + 7 日内申请”;第六十一条被提到引用第 1 条。
一次检索,可能漏掉关键信息
传统 RAG 的一次检索就要决定最终交给 LLM 的全部资料。如果第一次没找到,后面就没有机会再补。回到开篇那道题。问题里明确提到“这个电梯之前也出现过故障”,对应的第二十八条“反复故障应结合历史维修记录判断”,BM25 排到了第 26 位,连 20 个候选都没进,向量重排也没有把它提上来。
四、Agentic RAG - 智能检索
Agentic RAG 可以先看看检索结果,再判断还缺什么,如果发现信息不完整,就继续检索。也就是说,向量重排 优化的是“一次检索怎么找得更准”,而 Agentic RAG 进一步解决的是“没找全之后,接下来还要搜什么”。
用户问题 → Agent
↓
第一次搜索 → 阅读结果 → 判断缺什么 → 第二次搜索 → 阅读结果
↓ ↓
够了 ←──────────── 判断缺口 ────────────────── 继续
↓
整合调研草稿 → LLM 撰写 → 答案
参考论文《AgenticRAG: Agentic Retrieval for Enterprise Knowledge Bases》的思路,实现了 4 个检索工具:
| 工具 | 作用 |
|---|---|
search |
BM25 检索,查找相关文档,返回段落摘要 |
find |
在指定文档中定位关键词和条文 |
open |
按行号窗口读取单个文档的完整内容 |
summarize |
压缩已经检索到的内容,控制上下文长度 |
整个流程最多允许调用 15 次工具。先由 Agent 负责检索和整理资料,再交给最终模型根据这些资料生成回复。
第一次检索后,继续往下找
拿“装修师傅没登记就进来施工,电梯出了问题,物业要求业主承担费用”这道题来看。Agent 第一轮先从装修人员管理、费用承担、装修管理责任等方向搜索,找到相关条文。看完之后,它发现责任划分的依据基本齐了,但类似情况的实际处理案例还没找到,于是换个方向继续搜索。
图 4:Agentic 模式的检索循环实录。第一轮 search、三次 find 之后,模型判断“关键条文都拿到了,再查查案例”,发起第二轮 search。
除了换搜索方向,它也会换一种说法继续找。比如“这录像他们能留多长时间?”这道题,Agent 会尝试“监控录像保存期限”“录像保留多长时间”等不同表达,最终找到对应的条文。
复杂问题,检索结果也会跟着扩展
开篇那道题的效果更明显。Agent 通过多轮检索和文档定位,最终找到了监控与证据、历史故障、责任认定等多个部分的依据。三种模式里,只有 Agentic RAG 把这些关键维度同时放进了上下文。纯 BM25 和向量重排的 top 5 中,监控与证据这一部分始终没有出现。
图 5:Agentic 模式的检索过程部分截图。
Agentic RAG 也会漏掉一些内容
有一道题问物业要求业主承担八千元维修费,需要提供什么依据。真正相关的内容在费用明细、维修依据这一部分,但 Agent 在检索时没有想到这个方向(只列了“举证责任/监控/装修/报价单”几个方向),最终也没找到对应条文。这说明 Agentic RAG 虽然可以根据检索结果继续调整方向,但它能不能找到正确的内容,仍然取决于 Agent 对当前问题的判断。
图 6:Agentic 模式漏检示例 — 未检索到费用明细 / 维修依据部分。
五、三种模式放在一起看
把前面的结果放在一起,差异其实比较清楚:
| 题目 | 纯 BM25 | 向量重排 | Agentic |
|---|---|---|---|
| 监控期限题 | 第六十一条 第 11,✗ | 重排第 1,✓ | ✓(换词 search 一次命中) |
| 拒绝用梯题 | 第六十二条 第 18,✗ | 重排第 1,✓ | ✓ |
| 未登记工人题 | 第六十三条 第 8,✗ | 重排第 1,✓ | ✓(还多补了一轮案例) |
这三道题里,向量重排和 Agentic 的最终结论基本一致,都能召回相关条例。真正拉开差距的是前面那些更复杂的情况:一个问题涉及多个维度时,Agentic 可以继续补搜;条文已经找到但还缺案例时,也可以继续往下找。
以“未登记工人题”为例,三种模式都判断物业不能把责任全部推给住户,但回答依据有所不同:
- 纯 BM25:认为电梯维修费用通常应由公共维修资金或全体业主承担。这个判断符合常识,但知识库里没有直接依据。
- 向量重排:找到了第六十三条,明确提到物业未尽到出入管理义务,应承担相应的补充责任。
- Agentic:同样找到了“补充责任”,并通过继续查看相关案例,把后续处理进一步落到了举证因果关系、说明物业管理过错,以及需要补充哪些材料。
所以,从这几次结果来看,向量重排解决的是“相关内容能不能更容易被找出来”,Agentic RAG 则进一步解决“找到之后,还缺什么、要不要继续找”。
Token 和耗时比较
三道埋针题的实测开销(GLM-4.6 思考模式,token 含思考过程):
| 题目 | 模式 | 耗时 | token |
|---|---|---|---|
| 监控期限题 | 纯 BM25 | 24.1s | 1,177 |
| 向量重排 | 26.6s | 1,294(+36 embed) | |
| Agentic | 91.5s | 14,973 | |
| 拒绝用梯题 | 纯 BM25 | 24.3s | 1,219 |
| 向量重排 | 20.5s | 1,155(+34 embed) | |
| Agentic | 76.0s | 10,105 | |
| 未登记工人题 | 纯 BM25 | 27.1s | 1,396 |
| 向量重排 | 31.0s | 1,527(+43 embed) | |
| Agentic | 121.3s | 19,176 |
Agentic 的 token 大约是普通模式的 8~14 倍,耗时 3~4.5 倍。多出来的成本,换来的是智能检索的能力,但不代表每道题的答案都会更好。
六、总结
BM25、向量重排和 Agentic RAG 并不是简单的“一级比一级好”。BM25 解决的是词面匹配,向量重排进一步解决了表达方式不同的问题,而 Agentic RAG 则让检索过程多了一层动态判断,可以根据当前问题和已经找到的信息调整检索方式。但这种能力也带来了更高的 token 和时间成本。所以实际选择时,没必要为了 Agentic 而 Agentic。知识库和问题比较简单时,传统 RAG 已经够用;只有当普通检索很难一次处理好问题时,Agentic RAG 才值得考虑。