dsh-brain-memory
给 DSH 接一套「模拟人脑」记忆:FSRS-5 遗忘曲线 + 性格权重 + 中文 2-gram + 可选本地向量。 记忆存在独立的 SQLite 库里(不是 DSH 自己的 session 存储),每轮对话自动召回 3 段塞进上下文, 回合结束自动把这一问一答落库;聊得越久,越像跟同一个老朋友说话。
v2.0:遗忘曲线从线性衰减换成 FSRS-5,召回加了一路本地向量(CPU,不占显存), 新增人物账本和只读 3D 面板。插件本身(
lib/index.js)一行没改——服务接口向后兼容, 老库启动时自动迁移。
它到底做了什么
插件挂三条贡献:
- 召回(
system-prompt/assemble瀑布):拿最后一条用户消息去服务端查记忆, 取前 3 条(≤1200 字,服务端自带护栏模板)追加成一段动态上下文; - 落库(
agent/settled):回合结束时把「最后一问 + 最后答」写进记忆库,服务端按 sha256 去重、 按内容估重要度与性格权重、按 FSRS-5 慢慢淡忘; - 工具(
brain_memory):recall主动翻旧账、write手动钉一条、stats看库状态。
三条底线:只加记忆、不动人格;召回超时 800ms 硬截断、失败就当没有;注入文本里的 {{
会被拆开,不会让 system-prompt 的变量插值炸掉整次组装。
v2.0 相对 1.0 的改动
| 1.0 | 2.0 | |
|---|---|---|
| 遗忘 | 线性衰减(每天固定减一点) | FSRS-5:每条记忆有自己的牢固度 S 和难度 D |
| 召回 | 只有中文 2-gram | 2-gram + 本地向量两路 RRF 合并(向量可选) |
| 人物档案 | 无 | 账本表:喜欢/不喜欢/事实/经历/约定(带到期) |
| 观察 | /stats 一行数字 |
/graph + 只读 3D 星脑面板 |
| 库结构 | documents | + vectors + ledger + fsrs 字段(老库自动迁移) |
插件侧完全兼容:lib/index.js、cordis.patch.yml、test/smoke.mjs 都没动。
目录
lib/index.js 插件本体(cordis plugin)
cordis.patch.yml 一条 insert 贡献
package.json
server/memory_service.py 记忆服务(标准库,零依赖,Python 3.10+)
server/embed_service.py 向量服务(可选,torch + transformers,强制 CPU)
scripts/memory-nebula.mjs 星脑面板适配器(只读,Node 18+)
web/ 面板静态页 + vendor/three
docs/ 说明书 / 参数与调优 / FAQ
test/smoke.mjs 冒烟测试:假 ctx 跑一遍,验证三条贡献都接上了
安装插件
DSH 桌面版没有 dsh plugin add,手工装(和现有插件同一套流程):
把整个目录放进
~/.dsh/plugins/dsh-brain-memory在 profile 的
package.json里加依赖与 bundle 条目:"dependencies": { "dsh-brain-memory": "link:../../plugins/dsh-brain-memory" }, "dsh": { "profile": { "bundles": ["dsh-brain-memory"] } }在
~/.dsh/profiles/<profile>/node_modules下建同名的 junction;重启一次 DSH(或等它热加载),日志里出现
dsh-brain-memory就通了。
起服务
python server/memory_service.py # 默认 127.0.0.1:8790
接这个插件时把端口设成 8793(插件默认连这里):
set MEM_PORT=8793(PowerShell)或MEM_PORT=8793 python server/memory_service.py库位置也建议挪到 DSH 自己的目录,别跟别的实例混:
MEM_DB=%USERPROFILE%\.dsh\brain-memory\memory.db
想要语义检索再加一个进程(可选,CPU 跑,不占显存):
pip install torch transformers
huggingface-cli download BAAI/bge-base-zh-v1.5 --local-dir state/models/bge-base-zh-v1.5
python server/embed_service.py # 8794
向量服务挂了不影响任何事:请求失败就退回纯 2-gram,只是少了语义那一路。
配置
插件侧:
| 变量 | 默认 | 说明 |
|---|---|---|
DSH_BRAIN_URL |
http://127.0.0.1:8793 |
记忆服务地址 |
DSH_BRAIN_DIR |
~/.dsh/brain-memory |
插件日志目录(plugin.log) |
DSH_BRAIN_RECALL_TIMEOUT |
800 |
召回超时(ms),超了就当没记忆 |
DSH_BRAIN_WRITE_TIMEOUT |
2500 |
落库超时(ms),fire-and-forget |
服务端:见 docs/参数与调优.md(MEM_DB / MEM_PORT / MEM_K /
MEM_INJECT_CAP / MEM_FREEZE_BELOW / MEM_EMBED_* …)。
服务端接口:
GET /health /stats /graph /ledger/people
POST /write {text, importance?, personality?, emotion?, source?, pin?}
POST /recall {query, k?}
POST /context {query, k?, max_chars?} -> 带护栏模板的注入块
POST /decay {} 手动跑一次每日衰减
POST /reindex {limit?} 补向量(换模型后必跑)
POST /ledger/add | /ledger/list | /ledger/update | /ledger/digest | /ledger/due
从 1.0 升级
直接换代码就行,库会自动迁移:
- 停掉旧服务,备份库(WAL 模式下别只拷
.db):sqlite3 ~/.dsh/brain-memory/memory.db ".backup memory.db.bak" - 用 2.0 的
server/memory_service.py覆盖旧的,起服务; - 日志里会有一行
FSRS 迁移:补列 …;按 importance 反推初始 S/D 的记录 N 条—— 旧的重要度原样保留,只是给每条补上 S/D; - 如果起了向量服务,跑一次
curl -X POST 127.0.0.1:8793/reindex -d "{\"limit\":24}"给老记忆补向量(分批,别一次要太多); - 插件不用动,重启 DSH 即可。
/stats 里 vectors 追上 total 就说明向量补齐了。
面板(可选)
想看看库里长什么样:
MEM_BASE=http://127.0.0.1:8793 node scripts/memory-nebula.mjs --open # 8643
每个点是一条记忆,亮度和大小对应重要度;四个区域:钉住的、跟她自己有关的、快忘光的、日常话题。 只读——写接口一律 403,面板不是编辑器。
冒烟测试
# 先起服务(指向临时库,别污染日常记忆)
MEM_PORT=8794 MEM_DB=./tmp/db.sqlite MEM_LOG=./tmp/svc.log python server/memory_service.py
DSH_BRAIN_URL=http://127.0.0.1:8794 node test/smoke.mjs
预期输出几行 [ok] 加一行 [ok] 全部通过。
文档
License
MIT © Samanthara726。面板的视觉部分派生自
dsh-memory-brain-plugin 的 web 目录(同样 MIT),详见 NOTICE。
No comments yet. Be the first to write one.