记忆系统设计原理
CocoCat 的记忆系统解决一个核心问题:LLM 上下文窗口有限,Agent 需要长期工作记忆。设计借鉴了 nanobot 的 Dream/Consolidator 模式。
问题
- LLM 上下文窗口通常在 8K-128K tokens
- Agent 可能在一次任务中执行 10+ 轮工具调用
- 每轮产生的消息会被压缩或丢弃
- 关键信息需要跨会话持久化
架构
ReAct 循环
│
▼
┌─────────────────────────────────────┐
│ history.jsonl │ ← Episodic(情节记忆)
│ {timestamp, prompt, response, N} │ 每条任务记录
└──────────────┬──────────────────────┘
│ Dream(LLM 分析 + 提取)
▼
┌─────────────────────────────────────┐
│ MEMORY.md │ ← Semantic(语义记忆)
│ ## Key Decisions │ 可持久化的知识
│ - Decision 1 │
│ ## Facts Learned │
│ - Fact 1 │
└─────────────────────────────────────┘
│ Git commit
▼
┌─────────────────────────────────────┐
│ Git 版本历史 │ ← Versioned(版本化)
│ commit 1: initial │ 可回滚、可追溯
│ commit 2: added decisions │
└─────────────────────────────────────┘Dream — 核心机制
Dream 是 CocoCat 记忆系统的关键创新:让 Agent 自己管理和优化自己的记忆。
触发条件
| 条件 | 效果 |
|---|---|
| 距上次 Dream ≥ 30 分钟 | 强制触发 |
| 未处理记录 ≥ 3 条且距上次 ≥ 10 分钟 | 触发 |
| 积累 token 数 ≥ 阈值 | 触发 |
手动调用 dream 工具 | 立即触发 |
执行过程
1. 读取 .dream_cursor → 确定未处理历史起始位置
2. 读取从 cursor 开始的 history.jsonl 条目
3. LLM 分析 → 提取四类信息:
- Key Decisions(关键决策)
- Facts Learned(学到的事实)
- Preferences(偏好)
- Patterns(模式)
4. Agent 进入受限工具循环:
- 只允许 read_file + edit_file 两个工具
- 手术式编辑 MEMORY.md
- 添加 ### YYYY-MM-DD Dream 小节
5. 更新 .dream_cursor
6. Git commit(如果配置了 GitStore)为什么用受限工具循环?
普通 ReAct 循环有 26 种工具,Dream 只有 2 种(read_file + edit_file),原因:
- 防止副作用:Dream 是后台进程,不应产生外部影响
- 聚焦任务:Dream 的唯一任务是更新记忆,不需要其他能力
- 安全:降低权限,减少出错面
Per-User Dream
除了全局记忆,每个用户有独立的 profile:
用户对话 → run_user_dream() → data/users/{hash}/PROFILE.md这使 Agent 能记住每个用户的偏好和上下文,而不会混入公共记忆中。
Consolidator — 运行时压缩
与 Dream 不同,Consolidator 在 ReAct 循环运行时工作,目的是让 Agent 在当前会话中继续思考。
[LLM response] → [Tool results] → [历史超出预算] → Consolidator
│
LLM 压缩中间消息
│
[压缩后的摘要消息]边界感知 split
Consolidator 不会随意切断消息。它首先按"轮次"(tool call → result 对)分组,确保不会出现只有工具调用没有结果,或只有结果没有工具调用的情况。
Git 版本管理
记忆变更通过 Git 追踪:
bash
git log -- agents/{id}/memory/MEMORY.md这提供了:
- 可审计性:每次修改都可溯源
- 可回滚:使用
revert_memory工具回滚到上一个 commit - 可视化:查看记忆如何随时间演变
设计权衡
| 选择 | 替代方案 | 为什么选这个 |
|---|---|---|
| 文件存储 | 数据库 | 透明可读,可用 git 管理,无依赖 |
| LLM 提取 | 规则提取 | 灵活性高,可理解上下文 |
| Cursor 增量 | 全量重处理 | 高效,每次只处理增量数据 |
| 受限工具循环 | 直接写文件 | 安全,防止意外修改 |
| Git 版本 | 快照备份 | 接近零依赖,功能丰富 |
失败模式
| 问题 | 影响 | 处理方式 |
|---|---|---|
| Dream 失败 | 记忆未更新 | 下个周期自动重试 |
| git commit 失败 | 无版本记录 | 不影响记忆内容本身 |
| MEMORY.md 过大 | 占用上下文 | Agent 通过 consolidate 控制增长 |
| 重复内容 | 上下文浪费 | Dream 有去重逻辑 |