Hello! 欢迎来Regret的小站!

给 agent 装一个「不常驻」的记忆:dsh-lite-memory 的取舍


avatar
Regret 2026-11-06 33
记忆插件的两种收费方式
大多数把整段塞进提示词,每一轮都在付费

先说问题

agent 的记忆有个根本矛盾:

  • 记得太少:每次都从零开始,你上周说的规范它当没听见
  • 记得太多:每次都把整本手册塞进提示词,token 哗哗流,而且真正相关的信息被淹在噪音里

大部分方案选后者,因为实现简单——往系统提示里拼一段就完事了。但你每轮都在付费,而且是为一堆这一轮根本用不上的内容付费。

dsh-lite-memory 的设计目标只有一句:

全库不常驻:没有命中的轮次不追加记忆内容,命中时最多三条卡片,正文按需读。

三个数字:零常驻、最多三条、正文按需。

三级触发:什么时候它会写

这是整个插件最该先搞懂的部分。

级别 场景 行为
L0 你明确要求「记住这个」 立即写盘,回一条确认行
L1 它发现有跨会话价值的经验 一行灰字 memory · suggested "X" + 一个「保留」按钮;标题加一句话,看得懂才点,不点就永远不写,48 小时内不重复
L2 常识、一次性参数、凭据的值 永不写入

L1 这个设计很克制。它不是「自动帮你记」,而是「问你一句要不要记」。而且:

  • 标题里带一句话说明,你看得懂才点
  • 不点就永远不写
  • 同一个建议 48 小时内不重复骚扰

自动记忆最烦的地方是它记了一堆你以为它没记的东西,然后在你不知情的时候影响回答。这里把决定权留给你了。

L2 那条也值得说:凭据的值永不写入。不是「加密存储」,是不写。这个边界划得对。

写入前先蒸馏

这条规则直接决定了记忆质量:

标题是结论,正文只留原则、判断规则和触发条件,不把具体尺寸、字号、层级、颜色或一次性数字记进来;需要这些值时按记忆里的指针查当前代码或文档。

举个具体的:好记忆是「所有按钮的圆角走 --dsw-radius 变量,别写死像素」,坏记忆是「按钮圆角 8px」。

前者十年后还对,后者明天改了就变成误导。记忆存的是判断规则,不是某一时刻的快照。

配套的硬限制:单条正文超过 4096 字节直接拒绝,摘要超长自动截到 60 字。拒绝而不是截断,这个选择有意思——它逼你先把细节删干净再存。

同名怎么处理

记忆系统最容易烂掉的地方是「同一个东西记了五条,说法还不一样」。

它的处理规则:

  • 同层里标题完全一致 → 更新原条目(不并存两条同名)
  • 前置条件不同(用 when 区分)→ 各存一条,但更新的是同一条
  • 换过说法、标题变了 → 旧标题记成别名,以后也认得
  • 像但不同名 → 先回「相近:X」,你说要更新就用那个标题重存;确实是另一条,才用 resolution="distinct" 另存,且必须换个能区分的标题

最后那条「必须换个能区分的标题」是关键。它不让你偷懒存两条几乎一样的记忆。

读取:不猜

读取时如果标题只记得一半(到逗号或括号为止):

  • 唯一一条前缀对得上 → 直接读
  • 对得上两条 → 把候选标题列出来,不猜

同一名前缀的归档副本不算第二条候选,活条目优先。这种细节说明作者真的用过自己的东西。

每轮留在回复末尾的那几行

每次回复末尾,「已编辑 N 个文件」下面会多几行:

本轮参考 N 条
本轮更新 N 条

点开是记忆名,再点一条就地展开当前正文。名字和正文都取当前值——改过名显示新名字,归档的标「已归档」,删掉的显示「已删除」。

有个约束很有意思:这些行只属于产生它的那一轮。每轮按那轮自己的工具结果重建,重进会话还能看见,别的轮不会混进来。没读过也没写过,整段不出现。

这解决了「我到底这一轮用了哪些记忆」的可见性问题。否则记忆就是个黑箱,你永远不知道它这次是被哪条记忆带偏的。

为什么它「轻」

技术上的答案很干脆:

  • 0 依赖
  • 存储层无定时器、无监听、无网络
  • 只有同步单文件写
  • 写入用一把有超时的锁(500ms),别的进程正在写就明确报「忙」,不抢别人的锁

搜索最多返回 4 条、400 字。全文只在 memory_read 里出现,永不进上下文。

上限:

项 值
单条正文 4096 字节
整库正文 1 MB
每层条目 1000 条(200 条起提示)
标题 / 摘要 各 60 字
90 天未用 只留标题与版本

到硬上限时不拒绝新记忆:把同层最久没被读的一条移进归档(用户固定过的规则不动),保存结果里写明是哪条,正文与完整记录都留着,可人工取回。文件从不删除。

「用户明确说别记」也进归档。这条挺狠,也合理——你不让记的东西,连正文都不该留在活跃库里。

两层:项目和全局

默认只在这个项目生效。你明确说「以后所有项目都这样」,才进全局层。

检索时两层一起查,每条前面标归属([global] 或项目目录名如 [DSH])。

一个项目一个目录,项目之间互相看不见。这个隔离是硬隔离,不是「逻辑上分开」——客户端拼不了路径,也写不了别的项目的笔记。

面板能一键关掉

关掉项目记忆之后,这个项目不再使用任何记忆(包括全局层):自动注入、检索、读取、引用、保存全停,服务端也拒绝记忆工具和面板修改动作。

两个细节:

  1. 关闭只改权限,不删数据。候选、试用、生效、证据、整理额度都保留,计数照常显示
  2. 记忆工具与面板管理动作都在服务端拒绝,改前端绕不过

第二条是安全边界的正事。很多「开关」只在前端生效,改个 DOM 就绕过去了。这里明确说了服务端拒绝。

工具清单

memory_save · memory_suggest · memory_search · memory_read · memory_forget

五个。不多不少:存、建议、搜、读、忘。

「忘」是一个独立工具,而不是「存一个空值」。这个设计上的区别很重要——忘是有语义的操作,它该被记下来。

装

插件管理器里搜 dsh-lite-memory 直接装;或者 npm pack 后用 Plugin Manager 安装生成的 .tgz。

一句话

记忆的价值不在「存了多少」,而在「该出现的时候出现,不该出现的时候一个字都不占」。 大部分记忆插件解决的是「能不能记住」,这个插件解决的是「记住的代价」。


*参考:GitHub regrevia/dsh-lite-memory(MIT,4 stars),0.18.83,2026-11-04 更新。*

暂无评论

发表评论