工作区内存 v2(离线):研究笔记
适用范围
在以下情况使用此页面:
- 设计超越每日 Markdown 日志的工作区内存(~/clawd)
- 决定:独立 CLI 与深度 Clawdbot 集成
- 添加离线召回 + 反思(retain/recall/reflect)
目标:Clawd 风格的工作区(agents.defaults.workspace,默认 ~/clawd),其中"内存"存储为每天一个 Markdown 文件(memory/YYYY-MM-DD.md)加上一小部分稳定文件(例如 memory.md、SOUL.md)。
本文档提出了一种离线优先的内存架构,将 Markdown 保持为规范的、可审查的真实来源,但通过派生索引添加结构化召回(搜索、实体摘要、置信度更新)。
为什么要改变?
当前设置(每天一个文件)非常适合:
- “仅追加"日记
- 人工编辑
- git 支持的持久性 + 可审计性
- 低摩擦捕获(“只需写下”)
它在以下方面较弱:
- 高召回检索(“我们决定关于 X 的什么?",“上次我们尝试 Y?")
- 面向实体的答案(“告诉我关于 Alice / The Castle / warelay”)而无需重读许多文件
- 意见/偏好稳定性(以及更改时的证据)
- 时间约束(“2025 年 11 月期间什么是真实的?")和冲突解决
设计目标
- 离线:无需网络即可工作;可以在笔记本电脑/Castle 上运行;无云依赖。
- 可解释:检索的项目应该是可归因的(文件 + 位置)并且与推论分离。
- 低仪式:每日日志保持 Markdown,无需繁重的架构工作。
- 增量:v1 仅使用 FTS 就有用;语义/向量和图是可选的升级。
- 智能体友好:使"在令牌预算内召回"变得容易(返回小捆事实)。
北极星模型(Hindsight × Letta)
要混合的两部分:
- Letta/MemGPT 风格的控制循环
- 在上下文中始终保留一个小的"核心”(人格 + 关键用户事实)
- 其他所有内容都超出上下文并通过工具检索
- 内存写入是显式工具调用(追加/替换/插入)、持久化,然后在下一轮重新注入
- Hindsight 风格的内存基底
- 分离观察到的内容与相信的内容与总结的内容
- 支持 retain/recall/reflect
- 承载置信度的意见可以随证据演变
- 面向实体的检索 + 时间查询(即使没有完整的知识图谱)
提议的架构(Markdown 真实来源 + 派生索引)
规范存储(git 友好)
将 ~/clawd 保留为规范的人类可读内存。
建议的工作区布局:
~/clawd/
memory.md # 小:持久事实 + 偏好(核心类)
memory/
YYYY-MM-DD.md # 每日日志(追加;叙述)
bank/ # "类型化"内存页(稳定、可审查)
world.md # 关于世界的客观事实
experience.md # 智能体做了什么(第一人称)
opinions.md # 主观偏好/判断 + 置信度 + 证据指针
entities/
Peter.md
The-Castle.md
warelay.md
...注意事项:
- 每日日志保持每日日志。无需将其转换为 JSON。
bank/文件是精心策划的,由反思作业生成,仍然可以手动编辑。memory.md保持"小 + 核心类”:你希望 Clawd 在每个会话中看到的东西。
派生存储(机器召回)
在工作区下添加派生索引(不一定 git 跟踪):
~/clawd/.memory/index.sqlite支持它:
- 用于事实 + 实体链接 + 意见元数据的 SQLite 架构
- SQLite FTS5 用于词汇召回(快速、小巧、离线)
- 可选的嵌入表用于语义召回(仍然离线)
索引始终可以从 Markdown 重建。
Retain / Recall / Reflect(操作循环)
Retain:将每日日志规范化为"事实”
这里重要的 Hindsight 关键见解:存储叙述的、自包含的事实,而不是小片段。
memory/YYYY-MM-DD.md 的实用规则:
- 在一天结束时(或期间),添加一个
## Retain部分,其中包含 2-5 个要点:- 叙述(保留跨轮上下文)
- 自包含(独立以后有意义)
- 标记类型 + 实体提及
示例:
## Retain
- W @Peter:目前在马拉喀什(2025 年 11 月 27 日至 12 月 1 日)参加 Andy 的生日。
- B @warelay:我通过在 try/catch 中包装 connection.update 处理程序修复了 Baileys WS 崩溃(参见 memory/2025-11-27.md)。
- O(c=0.95) @Peter:偏好简洁的回复(<1500 字符)在 WhatsApp 上;长内容进入文件。最少的解析:
- 类型前缀:
W(world)、B(experience/biographical)、O(opinion)、S(observation/summary;通常生成) - 实体:
@Peter、@warelay等(slugs 映射到bank/entities/*.md) - 意见置信度:
O(c=0.0..1.0)可选
如果你不想让作者考虑它:反思作业可以从日志的其余部分推断这些要点,但有一个明确的 ## Retain 部分是最简单的"质量杠杆”。
Recall:对派生索引的查询
召回应该支持:
- 词汇:“查找精确术语/名称/命令”(FTS5)
- 实体:“告诉我关于 X”(实体页 + 实体链接的事实)
- 时间:“11 月 27 日左右发生了什么”/“自上周以来”
- 意见:“Peter 偏好什么?"(带有置信度 + 证据)
返回格式应该是智能体友好的并引用来源:
kind(world|experience|opinion|observation)timestamp(源天,或提取的时间范围(如果存在))entities(["Peter","warelay"])content(叙述事实)source(memory/2025-11-27.md#L12等)
Reflect:生成稳定页面 + 更新信念
反思是一个计划作业(每日或心跳 ultrathink),它:
- 从最近的事实更新
bank/entities/*.md(实体摘要) - 基于强化/矛盾更新
bank/opinions.md置信度 - 可选地提议编辑
memory.md(“核心类"持久事实)
意见演变(简单、可解释):
- 每个意见都有:
- 陈述
- 置信度
c ∈ [0,1] - last_updated
- 证据链接(支持 + 矛盾事实 ID)
- 当新事实到来时:
- 通过实体重叠 + 相似性(首先是 FTS,然后是嵌入)找到候选意见
- 通过小的增量更新置信度;大的跳跃需要强烈的矛盾 + 重复证据
CLI 集成:独立与深度集成
建议:深度集成到 Clawdbot 中,但保持可分离的核心库。
为什么要集成到 Clawdbot?
- Clawdbot 已经知道:
- 工作区路径(
agents.defaults.workspace) - 会话模型 + 心跳
- 日志记录 + 故障排除模式
- 工作区路径(
- 你希望智能体本身调用工具:
clawdbot memory recall "…" --k 25 --since 30dclawdbot memory reflect --since 7d
为什么还要拆分库?
- 保持内存逻辑可测试,无需网关/运行时
- 从其他上下文重用(本地脚本、未来的桌面应用等)
形状: 内存工具旨在成为一个小型 CLI + 库层,但这只是探索性的。
“S-Collide” / SuCo:何时使用它(研究)
如果"S-Collide"指的是SuCo(子空间冲突):它是一种 ANN 检索方法,通过在子空间中使用学习/结构化的冲突来定位强召回/延迟权衡(论文:arXiv 2411.14754,2024)。
~/clawd 的实用方法:
- 不要从 SuCo 开始。
- 从 SQLite FTS +(可选)简单嵌入开始;你将立即获得大多数 UX 胜利。
- 仅在以下情况下考虑 SuCo/HNSW/ScaNN 类解决方案:
- 语料库很大(数万/数十万个块)
- 蛮力嵌入搜索变得太慢
- 召回质量受到词汇搜索的真正瓶颈
离线友好的替代方案(按复杂性递增):
- SQLite FTS5 + 元数据过滤器(零 ML)
- 嵌入 + 蛮力(如果块数量很少,效果出奇地好)
- HNSW 索引(常见、稳健;需要库绑定)
- SuCo(研究级;如果有可以嵌入的可靠实现,则很有吸引力)
未解决的问题:
- 你的机器(笔记本电脑 + 台式机)上"个人助理内存"的最佳离线嵌入模型是什么?
- 如果你已经有 Ollama:使用本地模型嵌入;否则在工具链中运送一个小的嵌入模型。
最小的有用试点
如果你想要一个最小的、仍然有用的版本:
- 在每日日志中添加
bank/实体页和## Retain部分。 - 使用 SQLite FTS 进行带引用的召回(路径 + 行号)。
- 仅在召回质量或规模需要时添加嵌入。
参考
- Letta / MemGPT 概念:“核心内存块” + “存档内存” + 工具驱动的自编辑内存。
- Hindsight 技术报告:“retain / recall / reflect”,四网络内存,叙述事实提取,意见置信度演变。
- SuCo:arXiv 2411.14754 (2024):“子空间冲突"近似最近邻检索。