Skip to Content
设计Auto MemoryMemory 记忆管理系统

Memory 记忆管理系统

本文介绍 Qwen Code 中 Managed Auto-Memory(托管自动记忆)的记忆管理机制、触发时机和实现细节。


目录

  1. 概述
  2. 存储结构
  3. 记忆类型
  4. 记忆条目格式
  5. 核心生命周期
  6. Extract — 提取
  7. Dream — 整合
  8. Recall — 召回
  9. Forget — 遗忘
  10. 索引重建
  11. 遥测埋点

概述

Managed Auto-Memory 是一套在 AI 会话过程中自动积累、整合和检索用户相关知识的持久化记忆系统。它通过四个核心操作维护记忆的生命周期:

操作英文触发方式作用
提取Extract自动(每轮对话后)从对话记录中提炼新知识写入记忆文件
整合Dream自动(周期性后台任务)对记忆文件去重、合并,保持整洁
召回Recall自动(每轮对话前)检索与当前请求相关的记忆注入到系统提示
遗忘Forget手动(用户命令 /forget精确删除指定的记忆条目

存储结构

目录布局

~/.qwen/ ← 全局基础目录(默认) └── projects/ └── <sanitized-git-root>/ ← 项目标识(基于 Git 根路径) ├── meta.json ← 元数据(提取/整合时间戳、状态) ├── extract-cursor.json ← 提取游标(已处理的对话偏移量) ├── consolidation.lock ← Dream 进程互斥锁 └── memory/ ← 记忆主目录 ├── MEMORY.md ← 索引文件(自动生成,汇总所有条目) ├── user.md ← 用户偏好记忆(示例) ├── feedback.md ← 反馈规范记忆(示例) ├── project/ │ └── milestone.md ← 项目记忆(支持子目录) └── reference/ └── grafana.md ← 外部资源记忆

环境变量覆盖

  • QWEN_CODE_MEMORY_BASE_DIR:替换全局基础目录
  • QWEN_CODE_MEMORY_LOCAL=1:改用项目内路径 .qwen/memory/

关键文件说明

文件说明
meta.json记录最后一次 Extract / Dream 的时间、会话 ID、涉及的记忆类型、执行状态
extract-cursor.json记录当前会话已处理到对话历史的哪个偏移量,避免重复提取
consolidation.lockDream 运行时的文件锁,内容为持有者 PID,超过 1 小时自动失效
MEMORY.md所有主题文件的索引,每次 Extract/Dream 后重建,格式为 Markdown 列表

记忆类型

系统支持四种内置记忆类型,每种对应不同的信息维度:

类型存储内容何时写入何时读取
user用户的角色、技能背景、工作习惯了解到用户角色/偏好/知识背景时回答需要根据用户背景定制时
feedback用户对 AI 行为的指导:避免什么、继续什么用户纠正 AI 或确认某种非显而易见的做法时影响 AI 行为方式时
project项目进展、目标、决策、截止日期、Bug 追踪了解到谁在做什么、为什么、截止何时时帮助 AI 理解工作背景和动机时
reference外部系统资源指针(Dashboard、工单系统、Slack 频道等)得知某种外部资源及其用途时用户提及外部系统或相关信息时

不应该存入记忆的内容:代码模式/约定、Git 历史、调试方案、临时任务状态、已在 QWEN.md/AGENTS.md 中记录的内容。


记忆条目格式

每个主题文件使用 YAML frontmatter + Markdown body 格式:

--- name: 记忆名称 description: 一句话描述(用于判断召回相关性,要具体) type: user|feedback|project|reference --- 记忆主体内容(summary 行) Why: 背后原因(让 AI 能理解边界情况而不是盲目遵守规则) How to apply: 适用场景和使用方式

对于 feedbackproject 类型,强烈建议填写 WhyHow to apply,使记忆在边界情况下仍能正确应用。


核心生命周期


Extract — 提取

触发时机

每次 AI 完成一轮响应后,由 scheduleAutoMemoryExtract 自动触发(后台非阻塞)。

调度逻辑(extractScheduler.ts

跳过原因说明

原因含义
memory_tool本轮主 Agent 已直接写了记忆文件,跳过以避免冲突
already_running提取正在进行且无法入队
queued已有提取在运行,本次请求已入队

核心提取流程(extract.ts

提取游标(Cursor)

  • 字段:{ sessionId, processedOffset, updatedAt }
  • 每次提取后更新 processedOffset 为当前历史长度
  • 下次提取时,只处理 offset >= processedOffset 的消息
  • 跨会话时(sessionId 变化)从偏移量 0 重新开始

Patch 过滤规则

  • 摘要长度 < 12 字符 → 丢弃
  • 摘要以 ? 结尾 → 丢弃(疑问句)
  • 包含临时性关键词(today/now/currently/temporary 等)→ 丢弃
  • 相同 topic:summary 组合 → 去重

Dream — 整合

触发时机

每次 AI 完成一轮响应后,由 scheduleManagedAutoMemoryDream 自动触发(后台非阻塞)。但受多个门控条件保护,大多数情况下会被跳过。

调度门控(dreamScheduler.ts

门控参数

参数默认值说明
minHoursBetweenDreams24 小时两次 Dream 之间的最小时间间隔
minSessionsBetweenDreams5 个会话触发 Dream 所需的最小新会话数
SESSION_SCAN_INTERVAL_MS10 分钟会话文件扫描的节流间隔
DREAM_LOCK_STALE_MS1 小时lock 文件被视为过期的时间阈值

锁机制

  • lock 文件位于 <project-state-dir>/consolidation.lock
  • 内容为持有进程的 PID
  • 检查时:若 PID 进程已不存在(kill(pid, 0) 失败)或 lock 超过 1 小时 → 视为过期,自动清除

整合执行流程(dream.ts

机械去重逻辑

  1. 对每个主题文件内部:按 summary.toLowerCase() 去重,合并 why/howToApply 字段
  2. 按 summary 字母顺序重新排序
  3. 跨文件:相同 type:summary 的条目合并到最先发现的文件,删除重复文件

Recall — 召回

触发时机

每轮 AI 处理用户请求之前,由 resolveRelevantAutoMemoryPromptForQuery 自动触发,将相关记忆注入系统提示词。

召回流程(recall.ts

评分规则(启发式)

条件加分
query token 出现在文档内容中+2(每个 token)
query token 是该类型的特征关键词+1(每个 token)
文档 body 非空+1

每种类型的特征关键词

  • user:user, preference, background, role, terse
  • feedback:feedback, rule, avoid, style, summary
  • project:project, goal, incident, deadline, release
  • reference:reference, dashboard, ticket, docs, link

Prompt 构建规则

  • 最多注入 5 篇文档(MAX_RELEVANT_DOCS
  • 每篇文档 body 截断至 1200 字符(MAX_DOC_BODY_CHARS
  • 超出截断时追加提示:“NOTE: Relevant memory truncated for prompt budget.”
  • 包含文档的新鲜度信息(基于文件 mtime)

Forget — 遗忘

触发时机

由用户手动执行 /forget <query> 命令触发。

遗忘流程(forget.ts

Entry ID 设计

  • 单条目文件(常见情况):relativePath(如 feedback/no-summary.md
  • 多条目文件:relativePath:index(如 feedback/style.md:2
  • 使用稳定 ID 使模型可以精确定位条目而不影响同文件的其他条目

索引重建

MEMORY.md 是所有主题文件的导航索引,每次 Extract 或 Dream 后调用 rebuildManagedAutoMemoryIndex 重建:

- [用户偏好](user/preferences.md) — 用户是资深 Go 工程师,第一次接触 React - [反馈规范](feedback/style.md) — 保持回复简洁,不要尾部总结 - [项目里程碑](project/milestone.md) — 移动端发布切分支前的合并冻结窗口

索引限制

  • 每行最多 150 字符(超出用 截断)
  • 最多 200 行
  • 总大小不超过 25,000 字节

遥测埋点

系统内置三类遥测事件,用于监控记忆操作的性能和效果:

Extract 遥测

字段类型说明
trigger'auto'触发方式(当前仅自动)
status'completed' | 'failed'执行结果
patches_countnumber提取到的有效 patch 数量
touched_topicsstring[]被写入的记忆类型列表
duration_msnumber总耗时(毫秒)

Dream 遥测

字段类型说明
trigger'auto'触发方式
status'updated' | 'noop' | 'failed'执行结果
deduped_entriesnumber机械路径去重的条目数量
touched_topicsstring[]被修改的记忆类型列表
duration_msnumber总耗时(毫秒)

Recall 遥测

字段类型说明
query_lengthnumber查询字符串长度
docs_scannednumber扫描的文档总数
docs_selectednumber最终注入的文档数
strategy'none' | 'heuristic' | 'model'选择策略
duration_msnumber总耗时(毫秒)

相关源文件索引

文件职责
packages/core/src/memory/types.ts类型定义:AutoMemoryTypeAutoMemoryMetadataAutoMemoryExtractCursor
packages/core/src/memory/paths.ts路径计算:getAutoMemoryRootisAutoMemPath、各类文件路径 helpers
packages/core/src/memory/store.ts脚手架初始化:ensureAutoMemoryScaffold,索引/元数据读写
packages/core/src/memory/scan.ts扫描主题文件:scanAutoMemoryTopicDocuments,解析 frontmatter
packages/core/src/memory/entries.ts条目解析和渲染:parseAutoMemoryEntriesrenderAutoMemoryBody
packages/core/src/memory/extract.ts提取核心逻辑:runAutoMemoryExtract,游标管理,patch 去重
packages/core/src/memory/extractScheduler.ts提取调度器:ManagedAutoMemoryExtractRuntime,队列/运行状态机
packages/core/src/memory/extractionAgentPlanner.ts提取 Agent:runAutoMemoryExtractionByAgent
packages/core/src/memory/dream.ts整合核心逻辑:runManagedAutoMemoryDream,Agent 路径 + 机械去重
packages/core/src/memory/dreamScheduler.ts整合调度器:ManagedAutoMemoryDreamRuntime,门控检查,锁管理
packages/core/src/memory/dreamAgentPlanner.ts整合 Agent:planManagedAutoMemoryDreamByAgent
packages/core/src/memory/recall.ts召回逻辑:resolveRelevantAutoMemoryPromptForQuery,启发式+模型双路径
packages/core/src/memory/forget.ts遗忘逻辑:forgetManagedAutoMemoryEntries,候选生成+精确删除
packages/core/src/memory/indexer.ts索引重建:rebuildManagedAutoMemoryIndexbuildManagedAutoMemoryIndex
packages/core/src/memory/prompt.ts系统提示模板:记忆类型说明、格式示例、使用规范
packages/core/src/memory/governance.ts治理建议类型:AutoMemoryGovernanceSuggestionType
packages/core/src/memory/state.ts提取运行状态:isExtractRunningmarkExtractRunningclearExtractRunning
packages/core/src/memory/memoryAge.ts新鲜度描述:memoryAgememoryFreshnessText
Last updated on