coding-agents
vectorize-io/hindsightHindsight:会学习的 Agent 长期记忆系统,自动召回/保存、知识页、深度反思与按仓库隔离的记忆银行。
对话历史回忆:字面/模糊/语义三层检索全部历史会话的原始文本,完全本地离线——AI 再也不会忘记你说的话。一条命令安装(自带 `dsh.bundle.patch`),语义推理跑在 worker 线程。
🌏 English · 中文
AI 再也不会"忘记"你说的话了。
DeepSeek Harness (DSH) 原生插件:给 agent 一座记忆迷宫——为你们的每一段对话筑起走廊与房间。它记得你们之间发生过的一切:一个决定、一条设定、一次讨论、一句随口提的需求。你问"我们上次说到哪了",它走进迷宫,把当时的对话原样带回,再像聊天一样自然融进回答——你甚至察觉不到它"想了一下"。
对话历史回忆 · 三层检索(字面 / 模糊 / 语义)· 完全本地离线 · 压缩免疫
运行中,只在角落里安静地亮起一束扫动的光:
完成时,不留痕迹:
反过来:如果你的会话都很短、随时能翻,你大概用不上它——它专为"历史太长、记忆被压缩"的场景而生。
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 占用)
| 能力 | 实现 |
|---|---|
| 三层混合检索 | 字面 / 模糊 / 语义自动合并,覆盖率门控(≥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;断网也能用 |
recall 工具、三层检索、命中按会话聚合成事件、agent 按需拿到轻量粗召回或下钻窗口。ctx.sessions / ctx.sessionPersistence / ctx.sessionQuery)读取——不解析 .zstd、不碰私有格式。插件自有的 recall-index.db(SQLite)存放模糊索引、向量与 trigram FTS。compaction/summary,把每次压缩变成一条轻量锚点——历史被折叠后 agent 依然有方向感。| 层 | 技术 | 解决 |
|---|---|---|
| 字面 | 官方 FTS5 全文索引 | 精确命中原词 |
| 模糊 | 自建 trigram + 字符二元组索引(零依赖) | 记不清原话、只记得片段、换字漏字 |
| 语义 | 本地 bge-small-zh 模型(int8,24MB 预置) | 换词、意译、"大概意思"也能想起来 |
recall 永远有答案。回忆分两阶段,第二阶段只在 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,立即为被压缩会话注入一条轻量锚点:
detail 下钻,永远可还原。/compact 后,锚点在下一轮组装中注入,内容正确,3 轮后自动过期。workspace)、跨项目(all)只在用户明确要求时使用。| 指标 | 结果 |
|---|---|
| 粗召回成本(默认) | 每次调用约 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 |
npm 首个发布版本为 0.1.0;以下 0.0.x 为开发里程碑。
[startSeq..endSeq],文本块间隔 ≤5;阈值基于真实索引实测——p50 同主题间隔 3、61% ≤5)。粗召回每会话最多返回 3 个事件,token 纪律不变(只带片段;事件全文仍是一次 detail 下钻之遥)。v2 路线图全部完成。node eval/run-golden.mjs。detail ±3 原文窗口约 300 tokens/会话。压缩锚点端到端验证:真实 /compact 后,LLM 摘要 + 3 条关键原文片段在下一轮组装中自动注入,3 轮后自动过期。recall 默认轻量粗召回(标题+片段,token 大降),新增 detail 参数下钻原文(会话命中列表 / 精确原文窗口 / 分页翻阅);description 重写:agent 自主调用(压缩后、缺细节时主动回忆,无需用户开口),scope 红线与无感知呈现保留;压缩锚点——压缩后自动注入一次轻量锚点(LLM 摘要 + 关键原文片段,3 轮过期),细节随时可下钻。dsh.bundle.patch 自动接线插件行并启用全文搜索);23.9MB 语义模型拆为可选包 dsh-recall-models(--omit=optional 即轻量版);双语 README + 多语言 UI。recall 工具——官方 FTS5 全文检索全部历史会话(含压缩掉的历史),按会话聚合 + 上下文窗口;作用域控制(默认仅当前会话);无感知 UI(回忆中… / 回忆完成)。v1 · 完成 — 三层混合检索:官方 FTS5 字面 / 自建 trigram+bigram 模糊 / 本地 bge embedding 语义;覆盖率门控、后台预热、静默降级链。
v2 · 检索控制
compaction/summary,压缩后自动注入一次轻量锚点(摘要 + 关键原文片段),原文随时可下钻还原[startSeq..endSeq] 事件(阈值基于真实索引实测:p50 同主题间隔 3,61% ≤5);事件全文仍是一次 detail 下钻之遥v3 · 记忆组织
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-persistenceMIT