DSH ExpMem
English | 简体中文
面向 DeepSeek Harness 的经验记忆。
介绍
DSH ExpMem 是 DeepSeek Harness 的社区长期 记忆插件。它把用户习惯、可复用任务经验和工程洞见保存在可检查的本地文件中,并继续使用 DSH Session 历史作为原始 Recall。
设计结合了两条研究路线。MemGPT 提供记忆基础设施,包括分层存储、压力检测、检索和显式 记忆操作;Generative Agents 提供认知流程,包括重要性判断、按当前情境检索、形成 reflection,以及让记忆参与后续 planning。
DSH ExpMem 并非 DeepSeek 官方项目。
架构
flowchart TB
subgraph Runtime["DeepSeek Harness 运行时"]
Agent["DSH Agent"]
Meter["Token Meter"]
Sessions["Session Persistence<br/>JSONL"]
end
subgraph Memory["MemGPT 风格的记忆基础设施"]
Recall["Recall<br/>原始会话历史"]
Archive["ExpMem Archive<br/>本地 JSON 记录"]
end
subgraph Cognition["Generative Agents 风格的认知循环"]
Retrieve["检索<br/>相关性 + 新近度 + 重要性"]
Reflect["Reflection Run<br/>pending → prepared → completed"]
Plan["规划与行动<br/>位于 DSH Agent Loop"]
end
Sources["Claude Code / Codex<br/>Markdown 记忆"] -->|"幂等导入"| Archive
Sessions --> Recall
Meter -->|"70% 上下文压力"| Agent
Recall --> Retrieve
Archive --> Retrieve
Retrieve --> Agent
Agent -->|"晋升持久经验"| Archive
Agent --> Reflect
Reflect --> Retrieve
Retrieve --> Reflect
Reflect --> Archive
Agent --> PlanDSH 负责 Recall、上下文压缩和 Agent Loop。ExpMem 负责提炼后的 Archive、检索排序、 reflection 来源和可信记忆生命周期。它不会复制 Session 事件。
特色
- 分层记忆: DSH Session JSONL 保存原始历史;ExpMem 按记录保存用户习惯、任务经验和
洞见。
- 压力感知晋升: 上下文达到 70% 时,当前 Agent 会在压缩前保存持久知识;阈值跳变后
可以从 Recall 补做晋升。
- 个性化检索: 搜索结合相关性、新近度和 Agent 指定的重要性,结果参与后续 planning
和 reaction。
- 可审计 reflection: 高层洞见引用支撑它的观察或之前的 reflection。ExpMem 会拒绝
悬空引用、自引用和环路。持久化 Reflection Run 可以在中断后恢复,并且只消费实际引用的 来源 revision。
- 可信生命周期: candidate、verified、disputed 和 superseded 状态保留来源、冲突与
替代历史;确认删除后只留下最小 tombstone。
- 本地轻量: 不引入向量数据库、后台 Worker 或第二次模型调用,也不修改 DSH Agent
Loop。
兼容 Claude Code 与 Codex
ExpMem 可以导入两种工具生成的 Markdown 记忆:
pnpm dlx @creative-dswork/dsh-expmem import all --dry-run
pnpm dlx @creative-dswork/dsh-expmem import allClaude Code 默认扫描 ~/.claude/projects/**/memory/*.md;Codex 默认扫描 $CODEX_HOME/memories/**/*.md,未设置 CODEX_HOME 时使用 ~/.codex/memories/**/*.md。自定义目录可显式指定:
pnpm dlx @creative-dswork/dsh-expmem import claude --claude-dir /path/to/memory
pnpm dlx @creative-dswork/dsh-expmem import codex --codex-dir /path/to/memories每个源文件会成为一条 candidate experience 记录。它的 imported-file evidence 保存 来源 Agent、源文件绝对路径、SHA-256 和观测时间。重复执行时,未变化的文件会跳过; candidate 内容变化时原位更新;verified、disputed 或 superseded 内容变化时创建新的 candidate,并保留原记录。
ExpMem 不修改或删除源文件。可通过 --workspace /path/to/project 显式设置项目范围; 使用 Claude 默认目录结构时,ExpMem 会在映射唯一的情况下自动恢复源 workspace。
论文依据
MemGPT
MemGPT: Towards LLMs as Operating Systems 把 LLM 上下文窗口视为稀缺的工作记忆,并通过分层存储调度信息。ExpMem 采用了其中四个机制:
- DSH 上下文是当前工作集;
- DSH Session 历史是 Recall;
- ExpMem JSON 记录是 Archival store;
- 压力提示让 Agent 在上下文压缩前保存重要经验。
Generative Agents
Generative Agents: Interactive Simulacra of Human Behavior 定义了支持 retrieval、reflection 和 planning 的 memory stream。ExpMem 采用了与记忆 直接相关的机制:
- 每条记录保存重要性和最近访问时间;
- 检索结合相关性、新近度和重要性;
- reflection 以 insight 记录保存,并引用来源记忆;
- 未反思记忆的累计重要性触发当前 Agent 形成 reflection。
活动计划继续由 DSH task 和 Session 状态管理,因为它们会随执行过程变化。ExpMem 保存 应当影响后续计划的持久习惯、经验和 reflection。
安装
dsh plugin --profile web add @creative-dswork/dsh-expmem该 bundle 会启用 DSH Session Query,注册 Recall 与 ExpMem 工具,并安装记忆压力和 reflection 提示。按正常方式启动 DSH:
dsh web存储
默认文件布局:
$DSH_HOME/
├── sessions/ # DSH 持有的 Recall JSONL
└── expmem/
├── recall-index.sqlite # DSH 派生的全文索引
├── archive/
│ ├── habit/<uuid>.json
│ ├── experience/<uuid>.json
│ ├── insight/<uuid>.json
│ └── tombstones/<uuid>.json
└── reflection-runs/
└── <uuid>.jsonSchema v1 记录包含 claim、candidate|verified|disputed|superseded 状态、作者、证据、
重要性、最近访问时间、可选 workspace 和记录关系。ExpMem 会为 0.2.x 记录和早期 v1 记录补兼容默认值。损坏文件或未知未来版本会产生扫描告警,不会让同目录的有效记录消失。
每次写入都会在目标目录创建临时文件,再进行原子重命名。搜索只读取最终 .json 文件,因此中断留下的临时文件不会被当成不完整记录。
可信生命周期
新记录和导入记忆默认是 candidate。只有 verification 引用了以下合格证据时, expmem_transition 才允许将 candidate 升级为 verified:
- 用户确认,并绑定完整的 DSH Session 事件范围;
- 工具复现结果,并绑定完整事件范围;
- 通过 external URI evidence 回查独立来源。
candidate 或 verified 可以转为 disputed。新的 verified 记录可以声明单向 supersedes,ExpMem 在读取时反向计算 supersededBy。disputed 记录可以声明记录级 conflictsWith。旧 claim 会继续保留,不会被新结论覆盖。
外部 review-report 只是不透明 evidence。ExpMem 保存报告 Schema、ID、位置、报告 SHA-256,以及被评审 claim 的 SHA-256。ExpMem 不打开报告位置、不解析 verdict、 不运行评审模型,也不会仅凭 review-report 授予 verified。
排序检索与 reflection
每条记忆都有 1 到 10 的 importance 和 lastAccessedAt。搜索采用 Generative Agents 的三因子排序:
score = normalized(recency) + normalized(importance) + normalized(relevance)
recency = 0.995 ^ hours_since_last_accessrelevance 使用字面查询词覆盖率。只有实际返回给 Agent 的 hit 才会更新 lastAccessedAt。
insight 可以包含 reflection: { question, sourceMemoryIds }。来源 ID 可以指向观察记录或 之前的 reflection,从而形成可审计的 reflection tree。没有 ExpMem 来源记录时,reflection 必须引用完整的 DSH Session 事件范围。
未 reflection 的记忆累计达到 30 个 importance 点后,ExpMem 会创建一个持久化 Reflection Run:
pending
→ 提交高层问题并检索证据
→ 提交带引用的 insight candidate
→ completedRun 中断后会在下一 turn 或进程重启后恢复。commit 保持幂等,完成时只消费 insight 实际引用的来源 revision;未引用记录仍可进入后续 Run。来源 revision 由 claim SHA-256 和 importance 共同绑定。这个过程不增加第二次模型调用。活动计划继续保存在 DSH 任务和 Session 状态中。
notice 会提供 Run ID。主 Agent 先提交需要反思的问题:
{
"action": "prepare",
"runId": "<run-uuid>",
"questions": [
"哪些实现方式反复提升了代码评审的可靠性?"
]
}ExpMem 会为每个问题返回 questionId 和排序后的记忆结果。Agent 随后为每个问题提交一条 带引用的 insight:
{
"action": "commit",
"runId": "<run-uuid>",
"insights": [
{
"questionId": "<question-uuid>",
"title": "先提供证据,再给出结论",
"content": "聚焦的修改和明确证据能够提高代码评审的可靠性。",
"importance": 8,
"sourceMemoryIds": ["<memory-uuid>"]
}
]
}sourceMemoryIds 只能引用该问题 prepare 结果中的记忆。ExpMem 会把结果写成 insight candidate;完成 Run 不等于验证 claim。
ExpMem 通过持久化 Session Header 中的 origin: "subagent" 识别子 Agent。子 Agent 不会收到 Reflection Run notice,调用 expmem_reflect 也会被拒绝。普通 parentSession fork 仍可执行 Reflection Run。
工具
| 工具 | 用途 |
|---|---|
session_search | 在当前 workspace 中查找相关历史会话。 |
session_event_search | 在指定历史会话内搜索事件。 |
expmem_search | 按新近度、重要性和相关性排序检索经验。 |
expmem_write | 创建或更新 candidate,并记录 importance 与 reflection 来源。 |
expmem_reflect | prepare 或 commit 一个持久化 Reflection Run。 |
expmem_transition | 用证据验证或质疑记录,并添加冲突或替代关系。 |
expmem_forget | 删除 candidate,并留下最小 tombstone。 |
默认搜索 candidate、verified 和 disputed;检查历史时需要显式请求 superseded。 ExpMem 要求 Agent 把 candidate 和 disputed 视为未验证信息,不保存密钥、临时进度或 原始日志。
确认删除
Agent 工具只允许删除 candidate。verified、disputed 或 superseded 必须通过 CLI 删除:
pnpm dlx @creative-dswork/dsh-expmem forget insight <uuid> \
--reason-code incorrect命令会显示记录的 ID、分类、状态和标题,再等待显式确认。已经完成外部确认的非交互 操作可使用 --yes,机器读取结果可增加 --json。tombstone 只包含 Schema 版本、 ID、分类、删除时间和枚举 reason code。
压力晋升
每个模型 step 开始前,ExpMem 复用 DSH Token Meter 测量当前上下文。默认达到 70% 时, 它会注入一条 synthetic user notice,要求 Agent 先搜索已有 ExpMem 记录,最多保存三条 高价值 candidate,然后继续原任务。
该提示会进入 DSH Session 日志,因此每个成功压缩周期只触发一次。如果 DSH 在提示送达前 已经完成压缩,ExpMem 会改为提供被压缩事件的范围,要求 Agent 从 Recall 读取原始消息后 补做晋升。整个过程不需要后台 Worker 或独立的 LLM 总结器。
配置
在 profile 的 cordis.patch.yml 中覆盖 expmem:
- id: expmem
config:
rootDir: /absolute/path/to/expmem
maxEntryChars: 20000
maxPreviewChars: 1000
maxSearchResults: 20
promotionEnabled: true
warningRatio: 0.7
maxPromotionsPerCycle: 3
recoveryAfterCompaction: true
reflectionEnabled: true
reflectionThreshold: 30
recencyDecay: 0.995rootDir 必须是绝对路径。搜索先选择至少命中一个字面查询词的记录,再按三因子排序; 空查询会对过滤范围内的全部记录排序。 压力晋升只会在当前 DSH 组合同时提供 Token Meter 和模型上下文窗口元数据时启用。
如需修改 Recall 索引位置,可覆盖 bundle 中已有的配置行:
- id: session-query-sqlite
config:
path: /absolute/path/to/recall-index.sqlite
openAt: first-search开发
pnpm install
pnpm run check
pnpm run pack:dry-run将当前 checkout 安装到 profile:
dsh plugin --profile web add .
dsh --profile web --dump-config当前范围
- Archive 搜索采用透明的线性扫描;只有实际数据规模证明需要时才增加索引。
- 晋升采用 Agent 协作模式:由当前 Agent 判断哪些记录符合条件,也可以不写入任何记录。
- 暂不包含向量检索、后台 LLM 总结器、语义去重模型或保留周期调度。
- ExpMem 保存外部 review-report 链接,但不运行或解析审计管线。
- Recall 的删除与保留策略继续由 DSH 会话持久化负责。
许可证
[MIT](LICENSE)