Agent 系统中状态管理
·
在多 Agent 系统中,状态管理是决定系统协调性和效率的关键因素。让我为你详细解析状态管理的核心原理和实践方案。
1. 状态管理核心概念与挑战
1.1 状态类型分类
from enum import Enum
from typing import Dict, Any, List, Optional, Union
from dataclasses import dataclass
from datetime import datetime
import json
class StateType(Enum):
"""状态类型枚举"""
EPHEMERAL = "ephemeral" # 临时性状态(单次对话)
SESSION = "session" # 会话状态(用户会话期间)
SHARED = "shared" # 共享状态(跨Agent访问)
PERSISTENT = "persistent" # 持久化状态(长期存储)
CACHED = "cached" # 缓存状态(性能优化)
@dataclass
class AgentState:
"""Agent状态数据结构"""
state_id: str
state_type: StateType
owner_agent: str
shared_with: List[str] # 可访问的Agent列表
data: Dict[str, Any]
metadata: Dict[str, Any]
created_at: datetime
updated_at: datetime
ttl_seconds: Optional[int] = None # 生存时间
def is_expired(self) -> bool:
"""检查状态是否过期"""
if self.ttl_seconds is None:
return False
age = (datetime.now() - self.updated_at).total_seconds()
return age > self.ttl_seconds
def to_dict(self) -> Dict[str, Any]:
"""转换为字典格式"""
return {
"state_id": self.state_id,
"state_type": self.state_type.value,
"owner_agent": self.owner_agent,
"shared_with": self.shared_with,
"data": self.data,
"metadata": self.metadata,
"created_at": self.created_at.isoformat(),
"updated_at": self.updated_at.isoformat(),
"ttl_seconds": self.ttl_seconds
}
1.2 状态管理核心挑战
| 挑战 | 描述 | 影响 |
|---|---|---|
| 一致性 | 多Agent同时读写状态 | 数据冲突、脏读 |
| 并发控制 | 状态更新的时序问题 | 竞态条件 |
| 访问控制 | 状态权限和隔离 | 安全漏洞 |
| 性能 | 大规模状态同步开销 | 系统延迟 |
| 一致性模型 | 强一致性vs最终一致性 | 复杂性权衡 |
2. 集中式状态管理模式
2.1 中央状态管理器
class CentralizedStateManager:
"""集中式状态管理器"""
def __init__(self):
self.global_state_store: Dict[str, AgentState] = {}
self.agent_access_control: Dict[str, List[str]] = {} # Agent权限
self.state_locks: Dict[str, str] = {} # 状态锁
self.subscribers: Dict[str, List[str]] = {} # 状态订阅者
async def update_state(self, state: AgentState, requesting_agent: str) -> bool:
"""更新状态(带权限检查和锁机制)"""
# 1. 权限检查
if not self._check_write_permission(state.state_id, requesting_agent):
raise PermissionError(f"Agent {requesting_agent} cannot modify state {state.state_id}")
# 2. 获取锁(防止并发写入)
lock_acquired = await self._acquire_lock(state.state_id, requesting_agent)
if not lock_acquired:
raise ConcurrentModificationError(f"State {state.state_id} is locked by another agent")
try:
# 3. 检查状态是否存在
if state.state_id in self.global_state_store:
existing_state = self.global_state_store[state.state_id]
# 4. 合并更新(保留未修改的字段)
merged_data = self._merge_state_data(existing_state.data, state.data)
state.data = merged_data
# 5. 更新时间戳
state.updated_at = datetime.now()
# 6. 存储状态
self.global_state_store[state.state_id] = state
# 7. 通知订阅者
await self._notify_subscribers(state.state_id, state)
return True
finally:
# 8. 释放锁
await self._release_lock(state.state_id, requesting_agent)
async def get_state(self, state_id: str, requesting_agent: str) -> Optional[AgentState]:
"""获取状态(带权限检查)"""
if state_id not in self.global_state_store:
return None
state = self.global_state_store[state_id]
# 权限检查
if not self._check_read_permission(state_id, requesting_agent):
raise PermissionError(f"Agent {requesting_agent} cannot read state {state_id}")
# 检查过期
if state.is_expired():
del self.global_state_store[state_id]
return None
return state
def _check_write_permission(self, state_id: str, agent_id: str) -> bool:
"""检查写权限"""
if state_id not in self.global_state_store:
return True # 新状态允许创建
state = self.global_state_store[state_id]
return (agent_id == state.owner_agent or
agent_id in state.shared_with or
self._is_admin(agent_id))
def _check_read_permission(self, state_id: str, agent_id: str) -> bool:
"""检查读权限"""
if state_id not in self.global_state_store:
return False
state = self.global_state_store[state_id]
return (agent_id == state.owner_agent or
agent_id in state.shared_with or
state.state_type == StateType.SHARED or
self._is_admin(agent_id))
async def _acquire_lock(self, state_id: str, agent_id: str, timeout: int = 30) -> bool:
"""获取状态锁"""
import asyncio
start_time = datetime.now()
while (datetime.now() - start_time).seconds < timeout:
if state_id not in self.state_locks or self.state_locks[state_id] is None:
self.state_locks[state_id] = agent_id
return True
await asyncio.sleep(0.1)
return False
async def _release_lock(self, state_id: str, agent_id: str):
"""释放状态锁"""
if state_id in self.state_locks and self.state_locks[state_id] == agent_id:
self.state_locks[state_id] = None
class ConcurrentModificationError(Exception):
"""并发修改异常"""
pass
2.2 实际应用场景:项目协作状态管理
class ProjectCollaborationState:
"""项目协作状态管理"""
def __init__(self, state_manager: CentralizedStateManager):
self.state_manager = state_manager
self.project_states = {}
async def initialize_project(self, project_id: str, team_agents: List[str]):
"""初始化项目状态"""
# 创建项目主状态
project_state = AgentState(
state_id=f"project_{project_id}",
state_type=StateType.SHARED,
owner_agent="project_manager",
shared_with=team_agents,
data={
"project_id": project_id,
"status": "initialized",
"progress": 0,
"milestones": {},
"team_assignments": {},
"resources": {},
"risks": [],
"decisions": []
},
metadata={
"version": 1,
"created_by": "project_manager"
},
created_at=datetime.now(),
updated_at=datetime.now(),
ttl_seconds=86400 * 30 # 30天过期
)
await self.state_manager.update_state(project_state, "project_manager")
self.project_states[project_id] = project_state
# 为每个团队成员创建个人工作状态
for agent in team_agents:
await self._initialize_agent_state(project_id, agent)
async def _initialize_agent_state(self, project_id: str, agent_id: str):
"""初始化Agent工作状态"""
agent_state = AgentState(
state_id=f"agent_{agent_id}_project_{project_id}",
state_type=StateType.SHARED,
owner_agent=agent_id,
shared_with=["project_manager", agent_id],
data={
"project_id": project_id,
"assigned_tasks": [],
"completed_tasks": [],
"current_focus": None,
"blockers": [],
"progress_notes": [],
"availability": "available"
},
metadata={
"version": 1,
"role": self._get_agent_role(agent_id)
},
created_at=datetime.now(),
updated_at=datetime.now(),
ttl_seconds=86400 * 7 # 7天过期
)
await self.state_manager.update_state(agent_state, agent_id)
async def update_task_progress(self, project_id: str, agent_id: str,
task_id: str, progress_data: Dict[str, Any]):
"""更新任务进度(原子操作)"""
# 获取相关状态
project_state = await self.state_manager.get_state(
f"project_{project_id}", agent_id
)
agent_state = await self.state_manager.get_state(
f"agent_{agent_id}_project_{project_id}", agent_id
)
if not project_state or not agent_state:
raise ValueError("Required states not found")
# 构建事务性更新
updates = []
# 1. 更新Agent任务状态
task_found = False
for i, task in enumerate(agent_state.data["assigned_tasks"]):
if task["task_id"] == task_id:
agent_state.data["assigned_tasks"][i].update(progress_data)
task_found = True
break
if not task_found:
agent_state.data["assigned_tasks"].append({
"task_id": task_id,
**progress_data
})
# 2. 更新项目整体进度
if progress_data.get("status") == "completed":
agent_state.data["completed_tasks"].append(task_id)
# 重新计算项目进度
total_tasks = len(agent_state.data["assigned_tasks"])
completed = len(agent_state.data["completed_tasks"])
project_state.data["progress"] = (completed / total_tasks) * 100 if total_tasks > 0 else 0
# 3. 记录进度更新
progress_note = {
"timestamp": datetime.now().isoformat(),
"task_id": task_id,
"progress": progress_data,
"agent_id": agent_id
}
agent_state.data["progress_notes"].append(progress_note)
# 4. 原子性更新所有状态
await self.state_manager.update_state(agent_state, agent_id)
await self.state_manager.update_state(project_state, agent_id)
return {
"project_progress": project_state.data["progress"],
"agent_tasks_remaining": len([t for t in agent_state.data["assigned_tasks"]
if t.get("status") != "completed"])
}
async def handle_blocker(self, project_id: str, agent_id: str,
blocker_description: str, severity: str = "medium"):
"""处理工作阻塞"""
agent_state = await self.state_manager.get_state(
f"agent_{agent_id}_project_{project_id}", agent_id
)
# 添加阻塞记录
blocker = {
"id": f"blocker_{len(agent_state.data['blockers']) + 1}",
"description": blocker_description,
"severity": severity,
"reported_at": datetime.now().isoformat(),
"status": "open",
"reported_by": agent_id
}
agent_state.data["blockers"].append(blocker)
agent_state.data["availability"] = "blocked"
# 更新项目风险状态
project_state = await self.state_manager.get_state(
f"project_{project_id}", agent_id
)
risk_entry = {
"type": "blocker",
"description": blocker_description,
"affected_agent": agent_id,
"severity": severity,
"detected_at": datetime.now().isoformat()
}
project_state.data["risks"].append(risk_entry)
# 原子更新
await self.state_manager.update_state(agent_state, agent_id)
await self.state_manager.update_state(project_state, agent_id)
# 如果是高风险,通知项目经理
if severity in ["high", "critical"]:
await self._notify_project_manager(project_id, blocker)
return blocker
# 使用示例
async def demo_project_collaboration():
"""演示项目协作状态管理"""
state_manager = CentralizedStateManager()
collaboration = ProjectCollaborationState(state_manager)
# 初始化项目
team = ["alice_dev", "bob_qa", "charlie_designer", "diana_pm"]
await collaboration.initialize_project("proj_123", team)
# Alice 更新任务进度
result = await collaboration.update_task_progress(
project_id="proj_123",
agent_id="alice_dev",
task_id="task_001",
progress_data={
"status": "in_progress",
"completion_percentage": 60,
"notes": "API开发完成,正在进行单元测试"
}
)
print(f"Project progress: {result['project_progress']}%")
# Bob 报告阻塞
blocker = await collaboration.handle_blocker(
project_id="proj_123",
agent_id="bob_qa",
blocker_description="测试环境不稳定,无法执行回归测试",
severity="high"
)
print(f"Blocker reported: {blocker['id']}")
# 运行演示
import asyncio
# asyncio.run(demo_project_collaboration())
3. 分布式状态同步模式
3.1 事件驱动状态同步
import asyncio
from abc import ABC, abstractmethod
from typing import Callable, Awaitable
class StateEventBus:
"""状态事件总线"""
def __init__(self):
self.event_handlers: Dict[str, List[Callable]] = {}
self.event_queue = asyncio.Queue()
self.is_running = False
async def publish_event(self, event_type: str, event_data: Dict[str, Any]):
"""发布状态事件"""
event = {
"type": event_type,
"data": event_data,
"timestamp": datetime.now().isoformat(),
"event_id": f"evt_{len(self.event_queue._queue)}"
}
await self.event_queue.put(event)
def subscribe(self, event_type: str, handler: Callable[[Dict[str, Any]], Awaitable[None]]):
"""订阅状态事件"""
if event_type not in self.event_handlers:
self.event_handlers[event_type] = []
self.event_handlers[event_type].append(handler)
async def start_processing(self):
"""开始处理事件"""
self.is_running = True
while self.is_running:
try:
event = await asyncio.wait_for(self.event_queue.get(), timeout=1.0)
await self._dispatch_event(event)
except asyncio.TimeoutError:
continue
async def stop_processing(self):
"""停止事件处理"""
self.is_running = False
async def _dispatch_event(self, event: Dict[str, Any]):
"""分发事件到处理器"""
event_type = event["type"]
if event_type in self.event_handlers:
tasks = []
for handler in self.event_handlers[event_type]:
task = asyncio.create_task(handler(event["data"]))
tasks.append(task)
# 等待所有处理器完成
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)
class DistributedStateManager:
"""分布式状态管理器"""
def __init__(self, event_bus: StateEventBus, node_id: str):
self.event_bus = event_bus
self.node_id = node_id
self.local_cache: Dict[str, AgentState] = {}
self.sync_peers: List[str] = [] # 同步对等节点
self.conflict_resolution_strategy = "last_write_wins" # 冲突解决策略
# 订阅状态变化事件
self.event_bus.subscribe("state_updated", self._handle_remote_state_update)
self.event_bus.subscribe("state_request", self._handle_state_request)
async def update_local_state(self, state: AgentState) -> bool:
"""更新本地状态并广播"""
# 更新本地缓存
old_state = self.local_cache.get(state.state_id)
self.local_cache[state.state_id] = state
# 检查是否有冲突
if old_state and self._has_conflict(old_state, state):
resolved_state = await self._resolve_conflict(old_state, state)
if resolved_state:
state = resolved_state
else:
return False # 冲突无法解决
# 广播状态更新
await self.event_bus.publish_event("state_updated", {
"state": state.to_dict(),
"source_node": self.node_id,
"previous_version": old_state.data.get("version") if old_state else None
})
return True
async def request_state_sync(self, state_id: str, target_nodes: List[str] = None):
"""请求状态同步"""
sync_request = {
"state_id": state_id,
"requester_node": self.node_id,
"timestamp": datetime.now().isoformat()
}
targets = target_nodes or self.sync_peers
for target in targets:
await self.event_bus.publish_event("state_request", {
**sync_request,
"target_node": target
})
async def _handle_remote_state_update(self, event_data: Dict[str, Any]):
"""处理远程状态更新"""
remote_state_data = event_data["state"]
source_node = event_data["source_node"]
# 忽略自己发布的更新
if source_node == self.node_id:
return
remote_state = AgentState.from_dict(remote_state_data)
# 检查是否为最新版本
local_state = self.local_cache.get(remote_state.state_id)
if local_state and self._is_older_version(local_state, remote_state):
# 本地状态较旧,更新为远程状态
self.local_cache[remote_state.state_id] = remote_state
await self._notify_local_subscribers(remote_state.state_id, remote_state)
elif local_state and not self._is_older_version(local_state, remote_state):
# 可能存在冲突,需要解决
if self.conflict_resolution_strategy == "manual":
await self._handle_manual_conflict_resolution(local_state, remote_state)
elif self.conflict_resolution_strategy == "merge":
merged_state = await self._merge_states(local_state, remote_state)
self.local_cache[remote_state.state_id] = merged_state
else:
# 本地没有此状态,直接添加
self.local_cache[remote_state.state_id] = remote_state
def _has_conflict(self, old_state: AgentState, new_state: AgentState) -> bool:
"""检测状态冲突"""
if not old_state:
return False
# 检查版本冲突
old_version = old_state.data.get("version", 0)
new_version = new_state.data.get("version", 0)
# 如果新状态的版本不比旧状态新,可能存在冲突
if new_version <= old_version:
# 检查关键字段是否被修改
critical_fields = ["status", "progress", "assignments"]
for field in critical_fields:
if (old_state.data.get(field) != new_state.data.get(field) and
old_state.updated_at != new_state.updated_at):
return True
return False
async def _resolve_conflict(self, old_state: AgentState, new_state: AgentState) -> Optional[AgentState]:
"""解决状态冲突"""
if self.conflict_resolution_strategy == "last_write_wins":
# 最后写入获胜
return new_state if new_state.updated_at > old_state.updated_at else old_state
elif self.conflict_resolution_strategy == "merge":
# 尝试合并状态
return await self._merge_states(old_state, new_state)
elif self.conflict_resolution_strategy == "manual":
# 标记为需要手动解决
conflict_state = AgentState(
state_id=new_state.state_id,
state_type=new_state.state_type,
owner_agent="conflict_resolver",
shared_with=[old_state.owner_agent, new_state.owner_agent],
data={
"conflict_detected": True,
"old_state": old_state.to_dict(),
"new_state": new_state.to_dict(),
"resolution_required": True
},
metadata={"conflict": True},
created_at=datetime.now(),
updated_at=datetime.now()
)
return conflict_state
return None
async def _merge_states(self, state1: AgentState, state2: AgentState) -> AgentState:
"""合并两个状态"""
merged_data = {}
# 合并策略:对于冲突字段,保留两个版本
all_keys = set(state1.data.keys()) | set(state2.data.keys())
for key in all_keys:
val1 = state1.data.get(key)
val2 = state2.data.get(key)
if val1 == val2:
merged_data[key] = val1
else:
# 冲突字段,创建版本历史
merged_data[key] = {
"versions": [
{"value": val1, "source": state1.owner_agent, "timestamp": state1.updated_at.isoformat()},
{"value": val2, "source": state2.owner_agent, "timestamp": state2.updated_at.isoformat()}
],
"resolved_value": val2 # 默认采用较新的版本
}
# 创建合并后的状态
merged_state = AgentState(
state_id=state1.state_id,
state_type=state1.state_type,
owner_agent=f"merged_{state1.owner_agent}_{state2.owner_agent}",
shared_with=list(set(state1.shared_with + state2.shared_with)),
data=merged_data,
metadata={
**state1.metadata,
**state2.metadata,
"merged": True,
"merge_timestamp": datetime.now().isoformat()
},
created_at=min(state1.created_at, state2.created_at),
updated_at=datetime.now()
)
return merged_state
3.2 状态分区和分片
class ShardedStateManager:
"""分片状态管理器"""
def __init__(self, shard_count: int = 8):
self.shard_count = shard_count
self.shards: List[CentralizedStateManager] = [
CentralizedStateManager() for _ in range(shard_count)
]
self.shard_routing: Dict[str, int] = {} # state_id -> shard_index
def _get_shard_index(self, state_id: str) -> int:
"""获取状态应该存储的分片索引"""
if state_id in self.shard_routing:
return self.shard_routing[state_id]
# 使用一致性哈希确定分片
import hashlib
hash_value = int(hashlib.md5(state_id.encode()).hexdigest(), 16)
shard_index = hash_value % self.shard_count
self.shard_routing[state_id] = shard_index
return shard_index
def _get_shard(self, state_id: str) -> CentralizedStateManager:
"""获取对应分片的状态管理器"""
shard_index = self._get_shard_index(state_id)
return self.shards[shard_index]
async def update_state(self, state: AgentState, requesting_agent: str) -> bool:
"""跨分片更新状态"""
shard = self._get_shard(state.state_id)
return await shard.update_state(state, requesting_agent)
async def get_state(self, state_id: str, requesting_agent: str) -> Optional[AgentState]:
"""从对应分片获取状态"""
shard = self._get_shard(state_id)
return await shard.get_state(state_id, requesting_agent)
async def cross_shard_operation(self, operation_func: Callable, state_ids: List[str]):
"""跨分片操作(需要特殊处理)"""
# 按分片分组状态ID
shards_data = {}
for state_id in state_ids:
shard_index = self._get_shard_index(state_id)
if shard_index not in shards_data:
shards_data[shard_index] = []
shards_data[shard_index].append(state_id)
# 在每个分片上执行操作
results = {}
for shard_index, shard_state_ids in shards_data.items():
shard = self.shards[shard_index]
# 获取该分片的所有状态
shard_states = {}
for state_id in shard_state_ids:
state = await shard.get_state(state_id, "system")
if state:
shard_states[state_id] = state
# 在该分片上执行操作
shard_result = await operation_func(shard_states)
results.update(shard_result)
return results
4. 状态模式与设计模式应用
4.1 状态模式实现
from abc import ABC, abstractmethod
from typing import Protocol
class StateObserver(Protocol):
"""状态观察者协议"""
async def on_state_change(self, state_id: str, old_state: AgentState,
new_state: AgentState) -> None: ...
class StateSubject:
"""状态主体(被观察者)"""
def __init__(self):
self._observers: List[StateObserver] = []
self._state: Dict[str, AgentState] = {}
def attach(self, observer: StateObserver):
"""附加观察者"""
self._observers.append(observer)
def detach(self, observer: StateObserver):
"""分离观察者"""
self._observers.remove(observer)
async def _notify_observers(self, state_id: str, old_state: AgentState,
new_state: AgentState):
"""通知所有观察者"""
tasks = []
for observer in self._observers:
task = asyncio.create_task(
observer.on_state_change(state_id, old_state, new_state)
)
tasks.append(task)
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)
class ContextState(ABC):
"""上下文状态基类"""
@abstractmethod
def handle_request(self, state_manager: 'StatePatternManager',
state_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
pass
class InitialState(ContextState):
"""初始状态"""
def handle_request(self, state_manager: 'StatePatternManager',
state_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
if data.get("action") == "initialize":
# 转移到活跃状态
state_manager.set_state(ActiveState(), state_id)
return {"status": "initialized", "next_state": "active"}
return {"status": "invalid_action_for_initial_state"}
class ActiveState(ContextState):
"""活跃状态"""
def handle_request(self, state_manager: 'StatePatternManager',
state_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
action = data.get("action")
if action == "update":
# 处理状态更新
return state_manager._handle_active_update(state_id, data)
elif action == "pause":
# 转移到暂停状态
state_manager.set_state(PausedState(), state_id)
return {"status": "paused", "next_state": "paused"}
elif action == "complete":
# 转移到完成状态
state_manager.set_state(CompletedState(), state_id)
return {"status": "completed", "next_state": "completed"}
return {"status": "unknown_action"}
def _handle_active_update(self, state_manager, state_id, data):
# 具体的更新处理逻辑
return {"status": "updated", "state_id": state_id}
class PausedState(ContextState):
"""暂停状态"""
def handle_request(self, state_manager: 'StatePatternManager',
state_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
if data.get("action") == "resume":
state_manager.set_state(ActiveState(), state_id)
return {"status": "resumed", "next_state": "active"}
elif data.get("action") == "cancel":
state_manager.set_state(CancelledState(), state_id)
return {"status": "cancelled", "next_state": "cancelled"}
return {"status": "invalid_action_for_paused_state"}
class CompletedState(ContextState):
"""完成状态"""
def handle_request(self, state_manager: 'StatePatternManager',
state_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
# 完成状态通常不允许修改
return {"status": "cannot_modify_completed_state"}
class CancelledState(ContextState):
"""取消状态"""
def handle_request(self, state_manager: 'StatePatternManager',
state_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
return {"status": "cannot_modify_cancelled_state"}
class StatePatternManager:
"""状态模式管理器"""
def __init__(self):
self._states: Dict[str, ContextState] = {}
self._state_data: Dict[str, Dict[str, Any]] = {}
def set_state(self, state: ContextState, state_id: str):
"""设置状态"""
self._states[state_id] = state
async def handle_request(self, state_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
"""处理状态请求"""
if state_id not in self._states:
# 默认初始化状态
self.set_state(InitialState(), state_id)
state = self._states[state_id]
return state.handle_request(self, state_id, data)
def _handle_active_update(self, state_id: str, data: Dict[str, Any]):
"""处理活跃状态下的更新"""
if state_id not in self._state_data:
self._state_data[state_id] = {}
# 更新状态数据
self._state_data[state_id].update(data.get("updates", {}))
self._state_data[state_id]["last_updated"] = datetime.now().isoformat()
return {
"status": "updated",
"state_id": state_id,
"data": self._state_data[state_id]
}
4.2 备忘录模式实现状态快照
class StateMemento:
"""状态备忘录"""
def __init__(self, state_id: str, state_data: Dict[str, Any], timestamp: datetime):
self.state_id = state_id
self.state_data = state_data.copy() # 深拷贝
self.timestamp = timestamp
self.memento_id = f"memento_{state_id}_{int(timestamp.timestamp())}"
def get_state_data(self) -> Dict[str, Any]:
"""获取状态数据"""
return self.state_data.copy()
class StateCaretaker:
"""状态管理者(负责保存和恢复备忘录)"""
def __init__(self, max_snapshots: int = 10):
self.mementos: Dict[str, List[StateMemento]] = {}
self.max_snapshots = max_snapshots
def save_state(self, state: AgentState) -> StateMemento:
"""保存状态快照"""
memento = StateMemento(
state_id=state.state_id,
state_data=state.data,
timestamp=state.updated_at
)
if state.state_id not in self.mementos:
self.mementos[state.state_id] = []
self.mementos[state.state_id].append(memento)
# 维护快照数量限制
if len(self.mementos[state.state_id]) > self.max_snapshots:
self.mementos[state.state_id].pop(0) # 删除最旧的
return memento
def restore_state(self, state_id: str, memento_id: str) -> Optional[AgentState]:
"""恢复状态快照"""
if state_id not in self.mementos:
return None
for memento in self.mementos[state_id]:
if memento.memento_id == memento_id:
# 重建AgentState
restored_state = AgentState(
state_id=memento.state_id,
state_type=StateType.PERSISTENT, # 快照通常是持久化的
owner_agent="restored_from_memento",
shared_with=[],
data=memento.get_state_data(),
metadata={"restored_from": memento_id},
created_at=memento.timestamp,
updated_at=datetime.now()
)
return restored_state
return None
def get_available_snapshots(self, state_id: str) -> List[Dict[str, Any]]:
"""获取可用的快照列表"""
if state_id not in self.mementos:
return []
snapshots_info = []
for memento in self.mementos[state_id]:
snapshots_info.append({
"memento_id": memento.memento_id,
"timestamp": memento.timestamp.isoformat(),
"state_summary": {
"keys": list(memento.state_data.keys()),
"data_size": len(str(memento.state_data))
}
})
return sorted(snapshots_info, key=lambda x: x["timestamp"], reverse=True)
class StateSnapshotManager:
"""状态快照管理器"""
def __init__(self, state_manager: CentralizedStateManager):
self.state_manager = state_manager
self.caretaker = StateCaretaker()
self.auto_snapshot_enabled = True
self.snapshot_triggers = ["major_update", "state_transition", "manual_request"]
async def update_with_snapshot(self, state: AgentState,
requesting_agent: str,
create_snapshot: bool = None) -> bool:
"""更新状态并可选地创建快照"""
# 决定是否创建快照
should_snapshot = create_snapshot
if should_snapshot is None:
should_snapshot = self._should_create_snapshot(state)
# 保存当前状态(用于可能的回滚)
if should_snapshot:
old_state = await self.state_manager.get_state(state.state_id, requesting_agent)
if old_state:
self.caretaker.save_state(old_state)
# 更新状态
success = await self.state_manager.update_state(state, requesting_agent)
# 更新后创建新快照
if success and should_snapshot:
new_state = await self.state_manager.get_state(state.state_id, requesting_agent)
if new_state:
self.caretaker.save_state(new_state)
return success
def _should_create_snapshot(self, state: AgentState) -> bool:
"""判断是否应该创建快照"""
# 基于状态类型和更新内容决定
if state.state_type in [StateType.PERSISTENT, StateType.SHARED]:
return True
# 检查是否包含关键字段的更改
critical_fields_updated = any(
field in state.data for field in ["status", "progress", "assignments"]
)
return critical_fields_updated or self.auto_snapshot_enabled
async def rollback_state(self, state_id: str, memento_id: str,
requesting_agent: str) -> bool:
"""回滚状态到指定快照"""
# 恢复状态
restored_state = self.caretaker.restore_state(state_id, memento_id)
if not restored_state:
return False
# 更新状态管理器
success = await self.state_manager.update_state(restored_state, requesting_agent)
return success
5. 实际业务场景:智能客服状态管理
5.1 客服会话状态管理
class CustomerServiceStateManager:
"""客服会话状态管理器"""
def __init__(self):
self.session_states: Dict[str, AgentState] = {}
self.customer_contexts: Dict[str, Dict[str, Any]] = {}
self.conversation_history: Dict[str, List[Dict[str, Any]]] = {}
self.escalation_states: Dict[str, AgentState] = {}
async def initialize_customer_session(self, session_id: str, customer_id: str,
initial_context: Dict[str, Any]) -> AgentState:
"""初始化客户会话状态"""
# 创建会话状态
session_state = AgentState(
state_id=f"session_{session_id}",
state_type=StateType.SESSION,
owner_agent="customer_service_agent",
shared_with=["customer_service_agent", "supervisor_agent"],
data={
"session_id": session_id,
"customer_id": customer_id,
"status": "active",
"start_time": datetime.now().isoformat(),
"current_intent": None,
"resolved_issues": [],
"active_issues": [],
"satisfaction_score": None,
"interaction_count": 0,
"escalation_level": 0
},
metadata={
"channel": initial_context.get("channel", "chat"),
"priority": initial_context.get("priority", "normal"),
"language": initial_context.get("language", "zh-CN")
},
created_at=datetime.now(),
updated_at=datetime.now(),
ttl_seconds=3600 # 1小时过期
)
# 创建客户上下文
customer_context = {
"customer_id": customer_id,
"profile": initial_context.get("customer_profile", {}),
"preferences": initial_context.get("preferences", {}),
"history_summary": initial_context.get("history_summary", ""),
"current_emotion": "neutral",
"engagement_level": "medium"
}
# 初始化对话历史
conversation_history = [{
"timestamp": datetime.now().isoformat(),
"speaker": "system",
"message": "会话开始",
"intent": None,
"sentiment": "neutral"
}]
# 存储所有状态
self.session_states[session_id] = session_state
self.customer_contexts[customer_id] = customer_context
self.conversation_history[session_id] = conversation_history
return session_state
async def update_conversation_state(self, session_id: str, customer_id: str,
message: str, intent: str, sentiment: str,
agent_response: str = None) -> Dict[str, Any]:
"""更新对话状态"""
# 获取当前状态
session_state = self.session_states.get(session_id)
customer_context = self.customer_contexts.get(customer_id)
conversation_history = self.conversation_history.get(session_id, [])
if not session_state or not customer_context:
raise ValueError("Session or customer context not found")
# 更新对话计数
session_state.data["interaction_count"] += 1
session_state.data["current_intent"] = intent
# 更新客户情绪
if sentiment in ["negative", "frustrated"]:
customer_context["current_emotion"] = "negative"
customer_context["engagement_level"] = "low"
elif sentiment in ["positive", "satisfied"]:
customer_context["current_emotion"] = "positive"
customer_context["engagement_level"] = "high"
# 添加到对话历史
conversation_history.extend([
{
"timestamp": datetime.now().isoformat(),
"speaker": "customer",
"message": message,
"intent": intent,
"sentiment": sentiment
}
])
if agent_response:
conversation_history.append({
"timestamp": datetime.now().isoformat(),
"speaker": "agent",
"message": agent_response,
"intent": None,
"sentiment": "neutral"
})
# 检查是否需要升级
escalation_check = await self._check_escalation_trigger(
session_state, customer_context, conversation_history
)
if escalation_check["should_escalate"]:
await self._trigger_escalation(session_id, customer_id, escalation_check)
# 更新时间戳
session_state.updated_at = datetime.now()
return {
"session_state": session_state.data,
"customer_emotion": customer_context["current_emotion"],
"escalation_triggered": escalation_check["should_escalate"],
"suggested_actions": escalation_check.get("suggested_actions", [])
}
async def _check_escalation_trigger(self, session_state: AgentState,
customer_context: Dict[str, Any],
conversation_history: List[Dict[str, Any]]) -> Dict[str, Any]:
"""检查是否需要升级处理"""
triggers = []
suggested_actions = []
# 触发条件1:负面情绪持续
negative_interactions = len([
msg for msg in conversation_history[-5:]
if msg["speaker"] == "customer" and msg["sentiment"] == "negative"
])
if negative_interactions >= 3:
triggers.append("sustained_negative_sentiment")
suggested_actions.append("offer_supervisor_callback")
# 触发条件2:多次无解决
unresolved_count = len(session_state.data["active_issues"])
interaction_threshold = 10
if unresolved_count >= 2 and session_state.data["interaction_count"] >= interaction_threshold:
triggers.append("multiple_unresolved_issues")
suggested_actions.append("escalate_to_senior_agent")
# 触发条件3:客户明确要求升级
recent_messages = [msg["message"].lower() for msg in conversation_history[-3:]]
escalation_keywords = ["经理", "投诉", "不满意", "换人", "supervisor", "manager"]
if any(keyword in " ".join(recent_messages) for keyword in escalation_keywords):
triggers.append("customer_escalation_request")
suggested_actions.append("immediate_supervisor_handoff")
# 触发条件4:高价值客户
customer_value = customer_context.get("profile", {}).get("customer_value", "standard")
if customer_value == "premium" and session_state.data["interaction_count"] >= 5:
triggers.append("premium_customer_extended_session")
suggested_actions.append("priority_handling")
should_escalate = len(triggers) > 0
escalation_level = session_state.data["escalation_level"] + (1 if should_escalate else 0)
return {
"should_escalate": should_escalate,
"triggers": triggers,
"suggested_actions": suggested_actions,
"escalation_level": escalation_level,
"urgency": "high" if len(triggers) >= 2 else "medium" if should_escalate else "low"
}
async def _trigger_escalation(self, session_id: str, customer_id: str,
escalation_info: Dict[str, Any]):
"""触发升级流程"""
escalation_state = AgentState(
state_id=f"escalation_{session_id}",
state_type=StateType.SHARED,
owner_agent="escalation_manager",
shared_with=["supervisor_agent", "quality_assurance_agent"],
data={
"session_id": session_id,
"customer_id": customer_id,
"escalation_reason": escalation_info["triggers"],
"urgency": escalation_info["urgency"],
"suggested_actions": escalation_info["suggested_actions"],
"original_session_state": self.session_states[session_id].to_dict(),
"customer_context": self.customer_contexts[customer_id],
"conversation_summary": self._generate_conversation_summary(session_id),
"escalation_time": datetime.now().isoformat(),
"status": "pending_assignment"
},
metadata={
"escalation_level": escalation_info["escalation_level"],
"auto_triggered": True
},
created_at=datetime.now(),
updated_at=datetime.now()
)
self.escalation_states[session_id] = escalation_state
# 更新原会话状态
self.session_states[session_id].data["escalation_level"] = escalation_info["escalation_level"]
self.session_states[session_id].data["status"] = "escalated"
def _generate_conversation_summary(self, session_id: str) -> str:
"""生成对话摘要"""
conversation_history = self.conversation_history.get(session_id, [])
if not conversation_history:
return "No conversation history available"
# 简化的摘要生成逻辑
customer_messages = [msg for msg in conversation_history if msg["speaker"] == "customer"]
key_topics = []
sentiments = []
for msg in customer_messages[-5:]: # 最近5条客户消息
# 这里可以使用NLP提取关键信息
if len(msg["message"]) > 10: # 过滤太短的消息
key_topics.append(msg["message"][:50] + "...") # 截取前50字符
sentiments.append(msg["sentiment"])
summary = f"""
对话摘要:
- 总交互次数:{len(conversation_history)}
- 客户主要关切:{' | '.join(key_topics[:3])}
- 情绪趋势:{', '.join(set(sentiments))}
- 最新意图:{conversation_history[-1].get('intent', 'unknown') if conversation_history else 'unknown'}
"""
return summary.strip()
async def resolve_issue(self, session_id: str, issue_id: str,
resolution_notes: str) -> bool:
"""解决具体问题"""
session_state = self.session_states.get(session_id)
if not session_state:
return False
# 从活跃问题中移除
active_issues = session_state.data["active_issues"]
resolved_issue = None
for issue in active_issues:
if issue["issue_id"] == issue_id:
resolved_issue = issue
active_issues.remove(issue)
break
if resolved_issue:
# 添加到已解决问题
resolution_record = {
**resolved_issue,
"resolved_at": datetime.now().isoformat(),
"resolution_notes": resolution_notes,
"resolution_time_minutes": (
datetime.now() - datetime.fromisoformat(resolved_issue["detected_at"])
).total_seconds() / 60
}
session_state.data["resolved_issues"].append(resolution_record)
# 更新会话状态
session_state.updated_at = datetime.now()
# 如果没有活跃问题了,可以考虑结束会话
if not session_state.data["active_issues"]:
session_state.data["status"] = "resolved"
return True
return False
5.2 使用示例
async def demo_customer_service_state():
"""演示客服状态管理"""
cs_manager = CustomerServiceStateManager()
# 初始化客户会话
initial_context = {
"customer_profile": {
"customer_id": "cust_12345",
"customer_value": "premium",
"account_type": "enterprise"
},
"preferences": {
"language": "zh-CN",
"communication_style": "formal"
},
"channel": "chat",
"priority": "high"
}
session_state = await cs_manager.initialize_customer_session(
session_id="sess_67890",
customer_id="cust_12345",
initial_context=initial_context
)
print("会话初始化完成:", session_state.data["session_id"])
# 模拟对话流程
conversation_flow = [
{
"message": "我的订单一直没有发货,这到底是怎么回事?",
"intent": "order_status_inquiry",
"sentiment": "frustrated"
},
{
"message": "我已经等了一周了,你们到底能不能解决这个问题?",
"intent": "complaint_escalation",
"sentiment": "negative"
},
{
"message": "我要找你们的经理投诉!这种服务太差了!",
"intent": "supervisor_request",
"sentiment": "negative"
}
]
agent_responses = [
"非常抱歉给您带来不便,我来帮您查询订单状态。",
"我理解您的焦急心情,让我立即为您升级处理这个问题。",
"我马上为您转接到我们的主管,他们会亲自处理您的问题。"
]
for i, (conv, resp) in enumerate(zip(conversation_flow, agent_responses)):
result = await cs_manager.update_conversation_state(
session_id="sess_67890",
customer_id="cust_12345",
message=conv["message"],
intent=conv["intent"],
sentiment=conv["sentiment"],
agent_response=resp
)
print(f"\n第{i+1}轮对话:")
print(f"客户情绪: {result['customer_emotion']}")
print(f"是否升级: {result['escalation_triggered']}")
print(f"建议行动: {result['suggested_actions']}")
# 解决一个问题示例
await cs_manager.resolve_issue(
session_id="sess_67890",
issue_id="issue_order_delay_001",
resolution_notes="已联系物流部门,订单将在24小时内发出,并提供补偿券"
)
# 运行演示
# asyncio.run(demo_customer_service_state())
通过这套完整的状态管理体系,你可以在 Multi-Agent 系统中实现:
✅ 高效的状态共享与同步
✅ 并发安全的状态更新
✅ 灵活的状态访问控制
✅ 强大的冲突解决机制
✅ 完整的状态历史追踪
✅ 智能的状态模式管理
✅ 实用的业务场景适配
这些技术和模式将显著提升你的 Multi-Agent 系统的协调能力和可靠性!
更多推荐



所有评论(0)