记忆管理
让 AI 在多轮对话中保持上下文。Sira 的记忆机制由 LangGraph + Redis 自动接管,没有"用户偏好库 / 记忆笔记"这类独立产品——所有记忆都是对话历史本身的派生。
两种记忆类型(migration 014 后)
每个 Agent 在创建 / 编辑时选择一种 memory_type:
| Type | 行为 |
|---|---|
none | 不接 Checkpointer,每次对话独立。无任何上下文延续 |
summarize_at_limit(默认) | LangGraph RedisCheckpointer + LangChain SummarizationMiddleware,上下文接近模型 context window 的 15% 时自动摘要 |
旧版枚举已下线
旧版有 5 种类型(CONVERSATION_BUFFER / CONVERSATION_SUMMARY / CONVERSATION_BUFFER_WINDOW / VECTOR_STORE / NONE),其中 4 个代码从未真正消费。VECTOR_STORE 选了也不会启用任何向量库。Migration 014 把它们删了。
三层存储架构
记忆数据在 Redis 里分三层存放,各自独立:
| 层 | 用途 | Key 格式 | TTL |
|---|---|---|---|
| LangGraph Checkpointer | Agent 的对话历史 + 中间状态快照 | thread_id(= session_id) | 24 小时 |
| Redis 流式缓冲 | SSE chunk 暂存供前端拉取 | orchestrator:stream:{session_id} | 短期 |
| Redis 会话上下文 | 跨节点共享的临时上下文 | session:context:{session_id} | 1 小时 |
| Redis 外部会话 ID | Dify / n8n 的会话 ID 持久化(用于多轮对话延续) | external:dify:conversation:{session_id} external:n8n:conversation:{session_id} | 24 小时 |
Redis 不可用怎么办
找不到 Redis 时 Checkpointer 会回落到内存版(MemorySaverWrapper)——能继续工作但进程重启即丢失,多副本部署也无法共享。生产环境必须配 Redis。
自动摘要阈值
SummarizationMiddleware 触发条件(每个 Agent 自动算):
- 阈值 = 模型 context_window 的 15%
- 默认兜底:15000 tokens 或最近 10 条消息
- 安全顶(避免预算失控):80K tokens / 30 条消息
例:使用 GPT-4o(128K context)的 Agent,约累计 ~19K tokens 时触发摘要;使用 Claude 3.5 Sonnet(200K context)约 ~30K tokens 时触发。
阈值不可配
memory_config 字段在数据库里存在(JSON 类型),代码注释说"保留供未来扩展",当前完全不读。前端 UI 也不暴露相关入口。
在 UI 中开启 / 关闭
只有 Agent 级别 暴露设置(/agent-system/agents 详情页):
| 控件 | 选项 |
|---|---|
enable_memory 开关 | 开 / 关 |
memory_type 下拉 | "无记忆" / "自动摘要(默认)" |
编排器(Orchestrator)层面没有独立的记忆设置——记忆完全跟随其调度的 Agent。
默认行为
新创建的 Agent 默认:
enable_memory = true
memory_type = summarize_at_limit每次对话用 session_id 作为 LangGraph thread_id 持久化——同一会话内的所有轮次共享上下文,24 小时内回到同一个 session_id 还能续上。
跨渠道身份与记忆
Sira 的"用户身份"通过 跨渠道用户解析 打通——同一个员工在企微 / 飞书 / Web 用的是同一个 user.id。但 记忆是按 session_id 而非 user.id 存储的——同一员工在不同渠道发起的会话拥有独立 session_id,因此记忆不会自动跨渠道共享。
如需跨渠道延续上下文,业务层可以通过 模板变量 在 system prompt 里注入用户元信息。
外部系统会话 ID(Dify / n8n)
外部编排(Dify / n8n)有自己的会话上下文。Sira 把它们的 conversation_id 单独存 Redis,TTL 24 小时:
Request 1: 用户说"我叫张三"
→ 取 external:dify:conversation:{session_id} → null(首次)
→ DifyAdapter 调用 Dify API
→ Dify 返回 conversation_id="abc-123"
→ 存到 Redis: external:dify:conversation:{session_id} = "abc-123"
Request 2: 同一 session_id 下问"我叫什么"
→ 取 Redis 拿到 "abc-123"
→ 传给 Dify
→ Dify 识别会话并回"你叫张三"这层只用于让外部系统延续上下文,不参与 Sira 自己的 Agent 记忆。
排查清单
| 现象 | 可能原因 |
|---|---|
| AI 不记得上一句 | Agent enable_memory=false 或 memory_type=none |
| AI 记得但太久了忘 | 24 小时 TTL 过期;用户换了 session_id(关闭/重开聊天窗口可能重新分配) |
| 多副本部署下记忆丢失 | Redis 没接通,回落到了进程内 MemorySaverWrapper |
| Token 用量飙升 | 接近阈值被自动摘要——属于正常行为 |
| Dify/n8n 一直当作首次提问 | external:dify:conversation:{session_id} 在 Redis 里被清;查 TTL |
相关文档
- Agent System 架构 —— 整体三层概念
- 模板变量 —— 在 system prompt 注入用户/会话信息
- Dify 集成 / N8N 集成 —— 外部会话延续
