OpenAI Agents 会话记忆实战:4 种 Session 存储怎么选
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
你写的多轮对话机器人,第二句开始就"失忆"了?OpenAI Agents 的 Session 会话记忆机制,帮你把对话历史存下来、接得上,不用再手动拼上下文。
为什么会失忆
Runner.run本身是无状态的:每次调用只拿到你当轮传入的文本,模型看不到任何前文。于是用户问"我的快递到哪了",下一轮问"什么时候能到",模型根本不知道"它"指哪个快递。Session 就是为了解决这个问题。它的机制很简单:
- 运行前,Runner 调
session.get_items()取出历史,拼到本轮输入前面; - 运行后,本轮产生的新条目(用户输入、回复、工具调用)写回 Session;
- 之后每一轮重复前两步,上下文链就持续接得上了。
你不用手动管.to_input_list()这类脏活。
会话记忆最小可运行示例
下面用内置的SQLiteSession跑两轮客服对话。注意instructions里的"结合上文"不是必需的,它只是让回复更像人话:
import asyncio from agents import Agent, Runner, SQLiteSession async def main(): agent = Agent( name="客服助手", instructions="结合上文回答,简洁直接。", ) session = SQLiteSession("ticket_456") # 同一 session_id = 同一份记忆 r1 = await Runner.run(agent, "我的订单 A100 什么时候发货?", session=session) print(r1.final_output) r2 = await Runner.run(agent, "如果晚于周五,帮我改到自提。", session=session) print(r2.final_output) asyncio.run(main())第二轮的"如果晚于周五"没有重复订单号,但模型能接上,因为 Runner 在运行前自动把第一轮的历史塞进了输入,运行后又把第二轮写回。整个文件版示例见 examples/memory/sqlite_session_example.py。
4 种 Session 后端横向对比
| 实现类 | 存储介质 | 适用场景 | 注意事项 |
|---|---|---|---|
SQLiteSession | 内存或本地 SQLite 文件 | 本地开发、单机工具 | 不传路径即内存模式,进程一退就丢 |
OpenAIConversationsSession | OpenAI Conversations API | 对话历史托管在 OpenAI 侧 | 依赖 OpenAI API;恢复对话需传conversation_id |
SQLAlchemySession | 任意 SQLAlchemy 支持的数据库 | 团队生产,复用现有数据库 | 用from_url(...)建引擎,create_tables=True自动建表 |
EncryptedSession | 包装任意底层 Session | 含敏感数据的对话 | 是包装器不是独立后端;ttl过期条目在读取时静默跳过 |
几个容易忽略的差异:
SQLiteSession("id")是内存模式,SQLiteSession("id", "conv.db")才落盘;OpenAIConversationsSession()默认新建对话,OpenAIConversationsSession(conversation_id="conv_123")恢复已有对话;- 同一轮运行里,Session 不能和
conversation_id/previous_response_id这类运行级续接选项混用,二选一; EncryptedSession基于 Fernet 加密、HKDF 按 session 派生子密钥,适合叠加在任何后端之上。
三个实用操作
① 回退错误回复
用户说"刚才答错了"时,连续pop_item()即可撤销:先取走智能体的错误回复,再取走当轮的用户输入,然后用同一 session 重新跑Runner.run:
await session.pop_item() # 移除智能体上轮回复 await session.pop_item() # 移除用户上轮输入② 多个 Agent 共享同一会话
把同一个session传给不同的 Agent,它们读写同一份历史。分诊、审批、总结几个 Agent 接力处理同一张工单时,后手能直接看到前手的全部内容,不用各自维护一遍上下文。
③ 继承 SessionABC 写自定义后端
接 Redis、MongoDB 时照骨架实现即可。SessionABC是抽象基类,必须补全四个方法,把存取逻辑接到你自己的存储上(也可以不继承,直接按Session协议实现):
class MySession(SessionABC): session_id: str session_settings: SessionSettings | None = None async def get_items(self, limit=None): ... async def add_items(self, items): ... async def pop_item(self): ... async def clear_session(self): ...Session 选型建议
- 临时演示:内存版
SQLiteSession("id"),零配置,进程结束自动清理。 - 单机工具:文件版
SQLiteSession("id", "conv.db"),简单可靠。 - 团队生产:
SQLAlchemySession接现有数据库,复用现有连接与权限体系。 - 含敏感数据:上面任一后端外加
EncryptedSession包装,密钥从环境变量或 KMS 取,别写死。
容易踩的坑
- session_id 要稳定且可追溯:它是记忆的"主键"。同一用户多端登录却用了不同 id,历史就断了;建议按业务实体命名,如
user_12345、ticket_456。 - 别把加密密钥写进代码:
EncryptedSession的encryption_key一旦丢失,历史全部解不开;也正因为 HKDF 会按 session 派生密钥,session_id 本身参与加密,改名等于数据报废。 - 历史越长 token 越贵:默认每次运行都拉全量历史。长会话用
RunConfig(session_settings=SessionSettings(limit=N))只取最近 N 条,或用RunConfig.session_input_callback自行裁剪。 - 别把无状态配置当成有状态:
SQLiteSession内存模式、以及任何"进程内"后端,重启即清零;多进程部署必须换共享后端。
继续深挖
- docs/sessions/index.md:官方 Sessions 文档,全部内置后端与历史裁剪的完整说明。
- examples/memory/sqlite_session_example.py:最小示例,末尾还演示了
get_items(limit=2)的取法。 - src/agents/memory/session.py:
Session协议与SessionABC源码,四个核心方法定义都在这个文件里。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考