# https://github.com/shibing624/dual-mem 项目说明书

生成时间：2026-06-27 15:20:32 UTC

## 目录

- [整体架构与 L0–L7 记忆模型](#page-1)
- [写入链路：Gate、Extract、Reconcile 与演化链](#page-2)
- [读取链路：混合检索与多路召回](#page-3)
- [接入方式、配置与部署（SDK / REST / MCP / CLI / Skill）](#page-4)

<a id='page-1'></a>

## 整体架构与 L0–L7 记忆模型

### 相关页面

相关主题：[写入链路：Gate、Extract、Reconcile 与演化链](#page-2), [读取链路：混合检索与多路召回](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README_EN.md](https://github.com/shibing624/dual-mem/blob/main/README_EN.md)
- [mkdocs.yml](https://github.com/shibing624/dual-mem/blob/main/mkdocs.yml)
- [dual_mem/agent/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/__init__.py)
- [dual_mem/system2/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/system2/__init__.py)
- [dual_mem/writer/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/writer/__init__.py)
- [dual_mem/retrieval/__init__.py](https://github.com/shibing624/dual_mem/retrieval/__init__.py)
- [dual_mem/agent/prompts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/prompts.py)
- [dual_mem/sdk_models.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/sdk_models.py)
- [dual_mem/retrieval/intent.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/intent.py)
- [dual_mem/api/contracts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/api/contracts.py)
- [examples/_common.py](https://github.com/shibing624/dual-mem/blob/main/examples/_common.py)
</details>

# 整体架构与 L0–L7 记忆模型

dual-mem 是一个面向 LLM 应用与 Agent 的**双系统分层记忆 SDK**，在 System1 快速路径之外提供 System2 深度蒸馏，并在内部以 L0–L7 共 8 个语义层组织记忆节点。本文从整体架构、双系统分工、L0–L7 分层模型、检索与召回、以及接入模式四个维度梳理其设计。

## 双系统架构：System1 与 System2

dual-mem 在顶层将记忆处理划分为两个相互协作的子系统，对应 Kahneman 双过程理论的工程化映射：

- **System1（默认模式）**：负责 LLM 驱动的提取、摘要、对账（reconcile）、基础画像维护以及 `MemAgent` 编排。`dual_mem/agent/` 子包即为此子系统。资料来源：[dual_mem/agent/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/__init__.py)
- **System2（dual 模式启用）**：通过聚类、Agent 循环、工具调用、回写与跨领域扫描，把 L2/L4 事实蒸馏为 L6 Schema 与 L7 Intention。资料来源：[dual_mem/system2/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/system2/__init__.py)

两种模式由 `mode` 字段控制：`system1` 适合助手、客服机器人等快速集成场景；`dual` 在此基础上开启图关联与背景/定时蒸馏，适合深度用户建模、意图与行为模式抽取。资料来源：[README_EN.md](https://github.com/shibing624/dual-mem/blob/main/README_EN.md)

```mermaid
flowchart LR
    User[用户/Agent] -->|write| W[Writer 子包<br/>dual_mem/writer]
    W --> S1[System1<br/>agent/* 提取/摘要/对账]
    S1 --> L0["L0–L5 节点<br/>短期与事实层"]
    L0 -->|background| S2[System2<br/>system2/* 聚类/蒸馏]
    S2 --> L6L7["L6 Schema / L7 Intention"]
    L0 --> R[Retrieval 子包<br/>三路召回 + 演化链展开]
    L6L7 --> R
    R --> User
```

## L0–L7 分层记忆模型

dual-mem 的记忆按语义抽象度从原始对话到深层行为模式分为 8 个层级：

| 层级 | 名称 | 典型内容 | 写入路径 |
|---|---|---|---|
| L0 | Raw conversation | 多轮对话原文 | `add(messages=...)` |
| L1 | Summary | 长内容摘要 | `Summary_ZH/EN` 提示词 |
| L2 | Fact | 用户具体事实 | System1 抽取 |
| L3 | Profile slot | 画像槽位 | System1 画像工具 |
| L4 | Identity | 稳定身份特征 | System1 抽取 |
| L5 | Emotion/signal | 情绪与一次性信号 | System1 打分 |
| L6 | Schema | 行为模式 | System2 蒸馏 |
| L7 | Intention | 未来计划/意图 | System2 蒸馏 |

L2 与 L4 由 `dual_mem/agent/prompts.py` 中的提取提示词显式产出；`layer` 字段接受 `"l2_fact"` 或 `"l4_identity"`。资料来源：[dual_mem/agent/prompts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/prompts.py)

L6/L7 由 System2 在背景或定时触发时产出：`create_schema` 与 `create_intention` 是两类核心操作，schema 内容创建后不可变。资料来源：[dual_mem/system2/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/system2/__init__.py)

## 演化链（supersedes）

同一维度上的状态演进（如所在地、职业、长期偏好）通过显式 `supersedes` 指针串成链。SDK 读侧会自动展开 `evolution_chain`，供 LLM 看到完整历史。资料来源：[dual_mem/sdk_models.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/sdk_models.py)

典型链结构（A 为最新、C 为最旧）：
- A：「用户搬到东京。」
- B：「用户搬到上海。」(supersedes C)
- C：「用户住在北京。」

注意：偏好并存（如「喜欢咖啡」+「也喜欢茶」）**不构成链**，应作为独立 ADD。

## 三路召回与混合检索

读侧默认走 hybrid 路径：**无 LLM、含 embedding**；通过 5 路 anchor 检索 + fusion 重排。`retrieval/` 子包提供三路分类：profile（画像）、proactive（前摄）、normal（普通）。资料来源：[dual_mem/retrieval/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/__init__.py)

`retrieval/intent.py` 通过概念性触发词（how、why、风格、模式等）和导航噪声正则将查询路由到最合适的召回路径。资料来源：[dual_mem/retrieval/intent.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/intent.py)

`retrieval/formatter.py` 负责把三类结果合并为带日期前言的上下文字符串，默认仅渲染当前 head，`include_superseded=True` 时展开历史版本。

## 接入模式

dual-mem 提供 **5 种接入方式**：SDK（`MemoryClient` 异步、`SyncMemoryClient` 同步）、REST、CLI、MCP、Skill。REST 与 MCP 共享同一份 `MEMORY_TOOL_CONTRACTS`，由 `MemoryOperations` 统一实现，保证 tool 名与 HTTP 路径一一对应。资料来源：[dual_mem/api/contracts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/api/contracts.py)

CLI 示例（v0.1.2 起支持 `--content` 或 `--messages-file`/`--messages-json` 二选一）：

```bash
dual-mem add --content "用户在深圳做 ML" --user-id u1
dual-mem add --messages-file messages.json --user-id u1
dual-mem search "drink preference" --user-id u1
dual-mem digest   # dual 模式：触发 System2 蒸馏
```

默认情况下省略 `app_id` 即使用 `default_app_id="default"`；`user_id` 是主要的隔离键。资料来源：[README_EN.md](https://github.com/shibing624/dual-mem/blob/main/README_EN.md)

## 常见失败模式与注意

- **混淆链与并存偏好**：对「新增爱好」错误使用 `supersedes` 会让历史被遮蔽。资料来源：[dual_mem/agent/prompts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/prompts.py)
- **storage_dir 未自动创建**：v0.1.2 起 SDK 已自动建目录，但旧版本需手动 `mkdir`。
- **System2 仅在 dual 模式运行**：system1 模式下 `digest` 命令无效。
- **意图路由偏差**：包含 ID、URL、版本号等导航噪声的查询可能被错误路由，建议在 prompt 侧先归一化。

## 另见

- [README_EN.md](https://github.com/shibing624/dual-mem/blob/main/README_EN.md)
- [mkdocs.yml](https://github.com/shibing624/dual-mem/blob/main/mkdocs.yml) — 文档站点导航与扩展配置
- [skills/dual-mem/SKILL.md](https://github.com/shibing624/dual-mem/blob/main/skills/dual-mem/SKILL.md) — Agent Skill 接入约定
- [examples/_common.py](https://github.com/shibing624/dual-mem/blob/main/examples/_common.py) — 演示如何以独立 `storage_dir` 复现 demo

---

<a id='page-2'></a>

## 写入链路：Gate、Extract、Reconcile 与演化链

### 相关页面

相关主题：[整体架构与 L0–L7 记忆模型](#page-1), [读取链路：混合检索与多路召回](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [dual_mem/agent/__init__.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/__init__.py)
- [dual_mem/agent/prompts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/prompts.py)
- [dual_mem/agent/reconciler.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/reconciler.py)
- [dual_mem/sdk_models.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/sdk_models.py)
- [dual_mem/config.default.yaml](https://github.com/shibing624/dual-mem/blob/main/dual_mem/config.default.yaml)
- [examples/01_system1.py](https://github.com/shibing624/dual-mem/blob/main/examples/01_system1.py)
- [skills/dual-mem/SKILL.md](https://github.com/shibing624/dual-mem/blob/main/skills/dual-mem/SKILL.md)
</details>

# 写入链路：Gate、Extract、Reconcile 与演化链

## 概览

dual-mem 的写入链路是 `system1` 模式下的核心数据通路。每当调用方执行 `client.add(content=...)` 或 `client.add(messages=[...])` 时，写入链路会按顺序触发三个 LLM 驱动的处理阶段：**Attentional Gate → Extractor → Reconciler**。前两个阶段由 `MemAgent` 串行调度，落库后由 Reconciler 在向量召回的基础上合并演化链。

该链路的关键设计目标是：

- **过滤低价值信息**：通过 Gate 计算 `novelty / biographical_relevance / emotional_arousal`，避免把"纯寒暄"灌入存储。
- **结构化抽取**：Extractor 把对话/段落拆分为 `identity / facts / intentions / basic_info / emotion / is_ephemeral` 等字段，第三人称、自包含。
- **演化追踪**：Reconciler 把新记忆与既有 L2/L4 节点做向量检索，按 `supersedes` 指针形成"演化链"，确保旧认知可追溯。

```mermaid
flowchart LR
    A["add(content or messages)"] --> B["Gate<br/>novelty/biography/arousal"]
    B -->|通过| C["Extractor<br/>identity/facts/intentions"]
    B -->|降级启发式| C
    C --> D["fast-write<br/>L2_FACT / L4_IDENTITY"]
    D --> E["Reconciler<br/>向量召回 + LLM 决策"]
    E --> F["ADD / DELETE<br/>supersedes 链头更新"]
    F --> G[(存储层<br/>nodes + edges)]
```

资料来源：[dual_mem/agent/__init__.py:1-7]() 资料来源：[examples/01_system1.py:1-13]()

## 各阶段职责

### Gate：注意门控

Gate 与 Extractor 在同一次 LLM 调用中完成输出，避免额外往返。提示词要求模型在 JSON 顶层附带 `gate_decision` 对象，包含 `novelty`、`biographical_relevance`、`emotional_arousal` 三个 0.0–1.0 维度分数，以及 `reason` 简短理由。当 LLM 调用失败时，链路会降级为启发式判断，保证写入不被阻塞。

资料来源：[dual_mem/agent/prompts.py:EXTRACT_GATE_APPEND_ZH]()

### Extractor：结构化抽取

Extractor 输出 `is_ephemeral`、`emotion`、`identity`、`facts`、`intentions`、`basic_info` 等字段，并对每条记忆生成 1–3 个 `tags`。`is_ephemeral=true` 时下游不再写入；否则按 `layer` 字段（`L2_FACT` 或 `L4_IDENTITY`）落到对应存储桶。

抽取阶段还支持多轮对话 `messages` 输入：当整段对话超过上下文比例时，仅截断 `assistant` 轮，`user` 轮始终完整保留，因为它是"记忆主信号"。`role=system` 的消息在 `add` 时会被丢弃。

资料来源：[dual_mem/agent/prompts.py:EXTRACT_ZH]() 资料来源：[dual_mem/config.default.yaml:extract_history_context_ratio]()

### fast-write：直落 L2/L4

抽取结果不经过 System2 的 ReAct 循环，而是直接以 `add` 原子的方式写入 L2_FACT 与 L4_IDENTITY 节点。该路径默认 `reconcile_sync=false`，即写入立即返回，演化链合并异步进行；如需同步演化，可在配置中开启 `reconcile_sync=true`。

资料来源：[examples/01_system1.py:11-13]() 资料来源：[dual_mem/config.default.yaml:reader_mode]()

### Reconciler：演化链合并

Reconciler 的核心流程包含四步：

1. **向量召回**：对新记忆（可选地先用 LLM 改写查询）做 embed，在 L2/L4 ACTIVE 层检索候选。
2. **进化链合并**：`_merge_chains` 把候选按链头分组，附带 `history_versions`。
3. **LLM 决策**：中英 prompt（`RECONCILE_ZH/EN`）输入新旧记忆，要求输出 `updates` 数组；`supersedes` 与 `tags` 是数组类型，未变更时输出 `{"updates": []}`。
4. **解析校验**：`_parse_ops` 归一化 LLM 输出，去重冲突的 `supersedes` / `DELETE`。

输出操作类型包括 `ADD`（含 `supersedes` 旧节点）、`DELETE`（软删，标 SHADOW / `is_latest=False`），并附带 `update_type`（`OVERRIDE / SUPPLEMENT / TEMPORAL / NEGATE / CONFLICT`），由下游写入 `node.custom`。

资料来源：[dual_mem/agent/reconciler.py:核心流程（Reconciler.reconcile）]()

## 演化链与 supersedes

演化链（`evolution_chain`）是 dual-mem 的核心数据结构。一条链代表**同一维度上的状态演化**，例如"所在地"、"编程语言偏好"。

链的语义约定：

- **同主题不同时态**：链 A → B → C（A 最新，C 最旧）描述的是同一维度上的不同认知；A 是当前真值，B/C 是历史声明。
- **附加信息保留**：B/C 在被取代时，可能仍携带其他维度上的有效信息，这些信息不会被删除，而是由新节点选择性吸收。
- **共存不取代**：并列偏好（如"喜欢咖啡" + "也喜欢茶"）应通过 `ADD` 独立写入，而不是 `supersedes`。

Reconciler 决策时严格区分"取代"与"补充"：高召回保守模式下，禁止把多条记忆合并成一条，不同实体/日期/对象的事件必须独立保留。

资料来源：[dual_mem/agent/prompts.py:RECONCILE_ZH 段落 Understanding supersedes chains]() 资料来源：[dual_mem/agent/prompts.py:RECONCILE_POLICY_CONSERVATIVE_ZH]()

`MemoryItem.to_dict()` 在序列化时会自动展开 `evolution_chain`，把每个 `EvolutionItem` 的 `content` 与 `memory_at` 一并输出，便于上层调用方一次性读取完整历史。

资料来源：[dual_mem/sdk_models.py:to_dict 字段说明]()

## 配置开关

写入链路的关键参数集中在 `dual_mem/config.default.yaml`，下表列出与本主题最相关的条目：

| 配置项 | 默认 | 说明 |
| --- | --- | --- |
| `extract_retry_on_failure` | `true` | Extractor 失败时是否重试 |
| `extract_history_context_ratio` | `0.7` | 多轮 messages 截断阈值（仅截 `assistant` 轮） |
| `embed_merge_l1_gate` | `true` | 是否将 L1 + Gate 的 user-turn embed 合并为一次 API 调用 |
| `reader_mode` | `hybrid` | 读路径模式；写入完成后召回以此为准 |
| `reconcile_sync` | `false` | 是否在 `add` 同步执行 Reconciler |

资料来源：[dual_mem/config.default.yaml:extract_* / embed_merge_l1_gate / reader_mode]()

## 典型用法与失败模式

**正确用法**：`add(content=...)` 用于单条稳定画像；`add(messages=[...])` 用于会话结束批量写入。`memory_search` 应在 `memory_add` 之前或之后按需调用。

**应避免的写入**：纯寒暄、临时上下文、"ok / thanks" 类无实质内容的输入应在 Gate 阶段被识别为 `is_ephemeral=true`，不要直接落库。

**失败模式**：

- Gate / Extractor 的 LLM 调用失败时，会走降级启发式，**不会阻塞写入**，但抽取质量会下降。
- Reconciler 的 LLM 输出若违反 JSON 格式或类型约束，会被 `_parse_ops` 拒绝整批操作；此时新记忆以"未合并"状态留在存储中，需要后续重试。

资料来源：[skills/dual-mem/SKILL.md:何时写入 / CLI 示例]() 资料来源：[examples/01_system1.py:期望：第二轮写入后，"现在用什么编程语言"应命中 Python，并附 Java→Python 演化链]()

## See Also

- [架构总览](architecture.md)
- [快速上手](getting-started/quickstart.md)
- [MCP 集成](mcp_integration.md)
- 读路径：`hybrid` / `legacy` 模式在 [dual_mem/retrieval/__init__.py]() 中定义
- 系统 2 异步精炼：[dual_mem/system2/__init__.py]()

---

<a id='page-3'></a>

## 读取链路：混合检索与多路召回

### 相关页面

相关主题：[整体架构与 L0–L7 记忆模型](#page-1), [写入链路：Gate、Extract、Reconcile 与演化链](#page-2)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [dual_mem/retrieval/reader.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/reader.py)
- [dual_mem/retrieval/hybrid_engine.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/hybrid_engine.py)
- [dual_mem/retrieval/hybrid_scoring.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/hybrid_scoring.py)
- [dual_mem/retrieval/anchor_search.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/anchor_search.py)
- [dual_mem/retrieval/bm25.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/bm25.py)
- [dual_mem/retrieval/fusion_scorer.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/fusion_scorer.py)
- [dual_mem/retrieval/intent.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/intent.py)
- [dual_mem/sdk_models.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/sdk_models.py)
- [dual_mem/config.default.yaml](https://github.com/shibing624/dual-mem/blob/main/dual_mem/config.default.yaml)
</details>

# 读取链路：混合检索与多路召回

## 1. 概述与设计目标

`dual_mem/retrieval` 子包负责记忆系统的读侧（reader），核心职责是把用户查询转换为高质量、可解释的召回结果。其模块级 docstring 明确指出：包含**三路由召回、演化链展开、意图分类以及 hybrid（向量 + BM25）重排**工具  资料来源：[dual_mem/retrieval/__init__.py:1-7]()。

自 v0.1.1 起，混合模式（`reader_mode: hybrid`）取代传统三路由成为**默认读路径**：无需调用 LLM、仅依赖 embedding 即可完成主要工作；通过 **5 路 anchor + 融合排序（fusion）**实现高召回。社区 release notes 也将该点作为重点升级列出  资料来源：[v0.1.1 Highlights（README_EN.md / release tag）]()。

设计目标可归纳为三条：

1. **无 LLM 也能跑**：默认 hybrid 路径不依赖 LLM 推理，仅靠 embedding + 启发式 + BM25 即可工作，便于离线/低延迟场景。
2. **结构可解释**：每条召回结果携带 `category`（profile / fact / identity / schema / intention / raw 等）、`score`、`tags` 和可选的 `evolution_chain`，上层 Agent 可基于类别与分值做后处理  资料来源：[dual_mem/sdk_models.py:1-40]()。
3. **演化链透明**：写入时显式的 `supersedes` 指针在读侧自动展开为 `evolution_chain`（新→旧），让模型看到「同一维度上状态的迁移」  资料来源：[dual_mem/agent/prompts.py:1-30]()。

## 2. 混合检索的总体架构

混合检索的输入是一个查询字符串（也支持 messages 形式），输出是一组 `MemoryItem` 对象。下图展示了核心模块协作关系。

```mermaid
flowchart LR
    Q[query] --> A[intent classification<br/>retrieval/intent.py]
    A --> R[anchor_search<br/>5 路 anchor 召回]
    R --> E[evolution chain expansion<br/>reader.py]
    E --> H[hybrid_engine<br/>融合排序]
    H --> S[hybrid_scoring<br/>语义 + BM25 加权]
    S --> F[fusion_scorer<br/>图证据加成]
    F --> O[MemoryItem 列表]
```

各模块的角色如下：

- `retrieval/intent.py`：对查询做导航/概念类意图分类，使用 `_NAV_REGEX` 识别版本号、URL、UUID 等导航型查询，使用 `_CONCEPTUAL_TRIGGERS` 识别「怎么、为什么、整体风格」等概念型查询  资料来源：[dual_mem/retrieval/intent.py:1-40]()。
- `retrieval/anchor_search.py`：负责 5 路 anchor 召回（典型包含：原查询向量、查询扩展向量、profile/fact/schema/intention 分层 anchor），把不同入口命中的节点收集到统一候选池。
- `retrieval/reader.py`：读侧编排器，把意图分类结果路由到 anchor 召回，并在召回后触发演化链展开。
- `retrieval/hybrid_engine.py`：融合多路 anchor 召回结果，去重并产生候选池。
- `retrieval/hybrid_scoring.py` + `retrieval/bm25.py`：在候选池内做 **语义相似度 × BM25** 加权重排。
- `retrieval/fusion_scorer.py`：把图存储中的 L6 Schema 证据做加成（`hybrid_evidence_boost_max` 上限、`hybrid_evidence_saturate` 饱和计数）。

## 3. 配置参数与权重

混合检索的全部旋钮集中在 `dual_mem/config.default.yaml` 中，便于调优召回质量与延迟。

| 配置项 | 默认值 | 含义 |
| --- | --- | --- |
| `reader_mode` | `hybrid` | 读路径主模式；`hybrid` 走 5 路 anchor + 融合，`legacy` 走三路由 + RRF 基线  |
| `hybrid_w_sem` | `0.6` | 语义相似度权重（向量召回分） |
| `hybrid_w_bm25` | `0.4` | 池内 BM25 关键词重排权重 |
| `hybrid_evidence_boost_max` | `0.3` | 图证据（L6 Schema）对融合分的最大加成 |
| `hybrid_evidence_saturate` | `5` | 加成饱和计数（>N 条证据不再线性增长） |
| `embed_merge_l1_gate` | `true` | 将 L1 提取与 Gate user-turn 嵌入合并为一次 API 调用，降低延迟 |

资料来源：[dual_mem/config.default.yaml:读路径段]()。

权重 `0.6 / 0.4` 体现了 hybrid 的设计哲学：**以语义为主、关键词为辅**——BM25 在长尾、专有名词、版本号等场景下补足纯向量召回的盲点；而图证据加成（最大 0.3）则让 L6 Schema 在分数上压过零散 L2 Fact，引导上层 Agent 优先选择已凝练的行为模式而非单条事实。

## 4. 演化链展开与结果结构

读侧的最后一环是把 `supersedes` 链展开为 `evolution_chain` 字段。社区 release 明确指出：**显式 supersedes 指针在读侧会自动展开历史**  资料来源：[v0.1.1 Highlights]()。`MemoryItem` 上的字段语义如下：

- `evolution_chain`：同主题演化历史（新→旧），无链时为 `None`。
- `category`：路由类别（profile / fact / identity / schema / intention / raw），便于上层做条件渲染。
- `tags`：1–3 个小写主题关键词，优先复用已有标签以减少标签碎片化（写入时 prompt 中已约束）  资料来源：[dual_mem/agent/prompts.py:1-50]()。
- `memory_at` / `gmt_created` / `gmt_modified`：三段时间戳分别表示对话时间、入库时间与最后修改时间，辅助时序判断。

**典型使用模式**：Agent 在收到 `evolution_chain` 不为空的 `MemoryItem` 时，应将其视作「一个维度的状态迁移」而非「多条独立事实」。例如居住地维度 A→B→C：A 是当前真值，B/C 可能在其它维度仍携带有效信息，需要分别判别后再消费  资料来源：[dual_mem/agent/prompts.py:Understanding supersedes chains 段]()。

## 5. 常见失败模式与排查

1. **查询被误判为导航型**：URL/版本号正则 `_NAV_REGEX` 命中过宽，导致概念型查询走了短路径。检查 query 是否含 `v\d+\.\d+` 等模式。
2. **BM25 权重过大致长尾主导**：当语料以专有名词为主时，把 `hybrid_w_bm25` 调高（如 `0.5`）；反之偏向语义。
3. **图证据加成饱和**：当 L6 Schema 数远大于 `hybrid_evidence_saturate`（默认 5）时，加成被夹紧到 0.3 上限；可通过提升上限或先做更细粒度分面来缓解。
4. **演化链未展开**：通常是写入侧未生成 `supersedes` 指针（Reconcile 步骤被跳过），需检查 `extract_retry_on_failure` 与 LLM 调用日志  资料来源：[dual_mem/config.default.yaml:extract 段]()。

## See Also

- [系统架构总览（Architecture）](https://shibing624.github.io/dual-mem/architecture/)
- [快速开始（Quickstart）](https://shibing624.github.io/dual-mem/getting-started/quickstart/)
- [REST/MCP 接入](https://shibing624.github.io/dual-mem/mcp_integration/)
- [释放说明 v0.1.2](https://github.com/shibing624/dual-mem/releases/tag/v0.1.2)
- [释放说明 v0.1.1](https://github.com/shibing624/dual-mem/releases/tag/v0.1.1)

---

<a id='page-4'></a>

## 接入方式、配置与部署（SDK / REST / MCP / CLI / Skill）

### 相关页面

相关主题：[整体架构与 L0–L7 记忆模型](#page-1), [写入链路：Gate、Extract、Reconcile 与演化链](#page-2), [读取链路：混合检索与多路召回](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [dual_mem/sdk_models.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/sdk_models.py)
- [dual_mem/api/contracts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/api/contracts.py)
- [dual_mem/api/schemas.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/api/schemas.py)
- [dual_mem/config.default.yaml](https://github.com/shibing624/dual-mem/blob/main/dual_mem/config.default.yaml)
- [dual_mem/agent/prompts.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/agent/prompts.py)
- [dual_mem/retrieval/intent.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/retrieval/intent.py)
- [dual_mem/providers/llm.py](https://github.com/shibing624/dual-mem/blob/main/dual_mem/providers/llm.py)
- [skills/dual-mem/SKILL.md](https://github.com/shibing624/dual-mem/blob/main/skills/dual-mem/SKILL.md)
- [README.md](https://github.com/shibing624/dual-mem/blob/main/README.md)
- [README_EN.md](https://github.com/shibing624/dual-mem/blob/main/README_EN.md)
- [mkdocs.yml](https://github.com/shibing624/dual-mem/blob/main/mkdocs.yml)
- [examples/02_dual.py](https://github.com/shibing624/dual-mem/blob/main/examples/02_dual.py)

</details>

# 接入方式、配置与部署（SDK / REST / MCP / CLI / Skill）

## 概览

dual-mem 是一个面向 LLM 应用与 Agent 的**双系统分层记忆 SDK**。同一套核心逻辑（System1 即时抽取 + System2 异步巩固）通过统一的 `MemoryOperations` 操作层，对外暴露五种接入方式：SDK（同步/异步）、REST、MCP、CLI、Skill。v0.1.2 起 REST 与 MCP 共享同一份工具契约，避免接口分裂 ([README.md](https://github.com/shibing624/dual-mem/blob/main/README.md)、[dual_mem/api/contracts.py:1-30](https://github.com/shibing624/dual-mem/blob/main/dual_mem/api/contracts.py))。

下表为五种接入方式的关键对比：

| 接入方式 | 入口命令/类 | 安装 extras | 适用场景 |
|---|---|---|---|
| SDK（异步） | `MemoryClient` | `dual_mem`（默认） | FastAPI、Agent 长任务 |
| SDK（同步） | `SyncMemoryClient`（v0.1.2 新增） | `dual_mem` | 脚本、批处理、Jupyter |
| REST | `dual-mem serve` | `dual_mem[api]` | 跨语言、独立部署 |
| MCP | `dual-mem-mcp` | `dual_mem[mcp]` | Claude Desktop 等 MCP Host |
| CLI | `dual-mem add/search/...` | `dual_mem[cli]` | 调试、人工写入 |
| Skill | `skills/dual-mem/SKILL.md` | 复制到 Agent skills 目录 | Agentica 等 Agent 框架 |

## SDK 接入（同步 / 异步）

异步入口 `MemoryClient` 面向 `asyncio` 工作流；v0.1.2 新增的 `SyncMemoryClient` 为同步调用封装，底层复用同一 `MemoryOperations`，避免阻塞场景下重复造轮子 ([README_EN.md](https://github.com/shibing624/dual-mem/blob/main/README_EN.md))。

读侧返回统一使用 `MemoryItem` 数据类，包含 `memory_id / content / category / score / tags / memory_at / gmt_created / gmt_modified / evolution_chain` 字段；其中 `evolution_chain` 用于展开 `supersedes` 演化历史 ([dual_mem/sdk_models.py:1-50](https://github.com/shibing624/dual-mem/blob/main/dual_mem/sdk_models.py))。例如 dual 模式下 `client.digest()` 触发 System2 ReAct 循环与跨域 sweeper ([examples/02_dual.py:1-30](https://github.com/shibing624/dual-mem/blob/main/examples/02_dual.py))。

## REST / MCP 接入

REST 与 MCP 共用 `MEMORY_TOOL_CONTRACTS` 中的稳定工具 ID：`memory_add / memory_search / memory_list / memory_get / memory_update / memory_delete / ...`。每个工具声明 `http.method / http.path`，MCP 端直接复用 `name` 字段，因此同一套契约可直接驱动 REST 路由与 MCP tool schema ([dual_mem/api/contracts.py:10-30](https://github.com/shibing624/dual-mem/blob/main/dual_mem/api/contracts.py))。

启动方式：

```bash
pip install dual-mem[all]
dual-mem serve --host 0.0.0.0 --port 8000          # REST
dual-mem-mcp                                         # MCP stdio
dual-mem-mcp --transport streamable-http --port 8765 # MCP HTTP /mcp
```

响应模型 `MemoryItem`（Pydantic）与 SDK 数据类对齐，保证跨端点一致 ([dual_mem/api/schemas.py:1-30](https://github.com/shibing624/dual-mem/blob/main/dual_mem/api/schemas.py))。

## CLI 与 Skill 接入

CLI 适合调试：`dual-mem add --content "..." --user-id u1` 单条写入；`--messages-file messages.json` 支持会话级批量（v0.1.2 新增）。检索端不调 LLM，仅消耗 embedding，5 路 anchor + fusion 召回。

Skill 通过 `skills/dual-mem/SKILL.md` 描述 Agent 集成规范：建议「每轮 `search`、会话结束 `add(messages)`」以节省 token；当用户纠正旧信息时由 `supersedes` 形成演化链 ([skills/dual-mem/SKILL.md:1-30](https://github.com/shibing624/dual-mem/blob/main/skills/dual-mem/SKILL.md))。

## 配置与部署

最小配置由 `config.default.yaml` 首次启动自动生成，关键字段包括 `embed_base_url / embed_api_key / embed_model / embed_dim / default_app_id / app_whitelist / auth_disabled / mode (system1|dual)`。`user_id` 是主隔离键，`app_id` 缺省回落到 `default`；REST 鉴权可通过 `auth_disabled: true` 在本地关闭 ([dual_mem/config.default.yaml:1-30](https://github.com/shibing624/dual-mem/blob/main/dual_mem/config.default.yaml))。

依赖按 extras 拆分：`[api]` `[cli]` `[mcp]`，按需安装可减小运行时体积 ([README_EN.md](https://github.com/shibing624/dual-mem/blob/main/README_EN.md))。文档站点由 `mkdocs.yml` 描述（locale=zh，readthedocs 主题） ([mkdocs.yml:1-10](https://github.com/shibing624/dual-mem/blob/main/mkdocs.yml))。

## 常见问题

- **存储目录不存在**：v0.1.2 起 `storage_dir` 自动创建，不再需要手动 `mkdir`。
- **MCP 启动失败**：检查 `dual-mem-mcp` 是否安装（`[mcp]` extra），以及 Host 端 transport（stdio / streamable-http）。
- **检索召回空**：默认 hybrid 路径需要可用 embedding；检查 `embed_api_key` 与 `embed_dim` 是否与模型一致。
- **演化链未展开**：读侧需走默认 hybrid 路径才会自动展开 `evolution_chain`；直查 `memory_get` 仅返回当前节点。

## See Also

- [架构总览](architecture.md)
- [快速上手](getting-started/quickstart.md)
- [安装指南](getting-started/installation.md)
- [MCP 集成](mcp_integration.md)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：shibing624/dual-mem

摘要：发现 7 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：配置坑 - 可能修改宿主 AI 配置。

## 1. 配置坑 · 可能修改宿主 AI 配置

- 严重度：medium
- 证据强度：source_linked
- 发现：项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主，或安装命令涉及用户配置目录。
- 对用户的影响：安装可能改变本机 AI 工具行为，用户需要知道写入位置和回滚方法。
- 证据：capability.host_targets | https://github.com/shibing624/dual-mem | host_targets=mcp_host, cursor

## 2. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/shibing624/dual-mem | README/documentation is current enough for a first validation pass.

## 3. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/shibing624/dual-mem | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/shibing624/dual-mem | no_demo; severity=medium

## 5. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/shibing624/dual-mem | no_demo; severity=medium

## 6. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/shibing624/dual-mem | issue_or_pr_quality=unknown

## 7. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/shibing624/dual-mem | release_recency=unknown

<!-- canonical_name: shibing624/dual-mem; human_manual_source: deepwiki_human_wiki -->
