它是什么
Graph Memory 接管 DSH 会话里「模型可见的历史表面」。它原样保留最近 N 个已完成的用户轮次(默认 5 个),把更早的请求前缀替换成一个归档标记,再用召回把删掉的东西重建回来:一组数量受限的记忆轮次,每一条都带着当时的原始问题和最终回答。
安装前最值得弄清的一点,是图谱在这套设计里的位置。在 1.6 里它是导航层,而不是事实载荷:每个已完成的轮次触发一次结构化 LLM 调用,产出一句摘要、一个结果状态和零条或多条主谓宾三元组;社区发现与排序在这些摘要和三元组上进行,但最终交回模型的是节点指回的原问题和原回答。README 写得很直白:「Summary、SPO 与社区只负责导航;原始问题和最终回答才是证据。」
抽取靠 LLM,不是本地解析
三元组不是本地抽出来的。src/extractor/extract.ts 会针对当前轮次拼出提示词,要求模型恰好调用一次 submit_result 工具;src/extractor/contract.ts 里的合同是唯一闸门。不符合 schema 的输出会被隔离,不会被修补也不会入库,唯一出口是手动调用 gm_retry_extraction。
输入被刻意收窄:按仓库里的 cordis.patch.yml,一个已提交的 DSH 轮次就是一个抽取任务,只包含「原始用户问题和最终可见回答」,工具流量与推理过程永远不发给抽取模型。
路由也走同一份配置:GRAPH_MEMORY_LLM_PROVIDER 与 GRAPH_MEMORY_LLM_MODEL 指定专用抽取路由,补丁注释说明它优先于前台 Agent 模型。dsh.ts 的实现是 configured ?? route,route 即 DSH 最近记录的 agent 模型;两者都没有时抽取直接报错而不是猜。遇到永久性状态码(401/403/404)的失败会暂停后续 LLM 调用十分钟(src/engine/llm-guard.ts)。被隔离的轮次不会自动重试,启动时也不会导入已有历史。
记忆存在哪
全部在一个本地 SQLite 数据库里。组装补丁把 dbPath 设为 dshHomePath('graph-memory/graph-memory.db'),通常是 ~/.dsh/graph-memory/graph-memory.db;OpenClaw 适配器写 ~/.openclaw/graph-memory.db。文件内部,src/store/store.ts 把原始消息、节点、溯源、边、轮次记忆和向量分表存放,数据库以 WAL 模式打开并启用外键(src/store/db.ts)。
这一版用的是 Node 内置的 node:sqlite(src/store/sqlite.ts),不是第三方驱动——这正是它要求 engines.node >=22.13.0、也不需要原生编译的原因;npm 1.5.8 则依赖 @photostructure/sqlite。
召回是查询优先的:src/recaller/recall.ts 先用向量相似度或 FTS5 给已存轮次记忆排序,再以这些命中为种子在导航词上跑一遍个性化 PageRank,最后合并到 recallMaxNodes(默认 6)条。向量是可选的:src/engine/embed.ts 在没有 key 或 base URL 时直接返回空,召回退化为 FTS5。只配了 key 没给 base URL 时,默认端点是 https://api.openai.com/v1、模型 text-embedding-3-small;密钥由 Harness 的 credentials 服务在请求时解析,不落在配置或数据库里。
跨会话复用
召回不限定在当前会话内。存下来的记忆带着来源 session id 作为溯源,而召回路径在检索记忆和导航图时不做 session 过滤,因此一个全新的、属于另一个项目的会话也能命中它们;README 把这称为「跨轮次/跨会话/跨项目召回」。
两个 harness 适配器
这个仓库不只是 DSH 插件,而它的 topics 又在另一个方向上夸大了。代码里真正存在的适配器只有两个:
- DSH ——
dsh.ts加cordis.patch.yml,在根package.json里以"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }声明。它注入tools、llm、systemPrompt、agentLoop、agents、sessions、credentials、tokenMeter,挂载agent/created、agent/session-start、session/event,注册六个gm_*工具。补丁里assistantTools默认none,因为自动召回不需要工具调用。 - OpenClaw ——
index.ts加openclaw.plugin.json,以contextEngineslot 激活,注册gm_search、gm_record、gm_update、gm_stats、gm_maintain。
仓库 topics 里还写着 claude-code、codex、opencode,但代码里没有任何对应适配器;已跟踪来源中唯一提到它们的地方,是 docs/DSH_NATIVE_PLAN.md 里一张关于 Claude Code 兼容边界的表。把这些 topic 当作作者的生态标签来读,不要当成独立集成。
运行要求
- Node
>=22.13.0,来自engines,因为源码用的是内置 SQLite API。 - Harness —— 没有声明任何 DSH 版本。唯一与版本相关的说法是可选 peer 范围:
@deepseek-ai/cordis(>=4)与@deepseek-ai/dsh-typert-protocol(>=0.1.0-rc.5);README 只说实测跑在「最新 DSH 源码」上。没有具体目标,因此本条目不记录dshTarget。 - 安装 —— README 走 GitHub tag 而不是 npm:
npx @deepseek-ai/dsh plugin --profile web add github:adoresever/graph-memory#v1.6.0-beta.16。 - 安装期脚本 —— 没有
preinstall、install、postinstall、prepare;最接近的是prepack(发布时执行npm run build),而scripts/verify-package.mjs会在清单或运行依赖出现安装生命周期脚本时让构建失败。 - 运行依赖 ——
1.6.0-beta.16里只有@sinclair/typebox一个。 - 网络、权限、遥测 —— 抽取把每个已完成轮次的问题与最终回答发给所配置的模型路由,默认就是你自己的 agent provider;启用向量后记忆文本与查询发往你的 embedding 端点(见 FAQ)。已跟踪源码里没有遥测代码,README 也没有记录权限模型或隐私政策;请按「未说明」理解,而不是按「没有风险」理解。
已知限制
- npm 上的包不是这个插件。
npm view graph-memory version是1.5.8(发布于 2026-04-07),而仓库已经到1.6.0-beta.16(tag 打于 2026-09-09)。registry 清单完全没有dsh字段,main指向index.ts,依赖是@photostructure/sqlite、@sinclair/typebox、openai,peer 只有openclaw。装 npm 同名包得到的是 OpenClaw 时期的旧插件,README 自己也是这么说的。 - 公开的 benchmark 不是受控 A/B。 README 主动承认:两组用的是不同的 DSH commit,而且这次运行被定性为工程工作流实测,不是 LoCoMo/LongMemEval 分数。
75%这个数字出自作者。 它出现在 GitHub 仓库描述里;作者自己那次 20 轮实测报的是 T20 首个请求 −80.69%、T01–T20 −68.84%,口径与数字都不是同一个。本条目没有独立复现其中任何一个。- 「受邀发布在清华大学讨论会」出自作者。 它出现在 GitHub 仓库描述里,仓库另有
docs/images/history/tsinghua-sharing.jpg。本次可得的来源没有说明那是什么活动,也没有说明「受邀」是否成立。不要把它当事实转述。 - 召回有上限。
recallMaxNodes默认 6,README 也提到覆盖多主题的宽泛问题可能需要提高 Top-K 或者拆开提问。 - Releases 里有一个 Windows 安装包。 2026-03-18 的
v2.0.0携带OpenClaw-Graph-2.0.0-win-x64.exe(约 1.7 GB),而 npm1.5.8里那份 README 仍在把 OpenClaw 用户引导到它上面;当前 README 已不再提。 - Graph Memory Pro 是实验性的,也没有发布。 仓库里带了一个只读的 DSH Pro Lite Host + Client(
dsh-pro/)用于图谱视图;npm 上没有graph-memory-pro-dsh(404)。
什么时候用它、什么时候不要用
当会话已经长到工具轨迹和老轮次把真正的对话挤出去,而你又希望被丢掉的内容之后还能按语义找回来时,用它。最没有替代品的一点是:召回交回的是原问题与原回答本身,而不是改写版本。
不要冲着 npm 上那个名字去装,那不是一个插件。如果每次完成轮次都拿你的问题与回答额外调一次模型不可接受,也不要装。README 里的数字来自作者一次 20 轮合成实测,不要当成可迁移的结论。
FAQ
三元组是本地抽取的,还是调用 LLM?
调用 LLM。每个已完成的轮次就是一次结构化调用,必须通过一次 submit_result 工具调用返回摘要、结果状态和三元组;社区发现和 PageRank 是本地计算的,抽取不是。这次调用只带用户问题和最终回答。
图谱存在哪里?
一个本地 SQLite 数据库里。DSH 用 $DSH_HOME/graph-memory/graph-memory.db(通常 ~/.dsh/graph-memory/graph-memory.db),OpenClaw 用 ~/.openclaw/graph-memory.db。原始消息、节点、溯源、边、轮次记忆与向量都在这个文件的不同表里。没有服务端,也没有图数据库。
它会把我的对话发到哪里去吗?
会,两个方向,且都可控。抽取调用发往你配置的模型路由——默认是 agent 自己的路由——只包含某个已完成轮次的问题与最终回答,绝不包含工具输出或推理过程。启用向量后,记忆文本与查询发往你的 embedding 端点;完全没有向量配置时召回退回本地 FTS5。源码里没有发现遥测,但 README 没有记录任何隐私政策。
为什么这里的 package 装到的是旧版本?
因为 registry 上 serving 的就是 npm 1.5.8,它属于这个项目的 OpenClaw 时期:没有声明 dsh 字段,所以用这个名字做 DSH 安装得不到本插件。上游 README 改用 v1.6.0-beta.16 的 GitHub tag,并说要等到 npm 报告该版本或更新才切回 npm 名字。
我必须使用那些记忆工具吗?
不必。仓库自带的 DSH 补丁把 assistantTools 设为 none,自动召回不需要工具调用:召回跑在 pre-step 路径上并注入相关记忆。gm_search、gm_record 等工具是给显式控制和诊断用的,是否出现在工具列表里是一个配置选择。
安装时会执行什么吗?
当前这一版不会:没有安装生命周期脚本,运行依赖只有 @sinclair/typebox,用的是 Node 内置 SQLite,所以没有原生编译。仓库自带的 verify:package 会在这一点被破坏时让构建失败。