ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI Agent从Demo到生产:并发、状态与工具调用工程化实战复盘

2026/10/5 14:36:22 拓冰建站 浏览量
AI Agent从Demo到生产:并发、状态与工具调用工程化实战复盘 1. 半年卡点复盘AI Agent 从 Demo 到生产的鸿沟到底在哪去年秋天我第一次把 AI Agent 跑通的时候心情跟大多数人一样——觉得这玩意儿简直无所不能。一个基于 FastAPI LangChain 的智能体接上几个工具函数能查天气、能读数据库、能自动回复消息Demo 演示的时候行云流水老板看了直点头。但接下来半年我几乎把所有的精力都耗在了“让它真正稳定干活”这件事上而且进展极其缓慢。问题出在哪我后来复盘核心矛盾就一个Demo 是单次、单用户、理想输入生产是多轮、多用户、脏输入、还要扛并发。这两者之间的差距不是加几个 prompt 就能填平的它涉及到架构层面的重新设计。举个最直观的例子。我最初用 Python 写 Agent同步调用大模型接口一个请求进来就阻塞等结果。本地测试没问题因为就我一个人用。上线之后同时来五个用户整个服务直接卡死。这时候我才意识到AI Agent 本质上是一个长耗时、高不确定性、强状态依赖的服务它跟传统的 CRUD 接口完全不是一个物种。传统接口 50 毫秒返回Agent 可能要 30 秒甚至几分钟中间还要调用外部工具、等待模型推理、处理多轮对话状态。你拿写 Web 后端的那套思路直接套必然翻车。这半年我踩过的坑大致可以归成几类。第一类是并发与资源管理Python 的 GIL 加上同步阻塞调用让并发能力惨不忍睹我试过用线程池硬扛结果内存暴涨上下文切换开销大到离谱。第二类是状态管理多轮对话的上下文怎么存、存多久、怎么在多个服务实例之间共享我一开始用内存字典服务一重启全丢后来换 Redis又遇到序列化和过期策略的问题。第三类是工具调用的可靠性Agent 调用外部 API 失败是常态超时、限流、返回格式不对每一种都要单独处理而且模型有时候会“幻觉”出一个根本不存在的工具名你得在中间加一层校验。第四类是可观测性Agent 内部到底发生了什么模型为什么选了那个工具为什么这轮回复质量突然下降没有日志和追踪你根本无从下手。这四类问题每一个单独拎出来都能写一篇长文。但真正让我决定必须去 iRTE2026 的原因是我发现这些问题不是靠我一个人闷头查文档能高效解决的。AI Agent 这个领域变化太快了去年流行的框架今年可能就被替代去年没人提的并发方案今年可能成了标配。你需要一个场合能一次性看到大量真实项目的一手经验能跟同样在坑里的人面对面聊能听到那些“文档里不会写、但实际做的时候一定会遇到”的细节。我现在的判断是AI Agent 的技术栈正在从“能用”向“好用、耐用”过渡而这个过渡期最缺的就是工程化经验的流通。iRTE2026 这种场合恰好就是干这个的。下面我把自己这半年在架构选型、并发处理、状态管理、工具调用可靠性这几个方面的具体做法和思考整理出来既是给自己做个阶段总结也是给准备去或者正在犹豫要不要去的朋友一个参考——你到了现场至少知道该重点听什么、问什么。2. 架构选型为什么我从纯 Python 转向了 Rust Python 混合2.1 纯 Python 方案的瓶颈到底在哪我最初的技术栈很标准FastAPI 做 Web 层LangChain 做 Agent 编排LangGraph 做状态机Redis 做会话存储。这套组合上手快、生态全、文档多对于快速验证想法来说无可挑剔。但当我试图把它推到“能同时服务几十个用户”这个量级时问题就集中爆发了。最核心的瓶颈是并发模型。Python 的 asyncio 看起来能解决并发问题但 LangChain 和很多工具库底层是同步阻塞的你一旦在 async 函数里调用同步的模型接口整个事件循环就被卡住了。我试过用run_in_executor把同步调用扔到线程池但线程池的大小、超时控制、异常传播都变得极其复杂而且 Python 的 GIL 意味着多线程并不能真正并行执行 CPU 密集型任务虽然模型调用是 IO 密集型但 JSON 解析、prompt 模板渲染、状态序列化这些操作累积起来CPU 占用并不低。另一个问题是内存占用。每个 Agent 实例都要加载一份模型客户端、一份工具定义、一份 prompt 模板Python 对象的内存开销本来就大几十个并发会话下来内存轻松上 G。我试过用对象池复用但 LangChain 的链式调用设计让状态很难干净地重置复用反而引入了更难排查的 bug。还有一个容易被忽视的点是冷启动时间。Python 服务重启后第一次请求要等好几秒才能响应因为要初始化各种客户端和加载配置。对于需要弹性伸缩的场景这个冷启动时间直接决定了你的扩容速度。2.2 Rust 在 AI Agent 中台里的角色定位转向 Rust 并不是一时冲动。我观察到一个趋势越来越多的 AI Agent 中台开始用 Rust 写核心的调度层和工具执行层而把模型交互和 prompt 编排留给 Python。这个分工的逻辑很清晰——Rust 负责高并发、低延迟、强可靠的部分Python 负责快速迭代、生态丰富的部分。具体来说我用 Rust 重写了三个模块。第一个是请求调度器它接收所有进来的 Agent 请求做限流、排队、优先级排序然后分发给后端的 Python Worker。Rust 的 async 运行时tokio在处理大量并发连接时表现极其稳定我实测单机可以轻松维持上万个并发连接而内存占用只有 Python 方案的几分之一。第二个是工具执行网关所有外部 API 调用都经过这一层统一做超时控制、重试策略、熔断降级、结果缓存。Rust 的强类型系统让我在编译期就能发现很多参数传递的错误而 Python 里这些错误往往要等到运行时才暴露。第三个是状态存储层用 Rust 写了一个轻量的会话状态管理服务基于 Redis 做持久化但内存里维护了热数据的 LRU 缓存读写延迟控制在毫秒级。这个混合架构的关键在于通信协议的设计。Rust 调度器和 Python Worker 之间用 gRPC 通信定义清晰的 protobuf 接口。Python Worker 只负责“给定输入和上下文调用模型返回结果”不关心并发、不关心状态存储、不关心限流。这样 Python 端的代码变得极其简单几乎就是纯函数测试和维护成本大幅下降。而 Rust 端则承担了所有工程化的脏活累活发挥它系统级语言的性能优势。2.3 混合架构的实操配置与性能对比具体配置上我用的是 tokio 作为 Rust 的异步运行时tonic 做 gRPC 框架redis-rs 做 Redis 客户端。Python 端用 grpcio 做服务端LangChain 只用来做 prompt 模板管理和模型调用封装不再用它做 Agent 的流程控制——流程控制全部上移到 Rust 调度器里用状态机的方式显式管理。性能对比数据我记录了一组同样的硬件配置8 核 16G纯 Python 方案在 50 并发时平均响应时间从 3 秒飙升到 15 秒以上错误率超过 20%混合架构在 200 并发时平均响应时间稳定在 4 秒左右错误率低于 1%。内存占用方面纯 Python 方案在 50 并发时已经吃到 12G混合架构在 200 并发时 Rust 端占用 2GPython Worker 端占用 6G开了 4 个 Worker 进程。注意Rust 和 Python 的版本兼容性是个坑。我用的 Rust 1.75 和 Python 3.11grpcio 的版本必须和 tonic 的 protobuf 版本对齐否则会出现序列化不一致的问题。建议在 Dockerfile 里把两边的依赖版本都锁死不要用 latest 标签。这个架构不是没有代价。开发复杂度明显上升你需要同时维护两套代码、两套构建流程、两套监控。对于小团队或者验证阶段的项目我不建议一上来就搞混合架构。但如果你已经确定 Agent 要上生产、要扛并发、要长期维护那这个投入是值得的。我踩过的坑是一开始为了图快Rust 端和 Python 端的错误处理没有统一导致有些异常在跨语言调用时丢失了堆栈信息排查起来非常痛苦。后来我定了一个规矩——所有跨语言调用的错误必须包装成统一的错误码和错误消息结构原始堆栈只记日志不跨进程传递。3. 并发扛不住从限流到队列的完整实战方案3.1 并发问题的本质不是连接数是模型调用配额很多人一提到“扛并发”第一反应是加机器、加连接池。但 AI Agent 的并发瓶颈跟传统 Web 服务完全不同。传统服务的瓶颈通常在数据库连接数或者 CPU而 Agent 的瓶颈在模型 API 的调用配额和响应延迟。我算过一笔账假设你的模型供应商给你每分钟 60 次调用的配额每次调用平均耗时 5 秒。那么理论上你一分钟最多处理 60 个请求但因为有 5 秒的延迟实际上你需要至少 5 个并发槽位才能把配额吃满。如果你同时来了 100 个请求超出的 40 个要么排队、要么直接失败。这时候你加再多机器也没用因为瓶颈在供应商那边不在你这边。所以并发方案的第一步不是写代码而是搞清楚你的配额和延迟分布。我建议你做一个简单的压测用不同的并发数去打你的模型接口记录成功率、平均延迟、P95 延迟。你会发现一个临界点超过这个点之后延迟急剧上升、错误率飙升。这个临界点就是你的真实容量上限。3.2 三级限流 优先级队列的具体实现基于这个认知我设计了一个三级限流方案。第一级是入口限流在 Rust 调度器的最前面用令牌桶算法控制总的请求速率。令牌桶的容量和填充速率根据你的模型配额来设定比如配额是 60 次/分钟那填充速率就是 1 次/秒桶容量设 10 个作为突发缓冲。超过的请求直接返回 429让客户端稍后重试而不是让它们堆积在系统里。第二级是用户级限流防止单个用户或单个租户占满所有配额。我用 Redis 的滑动窗口实现每个用户每分钟最多 10 次请求。这个数字可以根据用户等级动态调整付费用户给更高配额。实现的时候要注意滑动窗口的粒度不要太细否则 Redis 的读写压力会很大。我一开始用秒级窗口结果 Redis QPS 飙到几万后来改成 10 秒级窗口精度略降但压力小了一个数量级。第三级是模型调用级限流在 Python Worker 里对每个模型供应商的客户端做并发控制。用信号量Semaphore限制同时进行的调用数这个数等于你的配额除以平均延迟。比如配额 60 次/分钟、平均延迟 5 秒那信号量就设 5。这样即使上游调度器放进来更多请求Worker 这边也不会把模型接口打爆。优先级队列是配合限流用的。不是所有请求都同等重要我把请求分成三档实时交互用户在等回复最高优先级后台任务批量处理、定时任务中等优先级预计算和缓存预热最低优先级。队列用 Redis 的 Sorted Set 实现score 是优先级加时间戳的组合保证高优先级的先出队同优先级里先到先服务。3.3 队列积压时的降级策略与用户体验限流和队列只能解决“不崩”的问题解决不了“用户体验”的问题。当队列积压严重时用户等 30 秒还没收到回复体验极差。这时候需要降级策略。我的做法是分级降级。第一级降级是切换模型从高配模型切到低配模型牺牲一点质量换速度。第二级降级是简化流程跳过一些非必要的工具调用直接给一个快速回复。第三级降级是返回缓存结果或预设话术明确告诉用户“当前繁忙请稍后重试”。降级的触发条件要提前设定好不能等系统快挂了才临时决定。我用的指标是队列等待时间的 P95 值超过 10 秒触发一级降级超过 30 秒触发二级超过 60 秒触发三级。这些阈值要根据你的业务容忍度来调没有标准答案。实操心得降级策略一定要在压测环境里验证过再上线。我遇到过降级逻辑本身有 bug触发降级后反而把系统搞得更慢的情况。另外降级要有日志和告警事后要能分析出为什么触发了降级是流量真的太大还是某个下游服务变慢了。还有一个容易被忽视的点是客户端配合。如果你的 Agent 是通过 API 对外服务的要在 API 文档里明确告诉调用方遇到 429 要退避重试退避时间建议用指数退避加随机抖动。我见过太多客户端收到 429 后立刻重试结果把服务端打得更惨。服务端能做的是在 429 响应里带上Retry-After头告诉客户端等多久再试。4. 状态管理与工具调用那些文档不会告诉你的细节4.1 多轮对话状态到底该怎么存多轮对话的状态管理我经历了三个阶段。第一阶段用内存字典简单直接但服务重启就丢而且没法水平扩展。第二阶段用 Redis 存整个对话历史每次请求把历史读出来、拼进 prompt、再把新消息写回去。这个方案能用但有两个问题一是 Redis 的读写量很大每轮对话都要全量读写二是 prompt 越来越长token 消耗和延迟都线性增长。第三阶段我改成了分层存储 摘要压缩。热数据最近 5 轮对话存在 Redis 里用 Hash 结构每个字段是一轮对话这样读写可以精确到轮次不用全量操作。温数据5 轮到 20 轮存在 MongoDB 里按需加载。冷数据20 轮以上做摘要压缩用一个小模型把历史对话总结成一段话只保留关键信息原始对话归档到对象存储。摘要压缩的触发时机很关键。我一开始每轮都压缩结果小模型调用太频繁成本反而上去了。后来改成每 5 轮压缩一次或者当 token 数超过阈值时压缩。压缩后的摘要会替换掉原始历史prompt 长度能控制在合理范围内。还有一个细节是状态的一致性。如果 Agent 在调用工具的过程中服务重启了状态怎么恢复我的做法是每一步操作都先写日志用 Redis 的 Stream 或者 Kafka记录操作类型、输入、输出、时间戳。服务重启后从日志里重放未完成的操作。这个机制我参考了事件溯源Event Sourcing的思路虽然增加了复杂度但对于需要保证“至少执行一次”的工具调用来说是必要的。4.2 工具调用的可靠性设计重试、熔断、幂等工具调用是 Agent 最容易出问题的环节。模型可能调用一个不存在的工具可能传错参数可能调用一个已经下线的 API。外部 API 可能超时、可能限流、可能返回格式不对。这些问题每一个都要处理。我的工具调用网关做了几件事。第一是工具注册与校验所有可用工具在网关里注册包括工具名、参数 schema、超时时间、重试策略。模型输出的工具调用请求先经过 schema 校验不合法直接拒绝不让它打到外部 API。第二是重试与退避对于可重试的错误超时、5xx用指数退避重试最多 3 次。对于不可重试的错误4xx、参数错误直接返回失败。第三是熔断如果某个工具的错误率超过阈值自动熔断一段时间期间所有调用直接返回降级结果不再打外部 API。第四是幂等对于有副作用的工具比如发消息、下单要求调用方传一个幂等键网关根据幂等键去重防止重试导致重复操作。注意幂等键的生成要小心。我一开始用请求 ID 做幂等键但重试的时候请求 ID 会变导致幂等失效。后来改成用“会话 ID 工具名 参数哈希”作为幂等键这样同样的调用无论重试多少次都只会执行一次。还有一个坑是工具返回结果的大小。有些工具返回的数据量很大直接塞进 prompt 会爆 token。我在网关里加了一个截断和摘要的逻辑超过一定大小的结果先截断然后让模型自己决定要不要进一步查询。这个逻辑要跟 prompt 设计配合在系统提示里告诉模型“如果结果被截断你可以用更精确的参数重新调用”。4.3 可观测性让 Agent 的黑盒变透明Agent 的可观测性是我花了最长时间才做好的部分。一开始我只记了请求日志和错误日志但排查问题时发现根本不够——你不知道模型为什么选了那个工具不知道每一步的耗时分布不知道 token 消耗在哪里。后来我引入了全链路追踪。每个请求生成一个 trace ID贯穿调度器、Worker、工具网关、模型调用。每个环节都记录 span包括开始时间、结束时间、输入摘要、输出摘要、状态。用 OpenTelemetry 做标准化的追踪数据采集后端接 Jaeger 做可视化。这样任何一个请求我都能看到完整的调用链路和每一步的耗时。除了追踪我还做了指标监控。关键指标包括请求量、成功率、P50/P95/P99 延迟、队列长度、模型调用次数、token 消耗、工具调用成功率、降级触发次数。这些指标用 Prometheus 采集Grafana 做面板。我设了一组告警规则比如成功率低于 95% 持续 5 分钟就告警队列长度超过 100 就告警。日志方面我区分了访问日志和调试日志。访问日志记录每个请求的基本信息用于审计和计费。调试日志记录详细的内部状态默认关闭需要排查问题时动态开启。调试日志的量很大我用了采样策略正常请求采样 1%错误请求 100% 记录。这套可观测性体系建好之后排查问题的效率提升了一个数量级。以前遇到“Agent 回复质量下降”这种问题只能靠猜现在可以精确地看到是哪一步出了问题是模型选错了工具还是工具返回了错误数据还是 prompt 拼接有问题。5. 去 iRTE2026 之前我整理了一份必问清单5.1 我准备在现场重点关注的几个方向这半年踩的坑让我意识到AI Agent 的工程化是一个系统性工程涉及架构、并发、状态、工具、可观测性等多个维度每个维度都有大量细节。我一个人闷头搞效率太低了。iRTE2026 这种场合能一次性接触到大量真实项目的一手经验对我来说价值极大。我整理了一份现场必问清单分几个方向。第一个方向是并发与调度我想知道别人是怎么处理模型配额瓶颈的有没有比我更好的限流和队列方案Rust 在 Agent 中台里的应用有没有更多实践案例。第二个方向是状态管理特别是长对话的摘要压缩策略有没有更成熟的方案事件溯源在 Agent 场景下有没有坑。第三个方向是工具调用的可靠性幂等、熔断、重试这些机制不同团队是怎么落地的有没有标准化的工具网关开源项目。第四个方向是可观测性除了 OpenTelemetry还有没有更适合 Agent 的追踪方案怎么追踪模型内部的推理过程。除了技术方向我还想了解团队协作和工程流程。AI Agent 项目的迭代节奏跟传统软件很不一样prompt 的修改、工具的增减、模型的切换这些变更怎么管理怎么做回归测试怎么保证上线不翻车。这些问题在文档里找不到答案只能靠跟同行交流。5.2 给准备入坑 AI Agent 的朋友几条实在建议如果你刚开始做 AI Agent或者正准备从 Demo 往生产推我有几条实在建议。第一不要一上来就追求完美架构。先用最简单的方案把流程跑通验证核心价值然后再逐步优化。我见过太多人一开始就纠结用 Rust 还是 Python、用 LangChain 还是自己写结果两个月过去了还在选型。第二把可观测性放在优先级很高的位置。Agent 的行为不确定性太强没有日志和追踪你根本不知道发生了什么。我建议在写第一行业务代码之前先把日志和追踪的框架搭好。第三限流和降级不是可选项是必选项。只要你对外提供服务就一定会遇到流量突增或者下游变慢的情况。提前设计好限流和降级策略比事后救火成本低得多。第四状态管理要提前想清楚。多轮对话的状态怎么存、存多久、怎么压缩这些问题在 Demo 阶段可能不明显但用户量一上来就会暴露。我建议在项目初期就确定状态存储的方案不要等到出问题了再改。第五工具调用要有统一的网关。不要让 Agent 直接调用外部 API中间加一层网关统一做校验、重试、熔断、幂等、日志。这层网关的投入会在后续的维护中加倍回报给你。5.3 关于 iRTE2026 的参会准备与预期去 iRTE2026 之前我做了几件事。一是把自己的问题和踩坑整理成文档方便现场跟人交流时快速说明背景。二是提前看了议程和讲师背景标记出最想听的场次和最想认识的人。三是准备了一个简单的 Demo万一有机会展示可以快速让人理解我在做什么。我对这次参会的预期很明确不是去听概念和趋势而是去挖可落地的工程细节。AI Agent 这个领域概念已经讲得够多了缺的是“怎么做”和“踩过什么坑”。我希望能在现场听到真实的项目复盘看到具体的代码和配置认识几个同样在坑里的朋友后续能持续交流。如果你也在做 AI Agent也在为并发、状态、工具调用这些问题头疼我建议你也去现场看看。这个领域变化太快闭门造车很容易走弯路。跟同行交流半天可能比自己查一周文档收获还大。我自己的体会是AI Agent 的工程化没有银弹但有大量前人踩过的坑可以借鉴。iRTE2026 就是一个集中获取这些经验的地方至少对我来说这半年的卡点值得去现场找找答案。