Skip to content

长期记忆机制

本章目标:

  1. 理解记忆为什么是"数字同事"的命门,以及它与 ChatBot 的本质区别
  2. 看懂记忆的写入链路:过滤 → 去抖队列 → LLM 抽取 → 原子落盘 → 注入
  3. 弄清 a-cdm 的 per-user/per-agent 命名空间隔离与"专家无记忆"策略

TL;DR

记忆系统让 Agent 跨对话记住用户的偏好/背景/事实。MemoryMiddleware.after_agent 过滤出 user+final-AI 消息塞进 get_memory_queue();队列去抖(默认 30s)批处理,MemoryUpdater 调 LLM 抽取事实、按内容 dedupe、原子写 memory/<namespace>.json;下次交互 apply_prompt_template 注入 top facts + context 到系统提示。namespace 隔离是 a-cdm 关键定制:默认 chat 落 usermem-{sub前8}(per-user),user-/project- 前缀 agent 落对应文件,原型专家 agent 不挂记忆(防跨用户套话泄漏)。

Overview(为什么记忆是"同事 vs ChatBot"的分水岭)

openspec/specs/roadmap/spec.md 把"做成了 RAG 工具不是同事"列为三大失败路径之一,早期症状是"每次对话都是新开始,没有记忆/偏好/习惯",根因是"agent-persistent memory 未启用"。换句话说:没有记忆,Agent 永远只是个聪明的问答器,不可能成为"记得你、懂你"的同事

但记忆不能简单"把所有历史塞进上下文"——会爆 token、会噪声淹没、会跨用户泄漏。deer-flow 的解法是结构化记忆 + 异步抽取 + 命名空间隔离:LLM 把对话蒸馏成离散事实(带 category/confidence),去抖批量更新避免每轮都跑,按 namespace 隔离保证 A 的偏好不会进 B 的提示。a-cdm 在此之上加了一层关键约束:谁有记忆、记忆落哪个文件,是按"防套话泄漏"原则设计的。

Architecture:memory 包组成

文件职责Source
memory_middleware.pyafter_agent 过滤+入队deer-flow/backend/packages/harness/deerflow/agents/middlewares/memory_middleware.py:24-81
queue.py去抖批处理队列(per-thread dedup)deer-flow/backend/packages/harness/deerflow/agents/memory/queue.py
updater.pyLLM 抽取 + dedupe + 原子落盘 + CRUDdeer-flow/backend/packages/harness/deerflow/agents/memory/updater.py:326
storage.pymemory.json 读写deer-flow/backend/packages/harness/deerflow/agents/memory/storage.py
namespace.py命名空间隔离deer-flow/backend/packages/harness/deerflow/agents/memory/namespace.py
message_processing.pyfilter_messages_for_memory / detect_correction / detect_reinforcementdeer-flow/backend/packages/harness/deerflow/agents/memory/message_processing.py
scope_extraction.py上下文边界检测deer-flow/backend/packages/harness/deerflow/agents/memory/scope_extraction.py
prompt.py记忆更新 prompt 模板deer-flow/backend/packages/harness/deerflow/agents/memory/prompt.py

数据结构(config.yaml:883-891 + updater.py):memory.json 含 User Context(workContext/personalContext/topOfMind)、History(recentMonths/earlierContext/longTermBackground)、Facts(id/content/category(preference/knowledge/context/behavior/goal)/confidence/createdAt/source)。

Components:写入链路细节

MemoryMiddleware.__init__(agent_name)(memory_middleware.py:36-43):agent_name 决定记忆落哪个 namespace。after_agent(memory_middleware.py:46-81):filter_messages_for_memory 只留 user + final AI(:76),统计 human/ai 消息,有意义对话才入队(:78-81),避免空轮污染记忆。

MemoryUpdater(updater.py:326):

  • _prepare_update_prompt(:368)把当前 memory + 新对话喂 LLM;
  • _fact_content_key(:317)做内容归一化 key 用于 dedupe——updater.py:43 注释点明:category 用英文 canonical 存储,前端 i18n 翻译显示,storage 一致才能 dedupe(否则中英文同义事实重复存);
  • _save_memory_to_file(:68)原子写(temp file + rename),get_memory_data/reload_memory_data/clear_memory_data(:73-110)是 CRUD,供 Gateway memory API 用;
  • _strip_upload_mentions_from_memory(:294)剔除上传文件提及——上传是临时的,不该进长期记忆。
  • detect_correction/detect_reinforcement(message_processing.py)识别用户在纠正/强化某事实,据此调整 confidence。

config.yaml:883-891 配置:debounce_seconds: 30max_facts: 100fact_confidence_threshold: 0.7injection_enabled: truemax_injection_tokens: 2000

a-cdm 关键定制:namespace 隔离与"专家无记忆"

这是 a-cdm 在 vendored 记忆系统上最重要的改造,逻辑在 _build_middlewares(agents/lead_agent/agent.py:250-259):

agent_name是否挂 MemoryMiddleware记忆落设计意图Source
None(默认 chat)memory/usermem-{sub前8}.json透明 per-user 隔离agent.py:251-258
user-* / project-* / usermem-* 前缀memory/{agent_name}.json平台 provision 的用户/项目 agentagent.py:258
其他原型 agent(consultant-agent / ba-expert 等)不挂无记忆防跨用户跨项目套话泄漏agent.py:250-256

为什么原型专家不挂记忆:这些是"咨询专家""BA 专家"这类共享原型,如果挂全局记忆,A 用户跟"咨询专家"说的话会被抽进记忆,B 用户再问"咨询专家"时可能被注入——跨用户信息泄漏。a-cdm 对齐 OpenSpec spec.md 方案 B "专家无记忆"(agent.py:253-256 注释),用 per-user 的默认 chat agent 承载个人记忆,专家保持无状态。这与"鉴权授权"章的隔离哲学一脉相承。

Configuration

config(config.yaml → memory)默认含义Source
enabled / injection_enabledtrue总开关 / 是否注入提示deer-flow/config.yaml:884,890
debounce_seconds30入队后等待批处理时间deer-flow/config.yaml:887
max_facts100事实存储上限deer-flow/config.yaml:889
fact_confidence_threshold0.7低于此 confidence 不存deer-flow/config.yaml:889
max_injection_tokens2000注入提示 token 上限deer-flow/config.yaml:891
storage_pathmemory.json相对 backend 目录deer-flow/config.yaml:885

Common Pitfalls / 实战 Tips

  • 记忆是异步的,不是即时的:去抖 30s + 批处理,刚说的偏好不会立刻在下一句生效,要等队列 flush。
  • category 必须英文 canonical 存:前端靠 i18n map 翻译显示,storage 存中文会破坏 dedupe(updater.py:43)。
  • 给专家加记忆是危险"修复":consultant-agent/ba-expert 不挂记忆是防泄漏的有意设计(agent.py:250-256),不要因为"专家不记事"就给它挂上。
  • 上传提及不进记忆:_strip_upload_mentions_from_memory(updater.py:294)有意剔除,别指望"我上传过的文件"被长期记住。
  • 原子写防损坏:_save_memory_to_file 用 temp+rename,但并发写不同 namespace 是安全的(文件按 namespace 分),同 namespace 靠队列 per-thread dedup 串行。

References

  • deer-flow/backend/packages/harness/deerflow/agents/middlewares/memory_middleware.py:24-81 — 过滤+入队(本章主源)
  • deer-flow/backend/packages/harness/deerflow/agents/memory/updater.py:294-411 — LLM 抽取/dedupe/原子落盘
  • deer-flow/backend/packages/harness/deerflow/agents/memory/queue.py — 去抖批处理队列
  • deer-flow/backend/packages/harness/deerflow/agents/lead_agent/agent.py:250-259 — namespace 隔离/专家无记忆定制
  • deer-flow/config.yaml:883-891 — 记忆配置项
  • deer-flow/backend/packages/harness/deerflow/agents/memory/message_processing.py — 消息过滤/纠正检测
PageRelationship
Agent 中间件链机制本章 MemoryMiddleware 是该章链 #14,条件挂载逻辑同源
Lead Agent 设计与图构建本章记忆由该章 apply_prompt_template 注入
鉴权与授权双层体系本章"专家无记忆"与该章隔离哲学一脉相承
项目概览与产品愿景本章是该章"不做成 RAG 工具"失败路径的关键缓解
审计、SSE 与后台任务本章记忆 CRUD 经 Gateway memory API 暴露

公司内部参考 · 由 claude-wiki-gen 基于源码自动生成的二次分析