wall1234567/dsh-rofm ↗★ 0

dsh-rofm

上下文超限时自动归档旧对话并按需回忆 适合需要超长对话历史、希望Agent具备长期记忆的用户。

包名
dsh-rofm
兼容性
待验证
版本
1.0.0
许可证
MIT
最近更新
2026年10月25日

安装

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:wall1234567/dsh-rofm

3. 配置(config.json)

改完保存即可,插件在每次用户消息 / 模型步骤前读取配置内容并热加载(按内容比较,不依赖 mtime;写到一半的损坏 JSON 会保留上一次可用配置)。

字段默认说明
enabledtrue总开关;false 时所有钩子立即空转
compress.enabledtrue是否启用归档(含回忆块再归档)
compress.triggerPercent60上下文占用超过该百分比时触发归档
compress.compressPercent20归档“最早的已用上下文”的目标比例(回忆块再归档与普通对话归档共用该比例);受 keepRecentMessages 与回合边界影响,实际通常更少(上限而非精确值)
compress.contextWindowTokens00 = 使用 DSH 上报的窗口;>0 时强制覆盖(测试/小模型用)
compress.minContextTokens512上下文小于该 token 数不归档
compress.minMessagesToCompress4可归档消息少于该数不归档
compress.minChunkChars200过小的回忆文件夹会并入前一个
compress.targetChunkChars1200单个回忆文件夹的目标字数(决定“分成几个”)
compress.maxFoldersPerRun100单次归档最多生成多少个文件夹
compress.keepRecentMessages2最近 N 条消息永不归档
compress.maxBoundaryOvershoot1.25回合边界对齐可能超调;超过目标的该倍数时改回上一个边界(少移除),防止一次归档删掉半个上下文;超大单回合会按消息拆成多个文件夹
compress.applyToSubagentsfalse是否处理子代理会话
compress.applyToMainSessionstrue是否处理主会话(与上一项配合可只在子代理上做隔离测试)
compress.preStepEnabledtrue每个模型步骤前也检查并归档(防一轮内工具输出撑爆窗口)
compress.emergencyPercent85普通归档后仍高于该百分比时启动紧急归档
compress.emergencyCompressPercent40每次紧急归档移除的比例
compress.maxExtraPasses2一次压力事件最多追加几次紧急归档
compress.hardLimitPercent95超过该线且无可归档内容时记录警告
importance.min / max0.01 / 1α 的取值范围(模型经工具提交的值会被夹到该区间);β 范围固定 -10~10,不是配置项
importance.warnAbove0.8α 超过该值时输出“高重要性需慎重”的警告
importance.weights见文件仅引擎离线 CLI/模拟使用的启发式权重;DSH 插件不使用(α 由当前模型经工具给出)
keywords.min / max3 / 8每个回忆文件夹的关键词数量范围(工具校验用)
keywords.extraStopwords[]追加停用词(关键词抽取/匹配用)
keywords.matchModecontainscontains 或 exact
recall.enabledtrue是否启用回忆
recall.firstGenMax10第一代最多成功加回几个文件夹(已在回忆块里的文件夹不占名额)
recall.mu / sigma5 / 3代数衰减公式参数
recall.maxGeneration00 = 不限代数
recall.probabilityScale1所有概率的额外乘数(调试用)
recall.seed0>0 时用固定随机种子(可复现测试)
recall.sortcreatedAt回忆排序:createdAt / alpha / generation
recall.maxRecalledBlocks64单会话累计回忆文件夹上限(安全阀,只丢块)
recall.maxRecalledChars120000单会话累计回忆字数上限(安全阀,只丢块;至少保留 1 条)
recall.persistInjectedtrue把已注入回忆持久化到本会话目录 recall-state.json:v2 快照(version: 2,含渲染好的 block 全文 + 每条回忆的内容 additions/messages 与 β);重启后即使回忆文件夹被删除/移动也能原样恢复,旧 v1 文件(只有 ids)仍兼容
recall.triggerSourceKinds["user"]哪些消息来源算“用户说话”(如 agent-message 用于子代理/团队消息)
recall.applyToSubagentsfalse是否给子代理也做回忆
recall.applyToMainSessionstrue是否给主会话做回忆
storage.dirmemory回忆根目录(相对插件目录;可写绝对路径)
storage.perSessiontrue每个会话独占 memory/sessions//;回忆不跨会话
storage.maxFolders10000单个会话记忆文件夹总数安全上限;达到上限时整次归档被拒绝(绝不部分写入、也不替换上下文)
logging.enabled / verbosetrue / falseDSH 日志输出
test.dryRunfalse保留字段(当前版本无行为)

⚠️ 关于高重要性 α(务必慎重)

α 不是“重要程度权重”,而是回忆概率的乘数。第一代回忆概率 = α, 也就是说 α=0.9 的回忆几乎每次被关键词命中都会被加回上下文;α=1 更是一定加回。 因此:

  • 不要为了“重要”随手把 importance.max 调到 1 并让大量文件夹拿到 0.9+;
  • 高 α 会让上下文增长很快,抵消归档腾出的空间;
  • 插件在 α > warnAbove 时会记录警告;请把“高重要性”留给真正需要反复回忆的约定/决策。

α / β / 关键词目前是怎么来的(重要说明)

不再是“归档时额外调用一次模型”,而是“当前会话模型在自己的回合里调用工具评分”:

  1. 归档是纯确定性代码,把最早一段对话切好、以“待评分”落盘、替换模型可见上下文;
  2. 下一次请求的 system prompt 出现 ## 记忆评分任务(dsh-rofm) 区块(两次列表:待评分新记忆、待复核记忆);
  3. 当前模型结合当前对话语境调用 memory_judge,提交 α、β、关键词(或对复核项 keep=true);
  4. 插件校验并写回 meta.json + index.json(scored: true、sources=llm);未评分的记忆不参与回忆。

因此:不会因为归档多一次 LLM 调用/延迟;如果模型一直不调用工具,该记忆会一直列在任务区且不能被回忆。 importance.weights 只保留给引擎离线 CLI/模拟使用。

β 与 α 分工不同:α 是回忆概率的乘数(决定“会不会被加回”),β 是写进回忆块的信赖度 (决定“被加回后能不能当事实/指令用”);β 不参与概率、名额或排序,调它不会让记忆更容易/更难被回忆。

高 α 仍要慎重:α=0.9 的回忆几乎每次被关键词命中都会被加回,α=1 一定加回; 插件在 α > warnAbove 时记录警告。