跳转到内容

记忆、Session 与对话压缩

AI-04: 记忆、Session 与对话压缩

学习目标

  • 掌握 SessionABC 四方法协议
  • 理解 SQLiteSession / OpenAIConversationsSession 两种持久化方案
  • 理解 OpenAIResponsesCompactionSession 自动对话压缩
  • 理解 RunState 序列化与 HITL 恢复流程

前置知识

本章涉及记忆系统的通用原理,建议先阅读:

下文直接聚焦 OpenAI Agents SDK 的具体实现。

项目实践

SessionABC 四方法协议

SDK 定义了统一的 Session 协议,两种实现方式(Session Protocol 和 SessionABC):

方法作用
get_items(limit)获取对话历史(限制时取最新 N 条,按时间顺序返回)
add_items(items)追加新 items 到历史
pop_item()原子删除并返回最新 item
clear_session()删除该 session_id 的所有 items

三种 Session 实现对比

SQLiteSession

  • 两种模式:内存(:memory:)或文件(Path
  • 线程安全:文件级 RLock(引用计数,跨实例共享同文件锁)
  • get_items 带 limit 时:ORDER BY id DESC LIMIT n 然后反转
  • pop_itemDELETE ... RETURNING 原子操作
  • 无效 JSON 行被静默跳过

OpenAIConversationsSession

  • session_id 首次 API 调用前为 None(懒初始化)
  • 存储完全在 OpenAI 服务端
  • clear_session 调用 conversations.delete() 并重置 session_id
  • 不能被 compaction session 包装(服务端管理历史)

OpenAIResponsesCompactionSession:自动对话压缩

这是一个装饰器模式,包装任何本地 Session(除 OpenAIConversationsSession):

session = OpenAIResponsesCompactionSession(
underlying_session=SQLiteSession(path="...", session_id="conv-001"),
model="gpt-4.1", # 用于压缩的模型
)

触发条件:默认当候选 items ≥ 10 时触发(可自定义 should_trigger_compaction)。

压缩流程

  1. 每个 turn 结束后,save_result_to_session() 检查 session 是否支持压缩
  2. 如有本地工具结果待处理 → 延迟压缩;否则立即执行
  3. 调用 client.responses.compact() 生成压缩摘要
  4. clear() + add_items() 替换底层 session 内容为压缩结果
  5. 更新内部缓存 _compaction_candidate_items_session_items

安全机制:如果 clear-and-replace 失败,尝试恢复之前 items。用户消息和已有 compaction items 被排除在候选集外。

Session 集成到 Runner.run()

与 Server-Managed Conversation 的互斥:当 OpenAIServerConversationTracker 活跃时(conversation_id/previous_response_id),session 持久化被完全禁用

问题与规避

问题规避方案
长时间对话未压缩导致 token 超限使用 OpenAIResponsesCompactionSession,设置合理的触发阈值
OpenAIConversationsSession 被 compaction 包装导致异常检查 session 类型,OpenAIConversationsSession 不使用 compaction
Session 恢复时 corrupted JSON 行pop_item 自动丢弃无效行并尝试前一条
多进程并发写同一 SQLite 文件使用文件级 RLock,或切换为 OpenAIConversationsSession

设计取舍

为什么 Session 持久化与 Server-Managed Conversation 互斥

当使用 OpenAI 服务端对话管理时,OpenAI 服务端已维护完整的对话历史和上下文窗口。此时 SDK 侧再维护一份 session history 会导致双重存储和状态不一致。因此 SDK 明确禁用 session 持久化。

为什么 compaction 使用 clear-and-replace 而非增量更新

responses.compact 返回的是一条压缩摘要消息。用这条消息替换全部历史(clear + re-add)比增量替换更简单、更不易出错。

风险:如果 replace 失败,可能丢失原始 items。SDK 通过尝试恢复来缓解此风险。

参考来源