dsh-memory-dict
一种长期、高效、低消耗且保证记忆完整的记忆方案。 在本地建立词典与日记,运行时只让 DSH 读取必要的记忆——在关键信息不丢失的前提下,大幅减少 token 消耗。
它解决什么
DSH 本身没有跨对话记忆。每次新会话,模型都从零开始:你是谁、在做什么、昨天聊到哪儿了,一概不知道。
常见的应付办法有两种,都有代价:把历史全塞进上下文,token 会线性膨胀;拼命压缩摘要,压到最后细节全丢。
这个插件走第三条路:记忆存在本地磁盘,运行时按需取用。
- 常驻的只有两级「基本记忆」,各 400 字封顶——称呼、过敏、当前主线的底线
- 其余内容都留在磁盘上,
memory_recall 按话题取回最相关的几条
- 日记按时间区间索引,问「去年秋天」也能捞出来
为什么又写了一个
社区里已经有不少 DSH 记忆插件。试过一些,都不太合手:要么把记忆拆成碎片,取回一堆没用的;要么为了省 token 把内容压得很短,细节全丢;要么结构复杂到自己都不敢改。
这个插件赌的是另一条路:
- 存的是一堆 Markdown 文件——一个词条一个文件,随时能打开、改、删,不锁在数据库里。
- 写入时多花钱,读取时少花钱——写的时候定分区、写摘要、列别名、查重;读的时候只做「搜、取、答」。
- 不做向量检索——靠关键词 + 别名打分,结果可预测、可调试,出了问题能一眼看明白为什么它排第一。
快速开始
# 桌面版启动的是 desktop profile,装错 profile 插件不会加载——这是最容易踩的坑
$dsh = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd"
& $dsh plugin --profile desktop add "C:\path\to\memory-plugin"
装完重启 DSH,之后正常对话就行:
- 「记住:我对花生过敏」→ 写进基本记忆,以后每次都在
- 「我之前说过喜欢什么?」→ 按话题检索,命中不了的会自动跨分区找一次
- 「今天干了什么」→ 记日记,说「去年秋天」也能查回来
数据落在 $DSH_HOME/memory/(也就是 C:\Users\<你>\.dsh\memory\),全是纯文本。
设计要点
- 分区隔离:每件长期独立的事一个分区(
日常、小说-归墟、工作-甲项目)。分区之间默认互不可见;当前分区里搜不到时,才跨分区兜底一次并标注来源。分区只在你明确同意后才创建。
- 扁平词条:分区内没有层级、没有继承。一个主题一个词条,写透,不拆碎。层级的价值被「合并成一个词条」取代。
- 写入时费功夫,读取时省事:写入要定分区、起名、写摘要、列全别名、标关联;读取只做「搜、取、答」。
- 摘要 + 事实 + 细节:
summary 用于排序和判断要不要展开;事实 是短句条目(可带槽位、可分节);细节 是可选的散文,只在 memory_open 时返回。
- 两级基本记忆:
- 全局基本记忆(
spaces/基本记忆.md)——和分区同级,任何分区下都常驻。放跨分区都成立的事:称呼、过敏、语言偏好。
- 分区基本记忆(
spaces/<分区>/基本记忆.md)——只在该分区工作时常驻。放只在这件事里成立的底线:小说里「主角不能死」、日常里「早餐不吃甜」。
- 两者都不进检索,各有 400 字预算。
- 纯文本落盘:一个词条一个 Markdown 文件,可以直接用记事本编辑、删除、备份。
工具
| 工具 | 作用 |
|---|
memory_recall | 首选。按话题在指定分区取回 Top-K 词条(含摘要与事实);当前分区没命中时跨分区兜底一次 |
memory_open | 打开词条全文(含细节与相关词条) |
memory_save | 写词条事实 / 摘要 / 别名 / 关联 / 细节;core: true 写基本记忆 |
memory_spaces | 列出所有分区及其词条名 |
memory_space_create | 新建分区(调用前必须先征得用户同意) |
journal_write | 按时间记日记(精确到天、月、季、年都行) |
journal_read | 按时间范围读日记 |
日记是全局的:时间是一条线,不分分区。写在 spaces/日记/,任何分区下都读得到、写得了。
存储结构
$DSH_HOME/memory/
└── spaces/
├── 基本记忆.md 全局基本记忆(所有分区都常驻)
├── 日记/ 全局日记,不分分区
│ └── 2026.md
└── 日常/ 默认分区
├── 分区.md 名称、说明、别名(元信息,不是记忆)
├── 基本记忆.md 本分区的基本记忆
└── 词条/
├── 饮食.md
└── 动漫.md
词条文件:
---
name: 饮食
aliases: [吃饭, 口味, 忌口, 点餐, 外卖]
summary: 点餐口味:微辣或不辣;午餐常配饮料;晚餐忌油腻
related: [外卖]
updated: 2026-10-28
---
# 饮食
## 事实
- [辣度] 吃饭一般选微辣或不辣
### 午餐
- 午餐喜欢顺便买瓶饮料
### 晚餐
- 晚餐不能太油腻
## 细节
(可选的散文,只在 memory_open 时返回)
[槽位]:同槽位的新值自动替换旧值。
### 分组:事实分节,只在事实区生效。
@since / @until:时效。
配置
- id: memory-dict
name: dsh-memory-dict
config:
dir: 'C:\Users\you\.dsh\memory'
defaultSpace: 日常 # 默认分区名
coreLimit: 400 # 基本记忆常驻字数预算
order: 9500 # 提示词片段排序位置
版本迁移
node tools/migrate-v7.mjs # v6(分级目录)→ v7(分区),预览
node tools/migrate-v7.mjs --apply # 执行,自动整目录备份
node tools/migrate-v6.mjs # v5 → v6,历史遗留
迁移规则:根目录 xxx.md → 词条 xxx;目录 xxx/ 下的 yyy.md → 并入词条 xxx、事实归入分节 yyy;只有一个子文件且无同名根文件的目录(如 兴趣/动漫.md)→ 词条 动漫。
本地开发
测试要解析 @deepseek-ai/*,这些包由 DSH 自己带着,不需要从 npm 装。把你的 node_modules 链接到本机 DSH 的依赖目录即可:
cmd /c mklink /J node_modules "$env:USERPROFILE\.dsh\profiles\node_modules"
然后:
npm test # 64 个用例:存储层 + 插件层
npm run audit # 扫已有记忆数据,找重复和缺字段
数据体检
查重只在写入那一刻生效,改不动已有的数据。定期跑一次体检:
node tools/audit.mjs # 词条内重复、词条与基本记忆冲突、缺摘要、缺别名、超额
node tools/audit.mjs --cross # 连同一分区内跨词条的重复也一起查
重复判定分三层:完全相同、短句被长句包含、两句够长(≥10 字)且相邻二字重合度 ≥0.78。最后一层专治「两版几乎一样、只差几个字」——这种句子谁也不是谁的子串,只靠包含判断抓不到。
已知限制
- 尚无管理面板、自动提取候选、敏感信息过滤。
- 检索为关键词 + 二元组 + 单字兜底,不做向量语义检索;同义词靠
aliases,所以别名写不全会明显影响命中。
- 索引为全量扫描(带 mtime 缓存),数千词条以内无需担心。
_usage.json 记录访问热度用于排序,删掉不影响记忆内容。
许可证
MIT