把本地 Markdown 笔记变成可随时检索的长期记忆
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add JackZo400/dsh-memory-search该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 9 处,展示前 9 条)
- 读取本地文件index.js:117
const info = statSync(config.sessionMap) - 读取本地文件index.js:119
const raw = JSON.parse(readFileSync(config.sessionMap, 'utf8')) - 写入本地文件src/store.js:17
mkdirSync(dirname(dbPath), { recursive: true }) - 读取本地文件src/recall.js:53
entries = readdirSync(dir, { withFileTypes: true }) - 读取本地文件src/recall.js:65
const info = statSync(full) - 读取本地文件src/recall.js:123
text = readFileSync(file.path, 'utf8') - 读取本地文件src/recall.js:149
const raw = JSON.parse(readFileSync(lockPath, 'utf8')) - 写入本地文件src/recall.js:159
mkdirSync(dirname(lockPath), { recursive: true }) - 写入本地文件src/recall.js:160
writeFileSync(lockPath, `${JSON.stringify({ spec, reason, at: new Date().toISOString() }, null, 2)}\n`)
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 本地笔记转长期记忆
- 混合召回检索
- 密级过滤
展开完整介绍(135 字)↓
把 Markdown 笔记变成智能体的长期记忆:本地 embedding + SQLite FTS5 混合召回,可选密级过滤(dsh 插件)· 给 dsh 智能体做长期记忆:在 Markdown 笔记上做混合检索(本地 embedding + SQLite FTS5)。
README
由 DeepSeek 最新模型翻译生成dsh-memory-search
给 DeepSeek Harness(dsh)用的长期记忆检索插件。
把一堆 markdown 笔记做成 Agent「想得起来」的记忆:两路召回(本地向量 + 关键词),每轮自动把相关的旧事带进上下文,Agent 也能自己 memory_search 去翻。
一个跑得久的 Agent,问题常常不是模型不够聪明,而是它不记得。
这个插件不训练、不微调,只做一件事:把你自己写的笔记,变成随时查得到的记忆。
同类里更成熟的选择:csyangwen/dsh-memory-evolve、Aik358/dsh-auto-memory、FuRongJun-1999/dsh-memory 都比这份成熟,要装先看它们。
我们这份留着的理由:它是我们自己线上记忆检索的抽出版——两路召回(本地向量 + 关键词)和密级过滤都是跑过的那套,自检自带语料、不用先接上你的数据,索引删了也能从 .md 重建。
功能面比上面几个窄,选之前先比一比。
展开完整文档(README 剩余 1 节)
dsh-memory-search
给 DeepSeek Harness(dsh)用的长期记忆检索插件。
把一堆 markdown 笔记做成 Agent「想得起来」的记忆:两路召回(本地向量 + 关键词),每轮自动把相关的旧事带进上下文,Agent 也能自己 memory_search 去翻。
一个跑得久的 Agent,问题常常不是模型不够聪明,而是它不记得。
这个插件不训练、不微调,只做一件事:把你自己写的笔记,变成随时查得到的记忆。
同类里更成熟的选择:csyangwen/dsh-memory-evolve、Aik358/dsh-auto-memory、FuRongJun-1999/dsh-memory 都比这份成熟,要装先看它们。
我们这份留着的理由:它是我们自己线上记忆检索的抽出版——两路召回(本地向量 + 关键词)和密级过滤都是跑过的那套,自检自带语料、不用先接上你的数据,索引删了也能从 .md 重建。
功能面比上面几个窄,选之前先比一比。
为什么需要它(用 markdown 当语料)
记忆存在磁盘上的 .md 里,数据库只是索引:
- 笔记你随时能打开改,改完索引自己跟上(按 mtime/size 增量重切,只动改过的那篇)
- 备份、diff、git 版本化都是现成的
- 索引删了随时重建 —— 笔记是唯一的真相来源
特性
- 混合召回:SQLite FTS5 关键词 + 本地 embedding 向量,RRF 融合 —— 「原话」和「意思」各管一半。
中文按重叠 bigram 在应用层切词,不用编译任何 SQLite 扩展。
- 零 API 花费:向量模型跑在本地(node-llama-cpp,CPU 就行)。
- 不装模型也能用:modelPath 留空就只跑关键词那一路,一条依赖都不用多。
- 两个出口:memory_search 工具(Agent 主动查)+ 每轮自动召回(塞进系统提示,不进对话记录)。
- 可选密级:同一堆语料里,群聊只可能召回 public,私事只在主人会话里出现。
- 切块规范有闸:改切块规则不会偷偷把全库向量重算一遍,要你显式点头。
安装
dsh plugin --profile web add github:JackZo400/dsh-memory-search
装完按下面的「配置」改一遍,再重启对应 profile。
环境要求:Node ≥ 22.5(用的是内置 node:sqlite;实测 22.22 直接可用,会打一条 ExperimentalWarning,属正常)。想开向量检索才需要装 node-llama-cpp 并自己下一个 GGUF 模型—— 它列在 optionalDependencies 里,装不上也不影响关键词检索。
配置
配置写在你的 profile patch 里(bundle patch 的 insert 段):
- insert:
- id: memory-search
name: dsh-memory-search
config:
dbPath: .dsh-memory/index.db # 索引库落哪;相对路径按 dsh 的工作目录算 roots: # 语料根目录:递归收集里面的 .md
- ./memory
modelPath: '' # GGUF 嵌入模型;留空 = 只跑关键词 recall: enabled: true # 每轮自动召回 limit: 4 # 最多带几条 budgetChars: 1600 # 注入的字符预算 order: 130 # 在系统提示里的排序位 embedding: enabled: true threads: 6 # CPU 线程数 contextSize: 1024 # 上下文窗口(开大更吃内存) batchSize: 256 queryInstruction: '' # 见下 search: candidatePool: 40 # 每路召回各取多少候选 rrfK: 10 # RRF 平滑常数
exclude: ['/.index/', '/node_modules/']
syncIntervalMs: 300000 # 多久扫一次新写的笔记 acceptSpecChange: false # 换切块规则才设 true(会重算全部向量)
几个容易踩的点:
- roots 不配就是空索引,日志会提醒你。
- modelPath 留空时插件只建关键词索引,embedding.enabled 开着也白开(不会报错)。
- queryInstruction:默认值是给 Qwen3-Embedding 用的指令前缀(它 instruction-aware,检索质量吃这个前缀)。换别的嵌入模型(bge-m3、nomic 之类)建议在配置里显式清空,不然前缀会污染语义。
- 换嵌入模型要删掉索引库重建 —— 向量维度不同,旧向量没法复用(代码会检测到维度不匹配,直接放弃语义那一路,不会给你算出垃圾结果)。
配置(语料怎么放)
没有固定结构,递归收 .md,两个建议:
1. 一条一事(一个 bullet 一件事、段落之间空行)。切块是按「空行 / 列表项 / 标题」这些边界走的 —— 相邻的两件事被塞进同一块,检索精度会掉。
2. 事实文件别混进大量流水账。语料里「日记里我正在讨论这件事」的段落会字面上更像查询,把真正的事实挤出前排。插件给 public.md / personal.md / secret.md 这类文件加了 1.5 倍来源权重、给 carryover/ 目录降了权,但语料结构还是你自己最清楚。
配置(密级,可选)
判据是文件名(放在哪个目录下都行):
| 文件名 | 密级 | 谁能召回 |
| public.md | public | 所有会话 |
| personal.md | personal | 只有 owner 会话 |
| secret.md | secret | 只有 owner 会话 |
| 其它任何文件 | personal(保守) | 只有 owner 会话 |
「谁是 owner」由可选的通道映射决定 —— 一个 JSON,把会话 key 映射到 session id:
{ "c2c:1A2B3C": { "sessionId": "8f0c…" }, "group:123456": { "sessionId": "ab12…" } }
配上 sessionMap 之后:group:/grp: 开头的 key 判成 group(只给 public)、在 ownerIds 里的判成 owner(全给)、其余判成 guest(只给 public)。
判不出通道时不召回(fail closed)—— 宁可少给,不可漏私事。
不配 sessionMap 就不做任何过滤,所有会话都当 owner —— 单人使用(不接群)的时候,这才是你想要的默认。
工作原理
markdown 语料 ──scan──▶ 切块(按条目边界)──▶ SQLite ├── chunks(正文 + 向量 BLOB) └── chunks_fts(bigram token)查询 ──┬── FTS5 MATCH ──▶ bm25 排名 ─┐ └── embed ──────▶ 余弦排名 ──┴── RRF 融合 ──▶ 按来源加权 ──▶ 密级过滤 ──▶ top-k
- RRF 融合:不比较两路的分数(bm25 和余弦根本不是一个量纲),只比名次。
- 切块:按空行 / 列表项 / markdown 标题切,条目超长才按长度硬切;保留起始行号,方便回原文。
- 增量:每个文件记 mtime + size,只重切变过的;删掉的文件从索引里忘掉。
- 切块规范闸:切块规则变了(CHUNK_SIG),默认只记账不重切 ——要重切得设 acceptSpecChange: true(那一下会把全部向量重算)。
- 两个出口:memory_search 工具返回原文片段 + 出处(不是摘要);自动召回挂在 system-prompt/assemble 上,往系统提示里加一段 memory-search,不写进对话记录,所以不会污染上下文历史。
测试
node test/selftest.mjs # 切块 / 分词 / 索引 / 检索(临时语料,无外部依赖)
node test/plugin-selftest.mjs # 插件契约:工具注册、系统提示段、服务暴露、密级
node test/spec-guard.mjs # 切块规范闸:改了规则不许偷偷重切
npm test # 上面三个一起
test/recall-eval.mjs 是评测脚手架,不是自检 —— 它对着你自己的索引库跑一批「问句 → 期望命中的片段/文件」的题,报告 top-1 / top-3 / top-5 命中率:
node test/recall-eval.mjs --db .dsh-memory/index.db --corpus ./memory
题目要按你自己的语料改(文件头部有示例)。这是这个插件最该动的地方 ——召回质量跟语料结构强相关,我给的默认权重只在一类语料上验证过。
已知局限
- 切块规则是启发式的(空行/列表/标题),对「一大段长文」的笔记不友好。
- 来源权重是硬编码的三条,按文件名/目录匹配。语料结构差异大的话,得改 src/recall.js。
- 向量检索是全量扫描(几百到几千块是毫秒级,上万块就该上专门的向量库了)。
- 中文分词只做 bigram,没有词表 —— 专有名词查得准,语法层面的理解不做。
- 嵌入模型只在 Qwen3-Embedding-0.6B 上验证过,换模型请留意 queryInstruction 和维度。
License
MIT © 2026 JackZo400
→ Full English README: README.en.md预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
JackZo400/dsh-memory-search
把本地 Markdown 笔记变成可随时检索的长期记忆
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,462已汉化DSH
73
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,848已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,246已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
DS Bot 是一个基于 DeepSeek Harness简称 dsh的 bot 插件,插件将 dsh 改造为 bot…
★ 4,717已汉化DSH
71.1
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,711已汉化DSH
71.1