首页
/ mem0 dream 技能全解:AI 编码代理记忆库的重复合并、矛盾裁决与过期清理机制

mem0 dream 技能全解:AI 编码代理记忆库的重复合并、矛盾裁决与过期清理机制

2026-09-05 14:41:35作者:昌雅子Ethen

本文围绕 mem0 插件中的 dream 技能展开,完整讲解这条“记忆整理流水线”的六个串行步骤、自动模式(--auto)的并发保护与提醒回写机制,并结合仓库中的配置解析脚本与周边技能源码,说明每一项合并、冲突与清理规则背后的实现依据。读完本文,你将掌握如何针对 AI 编码代理(Claude Code / Codex / Cursor 等)的持久记忆执行去重、矛盾仲裁与按保留策略淘汰,以及如何以交互式与非交互式两种方式落地这套整理流程。

概述:dream 是什么,为什么需要它

mem0 插件为 AI 编码代理提供跨会话的语义记忆:代理在会话中沉淀架构决策、工具配置、bug 修复经验等条目,后续会话通过搜索召回。但记忆只增不减会带来三个典型问题:近重复条目(同一事实换了种说法存了两遍)、矛盾条目(同一主题上断言相反的事实)、过期条目(早已失效的会话状态与压缩摘要)。

dream 技能就是针对这三个问题的记忆整理(consolidation)通道。根据 dream 技能定义,它的行为边界非常明确:

  • 拉取当前项目的全部记忆;
  • 识别近重复对、标记矛盾、按保留策略(retention policy)挑出过期条目;
  • 所有变更先以 diff 形式展示,经用户确认后才实际修改
  • 支持 --auto 非交互模式,可挂到周期性任务中。

一个硬性约束值得注意:技能文档开头特别强调六个步骤必须严格按 1 → 2 → 3 → 4 → 5 → 6 顺序串行执行,不允许并行或跳步,因为每一步都依赖上一步的结果(例如保留策略在步骤 1 解析、步骤 3 才使用)。

步骤 1:加载保留策略

整理规则的第一步是确定“哪些类型的记忆可以按年龄淘汰”。技能要求运行插件自带的解析脚本:

python3 "<PLUGIN_ROOT>/scripts/parse_mem0_config.py" "<cwd>"

其中 PLUGIN_ROOT 取当前平台对应的变量(${CLAUDE_PLUGIN_ROOT}${CODEX_PLUGIN_ROOT}${CURSOR_PLUGIN_ROOT})。脚本输出一个 JSON 字典,形如 category → days | null

该行为的实现证据在 配置解析脚本 中。脚本从项目根目录读取可选的 mem0.md 配置文件,定位其中的 ## Retention 小节(正则 ^##\s+Retention[^\n]*\n(.*?)(?=^##\s|\Z),大小写不敏感),逐行解析:

  • <category>: <N>d(如 session_state: 90d)→ 保留 N 天,解析为整数天数;
  • <category>: forever → 永不修剪,解析为 null
  • # 开头的行视为注释跳过,格式错误的行被静默跳过
  • mem0.md 不存在或没有 ## Retention 小节,load_retention_policies() 直接返回空字典。

因此当脚本失败或返回 {} 时,dream 技能回退到以下内置默认值:

metadata.type 默认保留期
session_state 90 天
compact_summary 90 天
其他所有类型 不修剪

解析出的策略会在步骤 3 的清理(prune)判定中使用。值得注意的是,mem0.md 是纳入版本控制、团队共享的配置文件——同目录下的 policy 技能 负责读写其中的 ## Instructions(提取策略)等小节,而 dream 只消费其中的 ## Retention 部分,职责分离清晰。

步骤 2:拉取项目的全部记忆

进入分析前,必须先拿到当前用户、当前项目的完整记忆集合,调用 MCP 工具 get_memories

get_memories(
    filters={"AND": [{"user_id": "<active_user_id>"}, {"app_id": "<active_project_id>"}]},
    page_size=200,
)

要点:

  • 过滤条件用 AND 组合 user_idapp_idapp_id 即当前项目 ID(顶层字段,不是 metadata 内的);
  • page_size=200 分批拉取,若响应提示还有更多页,必须翻页直到取完,在收集齐完整列表之前不得进入下一步——否则会漏掉后面的重复对与过期条目;
  • 若查询结果为 0 条,打印固定文案并直接终止:
No memories found for project <project_id>. Nothing to consolidate.

这里体现了一个防御性设计:整理流程的第一步就是“空集短路”,避免对空库执行无意义的分析与确认交互。

步骤 3:内存中分析,找出三类问题

这一步的关键纪律是 work entirely in-memory; do not modify anything yet——只分析、只分组、只记录候选,任何写入动作都推迟到步骤 5。所有记忆先按 metadata.type 分组(字段缺失时归入 "unknown" 组),随后在每组内做三项识别:

3a 近重复对(合并候选)

两条记忆构成近重复,当且仅当同时满足以下三条启发式规则:

  1. 相似度:估计的余弦相似度 > 0.9。由于 agent 侧拿不到真实向量,技能给出了可操作的代理指标——显著名词/关键词重叠度 > 60% 即视为相似度 > 0.9
  2. 类型一致:两条记忆的 metadata.type 相同;
  3. 均未固定:两条记忆的 metadata.pinned 都不为 true(被 pin 的记忆是用户显式保留的,不参与自动合并)。

典型例子是 “Use PostgreSQL for auth” 与 “Auth DB is PostgreSQL”——同一事实、不同措辞。对每一对符合条件的记忆,需要先起草一个合并版本,要求比任一原始版本更完整、更具体,而不是简单拼接。

这条 60% 名词重叠的阈值并非孤例:health 技能的深度模式/mem0:health --deep)在只读质量扫描中识别潜在重复时,使用了完全相同的判据(同一 metadata.type 组内共享名词/关键词 > 60%)。可以推断,整个插件有意把“重复”的代理指标统一成这一个阈值,让 health --deep 的扫描结果与 dream 的合并决策保持一致——前者负责“只报告”,后者负责“动手修”。

3b 矛盾(contradictions)

两条记忆矛盾,当且仅当它们就同一主题断言相反的事实,例如 “Deploy to ECS” 与 “Deploy to Vercel”。识别时同时判断可能的胜者(likely winner):时间更新、置信度更高的那条倾向胜出。但技能此时只把两条记忆的 ID 与内容记录下来,留给用户在步骤 5 逐对裁决——矛盾的最终判定权在人类,不在自动流程。

3c 清理候选(prune)

一条记忆成为清理候选,只要满足任一条件:

  1. 超龄:其 metadata.type 存在保留策略(步骤 1 解析或默认值),且记忆年龄超过配置天数(拿 created_at 与当天比较);
  2. 低置信度且无独特信息:置信度低于 0.3,并且内容不包含属于本项目的独特信息(没有文件路径、标识符或领域专有名词)。

第二条规则值得展开:低置信度本身不足以删除,只有“既不可靠又对本项目没有专属价值”的条目才进清理名单。这个“双弱”判据避免了误删那种置信度低但包含独特文件路径/约定、日后仍可能被检索命中的边缘条目。

还有一条贯穿 3a 与 3c 的绝对规则:metadata.pinned == true 的记忆无论多旧、置信度多低,一律跳过

步骤 4:打印 diff 报告

分析完成后、动任何写操作之前,必须以固定格式向终端打印结构化 diff:

## dream — consolidation report

Merges (<N>):
  [mem0:<id1>] + [mem0:<id2>] → "<merged content, 100 chars>"

Conflicts (<N>):
  [mem0:<idA>] vs [mem0:<idB>] — "<topic>" [A/B/skip]

Prune (<N>):
  [mem0:<id>] — <type>, <age>d old

Proposed: <N> merges, <N> prunes, <N> conflicts. Apply? [Y/n]

格式上有两条细节规则:

  • 某一类数量为 0 时,整个小节直接省略,不打印空列表;
  • 三类提案总数为 0 时,打印固定文案并终止,不做任何确认交互:
Dream complete. No duplicate, contradictory, or stale memories found.

这个“干净即退出”的分支意味着,对一个健康的记忆库运行 dream 的成本只是一次全量拉取与一轮分析,而不会产生无意义的确认提示。

步骤 5:等待用户输入并应用变更

5a 逐对裁决矛盾

报告中的每个 CONFLICT 对,等待用户输入 ABskip(大小写不敏感);空输入视为 skip。所有裁决记录完毕后,才进入最终确认。这保证了矛盾处理是“先收集完、后统一执行”,不会出现改了一半被取消的中间状态。

5b 最终确认

全部矛盾裁决完成后提示:

Apply? [Y/n]
  • 输入 nno(不区分大小写)→ 打印 Cancelled. No changes made. 并终止,此前收集的所有裁决一并作废;
  • 输入 Yyes直接回车(空输入) → 按以下顺序应用全部变更。

应用顺序固定为 Merges → Contradictions(已裁决)→ Prunes,其中各操作的底层调用是:

合并(每个已批准的合并对)

  1. delete_memory(<id1>)
  2. delete_memory(<id2>)
  3. add_memory 写入合并版本,参数约束非常具体:
    • text="<merged content>"
    • user_id=<active_user_id>
    • app_id=<active_project_id> —— 放在顶层参数,而不是 metadata 里
    • metadata={"type": "<原始类型>", "branch": "<当前分支>", "confidence": <两条原始记忆中较高的分数>, "source": "mem0-dream"}
    • infer=False

infer=False 的含义是直接把合并后的文本作为记忆存储,不再经过 Mem0 的事实抽取/推理管线——dream 已经完成了语义层面的“抽取”,再走一遍推断反而可能引入偏差。source: "mem0-dream" 则为这条记忆打了来源标记,方便日后区分“代理自然沉淀”与“整理器合成”的条目;confidence 取两条原始记忆中的较高值,语义是“合并版本的可信度不应低于其任一来源”。

矛盾(用户裁决为 A 或 B 的)

只删除落败者:delete_memory(memory_id=<loser_id>)。用户选择 skip 的矛盾对原样保留,不做任何改动。

清理

对每个清理候选直接 delete_memory(<memory_id>)

步骤 6:打印执行摘要

全部变更落地后,打印单行汇总:

Dream complete — merged: <N>, pruned: <N>, conflicts resolved: <N>, skipped: <N>

四个计数分别对应:成功合并的对数、删除的过期/低价值条目数、用户裁决解决的矛盾数、被跳过(skip)的矛盾数,构成一次整理运行的完整可审计记录。

自动模式:--auto

/mem0:dream --auto 面向无人值守场景(如定时任务),非交互运行,但保留人类判断的边界

  • Merges:自动应用(两条兼容、无矛盾,无需人工);
  • Prunes:自动应用(基于年龄/置信度的机械规则,无歧义);
  • Contradictions:一律跳过——矛盾裁决被明确划定为必须人类参与的决策。

并发保护(concurrency guard)

自动模式在开始任何工作前先检查锁文件 /tmp/mem0_dream_auto.lock

  • 锁文件存在创建时间距今不足 10 分钟 → 打印 [mem0-dream --auto] Another run in progress — skipping. 并终止,防止两个实例并发对同一记忆库做合并/删除;
  • 否则创建锁文件(写入当前时间戳),并且在所有退出路径上删除它——这一点与 10 分钟的过期窗口互为兜底:即使进程崩溃没来得及删锁,最多 10 分钟后锁自然失效。

自动模式的执行流程

  1. 按正常流程执行步骤 1–3(加载策略、拉全量记忆、分析);
  2. 静默应用合并与清理——不打印 diff、不发起任何确认
  3. 打印紧凑摘要:
[mem0-dream --auto] project=<id>  merged=<N>  pruned=<N>  conflicts_skipped=<N>
  1. 若检测到矛盾但被跳过,执行提醒回写(reminder),且先做去重检查:
    • 先搜索是否已存在同类提醒:search_memories(query="mem0-dream contradictions manual review", filters={"AND": [{"user_id": "..."}, {"app_id": "..."}, {"metadata": {"source": "mem0-dream-auto"}}]}, top_k=1)
    • 若已有结果且相似度 > 0.9,说明提醒已存在,跳过写入;
    • 否则写入提醒记忆:
add_memory(
    text="mem0-dream detected <N> contradiction(s) requiring manual review. Run /mem0:dream to resolve them interactively.",
    user_id="<active_user_id>",
    app_id="<active_project_id>",
    metadata={"type": "task_learning", "source": "mem0-dream-auto", "branch": "<active_branch>"},
    infer=False,
)

这个设计的用意是:自动模式“看见了但不管”的矛盾不能就此消失,而是转化为一条可被后续会话检索到的高优先级待办,把机器无权做的决定显式移交给人。去重检查(相似度 > 0.9 即不重复写入)保证了无论自动任务跑多少轮,提醒只有一条。提醒使用的 task_learning 类型来自插件的编码场景分类体系——见 分类初始化脚本,它将 Mem0 默认的消费向类别替换为 17 个面向编码的类别,其中 task_learnings 的定义是“特定任务上被验证成功的策略与做法”,提醒消息恰好落在这一语义域内。

协作技能:dream 在记忆生命周期中的位置

dream 并非孤立的命令,它与同插件的两个技能构成“发现—处理—兜底”的关系:

  • /mem0:forget:对指定记忆的定点删除(搜索或按 ID 定位 + 逐条确认 + 删除)。dream 是“批量整理”,forget 是“外科手术”,两者互补;
  • /mem0:health --deep:只做质量扫描、不应用任何变更的“体检”模式。其深度检查项与 dream 的分析维度一一对应——重复对(60% 名词重叠)、过期条目(session_state/compact_summary 超 90 天、置信度 < 0.3 且超 30 天)、矛盾、无类型孤立项——并在发现任何非零计数时提示 Run /mem0:dream to fix.。从源码结构看,推荐的使用姿势是:先 health --deep 低成本确认记忆库是否脏,再决定是否付出一次完整 dream 交互流程。

插件整体架构上,插件描述 声明其为基于 Mem0 Platform MCP 服务的跨会话记忆插件(当前版本 0.1.7,16 个斜杠命令 + 生命周期钩子),MCP 接入配置见 mcp_config.json:连接 https://mcp.mem0.ai/mcp/ 并以 Authorization: Token ${MEM0_API_KEY} 鉴权。dream 所调用的 get_memoriessearch_memoriesadd_memorydelete_memory 均通过该 MCP 通道执行,因此使用前提是本机已配置有效的 MEM0_API_KEY 且 MCP 连接可用——这一点也可以先用 health 技能的四项连接性检查预先验证。

小结

mem0 的 dream 技能把“记忆库维护”拆解成了一条可审计、可中止、人机分工明确的流水线:

环节 决策方 规则
保留策略 项目配置 mem0.md## Retention 小节,缺失时回退默认(session_state/compact_summary 90 天,其余不修剪)
重复识别 自动 同类型 + 名词重叠 > 60% + 双方未 pinned
矛盾识别 自动发现,人类裁决 更新且置信度更高者为建议胜者,A/B/skip 逐对裁决
清理 自动 超龄,或置信度 < 0.3 且无项目独特信息;pinned 一律豁免
变更执行 人类确认(交互)/ 规则驱动(--auto) 合并 = 删二写一(infer=Falsesource: mem0-dream);矛盾删败者;清理直删
无人值守兜底 自动 10 分钟锁文件防并发;矛盾以 mem0-dream-auto 提醒记忆回写(相似度去重)

核心设计哲学可以概括为两点:其一,所有破坏性操作都必须先 diff 后确认(交互模式)或限定在“无歧义”的子集内(自动模式);其二,机器负责机械规则,人类保留矛盾裁决权,且机器放弃裁决时留下的痕迹(提醒记忆)能被下一次会话检索到。相关实现与文档均可在仓库中查证:dream 技能定义保留策略解析脚本health 深度检查forget 定点删除

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384