DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

i11ustriouS /

i11ustriouS/dsh-mnemosyne

Verified

This plugin has no description yet.

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@a369811a

Mnemosyne

这次,我会给所有大肥鱼一个完整的人生。

Mnemosyne 是希腊神话里的记忆女神,九位缪斯之母。这个名字取的就是她的职能—— 让发生过的事留下来,并在需要的时候被想起来。

这是一个给 DeepSeek Harness 用的长期记忆插件。它把你和 AI 的每一轮对话自动收进一个 本地记忆库,之后每次对话开始时,只把「你是谁 + 可能相关的几件事」放进上下文, 剩下的全文留在磁盘上,需要时再展开。


⚠️ 先说清楚一件事

这个插件会不可避免地降低缓存命中率,请不要在工作场景使用。

原因很直白:它每一轮都会往上下文里注入新内容,而这部分内容随对话变化—— 缓存最怕的就是前缀不稳定。具体能降多少取决于你的对话模式、注入预算和话题切换频率, 我没法给你一个准确数字,但降是必然的。

如果你的场景对成本或延迟敏感(批量任务、长文档处理、生产环境), 关掉注入(inject: false)只用它的归档与检索,或者干脆别装。


它解决什么问题

AI 没有跨对话的记忆。每次开新会话,你都从零开始:重新介绍项目、重新说明偏好、 重新解释上次那个坑为什么不能踩。

把对话全量塞进上下文是个办法,但代价很直接——上下文有上限,塞满之后该记得的反而记不住。

Mnemosyne 的做法是分层:

层 内容 何时进上下文
事实 称呼、偏好、路径这类稳定状态 每轮(框架的一部分)
人设框架 从记忆里归纳出的「你是谁」 每轮常驻
话题 / 索引 过去发生过的事,一行一件 按当前提问检索
全文 你当时说的话、我当时的回答 留在磁盘,按 id 展开

框架常驻、索引按需、原文留库。这样注入量是可控的,而信息随时能取回来。


装

dsh plugin --profile web add github:i11ustriouS/dsh-mnemosyne

装完重启 DSH(Host 侧代码要重新加载),然后刷新页面。侧栏底部会出现「记忆女神」入口。

零第三方依赖,没有构建步骤——只用 Node 内置模块,装完即用。


它自己会长

记忆库不是让你手填的,它随对话自己长:

对话 → 每轮归档(顺带抽事实)
     → 攒够 personaEvery 条,把最近 60 条记忆 + 现有事实喂给模型归纳
     → 归纳结果走同一条事实管道(冲突消解)
     → 注入时投影成框架

归纳看的是一段时间的整体,所以能得出单轮看不出来的东西:稳定的偏好、反复出现的诉求、 你说话的方式。模型只被要求输出有证据的内容,宁可少也不能编。

框架页签顶部有「让 AI 重新归纳」按钮,想手动触发随时可以。

事实与冲突消解

「用户叫老王」是状态,「今天修了个 bug」是事件。混在一个池子里有两个后果: 稳定信息被流水淹没;用户改口后新旧值并存,检索时同时召回两个矛盾答案。

所以拆成两个库,事实层用槽位做冲突消解:

谓词类型 例子 行为
单值 nickname name calledBy persona role model language 新值写入 → 旧值失效
多值 preference personality path tag skill habit 各自成槽位,只去重不覆盖
否定极性 「以后别叫我老王」 不参与注入,只让匹配的那条失效
"以后叫我老王"   → user/nickname = 老王
"叫我王哥"       → user/nickname = 王哥,老王那条自动失效
"以后别叫我老王" → 只让"老王"失效,不影响当前称呼

三道防污染闸门

让模型自己写自己的人设,最大的风险是自己污染自己。所以归纳链路有三道闸:

一、事件只收长期约束。 模型很容易把「这次改了什么」当成里程碑。 prompt 里给了判据(这条信息三个月后还有用吗?),代码层再用规则兜底, 识别 自检 75/75 通过、修复了…bug、压缩 1034→80 行 这类工程流水。

二、拦截框架回流。 注入到系统提示的框架文本,有时会被会话摘要捕获,变成一条新记忆—— 再喂回归纳就成了自我强化的正反馈。识别并拒绝。

三、同一件事只留一条。 每次归纳的措辞都不同(全程离线不联网 / 要求全程离线不联网), 只比字符串会让它每轮追加一条。改为按共享实词判重。 但路径不做模糊合并——父目录和子目录是两个有效目录。

实测:24 条堆积事件 → 3 条,框架注入从 1391 字降到 1212 字。


话题聚合

「每轮一条流水」是记忆的反面:同一件事聊十二轮就散成十二条,检索时互相稀释。

所以按 同一会话 + 相邻间隔 < 2 小时 把轮次聚成话题:

2026-10-22 10:25~13:09 · 4轮 · 决策 — alerts.log / 第三方应用测试 | id=mv-xxx(含:…)

一行说清一件事,点开才是细节。话题标题优先取实体(项目名、文件名、域名), 没有实体才退回关键词。

跨会话不合并是刻意的:误合并会把两件不相干的事糊在一起,比分成两个话题更难纠正。


记忆固化

一直追加的结果是库越来越吵:同一件事反复说,近似条目互相稀释; 几个月前的琐碎轮次和昨天的决定同权竞争。

固化让库随时间变密而不是变吵:

动作 触发条件 结果
合并 同话题内摘要相似度 ≥ 0.82 保留信息最全的一条,其余归档
摘要 话题 ≥ 5 轮 且 结束 ≥ 3 天 压成一条 digest,原始轮次指向它
归档 ≥ 30 天 且 从没被召回 且 非决策类 退出自动召回

全程可逆:只打标签、只新增,原文永不删除。归档条目仍能被手动搜到; memory_recall(digestId) 会连带展开被压缩的原始轮次要点。

摘要条目在检索里有 1.3× 权重——同样命中一次,一整段对话的信息量大于单轮。

实测:74 条记忆 → 5 条摘要 / 归档 46 条,活跃区降到 33 条;再跑一次计划全 0(幂等)。

存储压缩

存档是追加式的:每轮归档、每次更新摘要、每次打标签、每次召回计数都写一行。 所以 80 条记忆会积到 1034 行、4.7 MB——内容没变,全是同一批条目被覆盖的中间版本。

压缩把它重写成「每条一行最终状态」:

条目:1034 行 → 80 行    4.7 MB → 355 KB(-92%)
事实:  31 行 → 17 行

安全措施:原子替换(失败自动回滚)、并发检测(压缩期间有新写入就重来)、 回放结果与压缩前完全一致。


历史回填

sessions/ 里已有的历史会话可以整个导进来,不用重新聊一遍。

  • 面板:记忆页签 → 「导入历史」
  • CLI:node test/backfill.mjs [会话数] [每会话轮数] [--dry]

实现上有个坑:会话日志是多帧追加的 zstd(一个 1.6 MB 的文件里可能有 600+ 个独立帧), 得按 zstd magic 切帧、逐帧解压再拼,才能拿到完整事件流。

回填不调用模型——几百轮逐条总结会烧掉大量 token,规则摘要足够让它"能被检索到"。


几个设计选择

记忆强度用对数。 每条记忆记 hits(被召回次数),召回升权是 1 + ln(1+hits) × 0.12。 反复被用到的会略微靠前,但不会盖过内容相关性——否则库里只会剩下那几条老面孔。

显示与检索分离。 中文三元组关键词保留在索引里参与匹配,但不渲染出来。 检索需要它,看的人不需要。

召回时顺带想起。 只按关键词匹配会漏掉同一件事的其它轮次,所以主命中之外还会带出 同会话相邻轮次、共享实体的条目。这些分数低于主命中,不会挤掉真正相关的结果。

自动召回跳过 test 与 archived;要包含就显式传 skipTags: []。


三个入口

面板

侧栏底部「记忆女神」→ 全屏面板,四个页签:

  • 记忆 —— 搜索、筛类型、展开原文、手动记一条、导入历史、固化
  • 人设框架 —— 看 AI 对你的认知,也能自己改;顶部有「让 AI 重新归纳」
  • 事实 —— 当前生效的稳定事实,可手动断言/失效
  • 召回预览 —— 输入一句话,看这轮实际会注入什么

第四个页签是我自己最常用的:调注入效果时,能直接看到模型实际收到了什么。

工具

工具 用途
memory_search 检索索引(返回摘要 + id,不含全文)
memory_recall 按 id 取原文(摘要条目会连带展开轮次要点)
memory_note 手动记一条
memory_profile 读/写人设框架
memory_facts 读/断言/失效稳定事实

HTTP API

GET  /mnemosyne/api/summary              概览
GET  /mnemosyne/api/entries              条目列表
POST /mnemosyne/api/search  { query }    检索
POST /mnemosyne/api/get     { id }       取原文
POST /mnemosyne/api/note    { text }     记一条
POST /mnemosyne/api/delete  { id }       删除
POST /mnemosyne/api/profile { profile }  写人设框架
POST /mnemosyne/api/preview { query }    看注入文本
GET  /mnemosyne/api/topics               话题列表
GET  /mnemosyne/api/facts?all=1          事实
POST /mnemosyne/api/facts    { action }  断言 / 失效
POST /mnemosyne/api/persona/rebuild      重新归纳框架
GET  /mnemosyne/api/persona/status       归纳状态
POST /mnemosyne/api/consolidate          固化({ dryRun } 预览)
GET  /mnemosyne/api/consolidate/status   固化状态
POST /mnemosyne/api/compact              压缩存储
POST /mnemosyne/api/backfill             导入历史
GET  /mnemosyne/api/backfill/status      导入进度

数据在哪

默认 $DSH_HOME/mnemosyne。

mnemosyne/
  entries/2026-10.jsonl   情景记忆:按月分片,逐行追加
  facts.jsonl             语义记忆:断言/失效/刷新操作流
  profile.json            手工维护的人设框架
  state.json              运行时状态

测试脚本按 MV_DATA_DIR → $DSH_HOME/mnemosyne → ~/.dsh/mnemosyne 的顺序找数据目录。

配置

- id: mnemosyne
  name: dsh-mnemosyne
  config:
    dataDir: ''                 # 留空用 $DSH_HOME/mnemosyne
    inject: true                # 关掉就只记录不注入
    maxInjectChars: 2600        # 注入预算
    autoSummarize: true         # 关掉就只用规则摘要,零模型调用
    summarizeProvider: ''       # 留空用当前默认模型
    summarizeModel: ''
    summarizeTimeoutMs: 25000
    maxEntries: 20000
    maxRecall: 8                # 单次最多带回几张索引卡片
    recordSubagents: false
    autoPersona: true           # 框架是否随对话自行生成
    personaEvery: 10            # 每新增多少条记忆触发一次归纳
    autoConsolidate: true       # 是否定时固化
    consolidateMinAgeDays: 30   # 归档门槛
    consolidateDigestAgeDays: 3 # 摘要门槛

已验证 / 未验证

自检 115 项(node test/selftest.mjs,纯离线,不碰真实库),另有实时验收脚本 (node test/verify-live.mjs,对着运行中的 DSH 打)。

覆盖到:

  • 分词、停用词、滑窗碎片过滤、实体抽取、事件类型判定、规则摘要
  • 规则事实抽取(叫我老王 → 断言、别叫我老王 → 否定、我喜欢X/不喜欢Y → 偏好正负)
  • 冲突消解:同槽位新值让旧值失效、同值只刷新、否定只命中匹配值、多值并存、已失效不参与判定
  • 存储回放、同 id 覆盖、删除、重启恢复、损坏行隔离、超限淘汰、压缩后内容一致
  • 中文/英文检索命中、不相干查询零误报、同会话延伸、共享实体延伸、空库不崩
  • 模型总结的 JSON 解析(裸 JSON / 代码块 / 尾逗号)、失败降级、超时降级
  • 注入渲染、预算约束、无内部细节泄漏
  • 话题聚类、话题卡片、同话题多轮合并
  • 多帧 zstd 解码、回填端到端与去重
  • 人设归纳:草稿过滤、事实进冲突消解、条数上限、空库安全、间歇故障重试 5 次
  • 防污染:路径事实只认真路径、框架回流被拒、开发流水被过滤、同一件事按共享实词归并
  • 固化:相似度、同话题并组、跨话题不合并、归档三重判据、digest 门槛、幂等
  • 压缩:追加流重写、事实库失效状态保留

没验证到的:真实的多用户场景、长期运行的稳定性、超大库(万条以上)的检索性能。 我的测试都在单机单用户的几十到几百条规模上。


已知短板

  1. 纯字面检索:上次那个 这类指代无法解析,需要结合最近几轮做 query expansion 或向量召回。
  2. 摘要质量依赖规则:digest 现在是"挑要点拼接",没有真正的模型归纳。 高价值话题可以考虑用模型精炼一次。
  3. 话题聚类按时间切:时间相近但主题不同的对话会被并进同一个话题 (实测踩过:Wallpaper Engine 那段掺进了渗透测试的内容)。应该引入实体相似度做二次切分。
  4. 事实抽取覆盖率低:规则只认明确句式,模型调用失败时基本抽不到。
  5. 归档条目仍保留全文:每条约 4.4 KB。库涨到几千条时体积会到几十 MB, 可以对归档条目截断正文字段。

⚠️ 再强调一次

这个插件会不可避免地降低缓存命中率。

它每轮都往上下文里注入随对话变化的内容,而缓存最怕前缀不稳定。 具体影响取决于你的使用方式,但降是必然的。

  • 对成本/延迟敏感 → 别装,或设 inject: false 只用归档检索
  • 个人长期使用、聊天为主 → 影响可以接受,记忆带来的收益通常值得
  • 生产环境 / 批量任务 → 不要用

开发

node test/selftest.mjs                  # 115 项离线自检
node test/preview.mjs "你那句话"         # 看注入效果(读真实库 + 当前源码,不用重启)
node test/verify-live.mjs               # 对着运行中的 DSH 验收
node test/backfill.mjs [会话数] [--dry] # 导入历史会话
node test/consolidate.mjs [--apply]     # 固化
node test/compact.mjs [--apply]         # 压缩存储

client.js 改完刷新页面即可;index.js 与 lib/*.js 是 Host 侧代码,改完要重启 DSH。

⚠️ 上面几个写数据的脚本会写 $DSH_HOME 下的记忆库,从沙箱子进程执行会被 EPERM 拦, 需要提权或改用面板按钮。


MIT License · 与 DeepSeek 无隶属关系 · 插件由作者维护,收录不构成背书

—/ 5

No ratings yet

Verified DSH bundle

Commit a369811a43a8

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout