Machine Learning Mastery

Stateful vs. Stateless Agent Design: Tradeoffs for Scalable Agentic Systems

8.5内容质量

TL;DR · AI 摘要

状态化与无状态代理设计在可扩展系统中各有优劣,选择需权衡可扩展性、成本和复杂性。文章通过Groq API实现案例对比两种架构差异。

核心要点

  • 无状态代理依赖客户端维护对话历史,适合高并发场景但缺乏上下文连续性
  • 状态化代理通过数据库存储记忆,支持复杂交互但增加运维复杂度
  • Groq的Llama 3.1 8B模型因14,400/天免费调用额度适合演示实现

结构提纲

按章节快速跳转。

  1. 介绍代理系统设计中状态存储位置对架构的决定性影响

  2. 通过Groq API展示客户端维护对话历史的实现方式

  3. 演示基于数据库层的记忆管理架构实现

  4. 解释Llama 3.1 8B模型在免费层级的性价比优势

  5. 对比两种设计在可扩展性、成本和复杂度的差异

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 状态化与无状态代理设计
    • 无状态代理
      • 客户端维护状态
      • 水平扩展优势
    • 有状态代理
      • 数据库存储记忆
      • 运维复杂度高
    • 实现案例
      • Groq API集成
      • Llama 3.1模型使用

金句 / Highlights

值得收藏与分享的关键句。

#AI代理#可扩展系统#状态管理#Groq API
打开原文

有状态与无状态代理设计:可扩展代理系统的权衡 - MachineLearningMastery.com

有状态与无状态代理设计:可扩展代理系统的权衡

作者

Iván Palomares Carrascosa

2026年7月24日

分类

人工智能

1

分享

文章

在本文中,你将学习代理处理状态的方式(无状态或有状态)如何影响其实现方式以及围绕它的部署架构。

我们将涵盖的主题包括:

  • 无状态代理与有状态代理的区别,以及每种设计对扩展性带来的权衡。
  • 如何实现一个完全依赖客户端提供对话历史记录的无状态代理。
  • 如何实现一个通过数据库层管理自身内存的有状态代理。

介绍

之前的一篇文章详细阐述了AI代理部署的全面架构路线图,考察了将代理引入生产环境所需的基础设施。

作为后续内容,我们现在转向一个基本且实际的问题,这个问题必须在配置任何负载均衡器之前得到解答:代理的内存存储在哪里?代理可能以不同方式处理其状态(到目前为止获得的上下文和对话历史),这种代码层面的决策可能会显著影响整个部署架构。

本文将分解处理代理状态的两种主要范式:无状态和有状态设计。通过使用快速Groq API提供的开源语言模型的简化版真实实现,将展示这些概念的实际应用。

初始设置

如果你是第一次在Python程序中使用Groq的语言模型,需要安装所需的库:pip install groq。

安装完成后,我们导入库并在以下代码中设置Groq API密钥:

import os from groq import Groq

在https://console.groq.com/keys获取API密钥并在此处设置

os.environ["GROQ_API_KEY"] = "PASTE_YOUR_GROQ_API_KEY_HERE"

初始化客户端

client = Groq()

使用Groq的高效模型:Llama 3.1 8B Instant

MODEL_ID = "llama-3.1-8b-instant"

2

3

4

5

6

7

8

9

10

11

import

os

from

groq

在https://console.groq.com/keys获取API密钥并在此处设置

.

environ

[

"GROQ_API_KEY"

]

=

"PASTE_YOUR_GROQ_API_KEY_HERE"

初始化客户端

client

(

)

使用Groq的高效模型:Llama 3.1 8B Instant

MODEL_ID

"llama-3.1-8b-instant"

此处一个重要的设置决策是选择特定模型。llama-3.1-8b-instant是一个高度成本效益的模型,在撰写本文时,Groq的2026年免费套餐慷慨地支持该模型:每天最多允许14,400次请求。这使其成为下文说明无状态和有状态代理范式的理想选择。

无状态代理:即发即弃

无状态代理将每个请求视为完全独立和隔离的。代理读取用户提示,调用LLM推理引擎,并交付输出。一旦该执行周期结束,所有信息都会被遗忘。

权衡

基于无状态代理的架构可以非常轻松地进行水平扩展。由于后端服务器上不会存储任何用户内存,传入的请求可以转发到任何可用的实例。然而,在多轮对话中存在一个重要限制:前端必须在每次新请求时重新发送整个对话历史记录。因此,上下文窗口会像雪球一样不断增长,迅速增加令牌使用量。

示例说明

以下可运行的代码通过一个基础场景,展示了无状态代理通常如何与Groq语言模型进行交互。

首先,我们定义了一个stateless_agent函数,该函数模拟代理与所选模型的交互。重要的是,该函数内部不会保留任何对话状态或记忆。相反,客户端可以将之前的对话历史记录作为参数传入,并追加到当前提示中。对Groq模型的API调用发生在client.chat.completions.create()中。

python
def stateless_agent(prompt: str, provided_history: list = None) -> str:
    """代理完全依赖客户端提供上下文。它不会在本地内存中保留任何历史交互信息。"""
    # 使用系统提示初始化
    messages = [{"role": "system", "content": "You are a helpful, concise assistant."}]
    # 如果客户端提供了历史记录则追加
    if provided_history:
        messages.extend(provided_history)
    # 追加新的提示
    messages.append({"role": "user", "content": prompt})
    # LLM处理整个消息链
    response = client.chat.completions.create(
        model=MODEL_ID,
        messages=messages,
        max_tokens=100
    )
    return response.choices[0].message.content.strip()

为了理解无状态代理的局限性,我们通过以下代码模拟一个简单的用户-模型对话:

python
# --- 测试无状态代理 ---
print("--- 第1轮 ---")
prompt_1 = "Hi, my name is Alice and I am learning about API infrastructure."
response_1 = stateless_agent(prompt_1)
print(f"Agent: {response_1}")

print("\n--- 第2轮(无客户端上下文)---")
# 由于代理未保留第1轮的记忆,此处会失败
prompt_2 = "What is my name and what am I learning about?"
response_2 = stateless_agent(prompt_2)
print(f"Agent: {response_2}")

print("\n--- 第2轮(有客户端上下文)---")
# 前端必须将历史记录注入到负载中,代理才能成功
frontend_payload = [
    {"role": "user", "content": prompt_1},
    {"role": "assistant", "content": response_1}
]
response_3 = stateless_agent(prompt_2, provided_history=frontend_payload)
print(f"Agent: {response_3}")

代理在此处失败,因为它没有保留第一轮的任何记忆

prompt_2

"我的名字是什么,我正在学习什么?"

response_2

"代理:{response_2}"

"\n--- 第二轮(无客户端上下文)---"

前端必须将历史记录注入到有效负载中,代理才能成功

frontend_payload

"助手"

response_3

"代理:{response_3}"

输出:

--- 第一轮 --- 代理:你好 Alice,很高兴见到你。学习 API 基础设施可以是一个迷人且富有回报的主题。你对 API 基础设施的哪些具体方面感兴趣或想讨论?你在寻找关于 API 管理、安全、部署或其他方面的信息吗? --- 第二轮(无客户端上下文) --- 代理:不幸的是,我没有任何关于你的信息,包括你的名字。我们的对话刚刚开始,所以我在这里帮助你解答任何你想了解的问题或主题。请随时分享你的名字和你感兴趣的某个主题。 --- 第二轮(有客户端上下文) --- 代理:你的名字是 Alice,你正在学习 API 基础设施。

--

-

轮次

代理

你好

Alice

很高兴

见到

学习

关于

API

基础设施

可以

一个

迷人

富有

回报

的主题

什么

具体

方面

探索

讨论

寻找

关于

管理

安全

部署

或其他

东西

信息

上下文

不幸的是

没有

任何

关于

你的

信息

包括

你的

名字

我们的

对话

刚刚

开始

所以

在这里

帮助

解答

任何

你想

了解

的问题

主题

随时

分享

你的

名字

感兴趣的

某个

主题

你的

名字

实现

很简单

如果没有

客户端

前端

每一轮

完整

对话

历史

发送

代理

代理

大型

语言

模型

就会

缺乏

回答

某些

问题

所需

上下文

有状态代理:基于上下文的连续性

在这种方法下,代理本身承担记忆负担。同时,客户端只需发送最新的用户提示以及一个唯一的标识符,通常与当前会话相关联。代理随后从数据库中检索会话历史或上下文,并将其附加到新消息上。一旦处理完大型语言模型的推理,代理就会更新数据库中的上下文。

从客户端的角度来看,这是一种更整洁的体验。它还促进了复杂的异步工作流程,其中代理可能需要暂停执行并等待工具、应用程序响应或人工批准。但这一切都伴随着成本:随着解决方案的扩展变得困难,首先是架构中需要持久数据库层。在水平扩展的基础设施中,为了防止“局部遗忘”,即会话历史记录被困在处理早期轮次的单个实例上,可能还需要采用诸如使用 Redis 的集中式内存缓存等策略。

我们通过引入一个“持久”数据库层来说明有状态代理的基本概念。为简单起见,我们使用一个小型的 SQLite 数据库。关键是让代理自行管理对话记忆,而不是依赖前端从外部提供:

/think

import sqlite3 import json

为笔记本测试初始化一个内存中的SQLite数据库

conn = sqlite3.connect(':memory:') cursor = conn.cursor() cursor.execute('''CREATE TABLE IF NOT EXISTS agent_memory (session_id TEXT PRIMARY KEY, history TEXT)''') conn.commit()

def stateful_agent(session_id: str, new_prompt: str) -> str: """代理使用数据库管理自己的状态。客户端只需发送新提示和会话ID"""

1. 从数据库中检索现有状态

cursor.execute("SELECT history FROM agent_memory WHERE session_id=?", (session_id,)) row = cursor.fetchone()

if row: conversation_history = json.loads(row[0]) else:

为新会话初始化系统提示

conversation_history = [{"role": "system", "content": "你是一个有帮助且简洁的助手。"}]

2. 添加新用户提示

conversation_history.append({"role": "user", "content": new_prompt})

3. 使用检索到的历史记录处理LLM调用

response = client.chat.completions.create( model=MODEL_ID, messages=conversation_history, max_tokens=100 ).choices[0].message.content.strip()

4. 用助手的回复更新状态

conversation_history.append({"role": "assistant", "content": response})

5. 将新状态保存回数据库

cursor.execute(''' INSERT INTO agent_memory (session_id, history) VALUES (?, ?) ON CONFLICT(session_id) DO UPDATE SET history=excluded.history ''', (session_id, json.dumps(conversation_history))) conn.commit()

return response

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

sqlite3

json

为笔记本测试初始化一个内存中的SQLite数据库

conn

connect

':memory:'

cursor

execute

''

'CREATE TABLE IF NOT EXISTS agent_memory (session_id TEXT PRIMARY KEY, history TEXT)'

commit

stateful_agent

session_id

new_prompt

代理使用数据库管理自己的状态。

客户端只需发送新提示和会话ID。

1. 从数据库中检索现有状态

"SELECT history FROM agent_memory WHERE session_id=?"

row

fetchone

conversation_history

loads

为新会话初始化系统提示

2. 添加新用户提示

3. 使用检索到的历史记录处理LLM调用

4. 用助手的回复更新状态

5. 将新状态保存回数据库

'

INSERT INTO agent_memory (session_id, history)

VALUES (?, ?)

ON CONFLICT(session_id) DO UPDATE SET history=excluded.history

dumps

注意会话标识符是如何用于从当前对话的历史交互中查询相关信息的。

现在让我们在一个类似之前的对话中进行测试,但这次用户要求代理回忆用户自己的名字:

--- 测试有状态代理 ---

print("--- 第1轮 ---") print(f"代理: {stateful_agent('user_123', '你好,我是Bob,我想扩展我的AI应用。')}") print("\n--- 第2轮 ---")

注意客户端现在不再发送上下文负载,只发送会话ID

print(f"代理: {stateful_agent('user_123', '我的名字是什么?')}")

--- 测试有状态代理 ---

"代理: {stateful_agent('user_123', '你好,我是Bob,我想扩展我的AI应用。')}"

"\n--- 第2轮 ---"

注意客户端现在不再发送上下文负载,只发送会话ID

"代理: {stateful_agent('user_123', '我的名字是什么?')}"

--- 第1轮 --- Agent:你好 Bob,扩展AI应用可能是一个复杂的过程。请问:

  1. 您的应用是基于哪种AI技术构建的?(例如,机器学习、自然语言处理、计算机视觉)
  2. 您是否使用了AWS、Google Cloud或Azure等云服务?
  3. 您的扩展目标是什么?(例如,增加用户数量、降低延迟、提升响应速度)

这些信息将帮助我更好地理解您的需求,并提供更有效的帮助。

--- 第2轮 --- Agent:您的名字是Bob。

Bob

扩展

AI

应用

复杂

过程

May

ask

1.

类型

技术

built

e

g

machine

natural

language

processing

computer

vision

2.

using

cloud

services

AWS

Google

Azure

3.

scalability

goals

increase

user

count

reduce

latency

improve

times

This

will

me

better

understand

requirements

provide

more

effective

assistance

这个示例当然与实际生产架构还有很大差距,但它有助于阐明有状态代理和无状态代理工作方式的关键差异。

总结:权衡取舍

在有状态和无状态架构设计之间的选择,归根结底是将基础设施与工作流程正确匹配:

  • 无状态代理更适合简单且目标明确的流水线,例如文本提取、摘要生成或单轮对话的分类聊天机器人。它们保持架构轻量,在此类用例中通常已足够,可避免数据库瓶颈并实现无缝横向扩展。
  • 如果计划开发长期运行的助手、代码助手或客服场景中的多轮对话机器人,有状态代理则更有意义。由于代理自身保存对话历史,每次交互的客户端负载保持较小,对话内容可以在服务器端进行裁剪或摘要,而无需重复发送完整内容。

更多相关内容

  • 用于时间序列的有状态和无状态LSTM…
  • 有状态LSTM在线学习的不稳定性…
  • 理解有状态LSTM循环神经网络…
  • 长期运行代理的上下文窗口管理…
  • AI代理工具设计:哪些有效,哪些无效
  • 多代理系统:AI驱动的下一个前沿领域

/.entry /think