对话历史回忆:字面/模糊/语义三层检索全部历史会话的原始文本,完全本地离线——AI 再也不会忘记你说的话。一条命令安装(自带 `dsh.bundle.patch`),语义推理跑在 worker 线程。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-recall
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:Relistencode/dsh-recall
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
🌏 English · 中文
对话历史回忆插件 —— 给 DeepSeek Harness 的 agent 一座"记忆迷宫"
AI 再也不会"忘记"你说的话了。
DeepSeek Harness (DSH) 原生插件:给 agent 一座记忆迷宫——为你们的每一段对话筑起走廊与房间。它记得你们之间发生过的一切:一个决定、一条设定、一次讨论、一句随口提的需求。你问"我们上次说到哪了",它走进迷宫,把当时的对话原样带回,再像聊天一样自然融进回答——你甚至察觉不到它"想了一下"。
对话历史回忆 · 三层检索(字面 / 模糊 / 语义)· 完全本地离线 · 压缩免疫
运行中,只在角落里安静地亮起一束扫动的光:

完成时,不留痕迹:

适合谁使用
- 长会话的重度用户——一场对话跨数天、几百轮,翻不到头
- 写作者 / RP / 酒馆玩家——设定、伏笔、人物关系散落在几个月前的对话里
- 代码与文档维护者——当时拍板的理由、踩过的坑,压缩后只剩一句摘要
- 任何说过"我们上次不是聊过吗"的人——它把原话找回来,而不是让你重讲一遍
反过来:如果你的会话都很短、随时能翻,你大概用不上它——它专为"历史太长、记忆被压缩"的场景而生。
快速开始
dsh plugin --profile web add dsh-recall@0.2.2
一条命令即可:包自带组合补丁(bundle 层),插件与它所需的全文搜索会自动接线。重启 dsh web 即可。没有额外步骤:模型随包预置(完整版约 37MB),首次搜索自动建立索引,随后在后台安静完成语义预热(几分钟,对你的使用无感知)。
也可以在 dsh-extension-hub 的插件管理页 「附加功能」 区块里一键安装/停用/卸载本插件。
从源码安装(git 克隆):
dsh plugin --profile web add git+https://github.com/Relistencode/dsh-recall.git
仓库已跟踪模型文件(models/model_merged.onnx)与内置推理运行时:git 安装完全离线可用,无构建步骤、无需 allowBuilds 配置。可选依赖 dsh-recall-models 仍会尝试从 npm 拉取;拉取失败时自动改用仓库内模型——两种情形语义层都可用。所有路径经 $DSH_HOME(默认 ~/.dsh)解析,harness 主目录在哪个位置安装效果完全一致。
可选配置
- id: recall
name: dsh-recall
config:
semantic: false # 关闭语义层(只保留字面 + 模糊,包体更小)
warmup: gentle # 慢速预热,降低后台 CPU 占用(仅预热期间占用,后续使用 0 占用)
它不是什么
- ❌ 不是上下文工程 —— 不把全部历史硬塞进模型窗口
- ❌ 不是提示词工程 —— 不靠 prompt 让模型"装作记得"
- ❌ 不是 memory 文档系统 —— 不需要手动维护 MEMORY.md / 备忘录
- ✅ 是真正的回忆能力:按需检索对话原始记录——包括已被压缩掉的历史(压缩只是摘要,原文永远可搜)
能力概览
| 能力 | 实现 |
|---|---|
| 三层混合检索 | 字面 / 模糊 / 语义自动合并,覆盖率门控(≥90%)+ 静默降级链 |
| 渐进披露 | 默认轻量粗召回(标题 + 片段 + 事件,约 100–800 tokens);需要时 detail 下钻原文——命中窗口 / 精确原文 / 分页翻阅 |
| 事件聚合 | 同一主题的多次提及合并为事件([startSeq..endSeq],文本块间隔 ≤5)——一次拿到完整片段集,而非零散碎片;事件全文仍是一次 detail 下钻之遥 |
| 自动调用 | agent 自主在需要时回忆(压缩后、缺细节时主动调用),无需用户开口;用户也可主动要求 |
| 压缩锚点 | 监听 compaction/summary,压缩后自动注入一次轻量锚点(摘要 + 关键原文片段,3 轮过期) |
| 作用域控制 | 默认仅当前会话;workspace / all 只在用户明确要求时使用 |
| 压缩免疫 | 索引覆盖全量历史,含 shadowed(压缩遮蔽)事件 |
| 增量索引 | live 会话走 ctx.sessions,持久化走 sessionPersistence,append-only 增量 |
| 后台预热 | worker 线程嵌入(~10 条/秒),host 事件循环零阻塞 |
| 无感知 UI | 「回忆中…」光波 → 「回忆完成」一行,结果不进 UI、由 agent 自然呈现 |
| 完全本地离线 | 零 npm 运行时依赖;无外部模型 API;断网也能用 |
架构
- 回合生命周期(顶部):一次回忆是一条直线——用户提问、agent 调用
recall工具、三层检索、命中按会话聚合成事件、agent 按需拿到轻量粗召回或下钻窗口。 - 检索层:三条独立的检索通道(字面 / 模糊 / 语义),在覆盖率门控下合并(见三层混合检索)。
- 索引与数据:全部走官方服务(
ctx.sessions/ctx.sessionPersistence/ctx.sessionQuery)读取——不解析 .zstd、不碰私有格式。插件自有的recall-index.db(SQLite)存放模糊索引、向量与 trigram FTS。 - 治理与作用域:作用域红线(默认当前会话)、覆盖率门控、降级链、token 预算都在这一层。
- 自动层:监听
compaction/summary,把每次压缩变成一条轻量锚点——历史被折叠后 agent 依然有方向感。
核心机制
三层混合检索
| 层 | 技术 | 解决 |
|---|---|---|
| 字面 | 官方 FTS5 全文索引 | 精确命中原词 |
| 模糊 | 自建 trigram + 字符二元组索引(零依赖) | 记不清原话、只记得片段、换字漏字 |
| 语义 | 本地 bge-small-zh 模型(int8,24MB 预置) | 换词、意译、"大概意思"也能想起来 |
- 模糊层是主路径(它已覆盖字面层的能力且容错更强);官方 FTS5 是兜底;语义层只在覆盖率 ≥90% 时才参与混合——否则保持沉默,绝不让排序变差。
- 任一层失败都静默降级到下一层——语义 → 模糊 → 字面,永不报错。
recall永远有答案。 - 推理在 worker 线程运行(WASM 放主线程会阻塞 host 事件循环;实测 ~9.6 条/秒零阻塞)。
- 全部本地运行、完全离线——无外部模型 API、无网络。
渐进披露
回忆分两阶段,第二阶段只在 agent 真正需要时触发:
| 阶段 | agent 拿到什么 | 成本 |
|---|---|---|
| 1 — 粗召回(默认) | 会话标题 + 片段 + 同主题事件,分组排序 | 最多 10 个会话约 100–800 tokens |
2 — detail 下钻 |
会话命中列表 / 精确原文窗口(readEvent)/ 分页翻阅 |
约 300 tokens/会话(如 ±3 事件窗口) |
实机实测:粗召回比旧版全量上下文窗口省 ~80% token(10 会话命中:2500–3000 → ~600,聚合前)。事件聚合保持同样的纪律——只带片段,事件全文一次下钻之遥——粗召回单次仍在 ~800 tokens 以内。无关内容从不进上下文——而需要时,原文永远一次下钻之遥。
压缩锚点
压缩是记忆最容易丢失的地方——harness 生成摘要,原文被遮蔽。dsh-recall 监听 compaction/summary,立即为被压缩会话注入一条轻量锚点:
- 内容:LLM 摘要 + 最多 3 条关键原文片段(优先用户消息,再取最长文本块)。
- 过期:3 轮组装后自动消失——它是路标,不是拐杖。
- 逃生口:精确原文随时
detail下钻,永远可还原。 - 实机端到端验证:真实
/compact后,锚点在下一轮组装中注入,内容正确,3 轮后自动过期。
作用域与隐私
- 默认作用域是仅当前会话——跨会话(
workspace)、跨项目(all)只在用户明确要求时使用。 - 呈现层无感知:一声安静的「回忆中…」光波、一行「回忆完成」,别无其他。结果不进 UI——由 agent 自然呈现。
- 数据留在本机:无外部 API、无遥测、无网络。
实测数据
token 收益(v0.2.1 实机)
| 指标 | 结果 |
|---|---|
| 粗召回成本(默认) | 每次调用约 100–800 tokens |
| 旧版全量上下文窗口(10 会话) | 约 2500–3000 tokens——多花 3–4 倍 |
detail ±3 窗口 |
约 300 tokens/会话 |
| 压缩锚点 | 实机验证:真实 /compact → 锚点下一轮注入,内容正确,3 轮自动过期 |
| 语义预热 | worker 线程 ~10 条/秒,host 事件循环零阻塞 |
检索质量(黄金评测集)
合成 4 会话语料(32 条文档)+ 23 条人工标注查询(精确 / 模糊错字 / 意译 / 跨会话),内存运行、真实模型——复现:node eval/run-golden.mjs:
| 变体 | recall@5 | MRR | nDCG@10 |
|---|---|---|---|
| 仅字面(模拟官方 FTS5) | 0.196 | 0.217 | 0.201 |
| 仅模糊 | 0.587 | 0.652 | 0.579 |
| 仅语义 | 0.533 | 0.609 | 0.529 |
| 混合(生产路径) | 0.696 | 0.761 | 0.687 |
- 混合融合胜过任何单层(比最佳单层 recall@5 高 +19%)——三层各有贡献,没有装饰层。
- 字面层单独最弱(仅精确匹配;unicode61 分词对中文不分词)——印证其兜底定位。
- 模糊层是主路径(胜过语义单层);语义层在意译、换词查询上补召回。
- 覆盖率门控验证:半预热时门控正确回退为仅模糊(0.587 = 纯模糊);强行使用半热语义层在小语料上有小幅增益(0.674)——0.90 门控是为真实长会话保留的保守安全默认,未针对本集调参。
- 已知漏检(已声明的边界):低于语义阈值且无字面重合的完全换词(如"打码" 找 "脱敏")、抽象概念查询(如"方案")。
更新记录
npm 首个发布版本为 0.1.0;以下 0.0.x 为开发里程碑。
- 2026-08 — 结果聚合:同一主题的多次提及合并为完整事件(
[startSeq..endSeq],文本块间隔 ≤5;阈值基于真实索引实测——p50 同主题间隔 3、61% ≤5)。粗召回每会话最多返回 3 个事件,token 纪律不变(只带片段;事件全文仍是一次detail下钻之遥)。v2 路线图全部完成。 - 2026-08 — 检索质量评测:黄金集(4 会话 / 32 文档 / 23 条人工标注查询)实测生产混合路径 recall@5 0.696 / MRR 0.761 / nDCG@10 0.687——比最佳单层高 +19%。消融确认模糊层为主路径、字面层为兜底;覆盖率门控实机验证(半预热正确回退为仅模糊)。复现:
node eval/run-golden.mjs。 - 2026-08 — v0.2.1 实机实测:粗召回约 100–600 tokens,旧版全量上下文窗口 10 会话命中约 2500–3000 tokens(省 ~80%);
detail±3 原文窗口约 300 tokens/会话。压缩锚点端到端验证:真实/compact后,LLM 摘要 + 3 条关键原文片段在下一轮组装中自动注入,3 轮后自动过期。 - 2026-08 — v0.2.1:修复——detail 原文窗口正确提取 assistant/message 的文本块(块数组)并按块类型过滤,助手回复的精确原文在下钻结果中完整可见(实机验证中发现)。
- 2026-08 — v0.2.0:渐进披露 + 手动/自动双模式——
recall默认轻量粗召回(标题+片段,token 大降),新增detail参数下钻原文(会话命中列表 / 精确原文窗口 / 分页翻阅);description 重写:agent 自主调用(压缩后、缺细节时主动回忆,无需用户开口),scope 红线与无感知呈现保留;压缩锚点——压缩后自动注入一次轻量锚点(LLM 摘要 + 关键原文片段,3 轮过期),细节随时可下钻。 - 2026-08 — v0.1.0:正式发布——一条命令安装(
dsh.bundle.patch自动接线插件行并启用全文搜索);23.9MB 语义模型拆为可选包dsh-recall-models(--omit=optional即轻量版);双语 README + 多语言 UI。 - 2026-08 — v0.0.6:语义层——本地 bge-small-zh(int8,随包预置,完全离线)跑在 worker 线程;字面/模糊/语义三层混合检索,覆盖率 ≥90% 门控 + 静默降级;后台预热(~10 条/秒,host 事件循环零阻塞)。
- 2026-08 — v0.0.4:模糊检索——自建 trigram + 字符二元组索引(零 npm 依赖):只记得片段、记不清原话、换字漏字也能找到。
- 2026-08 — v0.0.2:
recall工具——官方 FTS5 全文检索全部历史会话(含压缩掉的历史),按会话聚合 + 上下文窗口;作用域控制(默认仅当前会话);无感知 UI(回忆中… / 回忆完成)。
Roadmap
v1 · 完成 — 三层混合检索:官方 FTS5 字面 / 自建 trigram+bigram 模糊 / 本地 bge embedding 语义;覆盖率门控、后台预热、静默降级链。
v2 · 检索控制
- 两阶段召回(browse/detail 下钻):默认轻量粗召回(标题 + 摘要,约 100–800 tokens),agent 选定会话后按需精读完整上下文——无用信息不进上下文
- 压缩锚点:监听
compaction/summary,压缩后自动注入一次轻量锚点(摘要 + 关键原文片段),原文随时可下钻还原 - 自动调用:agent 自主在需要时调用(压缩后、缺细节时),无需用户开口;用户也可主动要求
- 结果聚合:同一主题的多次提及合并为完整"事件"——文本块间隔 ≤5 的连续命中归并为
[startSeq..endSeq]事件(阈值基于真实索引实测:p50 同主题间隔 3,61% ≤5);事件全文仍是一次detail下钻之遥
v3 · 记忆组织
- 主题聚类:embedding 相似度聚类,按话题归拢呈现
- 记忆沉淀:跨会话提炼设定/决策条目,沉淀为长期记忆
- 远期:评估主题化 / 分层压缩机制——只评估,不改 DSH 核心
已知边界
- 短查询(≤4 字)的语义补位较弱(bge 短文本余弦区分度有限),由模糊层 LIKE 兜底
- 语义排序对完全无字面重合的查询不完全可靠——模糊层始终是主路径,agent 最终判断
- 模型为 int8 量化,语义质量为"够用"级别;可换 fp32 模型(约 4 倍体积)追求极致
开发与测试
node .smoke-recall.mjs # 单元 + 集成(mock,无需模型)—— 90+ 断言
node .smoke-semantic.mjs # 真模型集成(需 models/ 就位)
覆盖:tokenizer 对拍(与 transformers.js 逐 token 一致)、索引增量、作用域、混合排序、降级、预热、事件聚合。
模块
| 文件 | 职责 |
|---|---|
lib/index.js |
工具注册、作用域解析、混合排序、会话与事件聚合、预热调度 |
lib/fuzzy-index.js |
自建 SQLite 索引(trigram FTS + bigram + 向量表),零 npm 依赖 |
lib/tokenizer.js |
BERT WordPiece 分词器(纯 JS,与官方实现逐 token 对拍一致) |
lib/semantic.js |
Embedder:worker 线程、批量嵌入、懒加载 |
lib/embed-worker.js |
worker 内 WASM 推理 + mask-aware mean pooling + L2 归一 |
lib/vendor/ |
vendored onnxruntime-web(入口 0.8MB + wasm 12MB)+ tokenizer.json |
models/ |
合并单文件 int8 模型(23MB,发布时拆为 optional 包) |
lib/client.js |
极简 ToolView(「回忆中…」/「回忆完成」,zh/en 随用户语言) |
发布结构
dsh-recall—— 主包(代码 + vendor 运行时 + tokenizer)dsh-recall-models—— optional 依赖(23MB 模型),npm 默认安装;--omit=optional即轻量版,缺失自动降级
参考与致谢
- 官方:
@deepseek-ai/dsh-session-query(-sqlite)、dsh-tools、dsh-session-persistence - 模型:BAAI/bge-small-zh-v1.5 (MIT) · onnx-community int8 导出 · onnxruntime-web (MIT)
- 生态参考:dsh-plugin-recall(一期同构的官方 FTS 检索工具)、dsh-mneme(本地语义记忆,混合召回降级链思路)
License
MIT
链接
同类插件
volcengine/OpenViking#examples/dsh-memory-plugin★ 28649
面向 DeepSeek Harness 的 OpenViking 记忆与上下文插件:pre-step 自动召回与画像注入、会话捕获、`viking://` URI 防护,以及对接 OpenViking 服务端的 recall/write 记忆工具。
vectorize-io/hindsight#coding-agents★ 20034
Hindsight:会学习的 Agent 长期记忆系统,自动召回/保存、知识页、深度反思与按仓库隔离的记忆银行。
dsh-engramory★ 154
把 Engramory 策展式记忆纪律做成可安装插件([npm: dsh-engramory](https://www.npmjs.com/package/dsh-engramory)):通过 `ctx.tools.guard()` 对 `MEMORY.md` 索引施加确定性的 200 行 / 25KB 上限(增长即拒、缩小的重写一律放行),并把协议注册为运行时 skill。记忆库是纯 markdown、一条事实一个文件,与 Claude Code、Codex、Kiro、OpenClaw 共用。
bowenliang123/dsh-context★ 107
上下文洞察面板:一眼看清模型上下文窗口的组成与变化——构成对照窗口大小、按请求历史趋势、压缩/注入事件、消息级 token 统计。
Co-Engram/Co-Engram★ 68
自进化团队记忆,以纯 Markdown 存于 Git:原生 Cordis 插件注册 38 个裸名记忆工具,并按每次组装动态注入 prompt-signals 段;含 RPE 强化、衰减与睡眠巩固;与 Claude Code(MCP)、OpenClaw 宿主共享同一数据仓;已对 DSH 0.1.0-rc.6 实测。
omdsh-dev/dsh-mnemon★ 55
由 Mnemon 驱动的 DeepSeek Harness(DSH)跨 Agent、本地优先的持久记忆插件。它可在支持 Mnemon 的 Agent 之间共享长期记忆,并提供运行时记忆、可检索项目档案、语义召回、知识图谱和 Sidebar UI。