跳到主要内容

无共享智能体:为水平可扩展性设计 AI 智能体

· 阅读需 13 分钟
Tian Pan
Software Engineer

你的负载均衡器将一个传入的智能体请求分配给副本 3。但用户的对话历史存储在副本 7 的内存中。副本 3 完全不知道过去六轮发生了什么,于是它从头开始,让用户一头雾水,你的值班工程师在凌晨 2 点被叫醒。你启用了会话粘滞。现在该用户的所有请求永远路由到副本 7。你用一个正确性问题换来了一个可扩展性天花板。

就在这一刻,团队意识到:AI 智能体的"水平扩展"和 Web 服务器的水平扩展根本不是同一个问题。修复方式不同,而那些看似直接的路径会以可预见的方式失败。

根本原因是隐式状态。大多数智能体实现将上下文积累在进程内部——对话历史、临时文件、中间工具输出、检查点数据——从未考虑当该进程消失或第二个进程尝试处理同一用户时会发生什么。这对原型来说没问题,在生产环境中却会严重失效。

解决方案来自分布式系统,而非 AI 研究:无共享架构原则。将每个智能体副本设计为对先前工作没有任何记忆。通过外部系统引入所有所需上下文,并将所有输出写回这些系统。让每个操作都可以安全重试。坚持这样做,你就能实现真正的水平可扩展性——添加副本、分发负载、优雅处理故障。本文将介绍如何实现这一目标。

为什么智能体会积累状态(以及为什么这很重要)

LLM 在设计上是无状态的。每次推理调用接收一个完整的提示并生成响应,模型内部没有隐藏的会话对象。这就是 LLM 提供商能够服务数百万用户的原因:每个请求都是独立的。

智能体打破了这一特性。智能体框架用控制循环包裹 LLM 调用,维护以下内容:

  • 对话历史:提供上下文所需的轮次序列
  • 工具输出:用于指导当前推理的先前调用结果
  • 工作文件:执行过程中写入的文档、日志、数据文件
  • 检查点数据:循环中断时恢复所需的足够状态

当这些数据存活在进程内存或本地文件系统中,你就创建了一个有状态的进程。添加第二个副本没有帮助——它无法访问第一个副本的内存。你需要会话粘滞,这意味着一个副本处理来自特定用户或会话的所有请求。你以运维麻烦换来了毫无意义的扩展。

随着智能体能力增强,问题会进一步恶化。一个处理 20 步研究任务的智能体可能积累数百 KB 的中间上下文。运行了 90 分钟的智能体积累了工具输出、部分结果和推理步骤,这些东西只存在于运行它的那台机器上。当那台机器重启,一切都丢失了。

无共享原则在智能体上的应用

无共享是一种分布式系统架构,其中每个节点在不假设共享状态的情况下运行。节点不共享内存,不共享本地磁盘,只通过显式消息传递——API、队列、数据库——进行协调。经典实现是 Web 请求:请求到达池中的任意服务器,该服务器从数据库获取所需内容,处理请求,写回结果,然后返回。下一个请求可以去任意服务器。

对于智能体,等价原则是:每次智能体调用必须能在任何可用副本上运行。这需要三件事:

所有上下文必须存在于进程之外。 对话历史、工具结果和检查点数据存入外部存储——Redis 用于快速读取,数据库用于持久性,对象存储用于大型工件。智能体在每轮开始时获取所需内容,在结束时写回结果。

上下文重建必须可从元数据实现。 你不应该需要重放整个历史来从中间任务恢复。存储每个步骤的元数据——发生了什么、做出了什么决定、指向存储工件的指针——这样新副本可以在毫秒内重建足够的上下文。

所有工具调用必须可以安全重试。 当工具调用中途失败,或当智能体从检查点重启时,它可能会再次调用相同的工具。非幂等的工具在重试时会损坏状态。

这三个要求是独立的,每个都可以单独解决。但你需要全部三个才能实现完整的水平可扩展性。

外部状态:三个层级

生产智能体系统通常根据访问速度和成本将外部状态组织为三个层级。

热上下文(Redis):当前轮次的工作上下文——活跃会话的对话历史、最近的工具输出、智能体的当前计划。Redis 查询运行在 10-50ms,当你的目标是交互式智能体 200ms 以下的响应时间时,这很重要。这是每轮立即需要的数据。Redis 还提供基于 TTL 的过期,因此会话状态在对话结束时自动清理。

温上下文(向量数据库和关系型存储):历史上下文、检索到的事实、先前会话摘要。并非每次调用都需要这些——只有当智能体决定需要背景信息时。获取需要 50-200ms,作为按需操作是可以接受的。这里的访问模式是基于检索的:智能体查询相关的先前上下文,而不是加载所有内容。

冷存储(对象存储):大型工件——智能体处理的文档、完整的工具输出日志、归档的会话数据。这些很少被访问,即使被访问,几秒钟的延迟也可以接受。智能体在热上下文中存储指针而不是工件本身:不是将 50KB 的工具响应嵌入上下文窗口,而是将其存储到 S3 并保留 URL。

这些层级之间的实际分配因使用场景而异。有许多短会话的交互式智能体大量使用 Redis,很少接触对象存储。运行 30 分钟工作流的批处理智能体对持久性使用更多关系型存储,对中间工件使用更多对象存储。

关键设计规范:没有重要内容只存在于进程内存中。当智能体将文件写入 /tmp 时,这个决定就是技术债务。当工具结果只积累在内存中的对话对象中时,这就是扩展性负债。

加载中…
Let's stay in touch and Follow me for more thoughts and updates