DeerFlow Memory架构

1. 概述

DeerFlow 的 长期记忆(Long-Term Memory) 系统使 Agent 能够在会话之间保留信息。与传统的聊天机器人在会话结束后会忘记一切不同,DeerFlow 会构建用户偏好、上下文和知识的持久记忆。

核心特性:

  • 跨会话持久化
  • 基于 LLM 的自动事实提取
  • 支持按 Agent 独立记忆
  • Token 限制的 System Prompt 注入
  • 防抖异步更新
  • 纠正/强化检测

2. 架构

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                        Memory System Architecture                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌──────────────┐     ┌──────────────┐     ┌──────────────────┐    │
│  │   Frontend   │────▶│  Lead Agent  │────▶│ MemoryMiddleware │    │
│  │   (User)     │     │              │     │  (after_agent)   │    │
│  └──────────────┘     └──────────────┘     └────────┬─────────┘    │
│                                                       │              │
│                                                       ▼              │
│                                              ┌──────────────┐       │
│                                              │ MemoryQueue  │       │
│                                              │ (Debounced)  │       │
│                                              └──────┬───────┘       │
│                                                     │               │
│                                    ┌────────────────┼───────────┐   │
│                                    ▼                ▼           ▼   │
│                             ┌──────────┐    ┌──────────┐  ┌─────┐  │
│                             │ Summarize│    │  Timer   │  │ 30s │  │
│                             │  Hook    │    │(threading│  │wait │  │
│                             └──────────┘    │  Timer)  │  └─────┘  │
│                                            └────────────┘           │
│                                                     │               │
│                                                     ▼               │
│                                              ┌──────────────┐       │
│                                              │MemoryUpdater │       │
│                                              │  (LLM-based) │       │
│                                              └──────┬───────┘       │
│                                                     │               │
│                                                     ▼               │
│                                              ┌──────────────┐       │
│                                              │FileMemory    │       │
│                                              │Storage       │       │
│                                              └──────┬───────┘       │
│                                                     │               │
│                                                     ▼               │
│                                              ┌──────────────┐       │
│                                              │ memory.json  │       │
│                                              └──────────────┘       │
│                                                                      │
│  ┌──────────────┐     ┌──────────────┐     ┌──────────────────┐    │
│  │   Frontend   │◀────│  Lead Agent  │◀────│  System Prompt  │    │
│  │   (User)     │     │   (Next      │     │  (Memory         │    │
│  └──────────────┘     │   Request)   │     │   Injection)    │    │
│                       └──────────────┘     └──────────────────┘    │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

3. 数据结构

3.1 Memory JSON 结构

存储在 backend/.deer-flow/memory.json:

json 复制代码
{
  "version": "1.0",
  "lastUpdated": "2026-04-21T10:30:00Z",

  "user": {
    "workContext": {
      "summary": "字节跳动高级软件工程师,从事 AI 基础设施工作...",
      "updatedAt": "2026-04-21T10:30:00Z"
    },
    "personalContext": {
      "summary": "精通中英文,对分布式系统感兴趣...",
      "updatedAt": "2026-04-21T09:15:00Z"
    },
    "topOfMind": {
      "summary": "目前专注于优化 DeerFlow 的memory系统。同时在探索...",
      "updatedAt": "2026-04-21T10:30:00Z"
    }
  },

  "history": {
    "recentMonths": {
      "summary": "自 2026 年 1 月起从事 DeerFlow 2.0 工作。实现了memory...",
      "updatedAt": "2026-04-20T16:00:00Z"
    },
    "earlierContext": {
      "summary": "之前从事 LangChain 集成工作。构建了多个自定义...",
      "updatedAt": "2026-03-15T11:00:00Z"
    },
    "longTermBackground": {
      "summary": "5 年以上 AI/ML 基础设施经验。强背景...",
      "updatedAt": "2026-01-10T08:00:00Z"
    }
  },

  "facts": [
    {
      "id": "fact_a1b2c3d4",
      "content": "用户更喜欢使用 Python 进行数据处理任务",
      "category": "preference",
      "confidence": 0.92,
      "createdAt": "2026-04-20T14:30:00Z",
      "source": "thread_abc123"
    },
    {
      "id": "fact_e5f6g7h8",
      "content": "用户正在研究 DeerFlow memory优化",
      "category": "context",
      "confidence": 0.88,
      "createdAt": "2026-04-21T10:00:00Z",
      "source": "thread_def456"
    },
    {
      "id": "fact_i9j0k1l2",
      "content": "用户之前对 debounce 机制有误解(避免:假设立即更新)",
      "category": "correction",
      "confidence": 0.95,
      "createdAt": "2026-04-21T09:45:00Z",
      "source": "thread_ghi789",
      "sourceError": "假设memory更新是同步发生的"
    }
  ]
}

3.2 Fact 类别

类别 描述 示例
preference 用户偏好的工具、风格、方法 "用户喜欢深色模式"
knowledge 用户的专业知识和技术掌握 "用户精通 PyTorch"
context 背景信息(工作、项目、地点) "用户在字节跳动工作"
behavior 工作模式和沟通习惯 "用户倾向于先问澄清问题"
goal 已声明的目标和项目愿景 "用户想优化 DeerFlow memory"
correction Agent 错误或用户纠正 "用户纠正了 Agent 关于 X 的说法"

3.3 置信度级别confidence

范围 含义 使用场景
0.9 - 1.0 明确陈述的事实 用户说"我从事 X 工作"或"我的角色是 Y"
0.7 - 0.8 从行为强烈暗示 用户持续使用 Python 而非 Java
0.5 - 0.6 推断的模式(谨慎使用) 多次观察到的明确行为模式

3.4 ConversationContext(队列项)

python 复制代码
@dataclass
class ConversationContext:
    thread_id: str                           # 线程标识符
    messages: list[Any]                      # 过滤后的对话消息
    timestamp: datetime                      # 入队时间(默认:现在)
    agent_name: str | None = None            # 按 Agent 记忆(None = 全局)
    correction_detected: bool = False        # 用户纠正了 Agent
    reinforcement_detected: bool = False     # 用户确认 Agent 有帮助

4. 核心组件

4.1 文件结构

复制代码
backend/packages/harness/deerflow/agents/memory/
├── __init__.py
├── storage.py              # MemoryStorage 接口 + FileMemoryStorage 实现
├── queue.py                # 带防抖的 MemoryUpdateQueue
├── updater.py              # MemoryUpdater(基于 LLM 的事实提取)
├── prompt.py               # MEMORY_UPDATE_PROMPT + 注入格式化
├── message_processing.py   # 消息过滤 + 纠正/强化检测
├── summarization_hook.py   # memory_flush_hook() 用于总结集成
└── memory_middleware.py    # MemoryMiddleware(Lead Agent 中间件 #13)

4.2 组件详情

4.2.1 storage.py

职责: 抽象存储接口和基于文件的实现。

关键类:

  • MemoryStorage(ABC):定义 load()、reload()、save() 接口的抽象基类
  • FileMemoryStorage:基于 JSON 文件的存储,带缓存

FileMemoryStorage 特性:

  • 每个 Agent 名称的线程安全memory缓存
  • 通过文件修改时间(mtime)检查缓存有效性
  • 通过临时文件 + 重命名的原子性保存
  • 支持按 Agent 记忆文件(根据 AGENT_NAME_PATTERN 验证)

默认存储位置:

复制代码
backend/.deer-flow/memory.json              # 全局记忆
backend/.deer-flow/memory_{agent_name}.json # 按 Agent 记忆
4.2.2 queue.py

职责: 用于批处理memory更新的防抖队列。

关键类: MemoryUpdateQueue

特性:

  • 可配置的防抖周期(默认:30 秒)
  • 按线程去重(每个 thread_id 只保留最新对话)
  • 基于线程的定时器延迟处理
  • flush() 用于同步处理,flush_nowait() 用于后台处理

单例模式:

python 复制代码
_memory_queue: MemoryUpdateQueue | None = None

def get_memory_queue() -> MemoryUpdateQueue:
    """获取全局memory更新队列单例。"""
    global _memory_queue
    with _queue_lock:
        if _memory_queue is None:
            _memory_queue = MemoryUpdateQueue()
        return _memory_queue
4.2.3 updater.py

职责: 基于 LLM 的memory更新和事实提取。

关键类: MemoryUpdater

核心方法:

  • update_memory() - 通过 ThreadPoolExecutor 同步更新
  • aupdate_memory() - 在异步上下文中使用的异步更新
  • _prepare_update_prompt() - 使用当前记忆 + 对话构建提示词
  • _finalize_update() - 解析 LLM 响应并持久化更改
  • _apply_updates() - 将结构化更新应用到记忆数据

关键特性:

  • 空白符归一化的事实去重(大小写不敏感、去空格比较)
  • max_facts 限制强制执行(默认:100,保留最高置信度)
  • 上传事件清理,防止临时文件路径进入记忆
  • 带有 sourceError 跟踪的纠正检测
4.2.4 prompt.py

职责: 操作memory的提示词模板。

关键模板:

  1. MEMORY_UPDATE_PROMPT - 用于 LLM 分析对话并生成更新:

    • 输入:当前记忆状态 + 新对话
    • 输出:更新 user/history 部分和新事实的结构化 JSON
    • 包含用于错误/重试检测的结构化反思说明
  2. FACT_EXTRACTION_PROMPT - 用于从单条消息提取事实

关键函数:

python 复制代码
def format_memory_for_injection(memory_data: dict, max_tokens: int = 2000) -> str:
    """
    格式化记忆以注入到系统提示词中。

    - 使用 tiktoken 进行精确 token 计数
    - 按置信度排序事实
    - 在 token 预算内包含尽可能多的事实
    - 格式:"- [category | confidence] content"
    """

def format_conversation_for_update(messages: list) -> str:
    """
    格式化对话消息以进行记忆更新。

    - 只过滤 human/ai 消息
    - 从 human 消息中去除 uploaded_files 标签
    - 截断超长消息(>1000 字符)
    """
4.2.5 message_processing.py

职责: 消息过滤和信号检测。

关键函数:

python 复制代码
def filter_messages_for_memory(messages: list) -> list:
    """
    只保留用户输入和最终助手回复。

    - 跳过仅包含文件上传的消息
    - 从内容中去除 uploaded_files 标签
    - 排除工具调用/结果消息
    """

def detect_correction(messages: list) -> bool:
    """
    检测用户明确的纠正。

    模式(英文):
    - "that's wrong", "that's incorrect"
    - "you misunderstood"
    - "try again", "redo"

    模式(中文):
    - "不对", "你理解错了", "你理解有误"
    - "重试", "重新来", "换一种", "改用"
    """

def detect_reinforcement(messages: list) -> bool:
    """
    检测明确的积极强化。

    模式(英文):
    - "yes, exactly", "perfect"
    - "that's right", "that's correct"
    - "keep doing that", "just like that"

    模式(中文):
    - "对,就是这样", "完全正确"
    - "就是这个意思", "正是我想要的"
    - "继续保持"
    """
4.2.6 summarization_hook.py

职责: 与总结系统的集成。

函数: memory_flush_hook(event: SummarizationEvent)

当总结系统即将压缩消息时(以保持在 token 限制内),此钩子确保这些消息首先被刷新到memory队列。这在信息被总结掉之前保留下来。

4.2.7 memory_middleware.py

职责: Lead Agent 中间件集成。

类: MemoryMiddleware(中间件链中的 #13)

中间件链中的位置:

  1. ThreadDataMiddleware
  2. UploadsMiddleware
  3. SandboxMiddleware
  4. DanglingToolCallMiddleware
  5. LLMErrorHandlingMiddleware
  6. GuardrailMiddleware
  7. SandboxAuditMiddleware
  8. ToolErrorHandlingMiddleware
  9. SummarizationMiddleware
  10. TodoListMiddleware
  11. TokenUsageMiddleware
  12. TitleMiddleware
  13. MemoryMiddleware ←
  14. ViewImageMiddleware
  15. DeferredToolFilterMiddleware
  16. SubagentLimitMiddleware
  17. LoopDetectionMiddleware
  18. ClarificationMiddleware

after_agent() 流程:

  1. 从运行时上下文或 LangGraph 配置获取 thread_id
  2. 从状态获取消息
  3. 过滤为用户输入 + 最终 AI 回复
  4. 检测纠正/强化信号
  5. 通过 get_memory_queue().add() 入队

5. 更新流程

5.1 完整更新时序

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                    Memory Update Sequence Diagram                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  1. 用户交互                                                        │
│  ┌────────┐      ┌──────────────┐      ┌──────────────────────┐    │
│  │ User   │─────▶│  Lead Agent  │─────▶│   MemoryMiddleware   │    │
│  │ Message│      │              │      │     after_agent()     │    │
│  └────────┘      └──────────────┘      └──────────┬───────────┘    │
│                                                     │                │
│  2. 入队 & 防抖                                     ▼                │
│                                          ┌──────────────────┐        │
│                                          │  MemoryQueue     │        │
│                                          │  .add()          │        │
│                                          │  (30s debounce)  │        │
│                                          └────────┬─────────┘        │
│                                                   │                  │
│  3. 定时器到期                                    ▼                  │
│                                          ┌──────────────────┐        │
│                                          │  _process_queue()│        │
│                                          │  (background)    │        │
│                                          └────────┬─────────┘        │
│                                                   │                  │
│  4. LLM 更新                                     ▼                  │
│                                          ┌──────────────────┐        │
│                                          │  MemoryUpdater   │        │
│                                          │  .update_memory()│        │
│                                          └────────┬─────────┘        │
│                                                   │                  │
│  5. 存储                                         ▼                  │
│                                          ┌──────────────────┐        │
│                                          │  FileMemory      │        │
│                                          │  .save()         │        │
│                                          │  (atomic write)  │        │
│                                          └────────┬─────────┘        │
│                                                   │                  │
│  6. 下次交互                                     ▼                  │
│                                          ┌──────────────────┐        │
│                                          │ format_memory    │        │
│                                          │ _for_injection() │        │
│                                          └────────┬─────────┘        │
│                                                   │                  │
│                                                   ▼                  │
│                                          ┌──────────────────┐        │
│                                          │  System Prompt   │        │
│                                          │  <memory> tag    │        │
│                                          └──────────────────┘        │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

5.2 步骤详解

步骤 1:消息收集

每次 Agent 执行后,调用 MemoryMiddleware.after_agent():

python 复制代码
# 获取 thread_id
thread_id = runtime.context.get("thread_id") or get_config().configurable.thread_id

# 获取并过滤消息
messages = state.get("messages", [])
filtered_messages = filter_messages_for_memory(messages)

# 检测信号
correction_detected = detect_correction(filtered_messages)
reinforcement_detected = not correction_detected and detect_reinforcement(filtered_messages)

# 入队等待处理
queue.add(
    thread_id=thread_id,
    messages=filtered_messages,
    agent_name=self._agent_name,
    correction_detected=correction_detected,
    reinforcement_detected=reinforcement_detected,
)
步骤 2:防抖队列

MemoryUpdateQueue.add():

  1. 检查记忆是否启用
  2. 与同一 thread_id 的现有上下文合并(保留最新,合并纠正/强化标志)
  3. 重置防抖定时器
python 复制代码
def _enqueue_locked(self, thread_id, messages, ...):
    # 如果线程已在队列中,用新消息替换
    # 这是"按线程去重" - 只保留最新对话
    self._queue = [c for c in self._queue if c.thread_id != thread_id]
    self._queue.append(ConversationContext(...))
步骤 3:定时器处理

30 秒后(可配置),调用 _process_queue():

python 复制代码
def _process_queue(self):
    with self._lock:
        contexts_to_process = self._queue.copy()
        self._queue.clear()

    for context in contexts_to_process:
        updater = MemoryUpdater()
        updater.update_memory(
            messages=context.messages,
            thread_id=context.thread_id,
            agent_name=context.agent_name,
            correction_detected=context.correction_detected,
            reinforcement_detected=context.reinforcement_detected,
        )
步骤 4:基于 LLM 的事实提取

MemoryUpdater._prepare_update_prompt() 构建提示词:

复制代码
Current Memory State:
<current_memory>
{当前记忆的 JSON}
</current_memory>

New Conversation to Process:
<conversation>
User: 我更喜欢使用 Python 进行数据处理

Assistant: 我会使用 Python 来帮助您处理这个任务...
</conversation>

Instructions:
1. 分析对话中的重要信息
2. 提取相关的事实、偏好和上下文
3. 根据需要更新记忆部分
...

MemoryUpdater._finalize_update() 解析 JSON 响应:

json 复制代码
{
  "user": {
    "workContext": { "summary": "...", "shouldUpdate": true },
    "topOfMind": { "summary": "...", "shouldUpdate": true }
  },
  "history": {
    "recentMonths": { "summary": "...", "shouldUpdate": true }
  },
  "newFacts": [
    { "content": "用户更喜欢使用 Python 进行数据处理", "category": "preference", "confidence": 0.92 }
  ],
  "factsToRemove": []
}
步骤 5:应用更新

_apply_updates():

  1. 在 shouldUpdate: true 的地方更新 user/history 部分
  2. 删除 factsToRemove 中的事实
  3. 添加新事实并进行去重(空白符归一化)
  4. 强制执行 max_facts 限制(保留最高置信度)
步骤 6:原子性保存

FileMemoryStorage.save():

python 复制代码
def save(self, memory_data, agent_name=None):
    # 1. 复制并添加时间戳
    memory_data = {**memory_data, "lastUpdated": utc_now_iso_z()}

    # 2. 写入临时文件
    temp_path = file_path.with_suffix(f".{uuid.uuid4().hex}.tmp")
    with open(temp_path, "w") as f:
        json.dump(memory_data, f, indent=2, ensure_ascii=False)

    # 3. 原子重命名
    temp_path.replace(file_path)

    # 4. 更新缓存
    with self._cache_lock:
        self._memory_cache[agent_name] = (memory_data, mtime)

6. Memory 注入

6.1 注入流程

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                    Memory Injection Flow                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  1. 下次用户请求                                                     │
│  ┌────────┐                                                         │
│  │ User   │                                                         │
│  │ Request│                                                         │
│  └───┬────┘                                                         │
│      │                                                              │
│      ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐    │
│  │                   make_lead_agent()                           │    │
│  │                                                             │    │
│  │   ┌─────────────────────────────────────────────────────┐   │    │
│  │   │              apply_prompt_template()               │   │    │
│  │   │                                                      │   │    │
│  │   │   System Prompt:                                      │   │    │
│  │   │   ┌──────────────────────────────────────────────┐   │   │    │
│  │   │   │ <memory>                                    │   │   │    │
│  │   │   │ - [preference | 0.92] 用户更喜欢 Python     │   │   │    │
│  │   │   │ - [knowledge | 0.88] 用户精通 PyTorch       │   │   │    │
│  │   │   │ - [context | 0.85] 用户在字节跳动工作       │   │   │    │
│  │   │   │ </memory>                                   │   │   │    │
│  │   │   └──────────────────────────────────────────────┘   │   │    │
│  │   │                                                      │   │    │
│  │   └─────────────────────────────────────────────────────┘   │    │
│  └─────────────────────────────────────────────────────────────┘    │
│      │                                                              │
│      ▼                                                              │
│  ┌──────────────┐      ┌──────────────┐      ┌──────────────┐       │
│  │  Lead Agent  │─────▶│  LLM Call    │─────▶│   Response   │       │
│  └──────────────┘      └──────────────┘      └──────────────┘       │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

6.2 注入格式

xml 复制代码
<memory>
User Context:
- Work: 字节跳动高级工程师,从事 DeerFlow AI 基础设施工作
- Personal: 精通中英文,对分布式系统感兴趣
- Current Focus: 优化 DeerFlow memory系统,探索基于 LLM 的事实提取

History:
- Recent: 自 2026 年 1 月起从事 DeerFlow 2.0 工作,实现了memory中间件
- Earlier: 之前从事 LangChain 集成,构建了自定义 Agent
- Background: 5 年以上 AI/ML 基础设施经验,分布式系统背景

Facts:
- [preference | 0.92] 用户更喜欢使用 Python 进行数据处理任务
- [knowledge | 0.88] 用户精通 PyTorch 和深度学习框架
- [context | 0.85] 用户在字节跳动从事 AI 基础设施工作
- [behavior | 0.78] 用户倾向于在实施前问澄清问题
- [correction | 0.95] 用户纠正了 Agent 关于 debounce 时序的问题(避免:假设立即更新)
</memory>

6.3 Token 预算

  • 默认:最大 2000 tokens
  • 使用 tiktoken 进行精确计数
  • 按顺序包含部分:User Context → History → Facts
  • 事实按置信度排序(最高优先)
  • 如果超出限制,截断事实

7. 中间件集成

7.1 中间件链位置

复制代码
1.  ThreadDataMiddleware        → 创建按线程的目录
2.  UploadsMiddleware           → 跟踪上传的文件
3.  SandboxMiddleware           → 获取沙盒
4.  DanglingToolCallMiddleware  → 修复中断的工具调用
5.  LLMErrorHandlingMiddleware  → 规范化 provider 错误
6.  GuardrailMiddleware        → 工具调用前授权
7.  SandboxAuditMiddleware     → 安全审计日志
8.  ToolErrorHandlingMiddleware→ 转换工具异常
9.  SummarizationMiddleware    → 上下文缩减
10. TodoListMiddleware          → 任务跟踪
11. TokenUsageMiddleware       → Token 指标
12. TitleMiddleware             → 自动生成线程标题
13. MemoryMiddleware           → ← 将对话排队等待memory更新
14. ViewImageMiddleware         → 为视觉模型注入图像
15. DeferredToolFilterMiddleware → 隐藏延迟的工具
16. SubagentLimitMiddleware    → 强制子代理限制
17. LoopDetectionMiddleware     → 检测重复循环
18. ClarificationMiddleware     → 处理澄清请求

7.2 MemoryMiddleware 生命周期

python 复制代码
class MemoryMiddleware(AgentMiddleware):
    def after_agent(self, state, runtime):
        """每次 Agent 执行后调用。"""
        # 1. 获取 thread_id
        thread_id = runtime.context.get("thread_id") or get_config().configurable.thread_id

        # 2. 获取并过滤消息
        messages = state.get("messages", [])
        filtered = filter_messages_for_memory(messages)

        # 3. 检测信号
        correction = detect_correction(filtered)
        reinforcement = not correction and detect_reinforcement(filtered)

        # 4. 排队等待异步处理
        queue = get_memory_queue()
        queue.add(
            thread_id=thread_id,
            messages=filtered,
            agent_name=self._agent_name,
            correction_detected=correction,
            reinforcement_detected=reinforcement,
        )

        return None  # 无状态更改

7.3 总结钩子

当 SummarizationMiddleware 即将压缩消息时,首先调用 memory_flush_hook():

python 复制代码
def memory_flush_hook(event: SummarizationEvent):
    """在即将被总结的消息刷新到memory队列。"""
    filtered = filter_messages_for_memory(list(event.messages_to_summarize))

    # 只有在有意义的对话时才处理
    if not user_messages or not assistant_messages:
        return

    correction = detect_correction(filtered)
    reinforcement = not correction and detect_reinforcement(filtered)

    queue = get_memory_queue()
    queue.add_nowait(
        thread_id=event.thread_id,
        messages=filtered,
        agent_name=event.agent_name,
        correction_detected=correction,
        reinforcement_detected=reinforcement,
    )

这确保信息在被总结掉之前被捕获。


8. 存储系统

8.1 存储接口

python 复制代码
class MemoryStorage(ABC):
    @abc.abstractmethod
    def load(self, agent_name: str | None = None) -> dict[str, Any]:
        """加载给定 Agent 的记忆数据。"""
        pass

    @abc.abstractmethod
    def reload(self, agent_name: str | None = None) -> dict[str, Any]:
        """强制重新加载给定 Agent 的记忆数据。"""
        pass

    @abc.abstractmethod
    def save(self, memory_data: dict[str, Any], agent_name: str | None = None) -> bool:
        """保存给定 Agent 的记忆数据。"""
        pass

8.2 FileMemoryStorage

python 复制代码
class FileMemoryStorage(MemoryStorage):
    def __init__(self):
        # 按 Agent 记忆缓存:{agent_name: (memory_data, file_mtime)}
        self._memory_cache: dict[str | None, tuple[dict, float | None]] = {}
        self._cache_lock = threading.Lock()

缓存逻辑:

  • 首次 load() 调用从文件读取
  • 后续调用如果文件 mtime 未变则从缓存返回
  • reload() 强制从文件重新读取,使缓存失效

原子性保存:

python 复制代码
def save(self, memory_data, agent_name=None):
    # 1. 创建带 UUID 后缀的临时文件
    temp_path = file_path.with_suffix(f".{uuid.uuid4().hex}.tmp")

    # 2. 写入临时文件
    with open(temp_path, "w", encoding="utf-8") as f:
        json.dump(memory_data, f, indent=2, ensure_ascii=False)

    # 3. 原子重命名(仅在写入完成时成功)
    temp_path.replace(file_path)

    # 4. 更新缓存
    with self._cache_lock:
        self._memory_cache[agent_name] = (memory_data, file_path.stat().st_mtime)

8.3 按 Agent 记忆

Agent 可以有独立的记忆存储:

python 复制代码
# 全局记忆(默认)
memory = get_memory_storage().load(None)

# 按 Agent 记忆
memory = get_memory_storage().load("agent_name")

文件存储在:

复制代码
backend/.deer-flow/memory.json           # 全局
backend/.deer-flow/memory_agent1.json    # 按 Agent

9. 配置

9.1 MemoryConfig 结构

python 复制代码
class MemoryConfig(BaseModel):
    # 主开关
    enabled: bool = True

    # 存储
    storage_path: str = ""  # "" = 默认为 {base_dir}/memory.json
    storage_class: str = "deerflow.agents.memory.storage.FileMemoryStorage"

    # 更新行为
    debounce_seconds: int = 30  # 1-300 秒

    # 用于基于 LLM 更新的模型(None = 使用默认模型)
    model_name: str | None = None

    # 事实存储限制
    max_facts: int = 100  # 10-500
    fact_confidence_threshold: float = 0.7  # 0.0-1.0

    # 注入设置
    injection_enabled: bool = True
    max_injection_tokens: int = 2000  # 100-8000

9.2 config.yaml 示例

yaml 复制代码
memory:
  enabled: true
  storage_path: ""                          # 使用默认位置
  storage_class: deerflow.agents.memory.storage.FileMemoryStorage
  debounce_seconds: 30                      # 最后一条消息后等待 30 秒
  model_name: null                          # 使用默认模型
  max_facts: 100                            # 保留前 100 个事实
  fact_confidence_threshold: 0.7             # 只存储置信度 >= 0.7 的事实
  injection_enabled: true                   # 注入到系统提示词
  max_injection_tokens: 2000               # 提示词中最多 2000 tokens

10. API 端点

所有端点位于 /api/memory 下。

10.1 端点汇总

端点 方法 描述
/api/memory GET 获取所有记忆数据
/api/memory DELETE 清除所有记忆
/api/memory/reload POST 强制从文件重新加载
/api/memory/facts POST 手动创建事实
/api/memory/facts/{id} DELETE 删除事实
/api/memory/facts/{id} PATCH 更新事实
/api/memory/export GET 导出记忆为 JSON
/api/memory/import POST 从 JSON 导入记忆
/api/memory/config GET 获取记忆配置
/api/memory/status GET 获取配置 + 数据组合

10.2 响应示例

GET /api/memory
json 复制代码
{
  "version": "1.0",
  "lastUpdated": "2026-04-21T10:30:00Z",
  "user": {
    "workContext": { "summary": "字节跳动高级工程师", "updatedAt": "..." },
    "personalContext": { "summary": "精通中英文", "updatedAt": "..." },
    "topOfMind": { "summary": "专注于 DeerFlow memory优化", "updatedAt": "..." }
  },
  "history": {
    "recentMonths": { "summary": "从事 DeerFlow 2.0 工作", "updatedAt": "..." },
    "earlierContext": { "summary": "之前从事 LangChain", "updatedAt": "..." },
    "longTermBackground": { "summary": "5 年以上 AI/ML 基础设施", "updatedAt": "..." }
  },
  "facts": [...]
}
GET /api/memory/status
json 复制代码
{
  "config": {
    "enabled": true,
    "storage_path": "",
    "debounce_seconds": 30,
    "model_name": null,
    "max_facts": 100,
    "fact_confidence_threshold": 0.7,
    "injection_enabled": true,
    "max_injection_tokens": 2000
  },
  "data": { ... }
}
POST /api/memory/facts

请求:

json 复制代码
{
  "content": "用户更喜欢使用 Python 进行数据处理",
  "category": "preference",
  "confidence": 0.92
}

响应:

json 复制代码
{
  "success": true,
  "fact": {
    "id": "fact_a1b2c3d4",
    "content": "用户更喜欢使用 Python 进行数据处理",
    "category": "preference",
    "confidence": 0.92,
    "createdAt": "2026-04-21T10:30:00Z",
    "source": "manual"
  }
}

11. 关键设计决策

11.1 异步 + 同步混合

MemoryUpdater 同时具有同步和异步更新方法:

python 复制代码
def update_memory(self, messages, ...):
    """通过 ThreadPoolExecutor 同步更新。"""
    return _run_async_update_sync(self.aupdate_memory(...))

async def aupdate_memory(self, messages, ...):
    """用于异步上下文的异步更新。"""
    # 为 CPU 密集型的 LLM 调用使用 asyncio.to_thread
    prepared = await asyncio.to_thread(self._prepare_update_prompt, ...)
    response = await model.ainvoke(prompt)
    return await asyncio.to_thread(self._finalize_update, ...)

为什么? 防止阻塞异步事件循环,同时仍支持同步调用点。

11.2 按线程去重

python 复制代码
def _enqueue_locked(self, thread_id, ...):
    # 移除此线程的现有条目
    self._queue = [c for c in self._queue if c.thread_id != thread_id]
    # 添加新条目
    self._queue.append(context)

每个 thread_id 只保留最新对话。这可以防止重复处理并减少 LLM 调用。

11.3 空白符归一化去重

python 复制代码
def _fact_content_key(content):
    """用于去重的大小写折叠、去空格比较。"""
    stripped = content.strip()
    return stripped.casefold()

"User prefers Python" 和 "user prefers python " 被视为重复。

11.4 上传事件清理

python 复制代码
_UPLOAD_SENTENCE_RE = re.compile(
    r"[^.!?]*\b(?:"
    r"upload(?:ed|ing)?(?:\s+\w+){0,3}\s+(?:file|files?|document|...)"
    r"|file\s+upload"
    r"|/mnt/user-data/uploads/"
    r"|<uploaded_files>"
    r")[^.!?]*[.!?]?\s*",
    re.IGNORECASE,
)

def _strip_upload_mentions_from_memory(memory_data):
    """从记忆摘要和事实中去除提及文件上传的句子。"""
    # 清理描述上传事件的事实

上传的文件是会话范围的,在未来的会话中无法访问。记录它们会导致混淆。

11.5 原子性文件写入

python 复制代码
temp_path = file_path.with_suffix(f".{uuid.uuid4().hex}.tmp")
with open(temp_path, "w") as f:
    json.dump(memory_data, f, ...)
temp_path.replace(file_path)  # 在 POSIX 上是原子的

使用临时文件 + 重命名模式。如果进程在写入中间崩溃,原文件保持不变。

11.6 总结前刷新memory

python 复制代码
def memory_flush_hook(event: SummarizationEvent):
    """在消息被总结之前,先刷新到memory。"""
    queue.add_nowait(
        thread_id=event.thread_id,
        messages=filtered_messages,
        ...
    )

即将被总结掉的信息首先被捕获到memory中,然后再压缩。

11.7 带 sourceError 的纠正检测

json 复制代码
{
  "id": "fact_abc123",
  "content": "用户纠正了 Agent 关于 debounce 时序的问题",
  "category": "correction",
  "confidence": 0.95,
  "source": "thread_xyz",
  "sourceError": "假设memory更新是同步发生的"
}

当用户明确纠正 Agent 时,sourceError 字段捕获 Agent 错在哪里,帮助避免同样的错误。

11.8 基于 Token 的注入限制

python 复制代码
def format_memory_for_injection(memory_data, max_tokens=2000):
    # 使用 tiktoken 进行精确 token 计数
    token_count = _count_tokens(result)

    # 如果超出限制,截断
    if token_count > max_tokens:
        char_per_token = len(result) / token_count
        target_chars = int(max_tokens * char_per_token * 0.95)
        result = result[:target_chars] + "\n..."

使用 tiktoken 进行精确 token 计数(不是字符近似)。


附录:文件位置

组件 文件路径
Memory 配置 backend/packages/harness/deerflow/config/memory_config.py
Storage backend/packages/harness/deerflow/agents/memory/storage.py
Queue backend/packages/harness/deerflow/agents/memory/queue.py
Updater backend/packages/harness/deerflow/agents/memory/updater.py
Prompts backend/packages/harness/deerflow/agents/memory/prompt.py
Message Processing backend/packages/harness/deerflow/agents/memory/message_processing.py
Summarization Hook backend/packages/harness/deerflow/agents/memory/summarization_hook.py
Middleware backend/packages/harness/deerflow/agents/middlewares/memory_middleware.py
Memory Router backend/app/gateway/routers/memory.py
默认 Memory 文件 backend/.deer-flow/memory.json

相关推荐
陈天伟教授6 分钟前
学术写作设计的 AI 助手 - Jenni AI
人工智能
海盗12346 分钟前
AI 新闻日报 2026-10-05:三周重构 30 万行 / macOS 给智能体加权限锁 / 具身订单结构被摆上台面
人工智能·macos·重构·机器人·人工智能aigc
deepseek237 分钟前
PDF 涂黑失效拆解:谷歌数据中心 52.65 兆瓦与 7.65 亿加仑的账本,被一次复制粘贴揭开
人工智能·pdf·数据中心
Dawson Zhu8 分钟前
《Agentic Design Patterns》第 3 章导读:并行化(Parallelization)
人工智能·语言模型·架构·aigc·agi
长三角智造观察2 小时前
中小制造ERP+MES选型避坑:对接集成VS原生一体化,深度对比TCO与落地痛点
大数据·人工智能·制造
一水鉴天8 小时前
映射、哈希表与哈斯图:计算机科学的三种基线 20261003(元宝)
开发语言·人工智能
198******126348 小时前
2026 企业 AI 办公产品选型指南:从场景匹配判断工具价值
人工智能
玫瑰互动GEO9 小时前
GEO优化学习九级模型:开发者从认知层切入
人工智能·ai·ai搜索·gem·生成式引擎优化·gem优化
海绵宝宝转agent9 小时前
learn-claude-code第1-5章开源学习笔记分享
人工智能·笔记·python·学习
每天都要写算法(努力版)9 小时前
【行业前沿报告】DAgger:让智能体在自己走到的状态上学习
人工智能·学习·机器学习