自我进化:AI 记忆的自动整理与巩固

自我进化:AI 记忆的自动整理与巩固

前三期聊了记忆系统的"为什么"、"存什么"、"怎么存"和"怎么找"。这一期聊一个更有趣的问题:记忆系统怎么自我进化?

人会遗忘,但人的大脑会在睡眠时自动整理记忆——把短期记忆巩固成长期记忆,把零散信息整合成知识网络。Claude Code 的记忆系统也有类似的能力,叫做 Dream

一、Dream:睡眠时间的记忆巩固

Dream 是记忆系统的自动整理机制。它的灵感来自人类睡眠时的记忆巩固过程:

白天积累零散的记忆碎片,晚上大脑自动整理——合并重复、强化关联、淘汰无用信息。第二天醒来,记忆更清晰。

1.1 触发条件

Dream 不是随时运行的,它有两个门控条件:

时间门控

  • 两次 Dream 之间最少间隔 24 小时——一天整理一次就够了,太频繁浪费资源
  • 最长间隔 168 小时(7 天)——超过一周没整理,记忆会膨胀失控

会话门控

  • 至少 5 个会话后才触发 Dream——一个会话产生的信息太少,不值得整理
  • 10 分钟扫描一次——检查是否满足触发条件

两个条件必须同时满足。时间到了但会话不够,不触发。会话够了但时间没到,也不触发。

这个设计很聪明。太频繁整理浪费计算,太少整理记忆质量下降。一天一次、至少五个会话,是经验上的最优平衡点。

锁机制

// 锁机制防止并发 Dream
const lock = await this.lockManager.acquire({
  key: 'dream-consolidation',
  ttl: 3600000,  // 锁过期时间 1 小时
  retry: {
    attempts: 3,
    backoff: 1000  // 1 秒后重试
  }
})

if (!lock) {
  // 另一个 Dream 进程正在运行,跳过
  return
}

文件锁防止多个 Dream 进程同时运行。锁持有者过期时间 1 小时——如果 Dream 进程崩溃了,锁会自动释放,不会永久阻塞。

1.2 Dream 流程

触发 Dream
    │
    ▼
获取整理锁
    │
    ▼
读取所有 CCB 记忆文件
    │
    ▼
合并重复记忆(基于内容哈希)
    │
    ▼
去重(保留最新版本)
    │
    ▼
增量整理(只处理变化的部分)
    │
    ▼
更新 MEMORY.md 索引
    │
    ▼
更新元数据文件
    │
    ▼
释放锁,记录整理时间

整个流程分六步:获取锁 → 读取记忆 → 合并重复 → 去重 → 增量整理 → 更新索引。

每一步都是幂等的——如果中途失败,下次 Dream 会从头重来,不会产生不一致。

1.3 增量整理

不是每次 Dream 都全量重写。增量整理的核心逻辑:

async processIncremental(memories) {
  const lastConsolidatedAt = await this.getLastConsolidatedAt()

  let skipped = 0, updated = 0, added = 0

  for (const memory of memories) {
    // 检查这条记忆上次整理后有没有变化
    const hasChanged = await this.hasMemoryChanged(memory, lastConsolidatedAt)

    if (!hasChanged) {
      skipped++  // 没变化,跳过
      continue
    }

    if (existsSync(metadataPath)) {
      updated++  // 已有但变化了,更新
    } else {
      added++    // 新增的,创建
    }

    await this.processMemory(memory)
  }

  console.log(`Dream 完成:${skipped} 跳过,${updated} 更新,${added} 新增`)
}

增量整理的效率很高。一个项目可能有几百条记忆,但每次 Dream 可能只有几条新记忆或变化的记忆。跳过未变化的部分,把计算集中在真正需要整理的记忆上。

这跟 git commit 的思路一样——只提交变更,不重复提交没改的文件。

二、配置体系

记忆系统的所有行为都可以通过配置文件控制。

2.1 核心配置

{
  "cache": {
    "enabled": true,
    "ttlHours": 24,
    "maxSize": 10000,
    "semanticThreshold": 0.9
  },
  "obsidian": {
    "mode": "auto",
    "cli": { "enabled": true, "timeout": 5000 },
    "direct": { "atomicWrites": true },
    "fallback": { "enabled": true, "maxRetries": 2 }
  },
  "autoDream": {
    "enabled": true,
    "timeGate": {
      "minHoursBetweenDream": 24,
      "maxHoursBetweenDream": 168
    },
    "sessionGate": {
      "minSessionsForDream": 5,
      "scanIntervalMs": 600000
    }
  },
  "retrieval": {
    "defaultStrategy": "both-priority-ccb",
    "intentAnalysis": {
      "enableLLM": true,
      "enableRules": true,
      "llmConfidenceThreshold": 0.7,
      "ruleConfidenceThreshold": 0.5
    },
    "progressiveSearch": {
      "enabled": true,
      "stages": [
        { "name": "ccb-fast", "limit": 5, "timeout": 100 },
        { "name": "magma-extend", "limit": 10, "timeout": 300 },
        { "name": "full-fusion", "enableFusion": true, "timeout": 800 }
      ]
    }
  },
  "fusion": {
    "maxTokens": 4000,
    "enableSemanticDeduplication": true,
    "semanticSimilarityThreshold": 0.85,
    "tokenBudget": { "dynamic": true, "maxTokensPerMemory": 500 }
  }
}

配置分为五个部分:

  • cache:意图分析结果的缓存配置。TTL 24 小时,最多缓存 10000 条
  • obsidian:Obsidian 集成配置。支持 CLI 和 direct 两种模式,带重试和降级
  • autoDream:Dream 自动整理的触发条件。时间门控和会话门控的参数都在这里
  • retrieval:检索配置。意图分析、渐进式检索的策略参数
  • fusion:融合配置。Token 预算、去重阈值、排序参数

2.2 双 LLM 配置

记忆系统使用了两个不同的 LLM,各自承担不同职责:

模型 用途 特点
硅基流动 (Qwen3-8B) FusionVerifier 无并发限制,响应快(3-5s)
智谱 AI (glm-4.7-flash) 意图分析 并发=1,需限流保护(2s 间隔)

为什么用两个模型?因为意图分析和融合验证是两个不同的任务,对模型的要求不同:

  • 意图分析需要准确理解语义,用更强的模型(智谱 AI)
  • FusionVerifier需要快速验证结果,用更快的模型(硅基流动)

而且两个模型有各自的限制——智谱 AI 只允许并发 1,硅基流动没有并发限制。根据每个任务的调用频率选择合适的模型,是成本优化的典型做法。

2.3 环境差异配置

{
  "environments": {
    "development": {
      "autoDream.timeGate.minHoursBetweenDream": 1,
      "retrieval.intentAnalysis.cacheEnabled": false,
      "retrieval.progressiveSearch.enabled": false
    },
    "production": {
      "autoDream.timeGate.minHoursBetweenDream": 48,
      "retrieval.intentAnalysis.cacheEnabled": true,
      "retrieval.progressiveSearch.enabled": true,
      "metrics.enabled": true
    }
  }
}

开发环境和生产环境的配置差异很大:

  • Dream 频率:开发环境 1 小时一次(方便调试),生产环境 48 小时一次(节省成本)
  • 缓存:开发环境禁用缓存(方便看到最新结果),生产环境启用缓存
  • 渐进式检索:开发环境禁用(直接走最慢但最全面的方式,方便调试),生产环境启用

三、Shared Memory System:代码实战

shared-memory-system 是从 Claude Code 主项目中独立出来的记忆管理库,提供 CCB 和 MAGMA 的互操作功能。

3.1 项目结构

shared-memory-system/
├── src/
│   ├── CCBReader.ts           # CCB 记忆读取器
│   ├── MagmaAdapter.ts        # MAGMA 记忆适配器
│   ├── crossSystem.ts         # 跨系统互操作
│   ├── index.ts               # 主导出文件
│   │
│   ├── agents/                # Agent 系统
│   │   ├── ExtractorAgent.ts  # 提取者 Agent
│   │   └── RefinerAgent.ts    # 提炼者 Agent
│   │
│   ├── autoDream/             # 自动记忆整理
│   │   ├── CCBConsolidator.ts
│   │   ├── MAGMAConsolidator.ts
│   │   ├── CCBToMAGMARefiner.ts
│   │   └── ConsolidationLock.ts
│   │
│   ├── consistency/           # 一致性检查
│   │   ├── ConsistencyChecker.ts
│   │   └── ConflictArbiter.ts
│   │
│   ├── routing/               # 智能路由
│   │   ├── IntelligentRouter.ts
│   │   └── IntentClassifier.ts
│   │
│   ├── retrieval/             # 检索和融合
│   │   ├── CrossSystemRetriever.ts
│   │   └── MemoryFusion.ts
│   │
│   ├── versioning/            # 版本控制
│   │   ├── MemoryVersioning.ts
│   │   └── ExpirationHandler.ts
│   │
│   └── utils/                 # 工具函数
│       ├── debug.ts
│       ├── errors.ts
│       ├── frontmatterParser.ts
│       └── readFileInRange.ts

项目结构很清晰,按功能模块划分:

  • agents/:Agent 系统,负责记忆的提取和提炼
  • autoDream/:Dream 自动整理,包括 CCB 和 MAGMA 各自的整理器
  • consistency/:一致性检查,确保 CCB 和 MAGMA 的记忆不冲突
  • routing/:路由系统,意图分类和决策
  • retrieval/:检索和融合
  • versioning/:版本控制和过期处理

3.2 核心 API

import { CCBReader, MagmaAdapter, CrossSystemInterop } from 'shared-memory-system'

// 1. 读取 CCB 记忆
const ccbReader = new CCBReader('path/to/ccb/memory')
const ccbDir = await ccbReader.readMemoryDirectory()
console.log(`找到 ${ccbDir.memoryFiles.length} 个记忆文件`)

// 2. 读取 MAGMA 记忆
const magmaAdapter = new MagmaAdapter({
  lancedbPath: 'path/to/lancedb',
  obsidianPath: 'path/to/obsidian'
})
await magmaAdapter.initialize()

// 3. 跨系统检索
const interop = new CrossSystemInterop('path/to/ccb/memory', magmaConfig)
await interop.initialize()
const results = await interop.retrieve({
  query: '用户偏好设置',
  limit: 10,
  searchCCB: true,
  searchMAGMA: true
})

三层 API 分别对应三个层次:

  1. CCBReader——直接读取 CCB 记忆,适合精确查询
  2. MagmaAdapter——直接操作 MAGMA 向量数据库,适合语义搜索
  3. CrossSystemInterop——跨系统互操作,封装了意图分析、路由、检索、融合的全流程

3.3 一致性检查

CCB 和 MAGMA 两个引擎可能存储同一份记忆的不同版本。一致性检查器负责发现并解决冲突:

// 一致性检查
async checkConsistency(): Promise<ConsistencyReport> {
  const ccbMemories = await this.ccbReader.readAll()
  const magmaMemories = await this.magmaAdapter.readAll()

  const conflicts: Conflict[] = []

  for (const ccbMemory of ccbMemories) {
    // 在 MAGMA 中查找语义相似的记忆
    const similar = await this.magmaAdapter.findSimilar(ccbMemory)

    for (const magmaMemory of similar) {
      if (this.isConflicting(ccbMemory, magmaMemory)) {
        conflicts.push({
          ccb: ccbMemory,
          magma: magmaMemory,
          type: 'content-mismatch',
          severity: 'high'
        })
      }
    }
  }

  return { conflicts, resolved: [] }
}

// 冲突裁决
async resolveConflict(conflict: Conflict) {
  // 策略 1:CCB 优先(结构化记忆更精确)
  if (conflict.ccb.type === 'user' || conflict.ccb.type === 'feedback') {
    await this.magmaAdapter.update(conflict.ccb)
    return 'ccb-wins'
  }

  // 策略 2:MAGMA 优先(非结构化知识更全面)
  if (conflict.magma.layer === 'L5') {
    await this.ccbReader.update(conflict.magma)
    return 'magma-wins'
  }

  // 策略 3:保留两者,标记为待人工处理
  return 'manual-review'
}

冲突裁决有三种策略:

  • CCB 优先:用户记忆和反馈记忆以 CCB 为准(更精确、更可解释)
  • MAGMA 优先:参考记忆以 MAGMA 为准(更全面、更新)
  • 人工处理:无法自动裁决的冲突,标记为待人工处理

3.4 版本控制

每条记忆都有版本信息:

interface MemoryVersion {
  id: string
  version: number           // 版本号,每次更新 +1
  createdAt: Date
  updatedAt: Date
  previousVersions: string[]  // 历史版本的 ID 列表
  changeLog: string          // 本次变更的说明
}

// 版本回滚
async rollback(memoryId: string, targetVersion: number) {
  const history = await this.versionStore.getHistory(memoryId)
  const target = history.find(v => v.version === targetVersion)

  if (!target) {
    throw new Error(`版本 ${targetVersion} 不存在`)
  }

  await this.ccbReader.update(target.content)
  await this.magmaAdapter.update(target.content)
}

版本控制保证记忆的可追溯性。每次更新都记录版本号和变更说明,支持回滚到任意历史版本。

3.5 过期处理

不是所有记忆都永远有效。项目结束了、用户换了角色、工具更新了——过时的记忆比没有记忆更危险:

// 过期检测
async checkExpiration() {
  const allMemories = await this.readAll()

  for (const memory of allMemories) {
    // 基于类型的过期规则
    switch (memory.type) {
      case 'project':
        // 项目记忆:检查项目是否仍然活跃
        if (await this.isProjectInactive(memory)) {
          await this.archive(memory, 'project-inactive')
        }
        break

      case 'reference':
        // 参考记忆:检查外部资源是否仍然可达
        if (!await this.isResourceReachable(memory)) {
          await this.markBroken(memory)
        }
        break

      case 'feedback':
        // 反馈记忆:不过期,但降低权重
        await this.decayPriority(memory, factor = 0.95)
        break
    }
  }
}

过期策略因类型而异:

  • 项目记忆:检查项目是否仍然活跃,不活跃就归档
  • 参考记忆:检查外部资源是否仍然可达,不可达就标记为断链
  • 反馈记忆:不过期(用户说过的话永远有价值),但随时间降低权重

四、Agent 系统

记忆系统内部有两个 Agent 负责记忆的提取和提炼:

4.1 ExtractorAgent(提取者)

负责从对话中提取值得记住的信息:

class ExtractorAgent {
  async extract(conversation: Conversation): Promise<Memory[]> {
    const prompt = `
      分析以下对话,提取值得记住的信息。

      规则:
      1. 只提取不可从代码/文件推导的信息
      2. 按四种类型分类:user / feedback / project / reference
      3. 如果对话中没有值得记住的信息,返回空数组

      对话:${conversation.text}
    `

    const result = await this.llm.chat(prompt)
    return result.memories
  }
}

提取规则很严格:只提取不可推导的信息。对话里说"这个项目的架构是微服务"——这是可从代码推导的,不提取。对话里说"集成测试不要用 mock"——这是不可推导的,提取为 feedback。

4.2 RefinerAgent(提炼者)

负责把提取的原始记忆精炼成高质量的记忆条目:

class RefinerAgent {
  async refine(rawMemory: RawMemory): Promise<Memory> {
    const prompt = `
      将以下原始信息精炼成高质量的记忆条目。

      要求:
      1. name:简短描述(不超过 50 字)
      2. description:一句话总结
      3. content:包含 What、Why、How to apply 三部分
      4. 相对日期转为绝对日期
      5. 去除冗余和口语化表述

      原始信息:${rawMemory.text}
    `

    return await this.llm.chat(prompt)
  }
}

提炼的关键动作包括:

  • 结构化——把口语化的对话整理成 What / Why / How to apply 的标准格式
  • 绝对日期——"下周"→"2026-06-12"
  • 去冗余——去除重复和无关信息
  • 精炼——保留核心信息,去掉废话

五、设计哲学

回顾整个记忆进化系统,有几个设计哲学值得总结:

1. 自动而非手动。 Dream 自动整理,不需要用户手动触发。好的基础设施是透明的用户不应该需要知道它的存在。

2. 增量而非全量。 增量整理、增量更新、增量检查。每次只处理变化的部分,把计算资源集中在真正需要的地方。

3. 分层而非一锅。 五层记忆架构、三层渐进检索、两层去重。每一层解决一个特定问题,层与层之间职责清晰。

4. 约束驱动质量。 200 行索引上限、Token 预算、锁机制。好的系统不是靠用户自觉,而是靠工程约束保证质量。

5. 可观测可回滚。 版本控制、变更日志、冲突仲裁。记忆系统必须有可追溯性——要知道一条记忆从哪来、怎么变的、为什么被删除。


这期完成了记忆系统四篇系列的最后一篇。回顾一下整个系列:

  1. AI 记忆系统:让 AI 拥有长期记忆——为什么需要记忆、四种记忆类型、双引擎架构概览
  2. 双引擎架构:文件 vs 向量数据库——CCB 和 MAGMA 的内部实现、知识图谱、跨系统协同
  3. 意图驱动:AI 如何理解你要找什么——意图分类、路由决策、渐进式检索、去重和排序
  4. 自我进化:AI 记忆的自动整理与巩固——Dream 机制、配置体系、代码实战

记忆系统是 AI 助手的"大脑"。没有记忆系统的 AI,再聪明也只是金鱼的伙伴。有了记忆系统,AI 才能真正成为长期协作的伙伴。

系列