Skip to content

Day 3 — Session 设计文档

设计目标:实现多用户多轮对话的会话管理,支持可插拔存储后端和 TTL 自动过期清理。


一、核心接口设计

1.1 ChatMessage

字段类型说明
roleMessageRoleuser / assistant / system / tool
contentstr消息正文
tool_call_idOptional[str]工具调用关联 ID
tool_callsOptional[List]LLM 返回的工具调用请求

为什么 role 和 OpenAI API 对齐?

  • Session 中的消息最终要发给 LLM
  • 格式一致 = 零转换成本
  • 避免中间层格式映射的 bug

1.2 Session

字段类型说明
session_idstrUUID 唯一标识
user_idstr用户标识
channelstr渠道名称
messagesList[ChatMessage]对话消息列表
created_atdatetime创建时间
updated_atdatetime最后更新时间
metadataDict扩展元信息

1.3 SessionStorage(抽象接口)

方法签名说明
saveasync save(session: Session)持久化会话
loadasync load(session_id: str) -> Optional[Session]加载会话
deleteasync delete(session_id: str)删除会话
list_allasync list_all() -> List[str]列出所有会话 ID

1.4 SessionManager

方法签名说明
get_or_createasync get_or_create(user_id, channel) -> Session查找或创建
saveasync save(session: Session)保存会话
deleteasync delete(session_id: str)删除会话
cleanup_expiredasync cleanup_expired()清理过期会话
list_active_sessionslist_active_sessions() -> List[Dict]列出活跃会话

二、关键流程图

会话查找/创建流程

过期判断逻辑

python
def is_expired(session, ttl_seconds):
    elapsed = now - session.updated_at
    return elapsed.total_seconds() > ttl_seconds

三、设计决策与权衡

决策 1:用 (user_id, channel) 作为会话路由键

方案优点缺点
user_id + channel(选择)同一用户在不同渠道有独立上下文换渠道时历史不共享
仅 user_id所有渠道共享一个会话不同渠道的对话混在一起
每次请求新建最简单完全无上下文,失去多轮对话能力

选择理由:不同渠道的使用场景通常不同(CLI 调试 vs WebChat 正式对话),分开管理更合理。

决策 2:内存索引 + 外部存储

SessionManager 内部维护 Dict[(user_id, channel), session_id] 索引表:

方案优点缺点
内存索引(选择)O(1) 查找,最快重启后需要从 storage 重建
每次查 storage无需内存索引O(n) 遍历,慢

权衡:教学阶段优先性能和简单性。生产环境中可以用 Redis 做分布式索引。

决策 3:TTL 手动触发 vs 后台定时器

方案优点缺点
手动调用 cleanup(选择)完全可控,无并发问题需要调用方主动执行
后台定时器全自动可能在不合适的时机触发,并发复杂

决策 4:InMemoryStorage vs FileStorage

两种实现各有场景:

场景推荐
单元测试InMemoryStorage(快、无副作用)
开发调试都行
需要重启后恢复FileStorage

四、与前序章节的集成点

  • 依赖 Day 1:ChatMessage 的 role 枚举借鉴了 GatewayMessage 的 StrEnum 方案
  • 依赖 Day 2:Session 的 channel 字段对应 Channel 的类型名
  • 被 Day 4 依赖:AgentRuntime 通过 Session 获取对话历史
  • 被 Day 7 依赖:ShortTermMemory 在 Session.messages 基础上做窗口裁剪

五、与真实生产系统的对比

维度miniOpenClaw生产级实现
存储内存 / JSON 文件Redis(快)+ PostgreSQL(持久化)
索引进程内 dictRedis Hash
TTL手动清理Redis 原生 TTL / 数据库定时任务
并发安全单进程无锁分布式锁 / 乐观锁
消息压缩长对话摘要压缩