这段时间一直在折腾 AI Agent 的落地,最深的一个感受就是:模型能力只是最后那一下“思考”,前面还有一大堆环境、部署、编排、检索、监控的事情,哪一环掉链子,Agent 就给你表演原地崩溃。我把从空白服务器到能稳定跑业务 Agent 的完整链路重新梳理了一遍,整理出了一份“全栈架构”落地指南,想分享给正在搭 Agent 或者准备搭 Agent 的同学们。
1. 先看全局:Agent 全栈架构到底拆成哪几层
1.1 四层视角:环境、模型、编排与检索
Agent 项目最大的错觉,是以为把大模型 API 一接、Prompt 一写,就是一个能用的 Agent。真正的生产环境里,它是四层东西叠起来的:
硬件与系统层。GPU、驱动、容器、Python 环境、依赖管理。这是最容易让人崩溃的一层。我见过太多人花三天调代码,最后发现是 CUDA 版本和显卡驱动不匹配。Agent 跑起来之后,底层环境一旦不稳定,上层再聪明的模型也白搭。
模型基座层。模型选多大、怎么量化、用什么推理框架加载、上下文窗口开多长、并发上限设多少。很多人忽视了这层的“工程属性”,以为模型是拿来就能用,结果并发一高就开始排队。
Agent 编排层。任务拆解、工具调用、状态记忆、循环控制。这是 Agent 区别于普通聊天机器人的地方。模型负责“想”,编排层负责“做”。这一层如果设计得不够严谨,Agent 会无限循环调用工具,或者答非所问地编造一个结果出来。
应用接入层。RAG 检索、权限管理、接口封装、日志追踪。RAG 负责给 Agent 装“外挂知识库”,让它在回答时能引用真实资料。权限和日志决定了你能不能审计它到底干了什么,这在业务场景里几乎是刚需。
把这四层画成一条流水线来看,就很好理解了:底层是厨房的灶台和锅(环境),中间是菜谱和厨师手艺(模型基座),上层是给服务员派活的流程(Agent 编排),最上面是顾客点菜时提供的菜单和食材参考(检索与应用接入)。四个环节任何一个掉了链子,端到端都跑不通。
1.2 落地路线图:小步迭代的三个阶段
我建议任何 Agent 项目都按“三阶段”来走,不要一上来就搭一个巨复杂的多智能体系统。
阶段一:跑通最小闭环。先让一个简单 Agent 能完成一件事。比如“接收工单 → 调用查询工具 → 返回结果”。这个阶段不追求规模,追求链路完整。
阶段二:扩大能力边界。在闭环稳定的前提下,逐步换更强的模型、接入更多业务工具、加 RAG 检索。每加一块,都做一次回归验证。
阶段三:硬化系统。监控、告警、灰度、回滚、会话持久化,全部补齐。这时候它才像一个能交给业务方使用的系统,而不是一个实验品。
很多项目死在阶段一和阶段二之间,原因是阶段一没打好底子,换模型的时候发现环境一团乱麻;工具调用没有超时机制,一次错误调用把整个服务拖崩。所以后面每讲一层,我都会把“为什么这样设计”讲清楚。
2. 运行环境准备:GPU 选型与容器化部署的实操要点
2.1 硬件与显存的匹配关系:先算账再买卡
准备环境之前,先算清楚模型吃多少显存。经验公式很简单:模型参数量 × 每个参数占用的字节数 = 模型本身占用的显存,另外还要给 KV Cache 和推理开销预留 20% 到 30% 的余量。
比如一个 7B 参数模型,用 BF16 精度加载,就是 7 × 2 个字节,大约要 14GB 显存;用 4bit 量化加载,大约 5GB 左右。70B 模型在 BF16 下要 140GB,4bit 下也要 28GB 左右。一张卡不够,就得考虑张量并行和多卡推理。
我的建议是:测试阶段找云厂商租一个按小时计费的 GPU 实例,而不是直接买卡。原因不只是钱的问题,而是你在调模型、调环境的过程中,大概率会反复重装系统,按量付费的裸机节点可以随时销毁重开,容错率很高。
2.2 从裸机到可用状态:一套规范化的环境搭建流程
拿到一台裸机之后,我推荐的流程是“系统层先验证,容器层做隔离,依赖层锁版本”。具体来说:
- 确认 GPU 驱动已经加载。装完系统之后,先用系统工具检查一下显卡状态,确认能被识别。
- 再检查 GPU 驱动与计算框架的版本匹配。不同驱动版本对计算框架的兼容性不一样,记住一句话:不要为了追求“最新”去升级驱动,而是让驱动版本适配你的计算框架版本。
- 安装容器引擎。这一步是为了环境隔离。容器能保证你在不同机器上复现同样的环境,不会出现本地能跑、换台机器就崩的问题。
- 在容器里创建独立的运行环境,把 Python、推理框架、依赖库全部装在容器内部,宿主机保持干净。
第 4 步极其重要。很多人图省事,直接在宿主机里 pip install 一堆包,一旦某个包版本冲突,轻则重装环境,重则需要重刷系统。用容器做隔离之后,环境坏了直接删除重建,几分钟就能恢复。
注意:GPU 设备映射要在启动容器时显式挂载进去,容器内才能使用 GPU。很多人第一次启动容器忘了这一步,进去之后用系统工具发现显卡为空,白白排查了很久。
还有一个容易被忽略的点:交换分区。当内存不够时,系统会用磁盘做交换。但在推理场景下,如果模型参数或者激活值被换到了磁盘上,推理速度会慢到让你怀疑人生。所以训练和推理机器上,建议不要过分依赖交换分区,宁可减少并发,也要保证内存和显存充足。
3. 大模型基座部署与推理优化
3.1 模型选型:7B、13B、70B 到底怎么挑
模型选型的唯一标准,是你的任务复杂度。整理一个我做选型时的判断矩阵:
| 任务类型 | 建议规模 | 原因 |
|---|---|---|
| 简单的文本分类、信息抽取 | 7B 级别 | 速度快,成本低,足够处理规则明显的任务 |
| 工具调用、结构化输出、多轮对话 | 13B 到 34B 级别 | 需要较强的指令遵循和工具调用能力 |
| 长文档理解、复杂推理、高质量生成 | 70B 以上 | 上下文容纳和思维链能力明显更强 |
举一个实际例子:做客服工单分类,7B 模型加上几个示例就够用;做“根据用户描述自动调用多个工具并在最后生成结构化总结”的任务,7B 就会开始偷懒,要么跳步骤,要么漏参数。这时候换 13B 或 34B,效果立竿见影。
这里想纠正一个误区:参数规模不是越大越好,而是“够用优先”。70B 模型的单次请求成本和小模型完全不是一个量级,如果你的任务用小模型就能做到 90% 的准确率,那剩下的 10% 提升,值不值得成倍的资源成本,需要业务侧来评估。
3.2 部署方式:本地推理框架与量化选择
模型选定之后,下一步是把它服务化。常见方案有两种:
离线批处理服务,适合不需要实时响应的场景,比如夜间的数据批量处理、文档信息抽取等。它追求吞吐量,可以一次性塞入大量请求,慢慢排队执行。
在线流式服务,适合聊天、工具调用等需要实时反馈的场景。它追求首 token 延迟和生成速度,用户发一句话,希望几百毫秒内就看到第一个字出来。
在线服务需要配置推理框架。这里有两个关键参数需要调:显存利用率和并发上限。推理时的 KV Cache 会随着并发请求数成比例增长,并发设太高,显存直接爆掉;设太低,GPU 又闲着。经验做法是从小到大逐步加压测试,找到“显存刚好够用、GPU 利用率接近饱和”的那个值,作为线上并发上限。
量化也是一个绕不开的话题。量化是把模型里的高精度数值转成低精度表示,以此减少显存占用、提升推理速度。常见的有 8bit、4bit 等。在 GPU 推理场景下,4bit 量化通常对效果影响可控,但显存占用能砍掉一半还多。不过如果任务对输出质量极度敏感,建议至少先跑一批测试数据做对比,不要直接量化上线。
3.3 Agent 场景下的推理参数调优
Agent 场景跟普通对话不同,参数的设置策略也不太一样:
温度参数要调低。工具调用的场景下,模型需要严格按照格式输出函数调用参数,温度太高会导致输出不稳定。建议在工具调用或者结构化输出任务里,把温度调到接近 0,但在最后生成自然语言回复时,可以稍微调高一点,避免回答过于机械。
上下文窗口要显式管理。Agent 在执行任务时,会把每一步的中间结果都写进上下文。如果任务步骤多,上下文很容易被撑爆。不要指望模型自己知道该忘掉什么,而是在编排层主动裁剪。
请求超时和重试策略必须有。工具调用不是模型生成完就结束,还要等外部工具执行。如果工具崩溃,Agent 会一直卡在那里。给每一步工具调用设置一个超时时间,超时就把错误信息喂给模型,让它换一条路继续走,而不是无限等待。
我在这个环节踩过一个大坑:一开始为了省显存,把并发上限压得很低,结果用户一多,请求全部排队,首 token 延迟飙升到十几秒。后来把模型量化降了一档,腾出显存给 KV Cache,把并发数提上来之后,延迟才恢复正常。显存空间要留给并发,不要全部压在模型精度上。
4. Agent 工作流编排:规划、工具调用与记忆管理
4.1 规划机制:不要让模型自由发挥
Agent 的“规划”,是让模型学会把一个复杂任务拆解成一串可执行的动作。目前最成熟的范式是 ReAct:模型在每个步骤里先输出思考(Thought),再决定行动(Action),然后观察结果(Observation),循环直到任务完成。
用一个例子来说明:用户问“我上个月订单为什么没发货”。一个没有规划能力的模型可能会直接编一个答案。有了 ReAct 范式之后,模型会这么走:
第一个循环:思考是“我需要查询订单信息”,行动是“调用订单查询工具,参数是用户 ID”;然后观察接口返回的数据,判断订单状态是“已支付待发货”;第二个循环:思考是“需要判断是否满足发货时间”,行动是“调用发货计划查询工具”;最终整合信息,生成回答:“您的订单已支付,预计今日发货,原因是仓库昨日盘点。”
ReAct 的工程化没那么神秘,核心是给模型一张“工具说明书”,并且要求它每走一步都输出结构化的行动指令。关键是流程边界:什么任务交给什么工具,什么情况结束循环,必须由编排层控制,而不是让模型无限调用下去。比如加一个最大循环次数,超过次数强制结束,防止模型陷入死循环。
4.2 工具调用:函数定义里的细节决定成败
工具调用是 Agent 连接外部世界的桥梁。同样的工具,定义得好不好,调用成功率能差出一大截。
工具描述要讲清楚“什么场景下用、输入参数是什么、单位是什么、边界条件是什么”。模型是靠描述来理解工具的,描述越模糊,它就越容易传错参数。举个反例:你给一个查询订单状态的工具,只写“查询订单”,模型就不知道用户输入“多少号买的”的时候,该不该把“购买日期”也传给工具。你需要在参数说明里写明“支持订单号、手机号、用户 ID 三种方式,任意一种即可”。
工具数量要克制。给模型挂 20 个工具,不等于它能用好 20 个工具。工具越多,模型选错的概率越大。我在项目里反复验证过一个结论:同一场景下,工具从 10 个减到 4 个,调用准确率有明显提升。如果业务确实需要大量工具,可以考虑把工具分组,先让模型选组,再在组内选具体工具。
工具结果必须有结构化反馈。工具执行成功后,返回值不要是一大段无格式文本,最好是 JSON 结构,方便模型提取关键字段。执行失败时,也不要只返回“error”,而是明确告诉模型“失败原因是参数缺失”还是“余额不足”,这样模型才能做出下一步决策。
4.3 记忆管理:短期上下文与长期记忆分层存
Agent 的记忆,本质上分为两层:
短期上下文,是当前任务进行过程中产生的所有中间信息,包括用户本轮输入、模型思考轨迹、工具调用结果等。这一层是临时的,任务结束就可以丢。需要警惕的是上下文溢出问题,尤其是任务步骤多的时候,所以最好设定一个“上下文预算”,超出预算就把中间步骤压缩成摘要。
长期记忆,是跨会话需要保留的信息,比如用户的偏好、历史订单、历史决策记录。这一层通常做成两种形式:一是结构化数据库存储(比如用户偏好表),二是向量检索库存储(比如历史对话摘要)。
我在项目里得到的经验是:两套记忆要物理隔离,不要混在一起喂给模型。长期记忆以“检索片段”的形式注入到当前上下文里,短期记忆则以完整轨迹的形式保留在对话窗口中。如果混在一起,模型会被历史噪声干扰,忘记当前任务的目标。做一个粗俗但贴切的类比:短期记忆是当前手上的工作台,长期记忆是仓库。工作台上的东西要时刻可见,仓库里的东西用到才取。你不能把仓库整个搬到工作台上。
5. RAG 与知识检索:给 Agent 装上可溯源的外挂大脑
5.1 为什么 Agent 必须接检索:减少幻觉的硬手段
模型训练完之后,知识就是静态的。你问它三个月前新发布的政策,它只能编一个出来。RAG 存在的意义,就是让 Agent 在回答之前,先到外部知识库里捞一遍相关资料,然后基于这些资料生成回答。
RAG 的实现链路听起来不复杂:加载文档 → 文本切分 → 向量化 → 存库 → 召回 → 注入大模型。但每个环节都有大量影响最终效果的细节,尤其是文本切分和召回结果的后处理。
5.2 切分策略与召回优化:小片段召回、大上下文融合
文本切分,指的是把长文档切成很多小块,以便检索时能定位到相关段落。切片大小会影响召回效果:
| 切片方式 | 优点 | 缺点 |
|---|---|---|
| 小切片(约 200 字) | 召回精准,定位到具体段落 | 上下文信息可能不完整 |
| 大切片(约 1000 字) | 上下文完整,生成时信息充足 | 召回时可能带入无关内容 |
实际场景中,我常用的是中等切片加重叠。比如以 400 字为基本块,相邻块重叠 50 字,这样既能定位到关键内容,又不至于丢失段落之间的上下文关联。
召回之后还有一步容易被忽略的关键环节:重排。向量召回本质上是“近似匹配”,返回的结果里往往混着噪声。如果直接把 Top 5 的结果全塞给模型,模型容易被其中一条不相关的内容带偏。建议做两层检索:先用向量召回 Top 20,再交给重排模型根据当前问题精排 Top 3 到 Top 5,最后只把精排后的结果注入上下文。
内存里有一个很重要的调参思路:召回数量不是越多越好,而是正好。注入的文档越多,模型的注意力越分散,反而可能忽略真正的关键段落。宁可只喂两三个高相关的片段,也不要喂一堆似相关又不相关的段落。
还有一条经验:对 RAG 的召回结果要打分判断“有没有答案”。当问题和知识库内容完全无关时,不要硬逼着模型用这些材料回答。我见过很多 Agent 在知识库里捞不到东西时,态度极其坚定地编造一个答案,还一本正经地引用了一个并不存在的文档编号。解决方案是在系统提示词里写清楚:检索结果若无直接关联,应回答“当前资料库没有覆盖该问题”,而不是自行推断。
6. 性能监控与常见问题排查实录
6.1 核心监控指标:延迟、显存、GPU 利用率和请求吞吐
Agent 上线后,最怕的是服务突然变慢或者 OOM。我建议至少盯住四个指标:
| 指标 | 含义 | 建议阈值 |
|---|---|---|
| 首 token 时延 | 用户发送请求到模型输出第一个 token 的时间 | 低于 1 秒 |
| 生成时延 | 完整输出一个回答的耗时 | 根据业务要求设定 |
| GPU 显存占用 | 当前显存使用量与上限的比值 | 长期超过 85% 有 OOM 风险 |
| GPU 利用率 | 计算单元的实际忙碌程度 | 长期低于 30% 说明并发配置不合理 |
这四个指标组合起来,能帮你快速定位问题:首 token 时延高,大概率是负载高或者模型排队;显存占用持续高位,多半是并发设置过高;GPU 利用率低,可能是请求量不够,也可能是模型加载方式有瓶颈。
监控面板不需要多花哨,能记录曲线、配有告警即可。我给自己的项目配的是最朴素的一套:把指标定期写入时序数据库,用一个小面板页面展示,超过阈值就发告警。工具是次要的,关键是先把指标打点做好。如果代码里没有埋点,时间序列数据就是空的,再高级的面板也白搭。
6.2 常见故障与排查速查表
实战中遇到的典型问题,可以整理成一张速查表:
| 现场现象 | 直接原因 | 修复方式 |
|---|---|---|
| 请求报显存不足(OOM) | 并发数叠加 KV Cache 超出显存 | 降低并发上限、量化模型、减少上下文长度 |
| 生成到一半突然中断 | 上下文长度超出窗口限制 | 开启上下文裁剪、启用自动摘要压缩 |
| 工具调用参数不合法 | 工具描述不清、模型温度过高 | 优化工具描述、降低温度、增加返回值校验 |
| 重启后对话记录全丢 | 会话状态没有持久化 | 把短期记忆按会话 ID 存入数据库 |
| 模型开始答非所问 | 上下文里混入了过多无关检索片段 | 收紧 RAG 召回数量、增加相关性阈值 |
| 长时间无响应 | 工具调用没有超时 | 为每个工具调用设置超时并返回超时错误 |
这里想专门强调一下“重启后会话丢失”的问题。Agent 服务跑在容器里,随时可能因为更新镜像、内存溢出等原因重启。如果重启之后,Agent 完全忘了用户刚才说过的所有内容,体验是非常割裂的。解决方案很简单:每轮对话结束后,把当前会话的短期记忆序列化存一份,重启后按会话 ID 恢复。这个改动很小,但体验提升巨大。
6.3 从上线到稳定:灰度发布与回滚设计
Agent 系统跟传统后端服务还不太一样,模型更新、Prompt 修改、知识库变动,都可能带来难以预估的行为变化。我做项目的原则是:任何变更都要可回滚。
模型版本切换时,不要直接全量切换。先把新模型部署成影子服务,让线上请求同时打到新旧两个模型上,观察新模型的结果是否有异常。确认稳定后,再切小部分流量试运行,最后才全量切换。一旦发现问题,立刻切回旧模型。
知识库更新也一样。新向量库先跟旧库并行建好,等新的文档切分、向量化流程跑完,再平滑替换。不要在大模型跑正忙的时候,临时重建索引。
环境层面更是如此。容器镜像打好标签,每发布一个版本都要能追溯到代码提交记录。上线之前的机器状态要保留快照,出现问题一键回滚。
我在项目里吃过一次亏:新版本镜像里顺手更新了一个依赖库,结果模型推理输出格式全变了,花了两个多小时才定位到是依赖版本问题。从那之后,所有依赖版本全部锁死,镜像升级必须走完整的测试流程,绝不在生产环境里顺手做任何小改动。
再分享一个从实践中得来的换模型经验:换大模型之后,不要只凭几个测试案例的感觉就判断效果变好了。建议固定一批验证集,每换一次模型就跑一遍,用准确率、延迟、成本三个维度综合对比。否则很容易出现“新模型有些问题变好了,但另一些问题悄悄变坏了”的情况,而人工测试根本感知不到。我在测试中发现,同一套 Agent 流程,从 7B 升到 34B 之后,工具调用成功率提升了差不多十个百分点,但首 token 延迟也翻了将近一倍。这就是典型的“效果和性能互换”,上线前一定要让业务方知晓。
最后说说我个人的体会吧。Agent 项目最容易踩的坑,不是模型不聪明,而是“周围的东西太脆弱”。环境不稳定、工具没有超时、上下文不管理、没有监控——这些问题任何一个都能让再聪明的模型表现得像个傻子。所以我的建议是:别急着追求大模型、炫技式的多智能体,先把单 Agent 的完整链路做扎实。链路稳了,后面的所有扩展才有意义。小技巧方面,有一个我可以无条件推荐:上线后一定要给工具调用加上输入输出日志,每次 Agent 调用工具都记录下来。否则出了问题,你只能对着模型生成的猜测文本干瞪眼,有了日志,你能精确知道它在哪一步开始跑偏。