Agent系列(七):知识库集成——Agent 调用 RAG 的正确姿势

作者:冬奇Lab日期:2026/5/28

RAG 遇上 Agent,不只是"给 LLM 接个搜索框"

很多人第一次接触 RAG,都是这个用法:用户问一个问题 → 检索知识库 → 把结果塞进 Prompt → LLM 生成回答。

这个模式叫 Pipeline RAG。它有效,但有个根本问题——它不思考

Pipeline RAG 对每一个问题都执行检索,不管这个问题是问"WonderBot 订阅多少钱"(确实需要查知识库),还是问"Python 列表怎么求平均值"(LLM 自己就知道)。它像一个只会一招的工人:不管手头的活是什么,都先去仓库跑一趟。

Agentic RAG 解决的是这个问题:让 Agent 自己判断何时检索、检索什么、检索完是否够用

本篇聚焦三个核心能力:

  1. 检索决策:这个问题需要查知识库吗?
  2. 多知识库路由:需要查,但查哪一个?
  3. 质量门控 + Fallback:查完了,够用吗?不够怎么办?

Pipeline RAG vs Agentic RAG:架构层面的本质区别

先看两种架构的对比:

1Pipeline RAG(每次必检索):
2  用户问题
3    
4  向量检索(无论问题类型)
5    
6  结果注入 Prompt
7    
8  LLM 生成
9
10Agentic RAG(智能决策):
11  用户问题
12    
13  [决策节点] 这个问题需要检索吗?
14    ├─ 不需要  LLM 直接回答(常识/数学/通用编程)
15    └─ 需要    查哪个知识库?
16                  ├─ product_kb(产品功能/价格)
17                  ├─ ops_kb(部署/运维/监控)
18                  └─ faq_kb(账号/退款/发票)
19                        
20                  检索质量够用吗?
21                    ├─   LLM 生成
22                    └─ 不够  重写查询  重试(最多 2 次)→ LLM 生成
23

关键差别:LLM 是控制中心,不是下游的文本生成器


Demo 1: Pipeline RAG vs Agentic RAG 核心差异

用 5 个问题对比两种模式:3 个需要查知识库,2 个不需要(通用常识、数学计算)。

Pipeline RAG 实现

1def pipeline_rag(question: str) -> dict:
2    """Pipeline RAG:检索→注入→生成,永远不跳过检索步骤"""
3    docs = unified_retriever.invoke(question)
4    context = "\n".join(d.page_content for d in docs)
5    answer = _ask(
6        f"根据以下参考资料回答问题,若资料无关请基于资料内容作答。\n参考:{context}",
7        question,
8    )
9    return {"answer": answer, "retrieved": True, "docs": len(docs)}
10

注意那个 若资料无关请基于资料内容作答——当知识库内容和问题完全不相关时,这个 Prompt 会让 LLM 产生奇怪的行为:要么强行把不相关内容和答案混在一起,要么输出"根据参考资料,无法回答您的问题"。

Agentic RAG 实现

1def agentic_rag(question: str) -> dict:
2    """Agentic RAG:先决策,再(选择性)检索"""
3    # Step 1:Agent 决定是否需要检索
4    decision = _ask(
5        "判断以下问题是否需要查询知识库才能回答。\n"
6        "需要检索的场景:产品定价/功能、运维操作、用户服务政策\n"
7        "不需要检索的场景:常识问题、数学计算、通用编程知识\n"
8        "只输出 yes  no",
9        f"问题:{question}",
10    ).strip().lower()
11
12    if "yes" not in decision:
13        answer = _ask("你是一个知识丰富的助手,请直接回答问题。", question)
14        return {"answer": answer, "retrieved": False, "docs": 0}
15    else:
16        docs = unified_retriever.invoke(question)
17        context = "\n".join(d.page_content for d in docs)
18        answer = _ask(f"根据以下参考资料回答问题。\n参考:{context}", question)
19        return {"answer": answer, "retrieved": True, "docs": len(docs)}
20

实测对比结果

针对 5 个问题的实际运行:

1问题类型     | Pipeline 检索  | Agentic 检索  | 问题
2─────────────────────────────────────────────────────────────────
3产品功能     |   (3)      |   (3)     | WonderBot Pro 基础版每月能调用多少次 API?
4运维操作     |   (3)      |   (3)     | 部署 WonderBot 服务最低需要多少内存?
5用户服务     |   (3)      |   (3)     | 购买 30 天后还能退款吗?
6通用常识     |   (3)      |   跳过      | Python 中如何计算列表的平均值?
7数学计算     |   (3)      |   跳过      | 1024 除以 32 等于多少?
8

Pipeline RAG 对全部 5 个问题都执行了检索(包括"1024 除以 32 等于多少"这种拿到知识库内容也毫无帮助的问题)。Agentic RAG 正确识别了通用常识和数学题,跳过了检索。

不是所有问题都值得"跑一趟仓库"。


Demo 2: 多知识库路由

真实的企业场景通常有多个知识库:产品文档、运维手册、用户 FAQ……不同问题需要查不同的知识库。

三个知识库

1PRODUCT_DOCS = [
2    Document(page_content="WonderBot Pro 订阅价格:基础版 ¥99/月,专业版 ¥299/月,企业版按需报价。"),
3    Document(page_content="API 调用限额:基础版 10K次/月,专业版 100K次/月,超出按 ¥0.01/次计费。"),
4    Document(page_content="WonderBot Pro 支持 GPT-4、Claude 3、Gemini Pro、GLM-4,可在控制台自由切换。"),
5    Document(page_content="数据安全:对话数据存储在中国区服务器,符合等保三级认证,支持数据加密导出。"),
6]
7
8OPS_DOCS = [
9    Document(page_content="部署要求:Docker 20+,内存  8GB,CPU  4核,推荐 docker-compose up --build。"),
10    Document(page_content="故障排查:服务无响应→检查 docker ps;API 超时→检查 LLM 连通性;内存溢出→调高内存 limit。"),
11    Document(page_content="备份策略:每日凌晨 2 点自动备份,保留 30 天,用 restore.sh 脚本恢复。"),
12    Document(page_content="监控告警:CPU > 80% 持续 5 分钟告警;内存 > 90% 告警;API 错误率 > 5% 告警。"),
13]
14
15FAQ_DOCS = [
16    Document(page_content="重置密码:登录页点击'忘记密码'→输入注册邮箱→查收重置邮件→设置新密码。"),
17    Document(page_content="退款政策:7 天内全额退款,7-30 天按比例,30 天后不退。"),
18    Document(page_content="申请发票:在'账单中心'点击'申请发票',3-5 工作日开出电子发票并发送邮箱。"),
19    Document(page_content="API Key 管理:在'开发者设置'中创建/撤销,每账号最多 5 个。"),
20]
21

LangGraph 路由实现

1class RoutingState(TypedDict):
2    question:  str
3    kb_choice: str     # "product" | "ops" | "faq"
4    context:   str
5    answer:    str
6    path:      list
7
8def route_node(state: RoutingState) -> RoutingState:
9    """Step 1:LLM 判断应查哪个知识库"""
10    decision = _ask(
11        "根据问题内容,判断应该查询哪个知识库,只输出知识库名称:\n"
12        "product - 涉及产品功能、价格、技术规格、支持的模型\n"
13        "ops     - 涉及部署、运维、故障排查、监控告警、备份恢复\n"
14        "faq     - 涉及账号密码、退款、发票、API Key 等用户服务",
15        f"问题:{state['question']}",
16    ).strip().lower()
17    ...
18

图结构非常简单:

1route  retrieve  generate
2

route_node 的输出决定 retrieve_node 使用哪个 retriever。

实测路由准确率

针对 6 个问题(每个知识库 2 个),真实运行结果:

1预期KB         |  实际路由  |  匹配  | 问题
2─────────────────────────────────────────────────────────────
3应查 product   |  product  |      | 专业版订阅每月多少钱?支持哪些大模型?
4应查 product   |  ops      |      | 数据存储在哪里,符合什么安全认证?
5应查 ops       |  ops      |      | 服务 API 超时了怎么排查?
6应查 ops       |  ops      |      | 监控到 CPU 超过 80% 会触发什么告警?
7应查 faq       |  faq      |      | 我买了 15 天,还能退款多少?
8应查 faq       |  ops      |      | 怎么给公司开增值税发票?
9
10路由准确率:4/6 = 67%
11

两个错误值得关注:

  • "数据存储在哪里" → 路由到 ops(应该是 product):LLM 认为"数据存储"更偏向运维范畴,这种歧义在单句路由判断中容易出错
  • "怎么给公司开增值税发票" → 路由到 ops(应该是 faq):发票里有"公司",LLM 把它跟企业运维关联了

这 67% 的准确率说明了一个重要问题:用 LLM 做路由判断是可行的,但对歧义问题需要额外增强。生产中常见的改进手段:

1# 改进方案:在路由 Prompt 中加入更多示例
2route_prompt = """
3判断应该查询哪个知识库:
4product:产品价格/功能/模型支持/数据安全认证
5ops:服务部署/故障排查/监控/备份恢复
6faq:账号密码/退款/发票/API Key/用户账单
7
8示例:
9"支持哪些大模型"  product
10"开发票"  faq          发票类问题属于用户服务
11"数据存储安全"  product   数据安全是产品特性
12
13问题:{question}
14"""
15

完整示例的实际回答

问题:"API 超时了怎么排查?" → 路由到 ops,检索后生成:

1路由到:ops_kb
2回答:API 超时了,可以按照以下步骤排查:
31. 检查 LLM(语言学习模型)的连通性,确保网络连接正常。
42. 查看 Docker 的运行状态,使用 docker ps 命令检查服务是否正常。
53. 如果是内存溢出导致的,可以尝试调高 Docker 的内存限制。
6

知识库命中正确,回答直接引用了 ops 文档中的排查步骤。


Demo 3: 质量门控 + 查询重写 Fallback

当检索结果质量不足时,与其直接用低质量内容生成,不如先修改问题再重试

核心思路

1retrieve  evaluate_quality
2                 ├─ 质量  0.6  generate
3                 └─ 质量 < 0.6 且重试次数 < 2  rewrite_query  retrieve(重新循环)
4

LangGraph 实现

1QUALITY_THRESHOLD = 0.6
2MAX_RETRIES = 2
3
4class QualityGateState(TypedDict):
5    question:      str
6    rewritten_q:   str    # 重写后的查询(初始等于原始问题)
7    context:       str
8    quality_score: float
9    answer:        str
10    attempts:      int
11    path:          list
12
13def qg_evaluate_node(state: QualityGateState) -> QualityGateState:
14    """让 LLM 评估检索内容与问题的相关度"""
15    score = _score_quality(state["question"], state["context"])
16    return {**state, "quality_score": score, ...}
17
18def qg_rewrite_node(state: QualityGateState) -> QualityGateState:
19    """把模糊问题改写为更具体的检索查询"""
20    rewritten = _ask(
21        "将以下模糊问题改写为更具体的检索查询,保留原意但增加关键词,只输出改写后的问题:",
22        state["question"],
23    ).strip()
24    return {**state, "rewritten_q": rewritten, "attempts": state["attempts"] + 1}
25
26def should_rewrite(state: QualityGateState) -> str:
27    if state["quality_score"] >= QUALITY_THRESHOLD:
28        return "generate"           # 质量够了,直接生成
29    if state["attempts"] >= MAX_RETRIES:
30        return "generate"           # 重试次数到上限,兜底生成
31    return "rewrite"                # 质量不够,重写查询
32

实测结果

用三个极度模糊的问题测试:

1原始问题            | 重试次数 |  最终质量 | 执行路径
2─────────────────────────────────────────────────────────────────────
3价钱怎么样           |    2    |   0.00   | retrieve  evaluate(0.50)  rewrite  retrieve  evaluate(0.00)  rewrite  retrieve  evaluate(0.00)  generate
4出问题了怎么办         |    2    |   0.50   | retrieve  evaluate(0.50)  rewrite  retrieve  evaluate(0.50)  rewrite  retrieve  evaluate(0.50)  generate
5钱的事             |    2    |   0.50   | retrieve  evaluate(0.50)  rewrite  retrieve  evaluate(0.50)  rewrite  retrieve  evaluate(0.50)  generate
6

详细追踪"价钱怎么样"这个问题:

1原始问题:   "价钱怎么样"
2   retrieve  检索到备份/部署/退款相关内容(无关)
3   evaluate  质量分 0.50(LLM 认为略微相关)
4   rewrite   "商品价格范围查询"(重写后反而更泛化了)
5   retrieve  检索结果质量下降
6   evaluate  质量分 0.00
7   rewrite   "商品价格范围查询"(重写无进展)
8   generate  生成兜底回答
9
10最终回答:根据您提供的参考资料,关于价格的信息并不包含在内。
11          如果您需要了解价格信息,建议直接联系服务提供商或访问官方网站。
12

这个结果很有教学价值:查询重写不是万能的。"价钱怎么样"这类极度模糊的问题,LLM 重写后给出"商品价格范围查询",反而丢失了特定产品的上下文,质量没有提升。

更好的处理方式是在质量评估之前加一个意图澄清环节:

1# 改进方案:质量持续低时,要求用户补充上下文
2if state["attempts"] >= MAX_RETRIES and state["quality_score"] < 0.3:
3    return "clarify"   # 新增节点:向用户追问"您想了解哪个产品/服务的价格?"
4

这就是 Agentic RAG 的真实挑战——检索质量低不一定是检索策略的问题,有时是问题本身信息不足


Agentic RAG 设计清单

设计一套 Agentic RAG 系统需要考虑的核心决策点:

检索决策层

  • 明确什么类型的问题需要检索(业务知识 vs 通用知识)
  • 给 LLM 的判断 Prompt 中提供具体的边界示例,减少歧义
  • 设置 skip_retrieval 类型:纯数学/代码语法/常识问题直接走 LLM

知识库路由层

  • 为每个知识库写清晰的描述(类型 + 典型问题 + 边界案例)
  • 路由准确率低于 80% 时,考虑加 Few-shot 示例或使用专用分类模型
  • 支持跨知识库检索(当问题涉及多个领域时,合并结果)

质量门控层

  • 设置合理的阈值(0.6 是合理起点,可根据业务调整)
  • 限制最大重试次数(建议 2 次,避免无限循环)
  • 记录每次重写的查询和质量分(用于后续数据优化)
  • 质量持续低时触发澄清(向用户追问),而不是硬生成

生产优化

  • 在 LangGraph 的路由 Prompt 中加入领域示例
  • 考虑用专门的 embedding 模型 + BM25 混合检索提升基础质量
  • 记录哪些问题被跳过检索、哪些触发了重写,用于评估和迭代

本篇小结

几个核心结论:

  1. Pipeline RAG 的问题不是检索,是不思考:对所有问题一刀切地执行检索,既浪费资源,又可能让不相关内容干扰回答
  2. Agentic RAG 的本质是 LLM 做调度:检索、路由、评估都是 LLM 的决策,不是固定流程
  3. 多知识库路由的真实准确率不完美:67% 的路由准确率说明用一句 Prompt 做路由有限制,生产中需要 Few-shot 或专用分类模型加持
  4. 质量门控 + 重写不是银弹:极度模糊的问题,重写有时会让查询更泛化,根本解法是追问用户
  5. LangGraph 的图结构让 Agentic RAG 易于扩展:加新知识库只需加一个节点,改路由 Prompt,不需要改整体架构

下一篇:上下文工程——Token 预算管理、动态上下文组装、以及如何在 128K 上下文窗口里把每一个 Token 用在刀刃上。


参考资料


欢迎来我的个人主页找到更多有用的知识和有趣的产品


Agent系列(七):知识库集成——Agent 调用 RAG 的正确姿势》 是转载文章,点击查看原文


相关推荐


计算机毕业设计:Python出行数据智能分析与预测平台 Django框架 可视化 数据分析 PyEcharts 交通 深度学习(建议收藏)✅
源码之屋2026/5/5

博主介绍:✌全网粉丝10W+,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久,选择我们就是选择放心、选择安心毕业✌ > 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与我联系了。🍅 点击查看作者主页,了解更多项目! 🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。🍅 1、毕业设计:2026年计算机专业毕业设计选题汇总(建议收藏)✅ 2、大数据毕业


OceanBase学习
摇曳的精灵2026/4/26

OceanBase(OB)是蚂蚁集团完全自研的原生分布式关系型数据库,2010年诞生,支撑支付宝/双11核心交易,金融级高可用,同时兼容 MySQL 与 Oracle 两种模式,是国产分布式数据库的标杆。 一、核心定位(一句话懂差异) Oracle:集中式商用数据库,闭源,高端硬件,强事务,金融传统核心。达梦DM8:集中式(可选共享存储集群),Oracle 高度兼容,政务/国企信创首选。OceanBase:原生分布式,MySQL/Oracle 双兼容,普通x86服务器,水平扩展,金融互联网核心


深度解析 Rollup 配置与 Vite 生产构建流程
发现一只大呆瓜2026/4/17

前言 为什么 Vite 在生产环境不使用 ESBuild 而是选择 Rollup?为什么 Rollup 打包出来的代码比 Webpack 更纯粹?本文将带你深入 Rollup 的核心配置,并拆解 Vite 是如何驱动 Rollup 完成生产环境构建的。 一、 Rollup 核心配置:构建系统的“方向盘” 1. 核心概念 Rollup 是 Vite 生产环境下的底层打包工具,专注于 ES 模块的打包优化。 注意:在 Vite 项目中,不需要单独编写rollup.config.js文件,所有 Rol


理解PDF的设计哲学,省下一半的编辑时间
databook2026/4/9

复制文字带换行?改一个字排版全乱?同一个文件到处显示一致? 我以前也觉得是PDF软件太垃圾。后来想通了:不是软件不行,是我一直把它用错了地方。 我被PDF坑过太多次了 从论文里复制一段话,贴出来全是"-"和莫名其妙的换行 想改一个错别字,后面的内容全跑了,调坐标调到想砸电脑 给客户发的报价单,在他电脑上竟然一模一样…… 最后一条其实不是坑,是惊喜。但前两条,真的烦。 后来我才搞明白一件事: PDF从一开始就不是让你编辑的。 它更像一张"数字相纸"——只管长啥样,不管你怎么改。 把它当电子纸


我用AI做了一个48秒的真人精品漫剧,不难也不贵
华洛2026/4/1

前言 最近花了点时间用AI做了一个48秒的真人精品漫剧,只能说在AI时代各行各业都被冲击的体无完肤... 制作方法 工具和平台 图片生成用到的模型是liblib、seedance2.0 视频生成用到的模型是可灵Omni、即梦图片5.0 平台用的是liblib、即梦 剪辑工具用到的是剪映 说一下这套工具的选择和搭配原因: 即梦作为当前生图、生视频第一梯队,一开始是我的首选,但是排队太久和真人验证确实令人心烦,后续逐渐演变为生图和补充的主力,不用来生视频了; 最终视频生成模型就选用了Omni,不过可


从 OpenClaw 到 Android:Harness Engineering 是怎么让 Agent 变得可用的
陆业聪2026/3/24

最近看到一张图,把 Agent 工程的演化路线列了出来:ReAct(2023初)→ Plan & Execute(2023末)→ Multi-Agent(2024)→ Context Engineering(2025)→ Harness Engineering(2025+)。配了一句话: "名词换了五六轮,核心问题从未改变。Agent 工程师的核心能力:在不确定性上构建确定性。" 这句话我反复想了一下,觉得说到点子上了。这篇文章不打算再讲 Harness Engineering 的定义,而是


基于 AST 与 Proxy沙箱 的局部代码热验证
July_lly2026/3/16

前言 在真实开发中系统中,我们常常会做/需要做一些代码运行或者检测工作。但是全量的代码运行消耗的时间是漫长的。那么我们有没有办法能够只处理我们修改的部分呢?答案是肯定的。 下面将验证介绍一种结合 AST (抽象语法树) 与 沙箱技术 的方案,局部代码热验证。 具体重服务mock代码会放在文章末尾 整体 -> 局部 我们切换一个方向:过去我们总是使用整体运行完拿到export的内容。在一些情况下,不论是 build 构建还是 dev 开发,我们通常都是全量编译打包一次。当然我们可以让他执行两次(比


GPT-5.4 API 上线了,在openClaw龙虾中试试
程序员陆通2026/3/7

突破性的前沿模型,现已全面开放 OpenAI 最新发布的 GPT-5.4 模型现已正式上线 WellAPI 平台!作为 OpenAI 迄今为止最强大的通用模型,GPT-5.4 在推理能力、编程水平和专业文档处理方面实现了质的飞跃,专为复杂专业工作场景打造 。 GPT-5.4 核心特性解析 1. 原生计算机操作能力 GPT-5.4 是 OpenAI 首个具备原生计算机使用能力的通用模型,这标志着 AI 代理(Agent)技术的重大突破。模型能够直接与计算机系统交互,为开发者和智能代理应用开辟了全新


实测UU远程云电脑:堪称游戏党专属“性能王”,游戏全程流畅,好用到出圈
啊阿狸不会拉杆2026/2/27

前言:本地设备性能拉胯,想畅玩《崩坏星穹铁道》《CSGO2》《鸣潮》《原神》?不用花大价钱组装高配电脑,UU远程云电脑直接帮你解决痛点!作为网易旗下主打游戏场景的云电脑工具,它凭借三款不同显卡机型、低延迟优化,稳居云电脑排行榜前列,堪称游戏党专属“性能王”,实测四款热门游戏全程流畅,好用到出圈。         UU远程云电脑核心优势的是精准适配游戏需求,目前推出三款显卡机型——GTX 1660S(入门款)、RTX 3660(主流款)、RTX 4070Ti/5070(旗舰款),按需选择灵活


IoT 平台可编程化:基于 Pydantic Monty 构建工业级智能自动化链路
Lupino2026/2/19

在万物互联的下半场,设备间的简单联动已无法支撑复杂的工业与商业场景。为了打破“配置化逻辑”的瓶颈,我们正式集成了 Pydantic Monty 运行时环境。这一演进赋予了开发者直接在云端编写 Python 脚本的能力,实现了从“被动连接”到“确定性逻辑自主”的跨越。 1. 核心底座:为什么是 Pydantic Monty? 我们选择了由 Pydantic 团队推出的 Monty 作为脚本引擎。它不仅是 Python 的子集,更是为高性能嵌入式场景量身定制的方案: 轻量级沙箱:相比庞大的标准 P

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读