dsh-memory-band
给 DeepSeek Harness 的本地三段式记忆带:24 小时保护带、按话题召回、场景回放,自动注入会话,不调用 embedding 或模型。
安装
dsh plugin --profile web add dsh-memory-band
沙箱测试
这个插件还没测过。提交测试 →
README
dsh-memory-band
<p align="center">
<img src="assets/band.svg" alt="dsh-memory-band" width="880">
</p>
<p align="center">
<img src="assets/homepage.png" alt="插件主页" width="880">
</p>
<p align="center">
<a href="https://github.com/13576751971/dsh-memory-band">GitHub</a> ·
<a href="site/index.html">主页</a> ·
<a href="docs/benchmark.md">实测报告</a> ·
<a href="docs/marketplace.md">上架说明</a>
</p>
<p align="center">
<img alt="license" src="https://img.shields.io/badge/license-MIT-blue">
<img alt="node" src="https://img.shields.io/badge/node-%3E%3D18-green">
<img alt="dsh" src="https://img.shields.io/badge/DSH-%3E%3D0.2.0-3157d5">
<img alt="deps" src="https://img.shields.io/badge/runtime%20deps-0-0f9f7a">
</p>
给 DeepSeek Harness 的本地记忆带:把“昨天说过什么”压成几百字,自动放进每一轮上下文。
检索全在本地做,不调模型、不建向量库;装进 DSH 就生效。
它解决的不是“存不下”,是“每轮都要重新找”
长会话里,模型要回答“我们之前约的暗号是什么”,常见的两条路都很贵:
- 把历史留得很长:每一轮都重发,token 随会话线性上涨;
- 现场去翻文件 / 搜索:多一次工具调用,就多一次模型 step,工具结果还要回灌上下文。
dsh-memory-band 选了第三条:只带几百字、和当前这句话有关的记忆。
它把记忆分成三段:
段 · 什么时候出现 · 作用
保护带 · 每个新会话的稳定前缀 · 最近 24 小时值得记的事,先兜住“昨天/刚才”
相关召回 · 当前这句话命中旧事时 · 2-gram 本地检索,只带更早的、真正相关的几条
场景回放 · 命中且开启时 · 把当时的上下文一起带上,避免只有摘要没有语境
保护带按会话缓存,不随每轮重写;相关召回只占一个很窄的位置。两段都通过 DSH 的
ctx.systemPrompt.context() 注入,宿主会按投影去重。
装进 DSH
方式一:插件市场 / 「添加插件」
本包已经是一个标准 DSH bundle:
package.json里的dsh.bundle.patch指向cordis.patch.ymlcordis.patch.yml的id等于包名dsh-memory-bandlib/index.js导出 Cordis 契约(name/inject/apply)- 声明了
engines.dsh >= 0.2.0,并带README、图标、上架条目
在 DSH 的 Plugins → 添加插件 里粘贴下面任意一种来源:
# GitHub(发布后) https://github.com/13576751971/dsh-memory-band # npm(发布后) dsh-memory-band # 本机目录(开发/内测) C:\Users\asus\Desktop\GitHub\dsh-memory-band
方式二:CLI
dsh plugin --profile desktop add dsh-memory-band
装完刷新页面即可;当前 DSH 的 HMR 会重新组合插件,通常不用重启。
方式三:本地开发
git clone https://github.com/13576751971/dsh-memory-band cd dsh-memory-band node --test --test-isolation=none
--test-isolation=none 只是为了避免 Windows 沙箱里测试 runner 拉子进程被拦;
普通环境直接 npm test 即可。
从旧版 memory-band 0.1.0 升级
旧版和新版共用 /dsh-memory-band 前缀。DSH 热卸载旧插件时,已经注册的回环路由
不一定会立刻释放;如果 GET /dsh-memory-band/health 还显示 version: 0.1.0,
重启一次 DSH 即可让 0.2.3 接管。记忆注入和 memory_band 工具不依赖这些路由,
通常已经即时生效。
装上之后,DSH 里会发生什么
1. 新会话自动多一段“最近 24 小时”
不需要用户开口,也不需要模型先调用工具。新会话的第一轮就会带上类似这样一段:
【记忆带 · 最近 24 小时(本地记忆,自动带入)】 ## 最近 24 小时(记得最清楚) - 11-02 18:50 DSH 记忆带实测暗号:TEST-CODE-7F3A。项目目录是 ...\dsh-memory-band。 (这是本地记忆带自动带入的旧事,不是用户这轮说的话;如果这里已经能回答, 就直接回答,别再读文件或搜索;自然用,别照读,也别提“记忆带”。)
2. 当前这句话命中旧事时,才补一条“相关旧事”
问“我们之前约的暗号是什么”,会补上更早的相关记忆;问“在吗”,则什么都不加。
命中才花预算,是这个插件和“每轮塞一大段记忆”最大的区别。
3. 多一个 memory_band 工具
模型可以显式做三件事:
action · 用途
recall · 查更早的旧事(本地检索,返回摘要)
remember · 把用户明确要求记住的一句话写进卡
stats · 看记忆条数、注入次数、估算 token
工具 schema 只占约 131 token;不用时不会产生调用。
4. 自动捕获“上一轮”,不捕获这一轮
用户在会话里说的话会本地落卡,但当前这句话不会在同一轮里重复注入。
自动捕获只收陈述句;问句是请求,不是记忆,默认不落卡,避免“把问题当记忆、
下一轮又召回问题”的自我污染。
5. 一个本地面板
插件在 DSH 的 webServer 上注册一组只接受回环访问的路由:
GET /dsh-memory-band/ # 状态面板 GET /dsh-memory-band/health # 健康检查 GET /dsh-memory-band/stats # 条数、注入量、估算 token GET /dsh-memory-band/block?q=... # 取某句话对应的召回块 GET /dsh-memory-band/recent?limit=20 # 最近记忆 POST /dsh-memory-band/add # 手动写一条 POST /dsh-memory-band/forget # 按 id 删除
数据默认落在 ~/.dsh/dsh-memory-band/:
memory-card.json # 记忆卡(纯 JSON,可直接备份/迁移) config.json # 预算、开关、提示词
实测:到底省不省运算?
测试环境:DSH 0.2.1-rc.5,deepseek-flash,standard preset,两个全新会话,
同一个测试项目,同一个问题:
我们之前约定过的项目暗号是什么?只回答暗号本身,不要解释。
测试项目里有一份 12 节的 notes.md,暗号只出现一次。对照组关闭插件;实验组开启插件。
每组各跑 2 次,取平均。
指标 · 关掉插件(基线) · 开启插件 · 变化
输入 token(uncached + cacheRead) · 76,153 · 25,474 · −66.5%
输出 token · 219.5 · 21 · −90.4%
总 token(输入 + 输出) · 76,372.5 · 25,495 · −66.6%
LLM step · 3 · 1 · −66.7%
工具调用 · 2.5 次(pwsh / glob / read) · 0 · −100%
LLM 耗时 · 4,276 ms · 997 ms · −76.7%
工具耗时 · 677 ms · 0 · −100%
单次会话的明细:
组 · 会话 · 输入 · 输出 · step · 工具 · LLM
基线 · session-0017feef… · 76,251 · 264 · 3 · 3 · 4,646 ms
基线 · session-6417d238… · 76,055 · 175 · 3 · 2 · 3,905 ms
插件 · session-41408faa… · 25,390 · 5 · 1 · 0 · 922 ms
插件 · session-b33bca05… · 25,558 · 37 · 1 · 0 · 1,072 ms
两次实验组都只用了 1 个 step,直接回答“TEST-CODE-7F3A”;两次基线都先列目录/搜索/读文件,
用了 3 个 step。清掉测试问句后再复验一次,保护带降到 201 字,仍是 1 step / 0 工具 /
25,363 输入 token / 6 输出 token。完整记录、会话 ID 和复现脚本见
[docs/benchmark.md](docs/benchmark.md)。
省下来的到底是什么
1. 少 2 个 LLM step:每一步都要重新发一次上下文。3 步 → 1 步,是最大头。
2. 少 2~3 次工具调用:pwsh 列目录、glob/grep 搜索、read 读文件,
以及工具结果回灌的上下文。
3. 少输出 token:不用再复述“我查到了……根据文件……”,直接给答案。
4. 本地检索替代向量检索:没有 embedding API、没有向量库、没有检索侧模型调用。
它自己花多少
成本项 · 实测
保护带 · 201~245 字(约 134~164 token)
相关召回 · 0~145 字(命中旧事时才有)
memory_band 工具 schema · 约 131 token
本地检索 · 单次 3~9 ms(1000~3000 条)
所以它不是“零成本”,而是“用两三百字换掉几千字的重复上下文和工具往返”。
什么时候省不了
- 模型仍然坚持去读文件确认:这一次的 3 个 step 就省不掉。提示词末尾已经明确
“这里能回答就直接回答,别再读文件或搜索”,但模型行为仍有随机性。
- 问题指向“某个文件里的某一节”,而不是“我们之前说过的事”:模型更倾向于查文件,
这时记忆带的价值是兜底,不是替代。
- 记忆卡是空的:只有骨架,没有可注入的内容,自然不会省。
一个必须说清的成本口径
上表的“输入 token”把 cacheReadTokens 也算进去了,因为那仍然是模型要处理的上下文。
但缓存命中价通常远低于未命中价,所以“token 少 66%”不等于“账单少 66%”。
如果你只看钱,请用你自己 provider 的缓存计价再算一遍;如果你看的是**计算量、
延迟、工具往返**,上表的 step / 工具 / LLM 耗时是更直接的证据。
它是怎么做到的
DSH session
│
├─ systemPrompt.context("dsh-memory-band-boot") 稳定前缀,按会话缓存
│ └─ 最近 24h 保护带(≤ 760 字)
│
├─ systemPrompt.context("dsh-memory-band-recall") 当前这句话命中才出现
│ └─ 2-gram 召回 + 场景(≤ 520 字)
│
├─ agent/inbox/inserted ──► 本地落卡(只收陈述句,当前轮不重复注入)
├─ session/event ──► turn/end 提交、assistant/message 补 botReply
│
└─ tools.register("memory_band") recall / remember / stats
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:2,最后更新 2026-11-02