☰
AI Agent架构核心模块拆解:大模型、记忆、RAG与工具调用落地指南
2026/10/23 3:30:09 网站建设 项目流程

做 Agent 的人应该都遇到过这个场景:大模型单聊的时候有问必答,一旦放进真实业务里,就像一位没有手、没有笔记本、也没有图书馆借书卡的专家,只能凭记忆里的那点东西硬撑。问它“帮我拉一下上季度的渠道数据”,它要么道歉说自己没有访问权限,要么一本正经地编一串数字。所谓 AI Agent,本质上是把这些缺失的“器官”——大模型的推理能力、记忆系统、知识检索(RAG)、以及工具调用——组装起来,让模型从“能说”变成“能做事”。

这篇文章我不打算聊什么宏大概念,也不会画那些看了更糊涂的架构图。我会把 Agent 架构里最常见的四个核心模块拆开讲:大模型、记忆、RAG、工具调用,它们各自负责什么、内部怎么做、互相之间怎么协同。内容以落地为主,适合正在做 Agent 应用开发的工程师、准备把大模型接入业务的产品和技术负责人,也适合那些对大模型有一定了解、想搞明白“Agent 到底是怎么组装起来”的爱好者。全程有实操思路、有参数参考、有踩坑记录,看完你至少能徒手设计出一个可运行的 Agent 原型。

1. 先想清楚:Agent 到底在解决什么问题

1.1 大模型是大脑,Agent 才是完整的人

很多人会把“大模型”和“Agent”混为一谈,这是第一个思维误区。大模型本质上是一个概率生成器:给它一段输入,它预测下一段最合理的输出。它可以在对话里展示出惊人的理解力,但这份理解力是“无根”的——没有状态,不能记住昨天的对话;没有外部知识源,训练截止日之后的世界对它来说是一片空白;没有执行能力,它无法真的去查询数据库、调用接口或者操作软件。

Agent 做的事情,就是给这个“大脑”配上记忆、配上知识库、配上可以操作外部世界的工具。我习惯用一个类比:大模型像一个只有大脑皮层的专家,知识面广、推理能力强,但他没有手、没有眼睛、也没有笔记本。Agent 是给这位专家装上了这些器官,让他可以翻笔记本、查资料、动手执行任务。这样一来,“脑”还是那个“脑”,但能力边界从“能回答”扩展到“能完成”。

这个区别决定了整个架构设计的方向:你不是在选一个更强的模型,而是在设计一套怎么让模型和其他组件协作的系统。系统设计的好坏,往往比模型本身的智商更能决定 Agent 的上限。同一个模型,配合合理的记忆和工具设计,可以稳定完成复杂任务;配合糟糕的编排,连简单问题都会答得颠三倒四。

1.2 四个模块各守一道防线

Agent 的架构设计有一个非常朴素的思路:每个模块解决一个明确的短板。用表格看会更清楚:

核心模块解决的问题实际类比
大模型意图理解、推理、决策、内容生成大脑
记忆跨会话状态、上下文维持、用户偏好笔记本
RAG外部知识、私有文档、实时信息获取图书馆
工具调用操作真实系统、获取结构化数据、执行动作手和脚

这四个模块不是可选项,而是彼此咬合的关系。没有记忆,Agent 每次对话都是“失忆”的,用户说“我刚才提过的条件你忘了?”会直接尬住。没有 RAG,私有领域的知识无从谈起,模型只能靠训练数据里的过期内容硬猜。没有工具调用,Agent 就永远停留在“嘴上分析”,无法真正完成取数、发消息、改配置这类操作。而大模型作为中枢,把其他三个模块串联起来,像一个调度员,随时判断当前任务该调动哪个模块、怎么解释模块返回的结果。

所以设计 Agent 架构的第一步,不是急着写代码,而是把任务的链路画出来:一个请求进来之后,经过哪些判断、哪些模块、最终怎么收尾。这个链路清晰了,后续的开发和排查都会轻松很多。

2. 记忆模块怎么落地:短期窗口、长期档案与记忆污染

2.1 短期记忆:上下文窗口的管理是门手艺

大模型的上下文窗口就算再大,也不可能无限装下所有历史对话。我在做项目时最常遇到的问题就是:对话进行到第 30 轮,把完整历史塞进 Prompt 里,Token 消耗暴涨、响应变慢,而且模型还会被早期无关的信息干扰。短期记忆的设计,本质上就是对上下文窗口的资源管理。

目前比较实用的是“滑动窗口 + 摘要压缩”的混合策略。滑动窗口很好理解:只保留最近 N 轮对话原文,比如 10 到 20 轮,更早的内容不再进入 Prompt。但只做滑动窗口会丢失重要信息,所以每隔几轮就把窗口外的历史用大模型压缩成一段摘要,作为“记忆概述”保留下来。实际用的时候,Prompt 里的结构大概是:任务指令 + 历史摘要 + 最近对话原文 + 当前问题。这样一来,模型既有长期脉络,又有近期细节,且 Token 开销可控。

我踩过的一个坑是:滑窗边界设置得太死。比如用户在第 25 轮说“我之前说的那个价格是指含税价”,如果你只保留近 20 轮,这个信息早就被挤出窗口了,模型自然无法正确理解。后来的改进是:在滑动窗口之外,专门设置一个“关键约束区”,只要对话中出现像“含税价”“截止时间”“排除项”这类的关键信息,就单独抽出来长期保留。这本质上已经有点往长期记忆靠了,但它很管用。

2.2 长期记忆:按主题归档的“Agent 档案库”

长期记忆要解决的是跨会话的问题。用户今天说的偏好,下次对话时最好还能记住。实现长期记忆的常见方案有两类:向量化记忆和结构化记忆。

向量化记忆的做法是:把历史对话、用户偏好、任务结论等文本切成片段,用 embedding 模型转成向量存进向量数据库。下次用户发起新问题时,先把问题向量化,在库里做相似度检索,把相关的历史记忆捞出来放进 Prompt。这个方案的优点是灵活,能处理没有固定结构的自然语言信息;缺点是召回不准时,容易把不相关的旧记忆带进来。

结构化记忆则是用固定的数据格式记录关键信息,比如用户偏好、实体关系、任务状态:

{ "user_profile": { "region": "华东", "contact_channel": "email", "language": "中文" }, "preferences": { "report_style": "简版", "data_granularity": "按周" }, "task_state": { "current_project": "某跨平台系统", "next_deadline": "2025-06-30" } }

结构化记忆的优点是精准、稳定,缺点是需要预先定义好 schema,无法覆盖所有场景。我现在的惯用做法是两者结合:核心的偏好和状态用结构化 JSON 管理,零散的信息和过程性内容走向量库。需要特别强调的是记忆的写入时机。不是所有对话内容都值得写入长期记忆。一次性的临时需求、随口一提的闲聊、带时效性的状态,都不应该污染长期档案。我会在每次对话结束后,让模型先做一个“记忆提取”判断:这条对话里有没有值得长期保存的信息?如果有,再格式化写入。这个过程会多花一点时间和 Token,但能避免长期记忆变成垃圾场。

2.3 两个最容易踩的记忆坑

第一个坑是长短记忆冲突。比如长期记忆里写着用户“偏好邮件通知”,但这次会话里用户明确说了“不要发邮件,直接打电话”。如果短期记忆和长期记忆同时塞进 Prompt,模型就会犹豫,甚至输出矛盾的内容。现在的处理办法是:在 Prompt 中给记忆标出优先级,明确告诉模型“近期对话中的明确指令优先于历史偏好记录”,并且尽量让短期记忆里的新指令覆盖长期记忆中的旧配置。

第二个坑是记忆膨胀和成本失控。向量库里的记忆如果不加管理,会随着使用时间不断膨胀,检索量变大、命中率下降、存储费用上升。我建议给每条长期记忆加上时间戳和访问频次,定期清理过期的条目,比如三个月未命中、且与当前任务无关的历史记忆,可以归档或者删除。还要为记忆检索设置一个上限,比如每次最多返回 5 条相关记忆,避免无关信息挤占上下文空间。

3. RAG 模块:给 Agent 装上“实时知识库”

3.1 RAG 的标准流水线:先归档,再召回

RAG(Retrieval-Augmented Generation,检索增强生成)是解决大模型“知识过期”和“私有知识缺失”的主流方案。它的核心思路很直接:模型不知道答案没关系,先让它从外部知识库里检索相关内容,再基于检索结果来生成回答。

离线阶段要做的是知识归档:把文档清洗、去噪,按语义切分成适宜检索的片段(chunk),然后逐段用 embedding 模型转成向量,写入向量数据库。在线阶段则是:收到用户问题 → 问题向量化 → 在向量库中召回最相似的 Top-K 个片段 → 将片段拼接进 Prompt → 模型基于片段生成回答。这里最容易影响效果的是 chunk 切分。chunk 太小,信息被切碎,一块完整的意思在多个片段里分散;chunk 太大,噪声增多,检索精度下降。就我自己测试的经验,通用文档用 300 到 500 字左右的 chunk 比较稳,相邻 chunk 之间保留 10% 到 20% 的重叠,能有效避免语义被切断。检索召回数量 top_k 我一般控制在 5 到 8 个,再往上拉高,命中的低质片段反而会稀释核心信息。

embedding 模型的选型也有讲究。不要盲目追求大参数模型,而是看你的语料是什么语言、什么领域。如果是中文业务文档,优先选中文语料表现好的 embedding 模型;如果是代码或英文技术文档,可以调整选型。模型之间没有绝对的好坏,最终都要用你自己领域的测试集跑一遍看召回效果。

3.2 Agent 场景里 RAG 的三个特殊之处

普通问答式 RAG 和 Agent 里的 RAG 是有区别的。普通 RAG 是一次性检索、一次性生成,流程固定;Agent 场景下,检索往往是动态的、多轮的、甚至要跟工具调用联动。

动态检索很好理解:Agent 在完成任务的过程中,会根据当前子任务临时发起检索,而不是从一开始就把所有检索结果都查出来。比如 Agent 要先分析问题,发现自己缺少某份背景资料,才触发一次 RAG 检索。多跳检索则更复杂一些:Agent 需要先查一轮,得到一个中间结果,再用这个结果作为线索去检索下一轮,有点像查资料时顺着参考文献一路追下去。这种情况下,每一轮检索的结果都应该被记录下来,作为后续推理的依据。

还有一个很容易被忽视的问题:检索结果和工具返回结果发生冲突时,该信谁?比如 RAG 里的文档写着“某产品线 2025 年 Q2 销售额持平”,但 BI 工具里拉出来的实时数据显示实际下降了 15%。如果不做处理,模型就可能把两个互相矛盾的数据都写进答案,或者随机采信一个。我的做法是:在 Prompt 中给不同来源的信息打上“来源标签”,比如 [知识库] 和 [实时工具],并设置优先级规则——实时工具数据优先作为事实依据,知识库内容用于背景解释和原因分析,冲突时要在回答里显式指出差异。

3.3 检索不出好东西?按这个顺序排查

如果你的 RAG 总是召回一些不相关的内容,别急着换 embedding 模型,按下面这个顺序排查:

先看 chunk 切分是否合理。如果检索命中的片段语义不完整,大概率是切分出了断层,需要调整 chunk 大小和重叠率。再看用户问题的检索改写。用户很少会用精确的术语提问,原始 query 直接拿去向量化,效果经常不如改写后的 query。让大模型把用户问题改写成一个更规范的检索语句,比如“华东区销量下降的原因”改写成“华东区 2025 年 Q2 销量下降原因分析”,能明显提升召回质量。

接下来检查召回数量和排序。如果 top_k 召回的结果里混着大量低相关片段,可以尝试加一层 rerank 粗排模型,先向量召回 30 个候选,再用 cross-encoder 精排选出 5 个最相关的。最后还要确认 Prompt 里的指令是否明确。如果模型总是不按检索内容回答,那就要在 Prompt 里写得强硬一点,比如“在缺乏检索依据的情况下,必须明确回答不知道,禁止编造”。

4. 工具调用模块:让 Agent 真的能“动手”

4.1 工具调用的本质:模型只出意图,执行器动手

工具调用(也叫 Function Calling)经常被误解为“模型自己去执行函数”,实际上模型并没有执行能力。它的本质是:模型根据用户的意图,从你提供的工具清单里选择一个工具,并生成结构化的调用参数,然后由外部代码真正去执行这个工具,最后把执行结果传回给模型做下一步推理。

一次完整的工具调用循环是这样的:

  1. 系统把可用工具列表(名称、描述、参数定义)注入 Prompt;
  2. 模型根据当前任务,输出一个或几个工具调用指令,格式为“工具名 + 参数字典”;
  3. 外部执行器解析指令,做参数校验,调用对应的函数或 API;
  4. 执行结果返回给模型,有时候是结构化数据,有时候是文本;
  5. 模型根据结果继续推理,生成最终回答或发起下一次工具调用。

工具定义的格式直接影响调用成功率。每个工具的描述要像“搜索词”一样精准,让模型能快速判断什么时候该用这个工具。参数定义要列出名称、类型、是否必填、示例值,例如:

{ "name": "query_sales_data", "description": "按地区和日期范围查询销售数据,适用于销售分析类问题", "parameters": { "type": "object", "properties": { "region": {"type": "string", "description": "地区,如华东、华南"}, "start_date": {"type": "string", "description": "起始日期,格式 YYYY-MM-DD"}, "end_date": {"type": "string", "description": "结束日期,格式 YYYY-MM-DD"} }, "required": ["region", "start_date", "end_date"] } }

描述写得模糊、参数定义不清晰,是工具调用失败的头号原因。模型宁可选择不调用任何工具,也不会去猜一个它看不懂的复杂工具。

4.2 工具注册与路由:别把所有工具塞进一个 Prompt

很多做 Agent 的新手容易犯一个错误:把自己系统里所有 API 都注册成工具,一股脑塞给模型。工具数量一旦超过十几个,模型的选择准确率就会明显下降,还会出现答非所问、选错工具的情况。Prompt 窗口再大,也不能这么挥霍。

我建议分两层做工具路由。第一层是“意图分流”:在模型之前,先用一个轻量分类器或者规则,把请求分为几个大类,比如“数据分析类”“日程操作类”“知识查询类”,然后只把对应类别下的工具列表注入 Prompt。第二层才是在这个精简后的工具集里让模型做精确选择。这样做的好处是既降低了模型的选择难度,也能有效控制 Token 开销,还能避免跨域工具之间的误用。

还有一个细节:工具的描述文本需要根据实际使用效果不断调整。模型对工具的理解完全来源于描述文字,描述中如果加入了恰当的触发词和典型场景,比如“适用于销售分析类问题”,往往能把工具调用的准确率提高不少。

4.3 工具层最常翻车的三个地方

工具调用是最能体现“看着简单、用起来全是坑”的模块。第一个坑是参数幻觉。模型不是计算器,它生成的参数有时会脱离实际,比如恶意地编造一个不存在的用户 ID,或者把一个日期参数生成成了非法格式。所以外部执行器必须做参数校验,而不是直接拿模型给的参数去调接口。校验不通过时,把错误信息返回给模型,让它重新生成参数。

第二个坑是工具结果过长。有些工具会返回几十条 JSON 记录,直接塞回 Prompt 会占掉大块上下文,还会干扰模型对重点信息的提取。常规做法是先压缩结果:保留结构化摘要、只截取前 N 条记录、对主要字段做聚合统计。如果工具支持筛选条件,甚至可以追加一轮调用,让工具先按模型需求做聚合。

第三个坑是安全边界。Agent 一旦有工具权限,就意味着它能操作真实系统,权限如果给得过大,后果可能很难收拾。我在设计工具时坚持最小权限原则:Agent 默认只允许查询类的只读工具;对写入、删除、发送类操作,要么单独二次授权,要么通过人工审批流程。不要为了方便,一股脑把管理员的全部权限都交给 Agent。

5. 协同机制拆解:一条任务的完整旅程

5.1 从用户消息到最终回复的模块流转

把四个模块装在一起,协同的过程可以拆成一条清晰的链路。以一条典型的企业知识库问答请求为例,整个流程是这样的:

用户提问 → 写入短期记忆 → 大模型解析意图 → 判断是否需要外部知识 → 触发 RAG 检索 → 判断是否需要实时数据 → 触发工具调用 → 汇总所有信息 → 大模型生成回答 → 更新长期记忆 → 输出结果

每一步都有一个明确的“负责人”。意图解析和生成回答由大模型负责;历史信息和用户偏好从记忆模块读取;知识库相关内容来自 RAG;实时操作和结构化数据来自工具调用。各个模块的数据都会汇聚到 Prompt 里,由大模型统一处理和判断。

这里有一个很容易忽略的环节:信息的组织方式。当三种来源的信息同时出现在 Prompt 里时,如果没有清晰的段落划分,模型就会“串味”,分不清哪个是历史偏好、哪个是知识库内容、哪个是实时数据。我在设计 Prompt 时,会刻意用分组标签把所有外部信息隔开,并在指令里声明每个来源的优先级和使用方式,模型回答的稳定性就会上一个台阶。

5.2 Agent Loop:循环什么时候该停

真正的 Agent 并不是“问一句答一句”的直线模型,它往往要经历多轮“思考-行动-观察”的循环。我把这个循环简化为三步:观察当前状态和已有信息,决定下一步行动;行动触发工具调用或检索;观察结果,判断是否还需要继续,或者是否可以生成最终回答。

这个循环需要设计终止条件,否则容易出现无限循环。我的项目里一般设置了三道保险:

  • 模型自身判断任务已完成,输出最终答案;
  • 达到最大迭代次数上限(一般设置在 8 到 10 轮),强制结束;
  • 循环中出现重复的相同工具调用且没有新增信息,触发中断。

有一回测试一个自动定票的 Agent,它在订票确认环节反复调用同一个查询接口,原因是因为上一步工具返回里的某个字段它没解析对,就一直重试。后来我在循环逻辑里加了“相同工具调用超过三次且参数相同就中止”的规则,把问题解决了。这类异常在真实场景里非常常见,建议你在设计循环时提前考虑。

5.3 一个具体例子:某销售数据分析 Agent

用一个虚构的场景把上面的协同串起来。假设你在做一个“销售数据分析 Agent”,用户问:“帮我看看这个月华东区销量为什么大幅下降。”

第一步,大模型解析意图,发现这是一个数据分析类请求。记忆模块的短期记忆记住了“当前对话客户想看华东区”,长期记忆里调出了用户偏好“报告用简版格式”。第二步,大模型认为缺少实时数据,触发工具调用 query_sales_data,参数是华东区、本月、环比上月。工具返回销售数据,结果显示两大主力产品线下滑明显。第三步,大模型不满足于这个现象,想知道下滑的可能原因,于是触发 RAG 检索,从公司知识库里检索“华东区 产品线 销量下滑 原因”相关文档,召回了两份资料:一份提到渠道政策调整,一份提到竞品低价策略。

第四步,模型把所有信息汇总:短期记忆里的对话目标、长期记忆里的用户偏好、工具返回的实时数据、RAG 检索到的背景资料,统一加工成一份简版分析报告,并指出“实时数据表明下滑集中在产品线 A,知识库资料显示同期渠道政策有调整,建议进一步核查”。第五步,系统把这次分析的关键结论写入长期记忆,方便用户下次追问时能直接关联。

这整个过程看起来并不复杂,但每一环都依赖前面模块输出的质量。记忆不准、检索不到、工具参数错误,任何一个环节出问题,最终回答都会失真。

6. 落地实操与排障手记

6.1 框架选型:从快速验证到深度定制

做 Agent 落地,第一个躲不开的问题是用编排框架还是自研。各种开源的 Agent 编排框架确实可以帮你快速搭出原型,省去写底层流程的功夫。但用的时间长了,你会发现框架带来的抽象有时也是一种负担:框架封装好的 Agent Loop、工具调用方式、记忆策略,不一定匹配你的场景,调试起来反而更费劲。

我的建议是分阶段走。在快速验证阶段,依赖主流的编排框架和云平台的 Agent 服务,尽快搭出闭环,验证核心场景的可行性。等业务逻辑跑通、产品方向明确以后,再考虑逐步替换:先自研 Prompt 管理、再自研工具调用层、再自研记忆和检索策略。自研不是目的,可控制性才是。大团队建议早点自研粘合层,因为框架的更新节奏和你的业务深度绑定之后,维护成本会越来越高;小团队则建议先框架后迁移,用最低成本验证价值。

6.2 常见问题速查表

我在实际项目里积累了一些高频问题和对应的排查思路,整理成一张速查表,方便大家遇到类似情况时直接对照:

故障现象排查思路参考方案
RAG 检索经常返回无关内容检查 chunk 切分是否合理;检查 query 是否需要改写;检查 top_k 召回数量调整 chunk 大小和重叠率;加 query 改写;引入 rerank 精排
工具调用频繁报参数错误查看模型生成的参数是否合法;检查工具描述是否清晰外部执行器做参数校验;优化工具描述和参数示例
Agent 反复执行无用操作是否出现相同调用循环;是否缺乏终止条件限制最大迭代次数;增加重复调用中断规则
回答前后矛盾短期和长期记忆冲突;多个信息来源无优先级在 Prompt 中声明优先级;新指令优先于历史偏好
调用链路过长、Token 消耗高工具结果过大未压缩;记忆检索范围过大工具结果摘要化;记忆检索设置上限;精简工具列表

6.3 调试与观测:没有日志就无法优化

Agent 这种多模块协作的系统,最怕的就是“黑盒”。用户给了一个指令,系统内部做了七八个步骤,最后输出一个答案,如果中间任何一步出了问题,你根本不知道是哪一步。所以我在做任何 Agent 项目时,第一件事就是把结构化日志搭起来。

每条请求分配一个 trace_id,日志里记录每个关键事件:用户输入、意图解析结果、记忆命中情况、RAG 召回片段、工具调用参数和返回结果、模型中间输出、最终回答。每个事件记录模块名、耗时和 Token 消耗。排查问题时,只需要捞出一条 trace_id,就能把整个执行链路完整还原出来,问题出在哪个环节一目了然。

大模型应用的调试方法和传统软件有一个很大的区别:没有 debugger 可以逐步断点跟踪,很多时候只能靠日志和中间产物来还原过程。这就更需要把“过程留痕”做到位。我还会用“影子模式”做灰度测试:新版本 Agent 先只记录所有决策和工具调用过程,不执行真实操作,跑一段时间和旧版本做对比,确认没问题后再切换线上流量。这种方式成本不高,但能挡住大量潜在事故。

踩过几次坑之后,我的体会是:Agent 不是把四个模块堆在一起就能跑的,真正决定上限的是模块之间的接缝处理。记忆怎么写入、检索结果怎么排序、工具结果怎么压缩、冲突信息怎么仲裁,这些细节在每个项目里都需要反复调优。你不需要一开始就追求完美架构,先把最小闭环跑通,再把日志铺好,然后一个一个坑去填平。这套方法论,比我见过的任何花哨设计都更可靠。

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

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

立即咨询