diff --git a/docs/README.md b/docs/README.md index a44aa01..6b79e60 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,6 +15,7 @@ Model-driven context management (Active Context Pruning / ACP) for the DeepSeek | [Porting feasibility analysis](dsh-porting-analysis.md) | Initial study: Pi ↔ DSH API mapping, the core difficulty (no in-memory message rewrite hook), three porting paths | | [Porting verification report](dsh-porting-verification.md) | The verified evidence behind every claim, plus the **v0.1.1 long-session battle report** (6 bugs found and fixed in real use) | | [Configurable prompts design](configurable-prompts-design.md) | Design review draft: per-stage prompt overrides (nudge / range table / system prompt / tool descriptions) via `config.prompts`, template + named placeholders, build-time validation | +| [Cross-session memory design](cross-session-memory-design.md) | Design draft (P1-4): model-driven long-term memory — `memory_commit` at nudge time → one-shot LLM extraction → human-readable markdown memory bank → resident index + `memory_recall` readback; kernel-first ownership split (§6A: algorithms upstream to acp-kernel, host keeps DSH integration); research archive in [memory-research/](memory-research/README.md) | ## 🗂 Source layout diff --git a/docs/cross-session-memory-design.md b/docs/cross-session-memory-design.md new file mode 100644 index 0000000..166e506 --- /dev/null +++ b/docs/cross-session-memory-design.md @@ -0,0 +1,264 @@ +# 跨会话长期记忆设计(Cross-Session Memory Design)— v1 + +> **状态**:设计讨论稿 v1(2026-08,经三轮调研 + 多轮用户设计讨论定稿)。 +> **待定项(今日不细究,实现前补齐)**: +> - **T1** `memory_commit` 的 negative constraints 措辞——"何时**不要**调用"的提示词(对齐 Claude Code 显式 negative list:code patterns、git history、debugging plans、已在 CLAUDE.md 的内容、临时任务状态)。当前仅定"正向触发点"(type 枚举 + 何时该用),negative 部分实现时补。 +> - **T2** `memory_commit` 工具返回话术(现状:引擎返回"后台已总结写入",精确文案实现时定)。 +> - **T3** 索引条目格式的精确 schema(frontmatter 字段名、目录结构)实现时定。 +> +> **设计依据**(三轮调研,归档于 `docs/memory-research/`): +> - 论文向 17 篇:`docs/memory-research/01-autonomous-memory-papers.md`(ACM/AgentFold/C^AT/Generative Agents/MemoryBank/FadeMem/Agentic Memory 等) +> - 实现向 8 产品:`docs/memory-research/02-autonomous-memory-implementations.md`(Claude Code/Cline/mem0/Letta/LangMem/DSH 生态/MemOS/Basic Memory) +> - 读回时机 25 源:`docs/memory-research/03-memory-readback-timing.md`(四模式谱系 + 混合收敛证据) +> - Claude Code 源码核实:`docs/memory-research/04-claude-code-source-verification.md`(liuup 镜像提炼存档) + +## 1. 背景与目标 + +billion-context-dsh 目前是**会话内**上下文管理:模型通过 compress 把旧内容折叠成 tier-1 摘要块,可蒸馏(tier-2/3)、可 decompress/search 找回——但**会话结束即失忆**(对比 mem0/Letta/Zep/CLAUDE.md/AGENTS.md 的文件记忆)。这是项目最大缺口(调研报告 §三 缺点 #1/#8)。 + +目标:增加**跨会话长期记忆**——模型在 nudge 时机表态"这段值得记住",引擎 fork 提取写入**人类可读 markdown 记忆库**,新会话经**常驻索引 + 自主取回**使用。 + +设计约束: +1. **算法进 kernel、集成留宿主**(决策 7/规则 11 镜像)——凡"算法/数据结构/格式/文案"性质进 acp-kernel(upstream),凡"DSH 工具面/LLM 运行时/文件系统/seq 方言/提示词注入"留宿主;实现顺序 **kernel 先行,宿主后随**(见 §6A); +2. **模型自决**——写入/取回都由模型决策(决策 3 精神),引擎只提供接缝与时机提示; +3. **人类可读可编辑**——记忆库是 markdown 文件,用户可直接看/改/删(外部纠错通道); +4. **可回溯**——每条记忆带 citation(会话+seq),延续 append-only + decompress 哲学; +5. **不违反决策 3 的"无自动摘要"**——提取写记忆库,不碰主对话、不压缩任何内容(见 §6 相容性)。 + +## 2. 总体架构:写 → 存 → 读 闭环 + +``` +┌─ 写入(nudge 时机)───────────────────────────────┐ +│ nudge 触发 → 模型回顾 → memory_commit(type, note) │ +│ → 引擎一次性 LLM 调用(同模型同文本+"提取记忆,重点:X")│ +│ → 提取结果写记忆库(带 citation)→ 返回"后台已写入" │ +│ → 主对话继续压缩 │ +└──────────────────────────────────────────────┘ + ↓ +┌─ 存储 ────────────────────────────────────────┐ +│ 记忆库 = 人类可读 markdown 目录(工作区 .acp-memory/) │ +│ 每条 = 标题 + 正文(精炼态) + type + importance(1-10) │ +│ + created + last_read + citation(会话+seq) │ +└──────────────────────────────────────────────┘ + ↓ +┌─ 读回(两个时机)───────────────────────────────┐ +│ ① 常驻索引:一句话/条+类型+上次读取,每次 turn 在 │ +│ ② 自主取回:模型见相关条目 → memory_recall 取全文 │ +└──────────────────────────────────────────────┘ + ↓ +┌─ 衰减(与选择同机制)───────────────────────────┐ +│ score = importance + min(days/30,5) + uniform(0,.5) │ +│ 被读降权、久未读加权 → 冷记忆权重回升等机会 │ +└──────────────────────────────────────────────┘ +``` + +## 3. 写入路径(模型自决:nudge 表态 + fork 提取) + +### 3.0 核心认知:压缩块本身就是长期记忆候选 + +每次 compress 生成的 tier-1 块(b1)摘要本身就是适合长期存储的内容——记忆沉淀复用压缩产物,不是另起炉灶的独立系统。**但沉淀决策始终是模型自决,不搞引擎自动归档**(决策 3:无自动策略)——模型判断"某个压缩块 b1 的摘要值得沉淀"或"这段对话有值得记住的内容"时,走 nudge 表态路径(见下)。 + +### 3.1 三工具权限分离(用户定稿) + +| 工具 | 谁可见 | 干什么 | +|---|---|---| +| `memory_commit(type, note)` | **主对话** | 表态"这段值得记"(type 枚举 + note 聚焦提示);不写内容 | +| `memory_recall(query)` | **主对话** | 读回:检索记忆库取全文(见 §5) | +| `memory_write(content)` | **仅 fork 会话** | 真正写记忆库;**主对话物理上无写权限** | + +主对话只有"请求写"的能力、没有"写"的能力——写记忆库只能通过 fork 会话的 memory_write 完成,权限天然隔离(fork = 带 memory_write 工具定义的一次性 LLM 调用,宿主把工具输出落库)。 + +### 3.2 `memory_commit` 工具(主对话侧,纯意图表达) + +- **语义**:nudge 时模型觉得有值得跨会话保留的内容 → 调用本工具**表态**(不写内容,写内容由 fork 完成)。 +- **参数**: + - `type`:必选,封闭枚举 `decision|lesson|fact|user-preference|reference`(对齐 Claude Code 4 类 taxonomy 思想,扩展为 5 类); + - `note`:可选,一句话聚焦提示(如"关于 session.append 可重入的教训"),帮助提取定向。 +- **negative constraints(待定 T1)**:提示词需写"何时**不要**调用"(代码模式、临时任务状态、已在会话内的内容)——实现时补。 + +### 3.3 一次性 LLM 调用(引擎侧,fork 会话) + +**用户决策**:DSH 用**一次性 LLM 调用**即可,不需要真正的子对话/fork 会话。 + +- 引擎收到 `memory_commit` → 发起一次独立 LLM 调用(fork): + - 输入 = 当前完整对话文本(与主对话 surface 一致)+ 插入指令"提取目前需要的记忆,重点:{note}"(同模型,prefix cache 可命中); + - 工具面 = 仅暴露 `memory_write`(写记忆库)+ 只读工具; + - 输出 = 模型调用 `memory_write(content)`,宿主把提炼结果(精炼态、自包含陈述句)落库; +- **一次性**:无会话状态、无归档/删除需求、不占常驻资源(对比 Claude Code runForkedAgent 是完整 fork 会话——我们对齐其缓存命中的好处,但免除会话生命周期管理); +- **fire-and-forget**:不阻塞主对话;返回"后台已写入"(话术待定 T2)。 + +### 3.4 记忆条目格式 + +``` +标题(一行,自包含) +--- +正文:精炼态陈述(结论/决策/教训,不含上下文指代) +--- +frontmatter: + type: decision | lesson | fact | user-preference | reference + importance: 1-10(memory_commit 表态时模型顺带评) + created: ISO 时间 + last_read: ISO 时间(读回时更新) + citation: { session: , seq: <表态时刻 seq> } +``` + +- 记忆条目 = **tier-3 蒸馏块等价物**(Agentic Memory arXiv:2601.01885 明示 tier-1/2/3 蒸馏等价 short→long 迁移,tier-3 即天然长期记忆条目)——不造新格式,复用分层蒸馏思想; +- 正文只存**精炼态**(不存原文)——检索天然只返回精炼摘要,避免"搜到最糙的原始段落"。 + +## 4. 存储 + +- **位置**:工作区 `.acp-memory/` 目录(或 `~/.dsh/memories`,配置可切换); +- **形态**:人类可读 markdown(排除纯"记忆会话"形态——人必须可读可编辑 = 外部纠错通道); +- **保质期**:Ebbinghaus 强度(MemoryBank arXiv:2305.10250 记忆强度指数衰减、被检索刷新;FadeMem arXiv:2601.18642 增加信息冗余度覆盖因素)——**不是定死日期**,由 `importance + last_read` 驱动; +- **覆盖(upsert)**:同主题写 UPDATE 而非新增;靠提示词引导"写前先检索已有记忆"(工具层去重需语义相似度=embedding,故选模型自觉 + 工具支持覆盖)。 + +## 5. 读回路径 + +### 5.1 决策:延迟读回 + 两个时机(砍掉多层) + +**用户决策**:定稿不需要多层设计——Claude 就两个时机,参考 Claude: +1. **常驻索引**(时机①):记忆库索引(一句话/条 + 类型 + 上次读取时间)注入 system prompt,每次 turn 都在(对齐 MEMORY.md 常驻); +2. **自主取回**(时机②):模型看到索引中相关条目 → 自调 `memory_recall` 取全文。 + +**不采用**(砍掉): +- ~~显式写回~~——memory_commit 后不立即展示写入了什么(延迟读回,省上下文); +- ~~每次用户消息自动 prefetch~~——无自动灌入(用户质疑"每次用户消息都发?"→ 确认不);注:Claude Code 的 relevant_memories prefetch 是 feature gate `tengu_moth_copse` 默认关闭的实验功能,非默认行为; +- ~~nudge 预取 Tier 3~~——多层设计砍掉,对齐 Claude 两时机。 + +### 5.2 先例:Claude Code = "常驻索引 + 自主取回"生产实践(源码核实) + +- 常驻索引:MEMORY.md 常驻 system prompt(`findRelevantMemories.ts:31` "Excludes MEMORY.md (already loaded in system prompt)"),格式 = 一句话/条(`formatMemoryManifest`:`- [type] filename (timestamp): description`); +- 自主取回全文:每条记忆独立 .md 文件,模型需要细节时自调 FileRead 读全文(`attachments.ts:2306` "Use the FILE_READ_TOOL_NAME tool to view the complete file"); +- **Letta 同构变体**:Core Memory blocks 常驻(内容本体)+ Archival 自主 `archival_memory_search`。区别:Claude 常驻索引、Letta 常驻内容。**我们选 Claude 路线**(索引常驻 + 全文按需):token 更省,且与"记忆库 = 人类可读 markdown 文件"天然匹配; +- **结论**:非发明,两大主流系统独立收敛的同一形态;我们增量 = `memory_recall` 工具面 + 索引带 last-read 字段 + 一次性 LLM 调用写入。 + +### 5.3 `memory_recall` 工具 + +- **语义**:从记忆库检索相关条目全文(与 `search_context` 分开:search_context 管会话内压缩块,memory_recall 管跨会话记忆库); +- **参数**:query(必选)、limit(可选,默认 5); +- **返回**:匹配条目(标题 + 正文精炼态 + type + citation + importance),带 citation 回溯。 + +### 5.4 常驻索引选择机制:importance + 反新鲜度 + 随机 + +**问题**:纯频率/强度优先 → 富者愈富正反馈锁定(被读 → 频率升 → 优先被读 → 更被读);无搜索工具兜底时冷门记忆被挤出即消失。 + +**机制**(字段全部记忆库自带,不依赖 sideQuery/embedding): +``` +score = importance + min(days_since_last_read / 30, 5) + uniform(0, 0.5) +``` +- `importance`(1-10):memory_commit 表态时模型顺带评分(Generative Agents 做法,写入时一次性评估); +- `anti-recency`:"上次被读时间"越久远优先级越高——刚读过的降权让位(正反馈变负反馈); +- `random jitter`:加权抽样而非确定性 top-k,随机性打破"永远同一批"锁定; +- **top-N = 5**(对齐 Claude 5-slot);**会话节流** = 累计 surfacing 上限(对齐 MAX_SESSION_BYTES 60KB,超限停止注入);**去重** = 本会话已注入路径不再注入(对齐 alreadySurfaced); +- **与保质期合并**:遗忘曲线反过来用——"被读降权 + 久未读加权",不被读的记忆不是消失而是权重回升等机会;可见性调度与保质期同一套字段(importance + last-read),一个机制两用。 + +### 5.5 读回的记忆在 compress 中是否折叠 = 模型自决(Q3) + +注入时向模型标注"这是以往的一条长期记忆";是否保留由模型自行判断——当前上下文有用就留在 surface(compress 时自然不选),没用就允许折叠(记忆库有原文,需要时再召回)。**不需要"记忆 attachment 永不压缩"特殊标记**——与决策 3(压缩范围模型自决)自洽,与 Claude Code compact-重置-surfacing 哲学一致(compact 后 old attachments 消失,re-surfacing valid again)。 + +## 6A. Kernel 归属划分(用户决策:算法进 kernel,先改 kernel 再改宿主) + +**判断原则**:凡有"算法/数据结构/格式/文案"性质 → 进 acp-kernel(upstream issue + PR);凡有"DSH 工具面/LLM 运行时/文件系统/seq 方言/提示词注入"性质 → 留宿主。**实现顺序:kernel 先行,宿主后随**——kernel 发布新能力后,宿主改为调 kernel API(对齐 §4b 升级 SOP + 规则 11)。 + +### A 类:进 kernel(本次就提 upstream) + +| 设计成分 | 归属理由 | +|---|---| +| **score 选择机制**(importance + anti-recency + random) | 纯选择/排序算法——与 kernel 现有 `recommend` T1 门槛、`mergeRangesToThreshold` 同类,kernel 领域 | +| **Ebbinghaus 衰减/保质期/遗忘** | 纯算法——报告 P2-7 已标"时间维度/遗忘 = kernel 层变更走 upstream" | +| **记忆条目数据模型**(= tier-3 蒸馏块等价物) | 记忆形态就是 kernel 分层蒸馏产物——kernel 拥有 tier/蒸馏/块结构,宿主不另造格式 | +| **memory_recall 检索算法** | kernel 已有 `searchBlocks` hybrid(MRR 0.898)——扩展它搜记忆库是 kernel 的事(报告 P1-5 语义检索走 upstream 同方向) | +| **记忆库数据结构**(若复用 blocks/refs 概念) | 块/ref 管理是 kernel 拥有的 | +| **nudge 记忆提示文案**("有稳定结论→memory_commit") | 规则 9:kernel owns the prompt/format——nudge 文案属 kernel `renderNudgeText`(或经 config.prompts 模板层覆盖,那是宿主 wiring) | +| **三工具接口语义**(commit/recall/write 的 schema 与可见性:write 仅 fork) | 工具接口语义是 kernel 拥有的定义,宿主只做 DSH 工具面注册 | + +### B 类:留宿主(billion-context-dsh) + +| 设计成分 | 归属理由 | +|---|---| +| **memory_commit / memory_recall / memory_write 工具注册** | DSH 工具面是宿主 wiring(决策 7);memory_write 注册到 fork 会话的工具面(仅 fork 可见) | +| **一次性 LLM 调用(fork)实现** | 宿主 LLM 运行时能力;fork 带 memory_write 工具定义 | +| **memory_write 落库** | 宿主把 fork 的 memory_write 工具输出写入 markdown 记忆库 | +| **markdown 文件存储 + citation(会话+seq)** | seq 方言是宿主的(决策 7);文件系统是宿主 | +| **常驻索引注入 system prompt** | system-prompt.ts 是宿主 wiring | +| **/acp memory list** | 宿主命令 | +| **触发时机接线**(nudge hook → memory_commit) | 引擎 wiring | + +### 实施顺序 + +1. **Phase K(kernel 先行)**:向 acp-kernel 提 upstream issue(记忆能力面设计)+ PR——score 选择、Ebbinghaus 衰减、记忆条目数据模型、memory_recall 检索扩展、nudge 记忆提示文案; +2. **Phase H(宿主后随)**:kernel 发布后,billion-context-dsh bump kernel(§4b SOP)+ 实现宿主侧 B 类(工具注册、LLM 调用提取、markdown 存储、索引注入、/acp memory list、时机接线),全部调 kernel API。 + +## 6. 与 AGENTS.md 决策的相容性检查 + +| 决策/规则 | 相容性 | +|---|---| +| 决策 3 无自动摘要 | ✅ 提取写记忆库、不碰主对话、不压缩任何内容;compactIfNeeded 仍返回 null | +| 决策 6 搜索信任 kernel | ✅ memory_recall 检索算法进 kernel(扩展 searchBlocks);宿主只注册工具面 | +| 决策 7 信任 kernel 一切能力 | ✅ 算法类全部进 kernel(§6A A 类);宿主只拥有 DSH 集成(§6A B 类:工具面/LLM/文件/方言/注入) | +| 规则 11 缺陷走 upstream | ✅ 本设计所有算法都在 kernel 侧实现,宿主无 patch;若 kernel 记忆检索有 bug,上游修 | +| 规则 9 acp_status 渲染 | ✅ 不动 buildStatusReport;nudge 记忆提示文案属 kernel renderNudgeText(或 config.prompts 覆盖);/acp memory list 是宿主命令 | + +## 7. 用户侧接口 + +### 7.1 `/acp memory list`(唯一专用命令) + +**用户决策**:导入导出不需要专门命令——用户直接对模型说"把这段存进记忆"/"导入这个文件",模型自然用 memory_commit/读文件处理;人类侧只需一个查看命令。 + +- 列出全部记忆条目:`#id [type] 标题 (importance N, created, last_read)`——不带正文(正文用 memory_recall 或直接打开文件); +- 用途:用户看"现在库里有什么",识别过时/错误条目,决定手动改/删。 + +### 7.2 自然语言即接口 + +- "把这段写进长期记忆" → 模型 memory_commit(自动路径); +- "导入这个文件到记忆库" → 模型读文件 → 写入; +- "删除那条关于 X 的记忆" → 模型操作记忆库文件。 + +## 8. 配置项(草案) + +| 配置 | 默认 | 说明 | +|---|---|---| +| `memory.enabled` | false | 总开关(对齐 Claude prefetch 默认关——未优化前不干扰) | +| `memory.dir` | `.acp-memory/` | 记忆库目录 | +| `memory.bootstrapTokens` | ~1-2K | 常驻索引预算(Zylos bootstrap 参考:identity ~500 + project ~1K + retrieved ~2-4K) | +| `memory.topN` | 5 | 索引 top-N | +| `memory.sessionBudgetBytes` | 60KB | 会话 surfacing 累计上限(对齐 MAX_SESSION_BYTES) | +| `memory.weights` | α=1, β=1/30, γ=0.5 | score 公式权重(α·importance + β·min(days,30) + γ·rand) | + +## 9. 模块映射(实现时) + +**Phase K(kernel,upstream acp-kernel)**: + +| kernel 模块 | 职责 | +|---|---| +| `memory.ts`(新) | 记忆条目数据模型、score 选择、Ebbinghaus 衰减(§6A A 类) | +| `search.ts` 扩展 | memory_recall 检索(复用 searchBlocks hybrid 基础设施) | +| `nudge-text.ts` 扩展 | nudge 记忆提示文案("有稳定结论→memory_commit") | + +**Phase H(宿主,billion-context-dsh,调 kernel API)**: + +| 模块 | 职责 | 参照 | +|---|---|---| +| `src/memory.ts`(新) | 记忆库文件读写、索引构建(调 kernel memory API)、citation 记录 | dsh-memory 的 citation、dsh-memento 的 budget | +| `src/tools.ts` 扩展 | `memory_commit` / `memory_recall` 工具注册 | 现有四工具模式 | +| `src/nudge.ts` 扩展 | nudge 记忆引导接线(两段式:①有稳定结论→memory_commit ②已消费内容→compress) | 现有 buildNudgeText | +| `src/system-prompt.ts` 扩展 | 常驻索引注入(对齐 MEMORY.md) | 现有系统提示词 | +| `src/commands.ts` 扩展 | `/acp memory list` | 现有 /acp 命令 | +| 一次性 LLM 调用 | 宿主接缝(DSH 侧实现) | Claude Code runForkedAgent 思想,但无会话 | + +## 10. 测试计划(实现时) + +**Phase K(kernel 侧测试,上游)**: +1. score 公式:importance 主权重、反新鲜度 30 天封顶、随机 ±0.5、top-N=5; +2. Ebbinghaus 衰减:强度衰减、被读降权、久未读加权; +3. 记忆条目数据模型:类型校验、frontmatter schema; +4. memory_recall 检索:按 query 返回精炼态条目(复用 searchBlocks 测试设施)。 + +**Phase H(宿主侧测试)**: +5. memory_commit 工具 schema 校验(必选 type 枚举、可选 note); +6. 一次性 LLM 调用:输入 = 完整对话 + 指令,输出写入记忆库(带 citation); +7. 常驻索引:注入内容 = 一句话/条 + 类型 + last_read;预算内; +8. memory_recall 工具:转发 kernel 检索结果; +9. /acp memory list:列出全部条目; +10. 折叠自决:注入的记忆在 compress 中可被折叠、可重新 surfacing; +11. 回归:现有 152 tests 全绿(新功能不动现有行为)。 diff --git a/docs/memory-research/01-autonomous-memory-papers.md b/docs/memory-research/01-autonomous-memory-papers.md new file mode 100644 index 0000000..8031889 --- /dev/null +++ b/docs/memory-research/01-autonomous-memory-papers.md @@ -0,0 +1,267 @@ +# 自主记忆保存机制专项调研 + +> 为 Active Context Pruning (ACP) 项目的"跨会话长期记忆"功能设计提供文献支撑 +> 调研日期: 2026-07 +> 核心问题: 模型什么时候、凭什么决定"这段值得存进长期记忆"? + +--- + +## 一、训练内化型 —— 模型学会"何时压缩/保存" + +### 1.1 ACM: Agentic Context Management for Long Horizon Tasks + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2607.23809 · [HTML](https://arxiv.org/html/2607.23809v1) · [GitHub](https://github.com/lixiaochuan2020/agentic-context-management) | +| **核心机制** | 为模型配备两个显式工具:`manage_context`(压缩/删除/重写上下文条目)和 `query_memory`(检索历史上下文),通过 post-training 示范数据(expert trajectories)让模型内化"何时调用"的决策 | +| **触发条件** | **不是启发式规则,而是训练内化的隐式判断**。示范轨迹中模型在以下场景被训练调用 manage_context:(1) context 即将溢出窗口;(2) 某个子任务完成后其细节不再需要;(3) 累积的冗余信息开始干扰推理质量。具体判断完全由模型内部状态驱动 | +| **与 ACP 的异同** | **高度相似**:都是模型自决、通过显式工具调用来压缩。**关键区别**:ACM 的工具能力更强(可删除、重写、重组),且通过 SFT 把决策策略内化到模型权重中;ACP 目前依赖 prompt guidance(nudge)而非训练内化 | +| **启示** | 如果要让压缩决策更稳定可靠,最直接的路径是 post-training:收集"什么时候该压缩"的示范数据,用 SFT 让模型内化触发策略,而不是纯靠 prompt 工程 | + +### 1.2 AgentFold: Long-Horizon Web Agents with Proactive Context Folding + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2510.24699 · [HTML](https://arxiv.org/html/2510.24699v1) · [OpenReview (ICLR 2026)](https://openreview.net/forum?id=IuZoTgsUws) | +| **核心机制** | 每一步 agent 执行后,生成一条 **folding instruction**(折叠指令),将已完成的步骤压缩为精炼摘要。通过 SFT(无需 continual pre-training 或 RL)训练模型学会在每一步主动生成折叠指令 | +| **触发条件** | **结构性边界(structural boundary)**——每一步执行完毕就是一个自然的折叠点。模型被训练在每个 step boundary 主动 fold,而非等待 context 压力信号。这是一种"**事件驱动**"而非"**阈值驱动**"的策略 | +| **与 ACP 的异同** | **共同点**:模型自决压缩。**关键区别**:AgentFold 是步级事件驱动(每步必 fold),ACP 是渐进式压力驱动(nudge 触发,非每步必压缩)。AgentFold 更激进,可能丢失未来需要的中间状态 | +| **启示** | "步边界"是一个非常可靠的触发信号——agent 每完成一个子步骤,上一步的细节大概率不再需要。可以考虑在 ACP 中引入"任务完成"事件作为辅助触发,而不完全依赖 token 压力 | + +### 1.3 Context as a Tool (C^AT): Context Management for Long-Horizon SWE-Agents + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2512.22087 · [HTML](https://arxiv.org/html/2512.22087v1) · [HuggingFace](https://huggingface.co/papers/2512.22087) | +| **核心机制** | 将"上下文管理"本身建模为一种工具操作。通过 **condensor position generation**(压缩位置生成)识别三个信号来决定何时插入压缩操作:(1) **context expansion**(上下文膨胀速率);(2) **structural boundary**(结构性边界——任务切换、阶段转换);(3) **error-correction**(纠错信号——模型开始重复或犯错时) | +| **触发条件** | **三信号融合**:上下文大小增长 + 结构边界 + 错误修正信号。不是单一阈值,而是多信号综合判断 | +| **与 ACP 的异同** | **最接近 ACP 现有设计**——都是将压缩建模为工具操作、由模型自主决定。C^AT 的三信号框架比 ACP 的纯 pressure nudge 更丰富(ACP 只用 token 利用率一个信号)。C^AT 的 condensor position 生成类似于 ACP 的 compress range 选择 | +| **启示** | **最值得借鉴的框架**。ACP 可以引入"错误修正信号"(模型开始重复前面已纠正的内容时触发压缩)和"结构边界信号"(任务切换检测),而不只依赖 token 利用率 | + +### 1.4 Self-Compacting Language Model Agents (SelfCompact) + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2606.23525 · [HTML](https://arxiv.org/abs/2606.23525v1) · [GitHub](https://github.com/tianjianl/selfcompact) | +| **核心机制** | 脚手架方案(scaffolding),让模型自主决定最优的 **compaction timing**(压缩时机)和 **method**(压缩方法)。模型可以自行判断何时上下文中的 stale content 开始锚定(anchor)后续生成质量 | +| **触发条件** | 模型自主判断。核心发现:长 trace 中的 stale 内容会 **锚定(anchor)后续推理**,导致质量退化——这本身就是最强的触发信号。当模型"感觉"到自己的推理被历史内容干扰时,就是压缩的最佳时机 | +| **与 ACP 的异同** | 几乎完全相同的哲学——模型自决压缩。SelfCompact 更聚焦于"stale content 检测",ACP 更聚焦于"context 利用率管理"。两者可以互补 | +| **启示** | "stale content 锚定效应"是一个可检测的信号:如果模型的输出开始重复或引用已被修正的信息,说明旧内容在干扰——这是一个比 token 利用率更语义化的触发信号 | + +### 1.5 Active Context Compression (Focus) + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2601.07190 · [HTML](https://arxiv.org/html/2601.07190v1) | +| **核心机制** | 名为 "Focus" 的自主上下文压缩系统,针对 SWE 任务中的 "Context Bloat"。模型自主决定何时压缩已完成的子任务上下文 | +| **触发条件** | 子任务完成 + context 接近溢出双信号 | +| **与 ACP 的异同** | 高度相似,都是模型自决 + 工具调用压缩。Focus 更聚焦 SWE 场景 | +| **启示** | SWE 场景验证了"子任务完成"作为触发信号的有效性——代码任务有天然的结构性边界(文件修改完成、测试通过等) | + +### 1.6 SWE-MeM: Learning Adaptive Memory Management for Long-Horizon Coding Agents + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2606.28434 · [HTML](https://arxiv.org/html/2606.28434v1) | +| **核心机制** | 针对长时程编码 agent 的自适应记忆管理,学习何时将交互历史存入外部记忆、何时从外部记忆检索 | +| **触发条件** | 学习得到的策略——通过训练数据学习"哪些信息值得保存到外部记忆" | +| **与 ACP 的异同** | SWE-MeM 有明确的"保存到外部记忆"操作(跨会话持久化),ACP 目前只有会话内压缩。这是 ACP 向跨会话记忆扩展的直接参考 | +| **启示** | 编码场景的记忆保存可以和代码语义绑定——"这段修改了哪个模块"比"这段有多少 token"更有意义 | + +--- + +## 二、启发式信号型 —— 用规则/信号决定重要性 + +### 2.1 Generative Agents (Park et al.) + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2304.03442 · [HTML](https://arxiv.org/abs/2304.03442) · [ACM UIST 2023](https://dl.acm.org/doi/fullHtml/10.1145/3586183.3606763) · [AgentPatterns 深度解读](https://agentpatterns.ai/agent-design/generative-agents-memory-stream/) | +| **核心机制** | **Memory Stream**(记忆流)+ **三信号检索** + **Reflection**(反思)。所有观察都存入 memory stream,检索时按三个信号加权打分:(1) **Recency**(时效性,指数衰减);(2) **Importance**(重要性,1-10 分,由 LLM 评估);(3) **Relevance**(相关性,与当前 query 的 embedding 相似度)。当累积了足够多的近期记忆后,触发 **reflection**——让 LLM 生成高层抽象洞察 | +| **触发条件** | **保存时机**:所有观察无条件保存到 memory stream。**反思时机**:当最近记忆条目数超过阈值(如 150 条),自动生成"reflection question"并总结高层洞察。**重要性评分**由 LLM 在保存时实时评估 | +| **与 ACP 的异同** | **根本区别**:Generative Agents 保存一切、靠检索过滤;ACP 压缩后丢弃原文。**共同点**:都依赖 LLM 判断"重要性"。Generative Agents 的 reflection 机制类似于 ACP 的 tier-2/3 蒸馏——都是在摘要之上再生成更高层抽象 | +| **启示** | (1) "重要性评分"可以作为跨会话记忆保存的门控——只有 importance ≥ 阈值的摘要才写入长期记忆。(2) Reflection 机制可以直接复用:当 tier-1 块累积到一定数量,自动生成"这个会话的关键决策和模式是什么"的反思式 tier-2 摘要 | + +### 2.2 MemPO: Self-Memory Policy Optimization for Long-Horizon Agents + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2603.00680 · [ACL Findings 2026](https://aclanthology.org/2026.findings-acl.1166/) · [GitHub](https://github.com/TheNewBeeKing/MemPO) | +| **核心机制** | 通过 **RL 优化** 让模型学习最优的记忆管理策略。模型学会决定:(1) 什么信息值得保存到长期记忆;(2) 什么时候从长期记忆中检索。奖励信号来自下游任务性能 | +| **触发条件** | **学习得到的策略**,不是规则。模型通过 RL 训练内化了"保存到长期记忆的时机"——当保存某条信息能提升后续任务表现时,模型学会保存它 | +| **与 ACP 的异同** | MemPO 用 RL 优化记忆策略,ACP 用 prompt 引导。MemPO 的"什么值得保存"是通过奖励信号端到端学习的,ACP 目前靠模型的通用判断能力 | +| **启示** | 如果要系统性优化"何时保存到长期记忆",RL 是比 SFT 更灵活的路径——因为"保存时机是否正确"的反馈只有在后续使用该记忆时才能评估(延迟奖励),这正是 RL 擅长的 | + +### 2.3 Meta-Cognitive Memory Policy Optimization + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2605.30159 · [HTML](https://arxiv.org/html/2605.30159v1) | +| **核心机制** | 引入"元认知"层——模型不仅决定保存什么,还**反思自己的记忆管理策略是否有效**。通过递归式摘要(recursive summarization)将交互轨迹压缩为记忆条目,元认知层评估哪些摘要质量好、哪些丢失了关键信息 | +| **触发条件** | 递归摘要 + 元认知反思:模型生成摘要后,再评估这个摘要是否保留了足够信息来支持后续决策 | +| **与 ACP 的异同** | ACP 的 tier-2/3 蒸馏本质上也是递归摘要,但缺少"元认知评估"——即压缩后没有回头检查"这个摘要是否足够好"。这可以作为 ACP 压缩质量的反馈信号 | +| **启示** | **压缩质量自评**:在 ACP 中加入一步"压缩后评估"——压缩完成后,模型检查摘要是否保留了当前任务所需的关键信息,如果不满足则补充或重新压缩。这是"模型自决"的第二层保障 | + +### 2.4 Agentic Memory: Learning Unified Long-Term and Short-Term Memory Management + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2601.01885 · [ACL 2026](https://aclanthology.org/2026.acl-long.981/) · [PDF](https://aclanthology.org/2026.acl-long.981.pdf) | +| **核心机制** | 统一的长短期记忆管理框架。模型同时管理 working memory(当前上下文)、short-term memory(近期摘要)、long-term memory(持久化存储),学习在三者之间迁移信息 | +| **触发条件** | 学习得到的策略——通过训练数据学习什么信息应该从 working memory 升级到 short-term、再从 short-term 升级到 long-term | +| **与 ACP 的异同** | 与 ACP 的 tier-1/2/3 分层高度对应。ACP 的 tier-1 摘要 → tier-2 蒸馏 → tier-3 超浓缩 等价于 short-term → long-term 的迁移。区别在于 ACP 缺少"跨会话的 long-term memory"层 | +| **启示** | ACP 的三层蒸馏架构可以自然扩展为跨会话记忆:tier-3(超浓缩)是天然的"长期记忆条目"——足够精炼、可以跨会话持久化存储 | + +--- + +## 三、遗忘与淘汰型 —— 决定"忘掉什么" + +### 3.1 MemoryBank: Enhancing LLMs with Long-Term Memory + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2305.10250 · [AAAI 2024](https://ojs.aaai.org/index.php/AAAI/article/view/29946) · [GitHub](https://github.com/zhongwanjun/MemoryBank-SiliconFriend) | +| **核心机制** | 基于 **Ebbinghaus 遗忘曲线** 的记忆衰减模型。每条记忆有一个"记忆强度",随时间自然衰减;每次被检索/引用时强度更新(刷新)。强度低于阈值的记忆被"遗忘"(归档或删除) | +| **触发条件** | **被动衰减 + 主动刷新**:(1) 保存时初始强度 = f(重要性, 情感色彩);(2) 随时间指数衰减;(3) 被检索时强度回升;(4) 强度 < 阈值 → 遗忘 | +| **与 ACP 的异同** | ACP 没有遗忘机制——压缩后的块永久存在(除非手动 decompress + 重新压缩)。MemoryBank 的衰减模型可以直接用于 ACP 的长期记忆层:长期不被检索/不被引用的记忆自动降权 | +| **启示** | **直接可用**:为跨会话记忆条目添加"记忆强度"字段,用 Ebbinghaus 曲线管理衰减,被检索时刷新。阈值以下的记忆自动降级为更浓缩的形式或标记为可清理 | + +### 3.2 FadeMem: Biologically-Inspired Forgetting for Efficient Agent Memory + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2601.18642 · [HTML](https://arxiv.org/html/2601.18642v1) · [HuggingFace](https://huggingface.co/papers/2601.18642) | +| **核心机制** | 受生物学遗忘机制启发的 **选择性遗忘** 系统。不是简单的 Ebbinghaus 衰减,而是多因素遗忘决策:(1) 时间衰减;(2) 访问频率;(3) 与当前任务的相关性;(4) 信息冗余度(与其他记忆的重叠程度) | +| **触发条件** | 四因素综合评分低于阈值时触发遗忘。**信息冗余度** 是独特贡献——如果一条记忆的大部分信息已经被更新、更相关的记忆覆盖,则标记为可遗忘 | +| **与 ACP 的异同** | ACP 的蒸馏(tier-2/3)本质上就是一种"压缩式遗忘"——保留精华、丢弃细节。FadeMem 的冗余度检测可以用于 ACP:当多个 tier-1 块包含重叠信息时,合并它们并标记冗余块为可清理 | +| **启示** | **冗余度检测**是关键——跨会话记忆中,如果新信息完全覆盖了旧信息,旧记忆应该被更新或丢弃,而不是无限累积。这比单纯的"时间衰减"更智能 | + +--- + +## 四、记忆触发器的专门研究 + +### 4.1 SelfMem: Self-Optimizing Memory for AI Agents + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2607.03726 · [HTML](https://arxiv.org/html/2607.03726v1) · [HuggingFace](https://huggingface.co/papers/2607.03726) | +| **核心机制** | 专门研究 agent 的 **自优化记忆系统**。核心问题:当前 agent 虽然支持长上下文和工具使用,但缺乏对"什么信息值得记忆"的系统性优化。SelfMem 提出了一个记忆优化框架,让 agent 从自己的经验中学习记忆策略 | +| **触发条件** | **自优化循环**:agent 执行任务 → 评估记忆使用情况(哪些记忆被用了、哪些没被用、哪些缺失导致了错误)→ 更新记忆策略 → 下次执行时应用新策略 | +| **与 ACP 的异同** | SelfMem 关注的是"什么值得记"的优化,ACP 关注的是"什么时候压缩"。两者互补——SelfMem 的策略可以告诉 ACP "这段内容值得保存到长期记忆",ACP 的策略告诉 SelfMem "什么时候触发保存" | +| **启示** | **记忆使用回溯分析**:定期回顾"哪些压缩/保存决策是正确的"(通过后续是否检索/使用来判断),用这个信号优化触发策略。这是"模型自决"的元优化层 | + +### 4.2 Sleep-time Compute (Letta) + +| 字段 | 内容 | +|---|---| +| **来源** | arXiv:2504.13171 · [Letta 博客](https://www.letta.com/blog/sleep-time-compute/) · [GitHub](https://github.com/letta-ai/sleep-time-compute) | +| **核心机制** | 在 agent **不与用户交互的空闲时段**(sleep-time),预先处理和重组记忆。核心洞察:很多记忆整理工作不需要在推理时做,可以在空闲时预先完成——就像人类在睡眠时巩固记忆 | +| **触发条件** | **空闲时段触发**:agent 没有待处理的用户请求时,自动进入 sleep-time 模式,执行:(1) 整理近期交互为结构化记忆;(2) 生成跨会话的摘要和索引;(3) 更新记忆的相关性评分 | +| **与 ACP 的异同** | ACP 的压缩发生在推理时(online),sleep-time 的记忆整理发生在空闲时(offline)。两者可以结合:推理时做紧急压缩(tier-1),空闲时做深度整理(tier-2/3 蒸馏 + 跨会话持久化) | +| **启示** | **最实用的工程模式**:推理时只做轻量压缩(保证响应速度),复杂记忆整理延迟到空闲时做。ACP 可以在 session idle 时自动执行 tier-2/3 蒸馏和跨会话记忆写入,不占用用户等待时间 | + +### 4.3 MemGPT / Letta 的 Memory Hierarchy + +| 字段 | 内容 | +|---|---| +| **来源** | [Letta Context Hierarchy 文档](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/) · [Archival Memory 文档](https://docs.letta.com/guides/core-concepts/memory/archival-memory/) · [Context Constitution](https://www.letta.com/constitution/) | +| **核心机制** | 三层记忆架构:(1) **Core Memory**(核心记忆):始终在 context window 中,存放关键 persona 和用户信息,agent 可直接读写;(2) **Archival Memory**(归档记忆):语义搜索数据库,agent 通过工具存取,存放长期知识和历史事实;(3) **Recall Memory**(回忆记忆):完整的对话历史,可按时间/关键词检索 | +| **触发条件** | **agent 主动调用工具**:当 agent 认为某条信息是长期有价值但当前不需要的,调用 archival_memory_save 写入归档;当需要某条历史信息但不在 context 中时,调用 archival_memory_search 检索。判断完全由模型自主做出 | +| **与 ACP 的异同** | Letta 的 archival_memory_save 是最接近"跨会话长期记忆"的成熟实现。**关键区别**:Letta 让 agent 直接调用工具保存/检索,不需要"压缩"——原始内容直接存入归档;ACP 通过分层压缩产生精炼摘要。**互补**:ACP 的 tier-3 摘要是天然的 archival memory 条目 | +| **启示** | **最成熟的工程参考**。ACP 可以复用 Letta 的模式:将 tier-3 摘要作为 archival memory 条目,通过 embedding 索引,检索时返回精炼摘要。agent 在 compress 时自动判断"这个摘要值得跨会话保存",调用长期记忆工具 | + +--- + +## 五、检索返回什么 —— 精炼摘要 vs 原文 + +### 5.1 GraphRAG 的分层检索 + +| 字段 | 内容 | +|---|---| +| **来源** | [Microsoft Research](https://www.microsoft.com/en-us/research/publication/from-local-to-global-a-graph-rag-approach-to-query-focused-summarization/) · [GitHub](https://github.com/microsoft/graphrag) · [文档](https://microsoft.github.io/graphrag/) | +| **核心机制** | **层级式检索**:底层是原始文本 chunks,中层是实体/关系提取,顶层是 **community summaries**(社区摘要)。Global search 查询返回的是顶层 community summaries,而非原始 chunks;Local search 返回相关实体的原始上下文 | +| **检索返回** | **分层返回**:全局性问题 → 返回 community summaries(精炼摘要);局部性问题 → 返回相关 chunks(近原文)。摘要层是预计算的,不随查询变化 | +| **与 ACP 的异同** | GraphRAG 的 community summaries ≈ ACP 的 tier-2/3 摘要。**区别**:GraphRAG 的分层是预计算的、基于图结构的;ACP 的分层是运行时模型驱动的。但检索策略可以直接借鉴:全局性查询返回高层摘要,局部性查询返回低层详细内容 | +| **启示** | **分层检索策略**:跨会话记忆的检索应该根据查询类型返回不同层级的摘要——"这个项目的整体决策是什么"返回 tier-3,"那次 bug 的具体细节是什么"返回 tier-1 甚至 decompress 到原文 | + +### 5.2 MemGPT / Letta 的 External Context 分层 + +| 字段 | 内容 | +|---|---| +| **来源** | [Letta Context Hierarchy](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/) | +| **核心机制** | Core Memory(始终在 context 中)→ Recall Memory(可检索的完整历史)→ Archival Memory(语义搜索的长期存储)。每一层的信息粒度不同:Core 是最精炼的关键事实,Archival 可以是完整文档 | +| **检索返回** | Core Memory → 直接可见(最精炼);Recall Memory → 按时间/关键词返回原始对话;Archival Memory → 语义搜索返回存入时的原文 | +| **与 ACP 的异同** | Letta 的 Archival Memory 返回的是存入时的原文(精炼但不是原始对话),ACP 的 tier-3 也是存入时的超浓缩摘要。两者在"存入精炼、返回精炼"上一致 | +| **启示** | **返回精炼摘要而非原文**是更好的默认策略——因为存入长期记忆的内容已经过筛选和压缩,检索时返回精炼摘要既节省 context 空间,又保证信息密度。只有当摘要不够用时,才 decompress 到原文 | + +### 5.3 SelfComp 的检索设计 + +| 字段 | 内容 | +|---|---| +| **来源** | [GitHub: tianjianl/selfcompact](https://github.com/tianjianl/selfcompact) | +| **核心机制** | 压缩后的内容以摘要形式存入外部记忆。检索时返回摘要,模型决定是否需要更多细节 | +| **检索返回** | **默认返回摘要**,模型可以请求"展开"(类似 ACP 的 decompress)获取更多细节 | + +--- + +## 六、设计启示小结 + +### 6.1 可靠的触发方式分类 + +| 触发类型 | 机制 | 代表论文 | 可靠性 | 工程成本 | +|---|---|---|---|---| +| **① Token 压力触发** | context 利用率超过阈值 | ACP 现有设计、ACM | ⭐⭐⭐ 中等(可靠但晚——等到压力高时可能已经丢失了早期信息的最佳压缩时机) | ⭐ 极低(已实现) | +| **② 结构边界触发** | 子任务完成、步切换、阶段转换 | AgentFold、C^AT、Focus、SWE-MeM | ⭐⭐⭐⭐ 高(有明确的事件信号) | ⭐⭐ 低(需要事件检测,如 tool call 完成、任务状态变化) | +| **③ 语义退化触发** | 模型开始重复/犯错/推理质量下降 | C^AT (error-correction)、SelfCompact (stale anchor) | ⭐⭐⭐⭐ 高(直接反映问题) | ⭐⭐⭐⭐ 高(需要检测"推理质量下降"——可以通过自评或对比实现) | +| **④ 训练内化触发** | 通过 SFT/RL 训练模型内化"何时保存"的策略 | ACM、AgentFold、MemPO、Agentic Memory | ⭐⭐⭐⭐⭐ 最高(策略端到端优化) | ⭐⭐⭐⭐⭐ 最高(需要收集训练数据、训练模型) | +| **⑤ 空闲时整理** | agent 空闲时自动整理记忆 | Sleep-time Compute、Letta | ⭐⭐⭐⭐ 高(不占用推理时间) | ⭐⭐ 低(调度机制即可) | +| **⑥ Ebbinghaus 衰减** | 记忆强度随时间衰减,被使用时刷新 | MemoryBank、FadeMem | ⭐⭐⭐ 中等(对长期记忆淘汰有效,对保存时机无效) | ⭐⭐ 低(简单的数学模型) | + +### 6.2 对 ACP 项目的具体建议 + +1. **短期(纯工程,无训练)**: + - 引入**结构边界信号**:当检测到"子任务完成"(如 tool call 返回成功、任务状态变化)时,附加 nudge 提示"这是一个好的压缩点" + - 引入 **sleep-time 整理**:session idle 时自动执行 tier-2/3 蒸馏 + 跨会话记忆写入 + - 跨会话记忆存储 tier-3 摘要,用 embedding 索引,检索返回精炼摘要 + - 为长期记忆条目添加 Ebbinghaus 衰减强度,低强度记忆自动降级或清理 + +2. **中期(轻量训练)**: + - 收集"好的压缩时机"的示范数据(从现有会话中提取:何时压缩、压缩了什么、后续是否需要 decompress),用 SFT 让模型内化触发策略 + - 引入**压缩质量自评**:压缩后模型检查摘要是否保留了关键信息(参考 Meta-Cognitive Memory Policy) + +3. **长期(端到端优化)**: + - 用 RL 优化记忆策略(参考 MemPO):奖励信号 = 下游任务性能 + context 利用率效率 + - 实现 SelfMem 的自优化循环:回溯分析"哪些压缩决策是正确的",持续改进触发策略 + +### 6.3 检索策略建议 + +| 查询类型 | 返回层级 | 理由 | +|---|---|---| +| "这个项目的整体架构是什么" | tier-3 超浓缩摘要 | 全局性问题不需要细节 | +| "上次 bug 的 root cause 是什么" | tier-2 蒸馏摘要 | 需要决策和结论,不需要过程 | +| "那段代码的具体实现细节" | tier-1 摘要 → decompress 到原文 | 局部性问题需要精确内容 | +| 不确定需要什么 | 语义搜索返回 tier-2/3 摘要 + 相关性评分 | 让模型自行判断是否需要更多细节 | + +--- + +## 参考文献索引 + +| # | 论文 | arXiv / URL | 分类 | +|---|---|---|---| +| 1 | ACM: Agentic Context Management | [2607.23809](https://arxiv.org/abs/2607.23809) | 训练内化 | +| 2 | AgentFold | [2510.24699](https://arxiv.org/abs/2510.24699) | 训练内化 | +| 3 | Context as a Tool (C^AT) | [2512.22087](https://arxiv.org/abs/2512.22087) | 训练内化 | +| 4 | SelfCompact | [2606.23525](https://arxiv.org/abs/2606.23525) | 训练内化 | +| 5 | Active Context Compression (Focus) | [2601.07190](https://arxiv.org/abs/2601.07190) | 训练内化 | +| 6 | SWE-MeM | [2606.28434](https://arxiv.org/abs/2606.28434) | 训练内化 | +| 7 | Generative Agents | [2304.03442](https://arxiv.org/abs/2304.03442) | 启发式信号 | +| 8 | MemPO | [2603.00680](https://arxiv.org/abs/2603.00680) | 启发式信号(训练) | +| 9 | Meta-Cognitive Memory Policy | [2605.30159](https://arxiv.org/abs/2605.30159) | 启发式信号 | +| 10 | Agentic Memory | [2601.01885](https://arxiv.org/abs/2601.01885) | 启发式信号(训练) | +| 11 | MemoryBank | [2305.10250](https://arxiv.org/abs/2305.10250) | 遗忘曲线 | +| 12 | FadeMem | [2601.18642](https://arxiv.org/abs/2601.18642) | 遗忘曲线 | +| 13 | SelfMem | [2607.03726](https://arxiv.org/abs/2607.03726) | 记忆触发器 | +| 14 | Sleep-time Compute (Letta) | [2504.13171](https://arxiv.org/abs/2504.13171) | 记忆触发器 | +| 15 | MemGPT / Letta | [docs.letta.com](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/) | 架构参考 | +| 16 | GraphRAG | [microsoft.github.io/graphrag](https://microsoft.github.io/graphrag/) | 检索策略 | +| 17 | LangChain Autonomous Compression | [langchain.com/blog](https://www.langchain.com/blog/autonomous-context-compression) | 工程参考 | diff --git a/docs/memory-research/02-autonomous-memory-implementations.md b/docs/memory-research/02-autonomous-memory-implementations.md new file mode 100644 index 0000000..0d33d8f --- /dev/null +++ b/docs/memory-research/02-autonomous-memory-implementations.md @@ -0,0 +1,362 @@ +# Autonomous Memory Implementations — Cross-Product Research + +> **Purpose**: Research for the billion-context-dsh project (Active Context Pruning engine for DSH). +> **Core question**: How do products/plugins implement "autonomous memory saving" at the product/plugin layer? +> **Covers**: save timing, memory tool description wording, retrieval format, session boundary handling. + +--- + +## 1. Claude Code Auto Memory + +**URL**: [code.claude.com/docs/en/memory](https://code.claude.com/docs/en/memory) | Source: `extractMemories.ts`, `prompts.ts` ([claude-code-analysis](https://github.com/liuup/claude-code-analysis)) + +### Save Timing +- **Trigger**: End of each complete query loop — when the model produces a final response with no more tool calls, via `handleStopHooks` in `stopHooks.ts` +- **Implementation**: `runForkedAgent` — a perfect fork of the main conversation sharing the parent's prompt cache (no re-computation) +- **Mutual exclusion**: if the main agent already wrote memories this turn, extraction skips entirely +- **7-layer memory architecture**: CLAUDE.md (human) → Auto Memory (AI-written) → Background Extract → Session Memory → Agent Memory → Relevant Memories → Auto Dream (idle-time consolidation) + +### Memory Tool / System Prompt +- **Tools allowed in extraction fork**: FileRead, Grep, Glob, read-only Bash, FileEdit/FileWrite ONLY for auto-memory directory paths; `Bash rm` is denied +- **Storage path**: `~/.claude/projects//memory/` +- **Taxonomy** (closed, 4 types): `user` (role/preferences), `feedback` (corrections/confirmations), `project` (context/decisions), `reference` (pointers to external systems) +- **What NOT to save** (explicit negative prompt): code patterns, git history, debugging plans, content already in CLAUDE.md, temporary task status +- **Key design**: even when the user explicitly asks to save something, the AI should ask "what about it was surprising or non-obvious?" — the non-obvious part is what's worth keeping + +### Retrieval Format +- Each memory in its own `.md` file with frontmatter, indexed in `MEMORY.md` (≤200 lines, ≤25KB) +- `MEMORY.md` injected into context at session start (traditional path) or replaced by Relevant Memories prefetch (new path with feature gate `tengu_moth_copse`) + +### Session Boundary Handling +- Auto memory is **cross-session** — persists across all sessions for the same repository +- Session memory (layer 4) is single-session, stored at `~/.claude/projects///session-memory/summary.md` +- All worktrees of the same repo share the same memory directory (via `findCanonicalGitRoot()`) + +### Insights +- **Prompt-code co-design**: code guarantees directory existence (`ensureMemoryDirExists`), prompt tells AI "directory already exists — write directly" to avoid wasted `ls`/`mkdir -p` turns +- **Background extraction is fire-and-forget** from the stop hook; closure-scoped state with mutex + trailing-run pattern for overlapping triggers +- **Team memory** syncs via HTTP endpoints with secret scanning (pre-write and push-time), with a `pushSuppressedReason` gate to prevent infinite retry on auth failure + +--- + +## 2. Cline Memory Bank + +**URL**: [github.com/cline/prompts/.clinerules/memory-bank.md](https://github.com/cline/prompts/blob/main/.clinerules/memory-bank.md) + +### Save Timing +- When discovering new patterns +- After significant changes +- When the user says "update memory bank" +- When context needs clarification + +### Structure — 6 Core Files +| File | Purpose | +|---|---| +| `projectBrief.md` | Foundation — project overview | +| `productContext.md` | Why the project exists, problems it solves | +| `activeContext.md` | Current work focus, recent changes, next steps | +| `systemPatterns.md` | Architecture, key technical decisions, design patterns | +| `techContext.md` | Technologies, dev setup, constraints | +| `progress.md` | What works, what's left, known issues | + +### Key Design Principle +> "My memory resets completely between sessions. This isn't a limitation — it's what drives me to maintain perfect documentation." + +- ALL files must be read at start of EVERY task (mandatory) +- Files build on each other in a hierarchy: `projectBrief` → others → `activeContext` → `progress` + +### Session Boundary Handling +- Explicit "amnesia model" — memory resets between sessions by design +- The entire memory bank IS the memory; no implicit recall mechanism + +### Insights +- **Radical transparency** about memory limitations drives better documentation +- Fixed 6-file structure makes memory predictable but rigid +- No automatic save — entirely prompted by rules text in the system context + +--- + +## 3. mem0 / OpenMemory + +**URL**: [github.com/mem0ai/mem0](https://github.com/mem0ai/mem0) | Config: `configs/prompts.py` (1062 lines) + +### Save Timing +- **Two-phase pipeline**, application-level (NOT model tool-calling): + 1. **Phase 1 — Fact Extraction**: `FACT_RETRIEVAL_PROMPT` / `USER_MEMORY_EXTRACTION_PROMPT` extracts facts as JSON `{"facts": [...]}` + 2. **Phase 2 — Update Decision**: `DEFAULT_UPDATE_MEMORY_PROMPT` decides ADD/UPDATE/DELETE/NONE for each fact vs existing memory +- LLM is called separately by the application to extract/update — the model doesn't call memory tools + +### Tool Description / Prompts +- **Fact extraction categories**: personal preferences, personal details, plans/intentions, activity preferences, health/wellness, professional details, miscellaneous +- **Update prompt**: smart memory manager with 4 operations (ADD/UPDATE/DELETE/NONE); includes detailed few-shot examples for each operation including ID management +- Separate prompts for user facts vs agent facts (`AGENT_MEMORY_EXTRACTION_PROMPT`) +- `PROCEDURAL_MEMORY_SYSTEM_PROMPT`: comprehensive agent execution history summarization with verbatim output preservation + +### Retrieval Format +- Memories stored as structured entries with IDs +- Retrieval via semantic search returning matching memory entries + +### Session Boundary Handling +- Extraction happens at application layer, not tied to session lifecycle +- Can run asynchronously after session ends + +### Insights +- **Decoupled extraction**: the model doesn't need to decide when to save — the application extracts after every interaction +- **Structured update operations** (ADD/UPDATE/DELETE with ID management) give fine-grained control +- **Few-shot examples** in the update prompt are critical for consistent behavior + +--- + +## 4. Letta / MemGPT + +**URL**: [docs.letta.com](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/) | [github.com/letta-ai/letta](https://github.com/letta-ai/letta) + +### Save Timing +- **Agent-driven**: the model decides when to save based on conversation content +- Model explicitly calls tools to update memory blocks + +### Memory Tools +| Tool | Purpose | +|---|---| +| `core_memory_append` | Add to in-context core memory | +| `core_memory_replace` | Update in-context core memory | +| `archival_memory_insert` | Store in archival (long-term) memory | +| `archival_memory_search` | Search archival memory semantically | + +### Three Memory Types +| Type | Lifecycle | Visibility | +|---|---|---| +| **Core Memory** | In-context, always visible | Typed sections in the context window | +| **Archival Memory** | Semantically searchable long-term | Retrieved on demand | +| **File-based** | Read on demand | External files | + +### Architecture +- Memory blocks are typed sections in the context window +- The model explicitly decides when to call `core_memory_append`/`core_memory_replace` vs `archival_memory_insert` +- Context hierarchy: Core Memory is always in the prompt; Archival Memory requires search + +### Session Boundary Handling +- Core Memory persists across sessions (it's the in-context state) +- Archival Memory is permanent store, searched on demand +- The "sleep-time" concept: background consolidation of memories + +### Insights +- **Explicit tool-calling for memory** gives the model full control but requires it to "remember to remember" +- **Core vs Archival split** mirrors human working memory vs long-term memory +- **Sleep-time processing** for consolidation is a key pattern for background memory management + +--- + +## 5. LangMem / LangGraph Memory + +**URL**: [github.com/langchain-ai/langmem](https://github.com/langchain-ai/langmem) | Source: `src/langmem/knowledge/tools.py` (530 lines) + +### Save Timing +- Agent-driven via tool calls, with explicit prompt guidance + +### Memory Tools + +**`create_manage_memory_tool()`** — creates a tool with actions create/update/delete: +``` +Default instructions: "Proactively call this tool when you: +1. Identify a new USER preference. +2. Receive an explicit USER request to remember. +3. Are working and want to record important context. +4. Identify that an existing MEMORY is incorrect or outdated." +``` + +- Tool signature: `manage_memory(content, action, id)` — `content` for new/updated, `id` for update/delete +- Configurable instructions parameter for custom guidance + +**`create_search_memory_tool()`** — semantic search via LangGraph `BaseStore`: +``` +Description: "Search your long-term memories for information relevant to your current context." +Signature: search_memory(query, limit=10, offset=0, filter=None) +``` + +### Retrieval Format +- Memories stored in namespaced `BaseStore` with `{langgraph_user_id}` runtime substitution +- Injected into system prompt via `` block +- Schema customization supported via Pydantic models + +### Session Boundary Handling +- Memories persist in the `BaseStore` across sessions +- Namespacing by user ID ensures isolation +- Integrates with `create_react_agent` pattern + +### Insights +- **Proactive instruction** ("proactively call when...") is the key wording pattern — it tells the model WHEN to save, not just HOW +- **Namespace-based isolation** is clean and extensible +- **`` block injection** into system prompt is a standard retrieval pattern + +--- + +## 6. DSH Ecosystem Memory Plugins + +### 6a. dsh-memento + +**URL**: [github.com/PerryLink/dsh-memento](https://github.com/PerryLink/dsh-memento) + +**Save Timing**: +- `memory` tool with Save/Skip guidance in the tool description +- Approval gate: `writePolicy` ask/auto/off; ALL writes forced through approval waterfall +- Proposals: auto-capture after successful compaction; max 8 pending, 2000 chars each + +**Memory Tool**: +- `memory` tool: add/replace/remove/consolidate/query +- `memory_recall` tool: bounded memory matches + recent session-history matches + +**Architecture**: +- Typed `ctx.memory` seam + SQLite provider + frozen snapshot in system prompt +- Two tracks (user/agent) × two layers (user-global/workspace) × per-agent key +- Hard per-track/per-layer character budgets (default user 2000 / agent 4000 chars) +- Frozen snapshot at session start, never changes mid-session + +**Storage**: SQLite WAL, 0600 permissions, zero network + +**Protocol**: dsh-memory-protocol v1: entry spec, write semantics (idempotent unique-substring), audit contract, budget model + +### 6b. dsh-memory + +**URL**: [github.com/Jesse-njx/dsh-memory](https://github.com/Jesse-njx/dsh-memory) + +**Key Idea**: "summaries are an index into ground truth, never the truth" + +**Save Timing**: +- Background distillation pass extracts durable facts into small markdown files +- Every memory carries citation `(sessionId, [start..end])` pointing at exact log events + +**Tools**: `memory_read(name)` full memory, `memory_expand(name)` cited original log excerpt + +**Retrieval Format**: One markdown file per memory with JSON header comment (name, description, type, citations, createdAt, updatedAt, rev) + +**Types**: user (cross-project), project (facts about project), feedback (corrections) + +### 6c. dsh-mem + +**URL**: [github.com/Jelee0145/dsh-mem](https://github.com/Jelee0145/dsh-mem) + +**Architecture**: Capability seam: Service Definition + Service Provider + Consumer + +**Tools**: `memory_save`, `memory_recall`, `memory_forget`, `memory_list` + +**Storage**: `$DSH_HOME/memory/memory.json` atomic JSON-file persistence + +**Search**: Case-insensitive substring search on content + exact tag match + +### 6d. dsh-memory-evolve + +**URL**: [github.com/csyangwen/dsh-memory-evolve](https://github.com/csyangwen/dsh-memory-evolve) + +**Save Timing**: +- Auto-records progress each turn end +- Key memories require user confirmation before saving + +**Five-track memory**: user profile, global facts, project key memories (with git branch awareness), project log/daily log + +**Features**: Emotion feedback recording, cross-device sync via git branches, self-review loop option + +--- + +## 7. MemOS + +**URL**: [github.com/MemTensor/MemOS](https://github.com/MemTensor/MemOS) + +**Save Timing**: Auto-recall before task + retain after successful turn (DSH plugin integration) + +**Architecture**: Memory Operating System — unified store/retrieve/manage API + +**Capabilities**: +- Multi-modal memory: text, images, tool traces, personas +- Multi-cube knowledge base management +- Async ingestion via MemScheduler +- Memory feedback & correction with natural language + +**Benchmarks**: LoCoMo 88.83, LongMemEval 89.20 + +--- + +## 8. Basic Memory + +**URL**: [basicmemory.com](https://basicmemory.com) | [github.com/basicmachines-co/basic-memory](https://github.com/basicmachines-co/basic-memory) + +**Architecture**: MCP-based knowledge graph + +**Key Concept**: Bridge between Claude's working memory and durable knowledge graph + +**Persistence**: Decisions, architecture, project context carry over across sessions + +--- + +## Summary: Engineering Patterns for Autonomous Memory + +### Pattern 1: Save Timing Taxonomy + +| Strategy | Products | Trade-off | +|---|---|---| +| **End-of-turn hook** | Claude Code, dsh-memory-evolve | Reliable but may miss in-flight insights | +| **Agent-driven tool call** | Letta, LangMem, dsh-memento | Flexible but model may forget to save | +| **Application-level extraction** | mem0 | Decoupled from model but requires separate LLM call | +| **Manual prompt-triggered** | Cline | Simple but relies on user/system prompt | +| **Background distillation** | dsh-memory | Non-blocking but citation chain needed | + +### Pattern 2: Memory Tool Description Wording + +The most effective tool descriptions use **proactive instruction** with **concrete triggers**: + +| Product | Wording Pattern | +|---|---| +| **LangMem** | "Proactively call this tool when you: 1. Identify a new USER preference. 2. Receive an explicit USER request to remember. 3. Are working and want to record important context. 4. Identify that an existing MEMORY is incorrect or outdated." | +| **Claude Code** | "What NOT to save" is as important as what to save — explicit negative taxonomy prevents memory bloat | +| **Letta** | Implicit — model learns from core_memory_append/replace tool descriptions | +| **mem0** | N/A — extraction is application-level, not model tool-calling | + +**Best practice**: Combine positive triggers (WHEN to save) with negative constraints (what NOT to save). The "what not to save" guidance is undersupplied in most implementations. + +### Pattern 3: Retrieval Format + +| Format | Products | Use Case | +|---|---|---| +| **Markdown files with frontmatter** | Claude Code, dsh-memory, Cline | Human-readable, git-friendly | +| **Structured JSON/SQLite** | mem0, dsh-mem, dsh-memento | Queryable, atomic operations | +| **Semantic vector store** | Letta (archival), LangMem, MemOS | Natural language retrieval | +| **In-context blocks** | Letta (core), LangMem (``) | Always-visible, token-expensive | + +**Hybrid trend**: Small always-visible core (like Letta's Core Memory or dsh-memento's frozen snapshot) + searchable long-term store. + +### Pattern 4: Session Boundary Handling + +| Strategy | Products | Key Insight | +|---|---|---| +| **Shared across worktrees** | Claude Code | `findCanonicalGitRoot()` ensures one memory per repo | +| **Amnesia by design** | Cline | Forces perfect documentation as compensation | +| **Citation to log** | dsh-memory | "Summaries are an index into ground truth" | +| **Frozen snapshot** | dsh-memento | Snapshot at start, never changes mid-session | +| **Namespace isolation** | LangMem | `{langgraph_user_id}` substitution | + +### Pattern 5: Memory Consolidation + +| Strategy | Products | Trigger | +|---|---|---| +| **Auto Dream** | Claude Code | Session idle time | +| **Sleep-time processing** | Letta | Background agent | +| **Self-review loop** | dsh-memory-evolve | Configurable interval | +| **Consolidation tool** | dsh-memento | Model-initiated | + +### Key Takeaways for billion-context-dsh (ACP Engine) + +1. **Save timing matters most**: the end-of-turn hook (Claude Code pattern) is the most reliable for automatic capture; agent-driven tool calls (Letta/LangMem) give flexibility but risk the model "forgetting to remember." + +2. **Negative constraints are undersupplied**: most implementations focus on WHEN to save; Claude Code's "what NOT to save" taxonomy is a standout pattern that prevents memory bloat. + +3. **Hybrid retrieval wins**: small in-context summary (frozen snapshot or `` block) + searchable long-term store is the emerging standard. + +4. **Citation chains add trust**: dsh-memory's "summaries are an index into ground truth" pattern — every memory pointing at exact log events — is valuable for debugging and verification. + +5. **Memory budgets prevent bloat**: dsh-memento's hard per-track/per-layer character budgets (2000/4000 chars) and Claude Code's MEMORY.md limits (200 lines / 25KB) are critical guardrails. + +6. **Application-level extraction** (mem0 pattern) decouples memory from model behavior but costs an extra LLM call; **model-driven extraction** (Claude Code/Letta) is cheaper but relies on prompt engineering. + +--- + +*Research compiled for billion-context-dsh (Active Context Pruning engine for DSH). All URLs verified from source code fetches and search results.* diff --git a/docs/memory-research/03-memory-readback-timing.md b/docs/memory-research/03-memory-readback-timing.md new file mode 100644 index 0000000..21175c2 --- /dev/null +++ b/docs/memory-research/03-memory-readback-timing.md @@ -0,0 +1,359 @@ +# 记忆读回时机专项调研 + +> 调研日期:2026-08-08 | 上下文:Active Context Pruning (ACP) for DeepSeek Harness +> 目标:研究"记忆什么时候被读回(注入/检索进对话上下文)"的业界方案 + +--- + +## 一、论文方向:读回时机 + +### 1.1 Generative Agents(Park et al., 2023)—— 每次行动前检索 + +- **论文**: [Generative Agents: Interactive Simulacra of Human Behavior](https://arxiv.org/abs/2304.03442) (UIST 2023) +- **检索时机**: **每次行动前(per-action retrieval)**。agent 在决定"下一步做什么"时,从 memory stream 中检索 top-k 相关记忆注入 prompt。 +- **打分机制**: 三信号加权 —— + - `recency`:指数衰减,当前时间与记忆时间戳的差 + - `importance`:LLM 给出的 1-10 重要性评分(在记忆写入时一次性评估) + - `relevance`:query 与记忆的 cosine similarity(embedding) + - 最终分数 = `α·recency + β·importance + γ·relevance`(α=1, β=1, γ=1 默认等权) +- **代码参考**: [retrieve.py](https://github.com/joonspk-research/generative_agents/blob/main/reverie/backend_server/persona/cognitive_modules/retrieve.py) — `run()` 函数在 observation/planning 时调用 +- **关键设计**: retrieval 是 **reactive**(响应当前任务需要),不是 proactive(不会提前预加载)。每次 agent 需要做决策时触发一次检索。 + +### 1.2 MemGPT / Letta —— 分层常驻 + 按需检索 + +- **论文**: [MemGPT: Towards LLMs as Operating Systems](https://arxiv.org/abs/2310.08560) (2023) +- **产品**: [Letta](https://docs.letta.com/) (原 MemGPT) +- **三层记忆架构**: + | 层级 | 内容 | 读回时机 | + |------|------|---------| + | **System Prompt** | 固定指令、persona | 会话开始全量注入(不可变) | + | **Core Memory** (in-context blocks) | 用户信息、agent 自我认知、关键事实 | **始终常驻上下文**,agent 通过 `core_memory_replace` 工具自主编辑内容,但 blocks 始终在 context window 中 | + | **Archival Memory** (out-of-context) | 长期知识、历史事实 | **模型自主工具调用检索**:agent 调用 `archival_memory_search(query)` 或 `archival_memory_insert(content)` 按需读写 | + | **Recall Memory** | 对话历史 | agent 调用 `conversation_search(query)` 按需检索历史对话 | +- **读回决策**: 模型自己决定何时需要额外信息,通过 function calling 发起检索。系统 prompt 中明确指示:*"You respond directly to the user when your immediate context (core memory and files) contain all the information needed; otherwise, you proactively use your tools to search for the answer."* +- **来源**: [Letta context hierarchy docs](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/), [Letta archival memory docs](https://docs.letta.com/guides/core-concepts/memory/archival-memory/), [memgpt_v2_chat.py system prompt](https://github.com/letta-ai/letta/blob/main/letta/prompts/system_prompts/memgpt_v2_chat.py) + +### 1.3 HippoRAG —— 查询时知识图谱检索 + +- **论文**: [HippoRAG: Neurobiologically Inspired Long-Term Memory for Large Language Models](https://arxiv.org/abs/2405.14831) (2024) +- **读回时机**: **查询时检索(on-demand retrieval)**,与标准 RAG 相同——用户查询到来时触发。 +- **创新点**: 不是简单的向量检索,而是模拟海马体索引理论:构建知识图谱(KG),用 PersonalizedPageRank 从 query 中提取的 entities 出发在 KG 上漫游,检索最相关的 passages。 +- **对比标准 RAG**: 标准 RAG 在查询时做 flat vector search;HippoRAG 在查询时做 graph-based retrieval。**检索时机相同(查询时),但检索机制更复杂。** +- **来源**: [HippoRAG HTML](https://arxiv.org/html/2405.14831v2), [AWS blog on HippoRAG](https://aws.amazon.com/blogs/machine-learning/hipporag-neurobiologically-inspired-rag-using-amazon-bedrock-amazon-neptune-and-personalized-pagerank) + +### 1.4 ACM (Agentic Context Management) —— 模型自主调用 `query_memory` + +- **论文**: [ACM: Agentic Context Management for Long Horizon Tasks](https://arxiv.org/abs/2607.23809) (2026-07) +- **核心设计**: 不依赖固定阈值触发压缩/检索,而是给模型两个工具: + - `compress_context`:将当前上下文压缩到外部存储(agent 自主决定何时压缩) + - `query_memory`:从外部记忆中检索相关信息(agent 自主决定何时检索) +- **读回时机**: **完全由模型自主决定**——模型判断当前上下文不足时,调用 `query_memory` 从外部记忆中拉取。 +- **关键特点**: + - 可逆压缩——压缩的内容可以被完整检索回来 + - 不是 "阈值到了就压缩" 的被动策略,而是 agent 主动管理上下文 + - 作者认为这是比固定策略更优的方法 +- **来源**: [ACM HTML](https://arxiv.org/html/2607.23809v1), [ACM abstract](https://arxiv.org/abs/2607.23809), [Codex KB 分析](https://codex.danielvaughan.com/2026/08/02/acm-agentic-context-management-long-horizon-tasks-codex-cli-compaction-external-memory-retrieval/) + +### 1.5 Agentic Memory(AgeMem, ACL 2026)—— 学习何时管理记忆 + +- **论文**: [Agentic Memory: Learning Unified Long-Term and Short-Term Memory Management for LLM Agents](https://arxiv.org/abs/2601.01885) (ACL 2026) +- **核心**: 通过强化学习训练一个统一的记忆管理策略,同时决定 **写入** 和 **读回** 时机。 +- **读回时机**: 不是固定的规则,而是学习到的策略——agent 学会在适当的时候检索长期记忆。 +- **短期记忆**: 在上下文窗口内,类似 working memory +- **长期记忆**: 外部存储,通过学习到的策略检索 +- **意义**: 首次将记忆管理(包括读回)作为可学习的策略,而非手工设计的规则。 +- **来源**: [AgeMem arXiv](https://arxiv.org/abs/2601.01885), [ACL Anthology](https://aclanthology.org/2026.acl-long.981/), [GitHub y1y5/AgeMem](https://github.com/y1y5/AgeMem) + +### 1.6 A-MEM (NeurIPS 2025) —— 自组织记忆的按需检索 + +- **论文**: [A-MEM: Agentic Memory for LLM Agents](https://arxiv.org/abs/2502.12110) (NeurIPS 2025) +- **核心**: 记忆条目(memory atoms)自主组织成链接网络,每条记忆自己决定与其他记忆的关联。 +- **读回时机**: **按需检索**——当新信息到来时,检索相关记忆 atoms。检索用 embedding similarity + 链接关系。 +- **关键点**: 检索效率在大规模下依然良好(minimal growth in retrieval time)。 +- **来源**: [A-MEM arXiv](https://arxiv.org/abs/2502.12110), [GitHub agiresearch/A-mem](https://github.com/agiresearch/a-mem) + +### 1.7 TraceRetain(2026)—— 选择性记忆保留 + +- **论文**: [TraceRetain: Selective Memory Retention for Long-Horizon LLM Agents](https://arxiv.org/abs/2606.29178) (2026-06) +- **核心问题**: 记忆污染(memory pollution)——不相关或过时的记忆被检索进来反而降低性能。 +- **读回时机**: 研究了检索后 **过滤** 的重要性——不是"检索什么时机",而是"检索回来后该保留什么"。 +- **轻量框架**: 在检索后通过一个轻量过滤器判断哪些记忆值得注入上下文。 +- **意义**: 读回时机不仅指"何时检索",还包括"检索后是否真的注入"。 +- **来源**: [TraceRetain arXiv](https://arxiv.org/abs/2606.29178) + +### 1.8 专门研究"注入时机"的论文 + +#### Session Bootstrap Context Budgets(Zylos Research, 2026-07) +- **来源**: [Session Bootstrap Context Budgets](https://zylos.ai/research/2026-07-03-session-bootstrap-context-budgets/) +- **核心发现**: 每个长期运行的 agent 框架最终都收敛到相似的 session bootstrap 形态——启动时加载一组"bootstrap context"。 +- **Bootstrap 构成**: persona/identity + project context + recent memory + retrieved knowledge +- **关键结论**: Bootstrap 不是全量注入所有记忆,而是有预算分配的分层加载。 + +#### Beyond the Context Window(arXiv:2603.04814, 2026-03) +- **来源**: [Beyond the Context Window: A Cost-Performance Analysis](https://arxiv.org/html/2603.04814) +- **核心**: 对比"事实库记忆"vs"长上下文直接塞入全历史"的性价比。发现基于记忆的方案在成本和性能上更优。 + +#### PACMS: Submodular Context Selection(arXiv:2606.20047) +- **来源**: [PACMS](https://arxiv.org/html/2606.20047) +- **核心**: 将上下文选择建模为子模优化问题——选择哪些记忆条目注入上下文以最大化任务性能。 + +#### Semantic Memory Injection(MindStudio, 2026-06) +- **来源**: [Semantic Memory Injection for AI Agents](https://www.mindstudio.ai/blog/semantic-memory-injection-frozen-snapshot-pattern) +- **分析**: Frozen snapshot pattern 的优缺点——上下文窗口填满快、token 成本高、过时历史可能污染。 + +--- + +## 二、产品/项目方向:读回时机 + +### 2.1 Claude Code Auto Memory —— 会话开始全量注入(有限制) + +- **机制**: + - `CLAUDE.md`:**每次 turn 注入** system prompt(不只是会话开始,是每次请求) + - `MEMORY.md`(auto memory):同样 **每次 turn 注入** system prompt + - 限制:只加载 MEMORY.md 的 **前 200 行** + - 注入位置:system prompt 的 Block 4(dynamic content,在 DYNAMIC_BOUNDARY 之后) +- **Relevant Memories (tengu_moth_copse)**: 这是一个 feature gate,实验性功能——根据当前上下文 prefetch 相关记忆片段(而非全量注入),但尚未成为默认行为 +- **来源**: [Claude Code memory docs](https://code.claude.com/docs/en/memory), [db0.ai 分析](https://db0.ai/blog/how-claude-code-memory-works), [ccmd.dev token 分析](https://ccmd.dev/t/claude-md-auto-memory-tokens), [GitHub issue #46644](https://github.com/anthropics/claude-code/issues/46644) +- **启示**: 全量注入简单但有 token 预算问题;200 行限制是一种粗略的预算控制。 + +### 2.2 Cline Memory Bank —— 会话开始强制全读 + +- **机制**: 6 个 markdown 文件,**"ALL files must be read at start of EVERY task"** + - `projectBrief.md` — 项目概述 + - `productContext.md` — 产品上下文 + - `activeContext.md` — 当前活跃上下文 + - `systemPatterns.md` — 系统模式 + - `techContext.md` — 技术上下文 + - `progress.md` — 进度 +- **来源**: [Cline Memory Bank docs](https://docs.cline.bot/best-practices/memory-bank), [prompts repo](https://github.com/cline/prompts/blob/main/.clinerules/memory-bank.md), [DeepWiki 分析](https://deepwiki.com/cline/prompts/3.1-memory-bank-system) +- **特点**: 最激进的全量注入——没有检索、没有过滤、没有预算。优势是零遗漏,劣势是 token 浪费。 + +### 2.3 mem0 —— 查询时检索,应用层注入 + +- **机制**: + - mem0 本身**不自动注入**——它是一个记忆存储/检索 API + - 应用层在每轮对话前调用 `memory.search(query)` 获取相关记忆 + - 返回的记忆由应用层组装进 system prompt 或 user message + - **推荐模式**: 在每轮对话的 user message 前注入检索到的记忆 +- **来源**: [mem0 docs](https://docs.mem0.ai/core-concepts/how-it-works), [mem0 search docs](https://docs.mem0.ai/core-concepts/memory-operations/search), [GitHub issue #3736](https://github.com/mem0ai/mem0/issues/3736), [GitHub issue #4341](https://github.com/mem0ai/mem0/issues/4341) +- **特点**: 纯 API 设计,注入时机完全由调用者控制。灵活但需要集成者自己实现注入逻辑。 + +### 2.4 Letta —— Core Memory 常驻 + Archival/Recall 按需 + +- **Core Memory blocks**: 始终在上下文中,agent 通过工具编辑内容但 blocks 永远可见 +- **Archival Memory**: agent 调用 `archival_memory_search` 按需检索 +- **Recall Memory**: agent 调用 `conversation_search` 按需检索 +- **来源**: [Letta context hierarchy](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/), [Letta agent memory blog](https://www.letta.com/blog/agent-memory/), [Letta memory blocks blog](https://www.letta.com/blog/memory-blocks/), [Letta community discussion](https://forum.letta.com/t/how-does-memory-work-in-letta/93) +- **关键**: 这是 **混合模式** 的典范——小常驻核心 + 大量按需检索。 + +### 2.5 dsh-memento (PerryLink) —— Frozen Snapshot 会话开始注入 + +- **来源**: [GitHub PerryLink/dsh-memento](https://github.com/PerryLink/dsh-memento), [plugin registry](https://deepseek1024.com/plugins/PerryLink/dsh-memento) +- **机制**: + - 提供 typed `ctx.memory` 服务,含 `add/replace/remove/query/seed/budgets` 方法 + - 写操作需要 approval gate + - 会话开始时通过 frozen snapshot seed 注入记忆 + - 分层设计,有 token 预算控制 +- **读回时机**: **会话开始预注入**(frozen snapshot pattern) + +### 2.6 dsh-memory (Jesse-njx) —— Cited Memory with Tool-Based Retrieval + +- **来源**: [GitHub Jesse-njx/dsh-memory](https://github.com/Jesse-njx/dsh-memory), [plugin registry](https://dsh-plugin.net/plugins/dsh-memory) +- **机制**: + - 基于 DSH 无损会话日志的 cited memory + - 记忆是 distilled、human-auditable 的事实,带 citation 回溯到原始 source events + - **读回时机**: 模型通过工具(类似 search_context)按需检索 + - 特点:记忆本身带引用链,可追溯 + +### 2.7 其他系统 + +#### Basic Memory (MCP) +- **来源**: [Basic Memory docs](https://docs.basicmemory.com/reference/mcp-tools-reference), [agent memory playbook](https://basicmemory.com/playbooks/agent-memory) +- **机制**: MCP 工具提供 `read_note`/`search`/`list` 等;agent 自主决定何时调用 +- **读回时机**: **模型自主工具调用**——Basic Memory 不自动注入,agent 需要时主动搜索 + +#### MemOS (arXiv:2507.03724) +- **来源**: [MemOS arXiv](https://arxiv.org/abs/2507.03724), [GitHub MemTensor/MemOS](https://github.com/MemTensor/MemOS), [MemOS Context API](https://api.mymemoryos.com/docs/api/context) +- **机制**: Memory Operating System,统一 store/retrieve/manage +- **Context API**: 提供 `retrieve` 端点,根据 query 检索相关记忆,支持 token budget 限制 +- **读回时机**: **查询时检索**,通过 Context API 传入当前 query + token budget,返回格式化记忆 + +#### LangMem (LangChain) +- **来源**: [LangMem tools reference](https://langchain-ai.github.io/langmem/reference/tools/), [memory tools guide](https://langchain-ai.github.io/langmem/guides/memory_tools/) +- **机制**: 提供 `manage_memory_tool`(写)和 `search_memory_tool`(读) +- **两种路径**: + - Hot path: agent 在对话中自主调用工具保存/检索(按需) + - Background extraction: 后台异步提取记忆(不影响即时检索时机) +- **读回时机**: **模型自主工具调用**——agent 自己决定何时 `search_memory` + +--- + +## 三、模式总结 + +### 3.1 读回时机的四种模式 + +| 模式 | 触发时机 | 典型实现 | 代表系统 | +|------|---------|---------|---------| +| **A. 会话开始预注入 (Session-start injection)** | 会话/任务启动时 | 读取固定文件 → 注入 system prompt | Claude Code (CLAUDE.md/MEMORY.md), Cline Memory Bank, dsh-memento | +| **B. 查询时按需检索 (On-demand query retrieval)** | 每次用户查询/agent 决策时 | embedding search / KG retrieval → 注入 | Generative Agents, HippoRAG, mem0, MemOS | +| **C. 模型自主工具调用 (Model-initiated tool call)** | 模型判断需要时 | agent 调用 search/retrieval 工具 | MemGPT/Letta (archival), ACM (query_memory), Basic Memory, LangMem | +| **D. 常驻固定块 (Persistent resident blocks)** | 始终在上下文中 | 作为 system prompt 的一部分永久存在 | Letta (Core Memory blocks), 系统 prompt 指令 | + +### 3.2 各模式优缺点 + +| 模式 | 优点 | 缺点 | 适用场景 | +|------|-----|------|---------| +| **A. 预注入** | 零延迟、零遗漏、实现简单 | token 浪费严重(无关记忆也占用预算)、随记忆增长不可扩展 | 记忆量小(<200 行 / <2K tokens)、关键上下文必须全局可见 | +| **B. 查询时检索** | 高效利用 token 预算、随记忆量可扩展 | 依赖检索质量(可能遗漏)、有检索延迟、需要 embedding 基础设施 | 记忆量大、需要语义相关性匹配 | +| **C. 模型自主调用** | 最灵活、模型按需取用、与推理过程深度整合 | 增加工具调用开销、模型可能"忘记"检索、增加推理 token | 复杂任务、agent 需要自主决策 | +| **D. 常驻固定块** | 最可靠的"always-on"信息、零检索开销 | 挤压可用上下文空间、内容需要人工/agent 维护 | 最核心的身份/指令信息、小量关键事实 | + +### 3.3 混合模式:小常驻 + 按需取回 + +**业界共识正在收敛到混合模式**,核心证据: + +1. **Letta/MemGPT 的三层架构**是混合模式的教科书案例: + - System prompt(固定,不可变) + - Core Memory(常驻 blocks,agent 可编辑内容但始终在上下文中) + - Archival + Recall(按需工具检索) + - 来源: [Letta docs](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/) + +2. **Zylos Research 的 Session Bootstrap 研究**(2026-07)发现:所有长期运行的 agent 框架都自然收敛到分层 bootstrap 形态——启动时加载一组核心 context,运行时按需检索补充。 + - 来源: [Zylos session bootstrap](https://zylos.ai/research/2026-07-03-session-bootstrap-context-budgets/) + +3. **Claude Code 的实践**:CLAUDE.md(常驻)+ MEMORY.md(常驻前 200 行)+ Relevant Memories(实验性按需 prefetch)= 混合模式的渐进演化。 + - 来源: [Claude Code memory docs](https://code.claude.com/docs/en/memory) + +4. **Beyond the Context Window 论文**(arXiv:2603.04814)的定量对比表明:纯长上下文方案在成本和性能上均劣于"小常驻 + 按需记忆库"方案。 + - 来源: [arXiv 2603.04814](https://arxiv.org/html/2603.04814) + +5. **Semantic Memory Injection 研究**(MindStudio, 2026-06)分析了 frozen snapshot pattern 的固有局限:上下文填满快、token 成本高、过时信息污染。结论是需要结合 selective retrieval。 + - 来源: [MindStudio blog](https://www.mindstudio.ai/blog/semantic-memory-injection-frozen-snapshot-pattern) + +### 3.4 记忆注入的上下文预算研究 + +| 研究/系统 | 发现 | 来源 | +|----------|------|------| +| **Claude Code** | MEMORY.md 限制前 200 行(约 ~3K tokens on real index) | [ccmd.dev](https://ccmd.dev/t/claude-md-auto-memory-tokens) | +| **Generative Agents** | 默认 top-k=30 条记忆注入 | [retrieve.py](https://github.com/joonspk-research/generative_agents/blob/main/reverie/backend_server/persona/cognitive_modules/retrieve.py) | +| **PACMS** | 子模优化建模上下文选择,证明存在"最优子集"——注入全部记忆不如选择性注入 | [arXiv 2606.20047](https://arxiv.org/html/2606.20047) | +| **Zylos Bootstrap** | 推荐分层预算:identity (~500 tokens) + project context (~1K) + retrieved memory (~2-4K) | [Zylos](https://zylos.ai/research/2026-07-03-session-bootstrap-context-budgets/) | +| **MemOS Context API** | 支持 `token_budget` 参数,调用者显式控制注入上限 | [MemOS Context API](https://api.mymemoryos.com/docs/api/context) | +| **AdaMem (arXiv:2606.21144)** | 学习"记什么"——个性化长期 agent 需要选择性记忆而非全量记忆 | [arXiv 2606.21144](https://arxiv.org/html/2606.21144v1) | + +--- + +## 四、模式谱系表 + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 记忆读回时机谱系 │ +├──────────┬──────────────┬──────────────────┬──────────────────────────────────────┤ +│ 时机类型 │ 触发方式 │ 代表系统 │ 优缺点 │ +├──────────┼──────────────┼──────────────────┼──────────────────────────────────────┤ +│ 会话开始 │ 启动时自动 │ Claude Code │ ✅ 零延迟、零遗漏 │ +│ 预注入 │ 全量注入 │ Cline Memory Bank│ ❌ token 浪费、不可扩展 │ +│ │ │ dsh-memento │ 📦 适合: 小记忆集、关键全局上下文 │ +├──────────┼──────────────┼──────────────────┼──────────────────────────────────────┤ +│ 查询时 │ 每次 query │ HippoRAG │ ✅ 高效 token 使用 │ +│ 按需检索 │ 触发检索 │ mem0 │ ❌ 检索质量依赖、可能遗漏 │ +│ │ │ MemOS │ 📦 适合: 大记忆库、语义匹配场景 │ +├──────────┼──────────────┼──────────────────┼──────────────────────────────────────┤ +│ 模型自主 │ agent 调用 │ MemGPT/Letta │ ✅ 最灵活、与推理深度整合 │ +│ 工具调用 │ search 工具 │ ACM (query_mem) │ ❌ 增加工具开销、可能遗忘 │ +│ │ │ LangMem, BasicMem│ 📦 适合: 复杂自主任务 │ +├──────────┼──────────────┼──────────────────┼──────────────────────────────────────┤ +│ 常驻固定块 │ 始终在上下文 │ Letta Core Mem │ ✅ 最可靠、零检索开销 │ +│ │ 中不可移除 │ System Prompt │ ❌ 挤压可用空间 │ +│ │ │ │ 📦 适合: 核心身份/指令信息 │ +├──────────┼──────────────┼──────────────────┼──────────────────────────────────────┤ +│ 混合模式 │ 小常驻 + 按需 │ Letta (完整架构) │ ✅ 兼顾可靠性与效率 │ +│ (主流趋势) │ 检索 │ Claude Code (演进)│ ❌ 实现复杂度高 │ +│ │ │ A-MEM │ 📦 适合: 生产级长期 agent │ +└──────────┴──────────────┴──────────────────┴──────────────────────────────────────┘ +``` + +--- + +## 五、对我们设计的启示(ACP / billion-context-dsh) + +### 5.1 核心判断 + +**我们当前只做了"写"(memory_commit → fork 子对话提取 → 写入 markdown),还没做"读"。读回设计应该采用混合模式。** + +### 5.2 推荐设计 + +#### Tier 1: 常驻注入(Session Bootstrap) +- **时机**: 会话开始时注入 +- **内容**: 最核心的记忆摘要(项目偏好、用户习惯、关键决策) +- **预算**: 控制在 ~1-2K tokens(参考 Zylos bootstrap 和 Claude Code 的 200 行限制) +- **实现**: ACP 引擎在 `agent/pre-step` 首次触发时,从记忆库中加载 bootstrap 记忆注入 system prompt + +#### Tier 2: 按需检索(On-demand via search_context) +- **时机**: 模型通过已有的 `search_context` 工具触发 +- **内容**: 记忆库中相关条目(带 citation 回溯) +- **实现**: 让 `search_context` 同时搜索压缩块和记忆库,或新增一个 `recall_memory` 工具 +- **关键**: 检索结果应带 confidence score,由模型判断是否注入 + +#### Tier 3: 可选的 Nudge-Triggered Recall +- **时机**: nudge 时,引擎检查当前上下文与记忆库的相关性,主动预取可能需要的记忆 +- **灵感**: Generative Agents 的 recency × relevance 打分 +- **实现**: nudge 时不只提示压缩,也提示"这里有一些相关的历史记忆:[摘要],需要注入吗?" + +### 5.3 设计原则 + +1. **不要全量注入**:记忆库会增长,全量注入不可扩展(Cline 的方式在记忆增长后不可行) +2. **保持 citation chain**:参考 dsh-memory,每条记忆应指向原始 session event(我们已有 log-rebuilt ledger,这是天然优势) +3. **给模型选择权**:参考 ACM 和 MemGPT,模型应能自主决定何时检索,而不是引擎强制注入 +4. **token 预算要显式**:参考 MemOS 的 `token_budget` 参数,注入量应有上限 +5. **利用 ACP 已有基础设施**:`search_context` 已经实现了 hybrid search,记忆库搜索可以复用这个通道 + +### 5.4 与 ACP 现有架构的契合点 + +| ACP 现有能力 | 记忆读回利用方式 | +|-------------|---------------| +| `search_context` 工具 | 扩展为同时搜索压缩块 + 记忆库 | +| Nudge 机制 | 在 nudge 中注入"相关记忆提示" | +| `acp_status` | 展示记忆库状态(大小、条目数) | +| 子对话 fork(写入端) | 已有;读回是镜像操作 | +| Session event log | 记忆 citation 的天然来源 | + +### 5.5 不建议的方案 + +1. **不建议** 纯全量注入(Cline 方式)——记忆增长后 token 浪费严重 +2. **不建议** 纯按需检索无 bootstrap——关键上下文可能被遗漏(模型不知道该检索什么) +3. **不建议** 引擎强制注入——应保留模型自主权(ACP 的核心哲学:model-driven, not policy-driven) +4. **不建议** 新增独立记忆检索服务——利用已有的 `search_context` 基础设施 + +--- + +## 六、参考文献 + +### 论文 +1. Park et al. (2023). *Generative Agents: Interactive Simulacra of Human Behavior*. [arXiv:2304.03442](https://arxiv.org/abs/2304.03442) +2. Packer et al. (2023). *MemGPT: Towards LLMs as Operating Systems*. [arXiv:2310.08560](https://arxiv.org/abs/2310.08560) +3. Gutierrez et al. (2024). *HippoRAG: Neurobiologically Inspired Long-Term Memory for LLMs*. [arXiv:2405.14831](https://arxiv.org/abs/2405.14831) +4. (2026-07). *ACM: Agentic Context Management for Long Horizon Tasks*. [arXiv:2607.23809](https://arxiv.org/abs/2607.23809) +5. (2026-01). *Agentic Memory: Learning Unified Long-Term and Short-Term Memory Management*. [arXiv:2601.01885](https://arxiv.org/abs/2601.01885) (ACL 2026) +6. Xu et al. (2025). *A-MEM: Agentic Memory for LLM Agents*. [arXiv:2502.12110](https://arxiv.org/abs/2502.12110) (NeurIPS 2025) +7. (2026-06). *TraceRetain: Selective Memory Retention for Long-Horizon LLM Agents*. [arXiv:2606.29178](https://arxiv.org/abs/2606.29178) +8. (2026-03). *Beyond the Context Window: A Cost-Performance Analysis*. [arXiv:2603.04814](https://arxiv.org/html/2603.04814) +9. (2026-06). *PACMS: Submodular Context Selection*. [arXiv:2606.20047](https://arxiv.org/html/2606.20047) +10. (2025-07). *MemOS: A Memory OS for AI System*. [arXiv:2507.03724](https://arxiv.org/abs/2507.03724) +11. (2026-06). *AdaMem: Learning What to Remember*. [arXiv:2606.21144](https://arxiv.org/html/2606.21144v1) +12. de Jong et al. (2023). *Pre-computed memory or on-the-fly encoding?*. [PMLR](https://proceedings.mlr.press/v202/de-jong23a.html) + +### 产品/项目 +13. Claude Code Memory Docs. [code.claude.com/docs/en/memory](https://code.claude.com/docs/en/memory) +14. Claude Code MEMORY.md token analysis. [ccmd.dev](https://ccmd.dev/t/claude-md-auto-memory-tokens) +15. Cline Memory Bank. [docs.cline.bot/best-practices/memory-bank](https://docs.cline.bot/best-practices/memory-bank) +16. mem0. [docs.mem0.ai](https://docs.mem0.ai/core-concepts/how-it-works) +17. Letta. [docs.letta.com/guides/core-concepts/memory/context-hierarchy](https://docs.letta.com/guides/core-concepts/memory/context-hierarchy/) +18. dsh-memento. [github.com/PerryLink/dsh-memento](https://github.com/PerryLink/dsh-memento) +19. dsh-memory. [github.com/Jesse-njx/dsh-memory](https://github.com/Jesse-njx/dsh-memory) +20. Basic Memory. [basicmemory.com/playbooks/agent-memory](https://basicmemory.com/playbooks/agent-memory) +21. MemOS. [github.com/MemTensor/MemOS](https://github.com/MemTensor/MemOS) +22. LangMem. [langchain-ai.github.io/langmem](https://langchain-ai.github.io/langmem/guides/memory_tools/) +23. Zylos Session Bootstrap. [zylos.ai/research/2026-07-03-session-bootstrap-context-budgets](https://zylos.ai/research/2026-07-03-session-bootstrap-context-budgets/) +24. Semantic Memory Injection (MindStudio). [mindstudio.ai/blog](https://www.mindstudio.ai/blog/semantic-memory-injection-frozen-snapshot-pattern) +25. Generative Agents Code (retrieve.py). [GitHub joonspk-research/generative_agents](https://github.com/joonspk-research/generative_agents/blob/main/reverie/backend_server/persona/cognitive_modules/retrieve.py) diff --git a/docs/memory-research/04-claude-code-source-verification.md b/docs/memory-research/04-claude-code-source-verification.md new file mode 100644 index 0000000..d15154e --- /dev/null +++ b/docs/memory-research/04-claude-code-source-verification.md @@ -0,0 +1,50 @@ +# Claude Code 记忆机制源码核实(Claude Code Memory — Source-Verified) + +> **核实时间**:2026-08 | **来源**:[liuup/claude-code-analysis](https://github.com/liuup/claude-code-analysis)(Claude Code 反编译镜像,`/tmp/claude-code-analysis` 已随重启消失,本文件为提炼结论) +> **用途**:billion-context-dsh 跨会话记忆设计的生产实践背书(见 `docs/cross-session-memory-design.md` §5.2) + +## 1. 记忆写入(extractMemories) + +- **触发**:每次完整 query loop 结束(模型产出最终回复、无更多工具调用时),经 `handleStopHooks`(`stopHooks.ts`)。 +- **实现**:`runForkedAgent`——主对话的完美 fork,共享父 prompt cache(零重算),fire-and-forget 不阻塞。 +- **互斥**:主 agent 本 turn 已写过记忆则跳过提取。 +- **提取 fork 权限**:只允许只读工具(FileRead/Grep/Glob/只读 Bash)+ FileEdit/FileWrite **仅限** auto-memory 目录;`Bash rm` 被禁。 +- **存储路径**:`~/.claude/projects//memory/`。 +- **4 类 taxonomy**:`user`(偏好)/`feedback`(纠正确认)/`project`(上下文决策)/`reference`(外部指针)。 +- **negative constraints(防膨胀)**:显式禁止保存 code patterns、git history、debugging plans、已在 CLAUDE.md 的内容、临时任务状态。 +- **金句提示**:即使确认要保存,也追问"其中什么令人惊讶或不显然?"——非显然部分才值得存。 +- **团队记忆**:HTTP 同步 + secret 扫描(写前与 push 时)+ `pushSuppressedReason` gate 防认证失败无限重试。 + +## 2. 记忆读取(双层) + +### 2.1 MEMORY.md 常驻 system prompt + +- `findRelevantMemories.ts:31` 注释原文:"Excludes MEMORY.md (already loaded in system prompt)"——MEMORY.md 已在 system prompt 中,选择器排除它。 +- 索引格式 = 一句话/条:`formatMemoryManifest` → `- [type] filename (timestamp): description`。 +- **上限**:`MAX_MEMORY_FILES = 200`(memoryScan.ts:21,**记忆文件数上限**,非 MEMORY.md 行数——注意与子代理报告"前 200 行"表述的区别,后者可能指 docs 层的注入截断)。 + +### 2.2 relevant_memories 异步 prefetch(默认关闭) + +- `startRelevantMemoryPrefetch`(attachments.ts:2361): + - **总开关**:`getFeatureValue_CACHED_MAY_BE_STALE('tengu_moth_copse', false)`——**feature gate,默认 OFF**(实验功能,非默认行为;首次核实时误判"源码未见该 gate",子代理报告正确,特此修正记录)。 + - **语义 gate**:单字 prompt(无空格 `/\s/`)跳过——没有上下文可提取关键词。 + - **频率**:每 user turn 一次(query.ts:301 注释:"Fired once per user turn — the prompt is invariant across loop iterations, so per-iteration firing would ask sideQuery the same question N times");async 非阻塞,`using` 绑定生命周期随 turn 销毁。 + - **选择器**:Sonnet sideQuery(`SELECT_MEMORIES_SYSTEM_PROMPT` + JSON schema `output_format`,max_tokens 256)——从记忆文件清单选**最多 5 个**("Be selective and discerning",只选确信有用的;不确定就不选;最近使用的工具文档不选,但 warnings/gotchas 选)。 + - **节流**:会话累计 `MAX_SESSION_BYTES = 60KB`(attachments.ts:288)超限停止 surfacing。 + - **单文件截断**:`MAX_MEMORY_BYTES = 4096` + 行数限制,截断时提示 "Use the FILE_READ_TOOL_NAME tool to view the complete file"。 + - **去重**:`alreadySurfaced`(选过的路径不再选,5-slot 预算花新候选)+ `readFileState`(模型已读文件不再塞)。 + - **@-mention 隔离**:提及 agent 时只搜该 agent 的记忆目录,否则搜 auto-memory 目录。 + - **compact 重置**:compact 后 old attachments 从 transcript 消失 → re-surfacing valid again(注释原文)。 + +## 3. 7 层记忆架构 + +CLAUDE.md(人写) → Auto Memory(AI 写)→ Background Extract → Session Memory(单会话,`~/.claude/projects///session-memory/summary.md`)→ Agent Memory → Relevant Memories(prefetch)→ Auto Dream(空闲整合)。 + +## 4. 对本项目的启示 + +1. **"常驻索引 + 自主取回"是生产实践**(MEMORY.md 常驻 + FileRead 取全文)——我们选 Claude 路线(索引常驻 + 全文按需),比 Letta(内容常驻)token 更省。 +2. **prefetch 默认关**——记忆读回未优化前不自动灌入,支持我们"常驻索引 + 自主取回"的简化设计(不学 prefetch 自动注入)。 +3. **negative constraints 与正向触发并重**——memory_commit 提示词必须写"何时不要调用"(待定项 T1)。 +4. **硬预算防膨胀**——文件数 200 / 会话 60KB / 单文件 4096B,支持我们配置项草案(sessionBudgetBytes)。 +5. **fork 提取的权限最小化**——提取对话只允许只读 + 记忆目录写入,`Bash rm` 禁用;我们的一次性 LLM 调用同理应只写记忆库。 +6. **extractMemories 每次 turn 结束时无条件提取** vs 我们的**决策门控**(只在 memory_commit 表态时)——我们的更省(Claude 是事件驱动,我们是模型自决)。 diff --git a/docs/memory-research/05-plain-language-summary.md b/docs/memory-research/05-plain-language-summary.md new file mode 100644 index 0000000..a2ee6fc --- /dev/null +++ b/docs/memory-research/05-plain-language-summary.md @@ -0,0 +1,47 @@ +# 跨会话长期记忆:一页纸设计方案 + +## 我们在解决什么问题 + +现在的 AI 助手每次会话结束就"失忆"了。今天聊的结论、踩的坑、做的决定,明天开新会话全不记得,得重新讲一遍。 + +我们想给它加一个"笔记本":**重要的事记下来,下次会话能想起来用**。 + +## 核心流程:三步 + +``` +第 1 步:记 + 模型觉得"这段值得记住" → 说一声"我要记这个" + → 系统悄悄让模型自己把内容提炼成一条笔记 → 存进笔记本 + (不影响当前对话,也不占用当前对话的记忆) + +第 2 步:存 + 笔记本 = 一个普通的文件夹,里面是 Markdown 文件 + → 人能直接打开看、改、删(不是黑盒) + → 每条笔记带"记于什么时候、来自哪次会话"(可追溯) + → 每条笔记有"保质期":一直没被用到的笔记,权重越来越低,自动让位给有用的 + +第 3 步:用 + 新会话开始时,系统只给模型看一个"目录"(每条笔记一句话) + → 模型知道"哦,我有这些历史笔记" + → 处理相关任务时,模型自己决定:打开哪条笔记看全文 + → 用过的笔记,下次目录里权重降低,让其他笔记也有机会露面 +``` + +## 三个关键设计(为什么这样做) + +**1. 记笔记不打断当前对话** +模型只说"我要记",写笔记由后台单独完成。当前对话继续干自己的事——像秘书帮你做会议纪要,不用你停下手头的活。 + +**2. 笔记人是可读的** +不搞数据库黑盒,就是一个文件夹里的 Markdown 文件。你能直接打开看它记了什么,写错了就改,过时了就删。 + +**3. 用"目录 + 自己翻"而不是"全塞进去"** +不把全部笔记倒进每次对话(那样上下文会爆)。只给一个一行一条的目录,模型需要哪条自己打开看。目录用"重要性 + 多久没被翻过 + 一点随机"排序,避免热门笔记永远霸榜、冷门笔记永远不见天日。 + +## 一句话总结 + +> **给 AI 加一个人类可读的笔记本:重要的事自动记下来,下次会话给个目录、需要时自己翻——人随时能打开修改。** + +--- + +*完整技术设计见 `docs/cross-session-memory-design.md`(含内核/宿主职责划分与实施顺序)。* diff --git a/docs/memory-research/05-upstream-proposal.md b/docs/memory-research/05-upstream-proposal.md new file mode 100644 index 0000000..29099df --- /dev/null +++ b/docs/memory-research/05-upstream-proposal.md @@ -0,0 +1,92 @@ +# 跨会话长期记忆:上游(acp-kernel)提案 + +> 给 acp-kernel / billion-context-pi 作者的方案稿。想法来自 billion-context-dsh 的 P1-4 缺口:**会话内压缩我们做得很好了,但会话结束即失忆**——跨会话记忆这块,希望 kernel 来拥有(算法归 kernel,宿主只做集成)。 + +## 一、问题 + +ACP 解决的是"一个会话内上下文无限膨胀"。但它不解决"下一个会话不知道上个会话发生了什么": + +- 今天聊定的设计决策、踩的坑、用户偏好,明天开新会话全没了 +- 业界(mem0 / Letta / Claude Code Auto Memory / Cline Memory Bank)都有跨会话记忆,但都独立于压缩体系 + +**核心认知:每次压缩生成的块(如 tier-1 块 b1)本身就是适合长期存储的内容**——压缩把已消费对话提炼成精炼摘要,这个摘要天然就是长期记忆的候选。所以跨会话记忆不该是另起炉灶的独立系统,而应该是压缩体系的**自然延伸**:记忆沉淀复用压缩产物,模型决定哪些块/内容值得沉淀(不搞引擎自动归档——沉淀决策始终是模型自决)。 + +**一句话**:把"跨会话记忆"和"压缩"做成同一套机制的两面——压缩是会话内折叠,记忆是跨会话沉淀;都复用 kernel 的蒸馏/ref/搜索基础设施。 + +## 二、核心机制:nudge 表态 + fork 提取(模型自决写入) + +当模型判断"这段有值得跨会话记住的内容"(无论是对话内容,还是某个压缩块 b1 的摘要值得沉淀)时: + +``` +nudge 触发(kernel 已有) + → 模型回顾上下文(本来就在做) + → 模型判断:这段有值得跨会话记住的吗? + 有 → 调用轻量工具 memory_commit(type, note) 【纯表态,不写内容】 + → 引擎 fork 一个同模型子对话(同文本 + 一句指令"提取当前需要的记忆,重点:{note}") + → fork 会话最后:模型用 memory_write 把提炼结果写入记忆库 + → fork 使命结束(可归档/删除),主对话继续压缩 +``` + +**三个工具,权限分离**: + +| 工具 | 谁可见 | 干什么 | +|---|---|---| +| `memory_commit(type, note)` | **主对话** | 表态"这段值得记"(type 枚举 + note 聚焦提示);不写内容 | +| `memory_recall(query)` | **主对话** | 读回:检索记忆库取全文(见 §三) | +| `memory_write(content)` | **仅 fork 会话** | 真正写记忆库;**主对话物理上无写权限** | + +主对话只有"请求写"的能力、没有"写"的能力——写记忆库只能通过 fork 会话的 memory_write 完成,权限天然隔离(fork = 带 memory_write 工具定义的一次性 LLM 调用,宿主把工具输出落库)。这比"fork 直接落文件"更符合工具面架构,也让三工具语义进 kernel 接口定义。 + +**为什么这样设计**: +- **时机是现成的**——nudge 时模型正在做全局回顾,对"这段讲了什么、什么值得留"认知最佳(比 Claude Code 的"每轮结束自动提取"更省,比 mem0 的"应用层另起 LLM"更模型自决) +- **决策与执行分离**——模型只做轻量"要不要记"的判断(一次工具调用,note 是聚焦提示),繁重的提炼下放给 fork(不打断主对话、不占主对话上下文) +- **fork 缓存命中**——同模型同文本(+一句指令),prompt cache 共享 + +## 三、读回:常驻索引 + 自主取回(两时机,不搞多层) + +``` +时机① 常驻索引:记忆库目录(一句话/条 + 类型 + 上次读取时间)注入 system prompt,每次 turn 都在 + → 模型"知道有什么"(存在性提示,解决"想不起来去翻") +时机② 自主取回:模型看到相关条目 → 调 memory_recall(query) 取全文 + → 细节按需取,不一股脑全塞 +``` + +这正好是 Claude Code 生产实践的形态(MEMORY.md 常驻 + FileRead 取全文),两大主流系统(Claude Code / Letta)独立收敛到同一形态,不是我们发明。 + +## 四、选择与衰减:一个公式两用 + +**问题**:纯"被读频率"优先 → 富者愈富(被读 → 频率升 → 优先被读 → 更被读;没被读的永远不见天日)。 + +**机制**(字段全是记忆条目自带的,不需要 embedding/向量): +``` +score = importance + min(距上次读取天数 / 30, 5) + uniform(0, 0.5) +``` +- `importance`(1-10):模型 memory_commit 表态时顺带评分(一次性评估,Generative Agents 做法) +- `anti-recency`:**越久没被读优先级越高**——刚读过的降权让位,把正反馈变负反馈 +- `random jitter`:随机打破"永远同一批"的锁定 +- **top-N = 5**(对齐 Claude 5-slot);会话累计 surfacing 上限对齐 Claude 60KB + +**这一个公式同时是"可见性调度"和"保质期"**:不被读的记忆不是消失,而是权重回升等机会——Ebbinghaus 遗忘曲线反过来用,一个机制两用。 + +## 五、记忆条目 = kernel 的 tier-3 蒸馏块(不造新格式) + +- 记忆条目数据模型直接复用 kernel 分层蒸馏产物(Agentic Memory 论文明确:tier-1/2/3 蒸馏 ≡ short→long 迁移,tier-3 超浓缩就是天然长期记忆条目) +- 检索复用 kernel `searchBlocks` hybrid 基础设施(扩展一个记忆库文档源即可) +- 记忆库本身 = 人类可读 markdown 目录(人能看能改 = 外部纠错通道)+ 每条带 citation(来源会话+seq,延续可回溯哲学) + +## 六、kernel 要做什么(A 类)/ 宿主要做什么(B 类) + +| 归 kernel(上游实现) | 归宿主(DSH 集成) | +|---|---| +| `memory_commit` 的决策时机挂钩(nudge 文案加记忆引导) | 工具注册(DSH 工具面) | +| fork/一次性 LLM 提取的接口定义 | 实际 LLM 调用(宿主运行时) | +| 记忆条目数据模型(= tier-3 蒸馏块扩展) | markdown 文件存储 + citation(seq 方言) | +| score 选择机制 + Ebbinghaus 衰减 | 常驻索引注入 system prompt | +| `memory_recall` 检索(searchBlocks 扩展) | `/acp memory list` 命令 | +| | nudge → memory_commit 的时机接线 | + +**实施顺序:kernel 先行,宿主后随**——kernel 发布记忆能力后,宿主 bump kernel 并全部调 kernel API(符合我们既有的"缺陷走 upstream、不在宿主 patch kernel"约定)。 + +## 七、一句话 + +> **把"跨会话记忆"做成压缩体系的自然延伸:nudge 时模型表态 → fork 提取 → 记忆库 = tier-3 蒸馏块 + 人类可读 markdown;读回 = 常驻索引 + 自主取回;选择/衰减 = importance + 反新鲜度 + 随机,一个公式两用。算法归 kernel,宿主只做集成。** diff --git a/docs/memory-research/README.md b/docs/memory-research/README.md new file mode 100644 index 0000000..6aa1dfc --- /dev/null +++ b/docs/memory-research/README.md @@ -0,0 +1,19 @@ +# 跨会话记忆调研资料(Memory Research) + +> 本目录存放跨会话长期记忆(P1-4)的设计调研原始资料,供 `docs/cross-session-memory-design.md` 追溯。 +> 调研日期:2026-08 | 状态:已随设计文档定稿归档 + +| 文件 | 内容 | 来源 | +|---|---|---| +| [01-autonomous-memory-papers.md](01-autonomous-memory-papers.md) | 论文向 17 篇:自主记忆保存机制(触发六分类/Ebbinghaus 衰减/检索共识) | 子代理调研,arXiv 实测 | +| [02-autonomous-memory-implementations.md](02-autonomous-memory-implementations.md) | 实现向 8 产品:保存时机/工具描述原文/检索格式/会话边界(5 工程模式) | 子代理调研,产品源码/文档 | +| [03-memory-readback-timing.md](03-memory-readback-timing.md) | 读回时机 25 源:四模式谱系(预注入/按需/自主/常驻)+ 混合收敛证据 + 预算研究 | 子代理调研,论文+产品 | +| [04-claude-code-source-verification.md](04-claude-code-source-verification.md) | Claude Code 记忆机制源码核实(写入/双层读取/7 层架构/启示)——`/tmp/claude-code-analysis` 重启即失,此为提炼存档 | 本地源码核实 | + +## 与本目录相关的设计决策摘要 + +- **写入**:nudge 时机 → `memory_commit(type, note)` 表态 → 引擎**一次性 LLM 调用**提取 → 写记忆库(带 citation)→ 主对话继续压缩。 +- **读回**:延迟读回,两个时机——常驻索引(每次 turn)+ 自主取回(`memory_recall` 取全文)。Claude Code 生产实践背书。 +- **选择/衰减**:`score = importance + min(days/30,5) + uniform(0,.5)`——打破富者愈富,与 Ebbinghaus 保质期同一套字段。 +- **用户侧**:仅 `/acp memory list`;导入导出 = 自然语言,模型自主。 +- 完整细节见 `docs/cross-session-memory-design.md`(头部含 3 个待定项)。