☰
从RAG到Agent:企业知识助手架构演进与实战指南
2026/10/8 4:36:10 网站建设 项目流程

1. 从检索到决策:为什么知识助手必须走向 Agent

先说个背景。去年我接手了一个企业内部知识助手的项目,目标是让新员工在入职第一天就能自助查规章制度、查技术规范、查项目文档,减少到处问人的时间。第一版做得很典型,就是标准的 RAG 架构:把文档切块、向量化、存向量库,用户提问时做相似度检索,把命中的文本片段塞给大模型,让它组织答案。

这个方案上线后效果一开始还可以,大家觉得能自动回答一些问题已经很新鲜了。但用了两三周,问题就暴露出来了。比如说有人问“新入职的研发同事多久能申请到测试环境权限”,这个问题的答案分散在入职指引、权限管理办法、测试环境使用规范三个文档里,单靠向量检索很难把三个片段同时命中有机地组合起来。又比如有人追问“那如果数据库账号也要一起申请呢?”——多轮对话的上下文一旦变了问法,系统就懵了。再比如员工问“我上周提交的工单到哪一步了”,知识库里根本没有这个信息,RAG 再怎么检索也答不上来。

所以说,RAG 本身没有任何问题,它是知识问答的地基,但它有一个天然边界:只能回答知识库里面“有”的东西,做的是检索加总结的活,既不能自主决定去外部工具里拿数据,也不能在一个多步骤的诉求里自己规划先做什么再做什么。要解决这些问题,就必需从静态的“查文档”升级到动态的“干活”:模型不仅要理解提问,还要能拆解问题、选择工具、调用接口、看结果、再决定下一步——这就是从 RAG 走向 Agent 的核心动力。

对企业知识助手来说,Agent 的意义不是炫技,而是把它从一个“问答玩具”变成一个“能完成任务的数字员工”。本文我会从整体设计、核心架构、代码实现、避坑经验四个层面完整拆解这个过程。

2. 整体架构设计:先解决“为什么”,再谈“怎么做”

2.1 企业知识助手到底在解决什么需求

企业知识助手和通用聊天机器人最大的区别在于,它面对的是业务问题,不是闲聊。我把企业的真实诉求拆成了四类:

  • 事实查询类:员工找制度、找规范、找联系方式。这类问题答案基本确定,本质是“知识定位”。
  • 多跳推理类:答案是分散在多个文档里的,需要先查A再查B,再组合起来。这类问题考验检索和取舍。
  • 状态查询类:问工单到哪步了、审批到哪个节点了、预算还剩多少。这类信息根本不在静态文档库,而在业务系统里。
  • 操作执行类:帮忙创建一个工单、发起一个审批、查询一条客户记录。这类问题已经从“问”变成了“做”。

我在项目里把前两类归为 RAG 的主场,后两类则是 Agent 的菜。第一版只做了前两类,所以用户一开始觉得还行,等到有人开始问“工单呢”“能帮我提个单嘛”就露馅了。这其实是一个需求分层的问题:想做一个真正能用的企业知识助手,一开始就得意识到答案不只在文档里,还在系统里。

一个关键的设计决策是:不要一开始就搞一个敞开式的全能 Agent。全能的 Agent 意味着模型可以自由调用所有工具,听起来很酷,但企业内部这不是越灵活越好,而是越可控越好。我的做法是“问答为主、工具为辅”:Agent 核心里先有一个 RAG 检索器,这个是基础能力,再逐步挂上工单查询、权限申请、人员查找这类只有明确入参和出参的轻量工具,有一个算一个,不追求一步到位。

2.2 RAG 的瓶颈和 Agent 的应对方案

为什么一定要在 RAG 之上做 Agent?把 RAG 的瓶颈拉出来对照看就清楚了。

先说检索瓶颈。RAG 的召回质量高度依赖文本切块的方式。按固定长度切会把语义切成碎片,按标题结构切又在长文档上控制不住每个块的体积。企业文档还喜欢用表格、流程图、附件,这些都可能让向量召回失灵。我就遇到过一种情况,某份制度的表格列被切到两个块里,检索时每个块和问题的相似度都不高,结果就是明明文档里有答案,助手却说“抱歉,未检索到相关信息”。

再说编排瓶颈。经典 RAG 只有“检索一生成”两步,就像一个只会查字典的学生,你问他一道综合题,他就翻一页字典抄一句话。而企业里大量问题是需要拆解的。这种“先做一步,看结果,再决定下一步”的能力,就是 Agent 的规划特长。模型在每轮先“思考”这一步要执行什么动作——是检索、是调用工具、还是直接回答——相当于把一个人脑考虑问题的流程显式地跑了起来。

最后是记忆瓶颈。RAG 每次问答都是无状态的,上一轮用户说“那帮我申请一个”,下一轮如果缺少上下文衔接,助手就不知道“那”指代的是哪个权限。Agent 的架构里天然包含对话记忆模块,短期记忆管理多轮上下文,长期记忆沉淀用户的偏好和历史操作,企业在落地时非常看重这一点。我在网上看到很多朋友搜 Agent 记忆相关的话题,其实在企业场景里就是这两层,短期内解决多轮指代问题,长期内做到千人千面。

用一句话总结 RAG 和 Agent 的边界:RAG 是让模型“知道”,Agent 是让模型“做到”。知道靠检索,做到靠工具加循环。企业知识助手两者都需要,架构上自然就形成了 RAG 是其中一种工具、而 Agent 是调度者的格局。

2.3 RAG 知识库的分类与选型

说到知识库,很多团队上来就问该选哪个向量数据库。我倒是觉得先别急着选,先把知识库里存什么捋清楚。网上关于“RAG 知识库和结构知识库区分”的讨论很多,我把它们摊开讲。

  • 非结构化知识库:放的是 Word、PDF、Markdown 这类自由文本,用 embedding 模型向量化存入向量库。适合规章制度、技术规范、知识沉淀。这类知识库是 RAG 的默认形态,优点是灵活,缺点是召回准确性不稳定,答案有时候模棱两可。
  • 结构化知识库:放的是有明确 schema 的数据,比如员工信息表、库存表、工单记录,这些通常不放在向量库里,而是放在 SQL 数据库或者表的字段里。对这类数据的访问不是向量检索,而是写查询语句去取。企业里大量脏话其实都是结构化数据,纯靠 RAG 是答不好的。
  • 混合知识库:两个都上,再配一个路由层。用户在提问时先判断意图:查文档走向量检索,查数据走 SQL 查询。Agent 天然适合做这个路由,因为它能够根据用户输入决定调用哪个工具,这就把两类知识库用一套交互统一起来了。

至于一个常问的问题:“RAG 知识库能存储图片吗?”我的回答是:能,但通常不是直接存图片本身。向量库存的是语义向量,不是文件。企业落地时有三种做法:第一种是把图片转成文字描述再入库,比如 OCR 提取图中文字;第二种是用多模态 embedding 模型,把图片编码成向量直接参与相似度检索;第三种是只把图片作为文档附件存进对象存储,向量库里面存图片的路径和说明文字。多数场景最务实的是第一种加第三种,不太需要上多模态模型。

3. 核心实现:Agent 框架、工具调用与安全边界

3.1 Agent 的核心运行循环

讲完了设计,看代码。下面这个简化版的 Agent 循环是最小可运行形态,理解了它,市面上任何 Agent 框架的底层思想都逃不开这一段。

from typing import Callable, Dict, Any, List import json class SimpleAgent: def __init__(self, llm: Callable, tools: Dict[str, Callable], max_steps: int = 5): self.llm = llm self.tools = tools self.max_steps = max_steps def run(self, user_query: str, history: List[Dict[str, str]]) -> str: messages = history + [{"role": "user", "content": user_query}] for step in range(self.max_steps): response = self.llm(messages, tools=self.tools) # 模型决定动作 action = self.parse_action(response) if action["type"] == "answer": return action["content"] if action["type"] == "tool_call": tool_result = self.execute_tool(action["tool"], action["args"]) messages.append({ "role": "tool", "name": action["tool"], "content": json.dumps(tool_result, ensure_ascii=False) }) return "步骤太多,已自动终止,请换一种说法试试"

这个循环里有几个关键设计,单独说明一下。

第一是 max_steps,这是安全底线。没有它,Agent 可能在一个长任务里陷入循环调用浪费 token。经验值设为 5 到 8 之间,简单问答 1 到 2 步就够了,超过 5 步的问题多为用户意图太宽泛,不如让它停下来反问用户。

第二是 tools 的传参方式。现在主流 LLM 支持函数调用格式,模型会输出类似 call_tool 的参数,框架再去做映射。这时候参数校验特别重要,代码里 execute_tool 内部必须做参数类型和枚举值校验。我见过不止一次模型把数字参数传成字符串、把日期传成“昨天”这种相对值,导致接口报经典 400。

第三是消息数组的维护。把工具返回结果以 role 为 tool 的消息继续丢回给模型,模型才能基于真实结果进行下一轮思考。这不只是写法问题,而是“感知-决策-行动”循环的消息协议。

3.2 用工具组装业务能力

下面的代码演示两个最典型的企业工具:工单状态查询和信息检索。前者接结构化数据库,后者接向量知识库。这样在代码层面就能直接体现“RAG 是 Agent 的一个工具”这一思想。

# 工具1:查工单状态(接 MySQL 或内部业务接口) def query_ticket_status(ticket_no: str) -> Dict[str, Any]: if not re.match(r"^TKT\d{6}$", ticket_no): return {"success": False, "error": "单号格式不正确,应为TKT加6位数字"} # 真实项目中这里是查 MySQL 或者调用内部 HTTP API row = db.execute( "SELECT status, owner, update_time FROM ticket WHERE ticket_no=?", (ticket_no,) ).fetchone() if not row: return {"success": False, "error": "工单不存在"} return {"success": True, "status": row[0], "owner": row[1], "update_time": row[2]} # 工具2:检索知识库文档(RAG 的核心功能) def search_knowledge_base(query: str, top_k: int = 3) -> List[Dict[str, Any]]: embedding = embed_model.encode(query) hits = vector_store.search(embedding, top_k=top_k) return [ {"title": h.title, "content": h.chunk_text, "score": h.score} for h in hits ]

再看一段和这个 Agent 的对话示例,能直观感受从 RAG 到 Agent 的跃迁。

用户问:“我名下有个工单 TKT202611,现在到哪一步了?”

Agent 的思考过程是:

  • 这个问题不是知识库查询,用户需要的是实时业务系统数据;
  • 需要调用 query_ticket_status 工具;
  • 工具返回“已流转到直属主管审批,当前负责人张三”;
  • 生成最终答复:“你的工单 TKT202611 当前处于主管审批环节,负责人张三,更新时间今天上午 10:24。如果 3 天内未处理,可以在 OA 内发起催办。”

用户继续问:“公司对工单处理时限的规定是什么?”

Agent 的思考过程是:

  • 这个问题属于制度知识,从向量知识库检索即可;
  • 调用 search_knowledge_base 工具,命中《工单管理办法》的相关段落;
  • 生成答复,并附上制度出处。

用户最后问:“那如果张三一直不批,我可以直接升级吗?”

这轮 Agent 需要联合两个工具:先检索管理制度(发现升级规则是需要工单超过三个工作日未审批),再结合之前查到的工单状态(未超时),给出结论——“现在还不满足升级条件,建议先与审批人沟通”。这个回答如果只有 RAG 做不出来,因为系统不知道张三的审批到底进行了多久;如果只有工具调用,模型不知道升级的制度条件。两者结合才是完整企业知识助手的样子。

3.3 记忆、Skill 与框架选型

不少朋友在热搜里反复对比 LangChain、Dify、CrewAI 这堆框架,问到底哪个好。我把最近在不同项目里折腾这些框架的经验梳理一下,不一定适用于所有团队,但应该能帮你在选择时更清楚取舍。

先说记忆。无论用什么框架,都要搞清楚它说的“记忆”是会话级还是用户级。很多框架自带的 memory 只是把最近 N 轮对话拼到提示词里,这是短期记忆。但企业场景里更需要的是长期记忆:比如某个员工第一次说自己所在部门是“平台研发中心”,那么下次提问时 Agent 能自动带上这个上下文,不用重复解释。框架上没有现成能力的话,建议用一个简单的 key-value 存储,用户维度的记忆做进 prompt 的系统提示词里,比硬套框架效果好。

再说 Skill。这个概念今年很火,本质是把“工具+提示词+参数说明”打包成一个可复用的技能单元。我用下来觉得真正有价值的地方在“面向场景的组合复用”,比如“工单操作”这个 Skill 里面包含查状态、催办、创建子任务三个工具,Agent 一旦识别到用户是来处理工单的,就自动挂载这个 Skill,而不是让它面对几十个工具大海捞针。这样既压缩了决策空间,又提高了准确率。

框架选型方面,给一个比较朴素的判断标准:

  • LangChain 类偏底层,灵活度最高,但学习和调试成本也最高,适合团队里有较强模型功底的人,而且在多工具复杂链路中它给开发者更多的控制权。
  • Dify 类偏应用,可视化编排和测试工具友好,适合快速做 Demo 和给业务人员做 prompt 调优。但是在需要深度定制和复杂状态管理的场景,它反而会成为一种约束。如果你看到团队里大量复制现有节点模板,说明项目已经长大,Dify 可能就不是最优解。
  • CrewAI 类偏角色协作,适合做多 Agent 的任务拆解,不过说实话,企业内部多数知识助手的任务复杂度还远没到需要多 Agent 协调的程度,单 Agent 加工具就足够了。多 Agent 的通讯成本、调试成本都要高一个量级,用不好会出现 Agent 之间互相甩锅。

站在个人经验上说,我的建议是:不要一开始就绑定大而全的框架,先自己写好一个简单的循环,比如我上面这份代码,把知识库工具和业务工具各接一个进去,端到端跑通。再让业务同学试用一两个星期收集问题,等到你明確知道缺什么,再去用框架补什么,不然很容易出现被框架拖着的被动局面。

3.4 安全边界与权限管控

企业里的 Agent 和拿着玩的那种个人助手,安全级别完全不是一个概念。Agent 一旦接上工具,它就从“语言模型”变成了“执行者”,安全问题怎么强调都不过分。

我把需要注意的点分成三层:

  • 第一层是权限最小化。给 Agent 的每一个工具都要单独授权,不要图省事给一个万能数据库账号。比如工单查询工具只能查本人相关工单,系统提示词之外,还要在工具内部做硬校验。因为提示词是可注入的,模型可能会被诱导“忽略之前的指令”,但工具里的代码永远不会被诱导——当用户输入试图越权时,工具直接拒绝。
  • 第二层是写操作确认。涉及创建、修改、删除这类的工具,必须设置 human-in-the-loop 环节。具体做法是 Agent 先把操作意图输出给用户确认,用户明确回复“确认”,才真正执行。不要完全信任 AI 在一条链上自作主张跑完所有写操作。
  • 第三层是输入输出过滤。用户输入里可能包含恶意指令,模型输出里可能包含隐藏提示。企业内部建议至少做一次敏感信息扫描,对身份证、手机号、银行卡做脱敏处理再入库。

关于网上很多人担心的“Agent 安全”问题,我实际的体会是:单点防护不如全局管控。模型层的 system prompt 可以做第一道防线,工具层的参数校验和权限校验做第二道,流程层的“高风险操作必须人工兜底”做第三道。这三道都立住了,Agent 就没有想象中那么可怕。

4. 实操中的坑:问题排查与避坑实录

4.1 高频问题与对应解法

这个部分我想直接放一个速查表,把我在几家公司项目里真实踩过的坑罗列出来。每个问题都是实际发生过,解法也是验证过的。

问题现象根因解决方案
多轮对话中用户在第三轮问“那审批流程呢”,结果一塌糊涂模型没有记住前两轮的“办证”主题,上下文被截断或拼接错序对消息列表做截断时要保留首轮系统指令和用户目标描述,可引入消息摘要压缩过长的历史
工具调用时把数字参数传成文本函数描述里类型约束不严,模型自由发挥在工具 JSON Schema 中强制类型并附正则示例;更稳妥的是在代码层做二次断言并返回友好错误
检索结果里混入大量无关段落,但相似度分数还很高embedding 模型对短实体型 query 区分度不足增加一个重排序层,比如用 cross-encoder 对 Top20 重排,截断前半部分
用户问“上周的权限申请”但知识库里查“上周”语义为空知识库没有做时间词归一化引入文档更新时间和会话时间作为过滤条件,涉及“最近”“上月”先做时间归一化解析
Agent 连续调用工具三次以上,用户等得不耐烦步骤多、推理慢、工具响应慢对工具响应做缓存,同类参数直接走缓存;给用户实时的“正在查询工单系统”过程提示,体验差别极大

4.2 一个精准定位检索偏差的实战案例

展开讲一个我耗时最久的排障经历。现象是所有“怎么申请测试环境”相关问题,回答总是漏掉关键步骤,比如漏了“必须由直属主管先在 OA 上提交资源申请”这一步。起初我以为是文档内容不完整,把制度文件翻了个底朝天,发现内容其实都在。

后来逐步排查发现两个问题叠加。第一个问题是切块方式把包含申请流程的表格单独切成了一个块,表格文本在向量化时丢了行列表结构的语义,模型看到的是一堆散开的单元格字符串。第二个问题是召回的 Top3 里有两段来自同一个长规程,内容高度相似,把表格结果挤到了第四位。

修复方案是三层同步调整。第一层把表格类内容转成自然语言描述后入库,而不是直接向量化原始表格;第二层在检索阶段做 MMR 最大边际相关去重,避免 TopN 被相似段落占满;第三层加了重排。最终这个话题的答案准确率从不到六成提升到九成以上,效果非常明显。

4.3 成本控制与性能优化心得

Agent 比 RAG 贵,这是事实。RAG 一次问答通常一次模型调用,Agent 可能要三五次。我总结了一些经验来平衡成本和效果。

方法是给问题做个路由分类,用一个小模型判断意图,让简单问题走普通 RAG 甚至直接命中高置信度文档,让复杂问题才付高昂的 Agent 推理成本。这个路由看似多花了一次调用,实际上省掉的是 Agent 反复无效检索和不停思考的 token 费,从账面上看完全是划算的。

另一个心得是为同一类高频问题做“确定性问题即答合集”。知识库里有大量类似“会议室 Wi-Fi 密码是什么”“打印机型号”这样的确定性问答,根本不需要向量检索,命中精确规则直接返回。一个简单的关键词到答案映射表或别名表就能覆盖很多高频问题。知识助手百分之八十的问答,可能都是这类简单问题,这种直接答的方式对用户体验提升很大。

5. 从单 Agent 到多 Agent 的扩展方向

项目跑通以后,团队自然会思考一个问题:是不是该上多 Agent 了?我的建议是在确认以下条件之前,不要动这个念头:

  • 已经存在至少三个差异明显的专业角色,各自维护着自己独立的工具集和知识库;
  • 用户的任务经常需要跨越这些专业角色协作完成,比如“帮我查一下这个项目的延期风险和预算超支情况”既涉及项目管理工具又涉及财务系统;
  • 单个 Agent 的提示词已经变得难以维护,经常为了顾全某个子领域而影响主线任务。

满足这三点之后再考虑多 Agent,否则就是自寻烦恼。多 Agent 架构会引入新的问题:Agent 之间的同步通信、任务依赖编排、失败重试传播等。我见过有人为了演示效果硬上三四个 Agent 的架构,最终效果不升反降的问题常出在“一个 Agent 的判断结果偏差,后面全都跟着错”。

真要上多 Agent 的话,我比较推荐“主编排 + 子专家”的星型架构,而不是 Agent 互相聊天的网状架构。星型架构有一个中心调度 Agent 负责接收用户请求、拆分任务、分发给专家 Agent 并汇总结果。这样的好处是可控性和可观测性都强,每个子 Agent 的问题可以单独排查,不至于乱成一锅粥。网状架构下 Agent 之间的对话链路难以跟踪,排障成本太高,企业场景慎用。

另外一个正向演进路径是逐步把 Agent 能力和企业流程体系打通。比如把知识助手接入 IM 机器人工单系统,让它在钉钉或者企业微信里可以直接被对话召唤,把查询到的信息一键转成工单。这已经超出了纯技术的范围,但确实是企业知识助手最终落地的常见形态。

6. 收个尾:我自己的一些实际操作体会

如果再让我从零做一遍这个项目,我会把优先级定成这样:先保证 RAG 的检索质量,再接入一个查询类工具,最后才上需要写操作的工具。每一步都跑稳了再走下一步,不要一上来就整一个大而全的 Agent,那多半会翻车。

个人实际体会最深的一点是,Prompt 工程在 Agent 项目里的作用被大大低估了。很多人花大量精力调模型、调工具,却忽略了一件事:Agent 的“思考”过程本质上是模型在自我打分,你必须在提示词里告诉它什么时候该动用工具,什么时候不该动。我的做法是在 system prompt 里写明工具使用的判定条件和输出格式,模型的行为稳定性明显提升。

还有一个小建议:重视日志和可观测性。Agent 项目比传统接口多了一个“推理轨迹”,排查问题的时候如果看不到模型每一步在想什么调用了什么拿到什么结果,就只能靠瞎猜。我后来强制要求所有 Agent 调用都输出一份 JSON 日志,包含每一步的动作、入参、出参、耗时,调试效率直接翻倍。

从 RAG 到 Agent,不是一次替换,而是一次能力边界的扩展。先把检索的地基打好,再把工具的手脚接上,让模型在需要的时候自己决定用哪条路。这个演进路径,是当前企业落地 AI 应用最踏实、回报也最直接的一条路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询