Skip to content

[Feature] 存储生命周期:归档区出口 + 审计表保留(容量治理议题) #275

Description

@heptaspirit

使用场景

近期用下来我注意到记忆库增长得比较快,做了一轮审计后觉得有一定无序膨胀的风险,于是回头核实了一遍现有代码,并在 #164 的基础上提出这个想法。

我心里的目标形态是:活跃的保持数百条、持续有用;归档是数千条这个量级;有长期价值的记忆应该沉淀成文档留下来,库里只留索引,而不是被切碎摊在记忆库中。既有效、又不至于把自己撑大,说的就是这个。

有点意思的是,本机这份库数字上刚好落在这个区间(活跃 260、归档约 2,400),但数字对上不代表形态对了。审计之后发现内容上的问题还很大:归档区里积着大量同主题的条目没整理过——0.90 阈值下近重复对约 2,800 对、最大单主题簇 207 行,而活跃侧同期重复为 0。去重确实落在归档侧,缺的是把它收掉的出口。

这个区间只看数字也维持不住:按现在的速度,大约四天就会越过三千。现在还没坏,缺的是撑着这个形态的机制。

这是议题,不是成品方案。我估计得分成几步做,没法一口气吃完;更想先确认问题切得对不对,以及有没有比「加一层回收」更根本的解法。

已查现状声明

读过 README、CHANGELOG、路线图与现有全部 issue。有几项已经被现有开关覆盖,本议题不重造:

  • 逐回合自动唤回 = autoInject;空闲期蒸馏 = autoSummarize + autoDream
  • 写入侧有质量闸(memoryQualityFilter.enabled,默认开),归档侧有理由护栏(长保留类型须带「重复/过时」理由)
  • 审计表已有保留期范式(deleteOldLlmAudits / deleteOldFailures),而 dream_runs 没有
  • 向量解析已有 cache-first(getParsedEmbedding

另外,已关闭的 #202(由他人提出)在处置表里列了「清理 dream_runs 历史(待做)」,而关闭它的 PR #203 只做了检索路径三处固定成本,没有碰 dream_runs

本机活库只读实测

口径 说明
活跃 archived=0 260 连续两日不变,由默认开启的 autoDream 维持
归档 archived=1 约 2,400 +143 条/天,且没有任何周期性动作
库文件 53 MB freelist = 0(从没删过行)
dream_runs payload 15.6 MB 占全库 payload 50%,最大的一张表

读源码还能确认三条:setArchived 只翻标志位、不清向量;检索 SQL 恒带 archived = 0,而归档行仍带向量(约 4 MB 按定义不可达);全仓没有 VACUUM / PRAGMA optimize

期望的行为变化

  1. 归档之后空间能真的被回收,而不只是「检索时看不见」——现在归档行的向量和不可达占用一直留着。
  2. dream_runs 这类审计表有保留期:run 的骨架与决策结果保留,可重建的输入快照不必长期留存(它占该表约 83%)。
  3. 升格([Feature] document 型记忆:agent 产出的长文档入库——注册校验、摘要+指针落库、supersede 记账 #230)吸收的 evidence 记忆随之退出活跃面。现在 document.js 只在 type: "document" 的行里找被取代目标,所以一次升格吸收了 20 条,库里是 21 行不是 1 行
  4. 归档区有周期性的处理动作,而不是线性只增。
  5. 这些动作的实际效果可观察:建议在 聊几个我觉得值得做的方向 #164 已有的四指标上再加一个「归档净增速率 + 可压掉行数」。

我不主张设「最大条数」硬门槛,也不主张按热度或价值阈值自动删——真删应当由人显式确认。

急迫性

不拿「今天检索变慢」当选理由:活跃侧自稳、归档行不可达,当前的性能问题不在归档区。真正的问题是修补成本会随库增长。

  1. dream_runs 是 payload 第一名(50%),每天仍在增加,而缺陷已被记录却未落地(见上一节)。
  2. 第一次真正的删除还没发生过freelist 为 0)。一开始回收,页回收、VACUUM 的耗时与并发影响、历史引用链的完整性,全是第一次面对;VACUUM 代价是 O(库大小),现在便宜、以后贵
  3. 合并与升格的裁决成本随「结构」增长,不只是条数:归档侧已经出现 207 行一个主题的簇(见上一节),簇一多,每簇都要先理解主题才能判断该不该升格。

#164 的关系

#164 已对齐的议案 这里补什么
「对话接近尾声提醒整理」 触发源:从周期性提醒换成确定性信号(水位 / 新增条数 / 会话收敛);AI 做裁决者
「压缩边缘抢救工作状态」 出口:边缘产出的连续性记忆没有出口,只会变成归档区里第 N 条同主题条目
失败判据与四指标 判据「批量把历史塞进上下文」的存储侧形态就是归档区无出口(见上「期望的行为变化」第 5 条)
#231 的「AI 什么时候调用整理接口」 回答:把「何时」从 AI 判断里拿出来,交给确定性信号

可能的做法(仅供讨论,不是方案)

如果方向认可,我看到的落点有三个,都还没开始做:

落点 大概能回收 为什么说它零损失
dream_runs 裁列:输入快照置空,保留 run 骨架与决策 约 13 MB 输入快照是当时的记忆快照,可由记忆库重建;决策与结果不可重建
清掉归档行的向量 约 4 MB 检索按定义不可达
向量改二进制存储 省约 80% 位级等价,顺带消掉检索路径的 JSON.parse

合计约本机的 38%,一条记忆不减、一次价值判断不做。有个配套关系得提前说明:freelist 为 0 时只改列文件不会变小,得配一次 VACUUM,两步要一起。

顺序上我猜是「先回收 → 再修升格出口 → 最后做归档区的跨窗口聚类」,其中第三步强调「跨窗口」是因为现有 dream 候选取的是最近 N 条,而重复项的时间是分散的,同一主题永远进不了同一个窗口

想请你拍板的

  1. 归档区的出口形态:批量归档 / 只清不可达向量 / 直接删?分步还是一次到位?
  2. dreamMinIntervalMinutes(默认 0)与 dreamMaxArchivePerRun(默认 8)要不要联合整定?现在的组合约等于「一天分二十几次做掉一百多条」。
  3. dream_runs 的保留策略:裁列(输入快照置空)可以接受吗?
  4. entity_attrs / entity_relations(本机约 2.2 万行,行数第一名)要不要随归档失效?
  5. 升格([Feature] document 型记忆:agent 产出的长文档入库——注册校验、摘要+指针落库、supersede 记账 #230)吸收的 evidence 记忆要不要一并归档?这关系到 [Feature] document 型记忆:agent 产出的长文档入库——注册校验、摘要+指针落库、supersede 记账 #230 的验收口径。

还想请你指个方向:上面是不是把问题切小了?如果记忆库容量有更根本的解法(比如不靠归档,或者另设一层冷存),我更想听。

@modusensus

数据来源:本机活库只读探测 + src/ 源码核实;单库样本,不代表全部用户。毫秒级差异不作结论,10 万条级别延迟是线性外推。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions