记忆系统

📚 学习路径:本文档是架构文档的第 8 部分。建议按顺序阅读:

前言

记忆系统是 OpenClaw 的长期记忆组件,负责存储、索引和检索对话历史中的重要信息。本文档将深入解析记忆系统的设计、存储结构和检索机制。

通过阅读本文档,你将能够:

  • 理解记忆系统的概念和作用
  • 掌握记忆存储结构和格式
  • 了解混合检索机制
  • 理解记忆管理和优化策略

一、记忆系统概述

1.1 什么是记忆?

记忆(Memory)是指 Agent 的长期记忆,用于存储和检索对话历史中的重要信息,包括:

  • 对话摘要:对话的摘要和关键信息
  • 用户偏好:用户的喜好和习惯
  • 重要事实:用户提到的重要事实和信息
  • 任务记录:完成的任务和待办事项

1.2 记忆 vs 会话

记忆特点

会话特点

记忆 vs 会话

会话

记忆

短期记忆

完整对话

会话级别

实时更新

长期记忆

摘要信息

全局级别

定期更新

维度 会话 记忆
类型 短期记忆 长期记忆
内容 完整对话历史 摘要和关键信息
范围 会话级别 全局级别
更新 实时更新 定期更新
存储 JSONL 文件 SQLite + 向量数据库
检索 按时间顺序 语义搜索 + 关键词搜索

1.3 记忆的作用

实现方式

记忆的核心作用

上下文增强

个性化体验

知识积累

跨会话记忆

语义检索

用户画像

事实提取

全局索引

作用 说明 实现方式
上下文增强 为 Agent 提供相关历史信息 语义检索
个性化体验 记住用户的偏好和习惯 用户画像
知识积累 积累重要的事实和信息 事实提取
跨会话记忆 跨越不同会话的记忆 全局索引

二、记忆存储结构

2.1 物理存储路径

~/.openclaw/memory/
├── memory.db              # SQLite 数据库
├── embeddings.db          # 向量嵌入数据库
└── cache/                 # 嵌入缓存
    └── <hash>.json        # 嵌入缓存文件

说明

  • memory.db:SQLite 数据库,存储记忆元数据和关键词索引
  • embeddings.db:向量数据库,存储嵌入向量
  • cache/:嵌入缓存,避免重复计算

2.2 SQLite 数据库结构

表:memories

字段 类型 说明
id TEXT 记忆 ID
session_key TEXT 关联的会话键
content TEXT 记忆内容
type TEXT 记忆类型(fact/preference/task/summary)
importance REAL 重要性评分(0-1)
created_at TEXT 创建时间
updated_at TEXT 更新时间

表:keywords

字段 类型 说明
id TEXT 关键词 ID
memory_id TEXT 关联的记忆 ID
keyword TEXT 关键词
frequency INTEGER 词频

2.3 向量数据库结构

表:embeddings

字段 类型 说明
id TEXT 嵌入 ID
memory_id TEXT 关联的记忆 ID
vector BLOB 嵌入向量(二进制)
model TEXT 使用的嵌入模型
created_at TEXT 创建时间

2.4 记忆数据示例

{
  "id": "mem_abc123",
  "sessionKey": "agent:main:telegram:default:dm:123456789",
  "content": "用户喜欢简洁的回答,不喜欢长篇大论",
  "type": "preference",
  "importance": 0.9,
  "createdAt": "2024-01-01T12:00:00Z",
  "updatedAt": "2024-01-01T12:00:00Z"
}

三、混合检索机制

3.1 检索流程

用户查询

查询扩展

向量搜索

关键词搜索

结果融合

排序返回

3.2 向量搜索

代码位置src/memory/vector-search.ts

export async function vectorSearch(
  query: string,
  options: VectorSearchOptions,
): Promise<MemoryResult[]> {
  // 1. 生成查询嵌入
  const queryEmbedding = await generateEmbedding(query);

  // 2. 在向量数据库中搜索
  const results = await vectorDb.search({
    vector: queryEmbedding,
    limit: options.limit || 10,
    filter: options.filter,
  });

  // 3. 返回结果
  return results.map(result => ({
    memoryId: result.memoryId,
    score: result.score,
    memory: await loadMemory(result.memoryId),
  }));
}

3.3 关键词搜索

代码位置src/memory/keyword-search.ts

export async function keywordSearch(
  query: string,
  options: KeywordSearchOptions,
): Promise<MemoryResult[]> {
  // 1. 提取查询关键词
  const keywords = extractKeywords(query);

  // 2. 在 SQLite 中搜索
  const results = await sqliteDb.search({
    keywords,
    limit: options.limit || 10,
    filter: options.filter,
  });

  // 3. 返回结果
  return results.map(result => ({
    memoryId: result.memoryId,
    score: result.score,
    memory: await loadMemory(result.memoryId),
  }));
}

3.4 结果融合

代码位置src/memory/hybrid.ts

export function mergeHybridResults(
  vectorResults: MemoryResult[],
  keywordResults: MemoryResult[],
  alpha = 0.7,
): MemoryResult[] {
  // 1. 合并结果
  const merged = new Map<string, MemoryResult>();

  // 2. 处理向量搜索结果
  for (const result of vectorResults) {
    merged.set(result.memoryId, {
      ...result,
      score: result.score * alpha,
    });
  }

  // 3. 处理关键词搜索结果
  for (const result of keywordResults) {
    const existing = merged.get(result.memoryId);
    if (existing) {
      // 加权融合
      existing.score = existing.score + result.score * (1 - alpha);
    } else {
      merged.set(result.memoryId, {
        ...result,
        score: result.score * (1 - alpha),
      });
    }
  }

  // 4. 排序并返回
  return Array.from(merged.values())
    .sort((a, b) => b.score - a.score);
}

融合算法

最终得分 = 向量搜索得分 × α + 关键词搜索得分 × (1 - α)

参数说明

  • alpha:向量搜索权重(默认 0.7)
  • 1 - alpha:关键词搜索权重(默认 0.3)

四、嵌入模型

4.1 支持的模型

模型类型 提供商 特点 适用场景
openai OpenAI 高质量嵌入,API 依赖 通用场景
gemini Google 多语言支持,API 依赖 多语言场景
mistral Mistral AI 开源模型,平衡性能和质量 本地部署
ollama 本地 完全离线,隐私友好 隐私敏感场景
local 本地 基于 llama.cpp,完全离线 完全离线场景
voyage Voyage AI 长文本嵌入能力 长文本场景

4.2 嵌入生成

代码位置src/memory/embedding-provider.ts

export async function generateEmbedding(
  text: string,
  options: EmbeddingOptions,
): Promise<number[]> {
  // 1. 检查缓存
  const cacheKey = hashText(text);
  const cached = await loadFromCache(cacheKey);
  if (cached) {
    return cached;
  }

  // 2. 生成嵌入
  const provider = resolveEmbeddingProvider(options.provider);
  const embedding = await provider.embed(text);

  // 3. 保存到缓存
  await saveToCache(cacheKey, embedding);

  // 4. 返回嵌入
  return embedding;
}

4.3 嵌入缓存

代码位置src/memory/embedding-cache.ts

export class EmbeddingCache {
  private cache = new Map<string, number[]>();

  async get(key: string): Promise<number[] | undefined> {
    // 1. 检查内存缓存
    const cached = this.cache.get(key);
    if (cached) {
      return cached;
    }

    // 2. 检查磁盘缓存
    const cachePath = resolveCachePath(key);
    if (await fs.exists(cachePath)) {
      const content = await fs.readFile(cachePath, 'utf-8');
      const embedding = JSON.parse(content);
      this.cache.set(key, embedding);
      return embedding;
    }

    return undefined;
  }

  async set(key: string, embedding: number[]): Promise<void> {
    // 1. 保存到内存缓存
    this.cache.set(key, embedding);

    // 2. 保存到磁盘缓存
    const cachePath = resolveCachePath(key);
    await fs.writeFile(cachePath, JSON.stringify(embedding), 'utf-8');
  }
}

五、记忆管理

5.1 记忆创建

代码位置src/memory/memory-manager.ts

export async function createMemory(
  content: string,
  options: CreateMemoryOptions,
): Promise<Memory> {
  // 1. 生成记忆 ID
  const memoryId = generateMemoryId();

  // 2. 提取记忆类型
  const type = await classifyMemoryType(content);

  // 3. 计算重要性
  const importance = await calculateImportance(content);

  // 4. 生成嵌入
  const embedding = await generateEmbedding(content);

  // 5. 保存到数据库
  const memory: Memory = {
    id: memoryId,
    sessionKey: options.sessionKey,
    content,
    type,
    importance,
    createdAt: new Date(),
    updatedAt: new Date(),
  };

  await saveMemory(memory);
  await saveEmbedding(memoryId, embedding);

  // 6. 提取关键词
  const keywords = await extractKeywords(content);
  await saveKeywords(memoryId, keywords);

  return memory;
}

5.2 记忆更新

export async function updateMemory(
  memoryId: string,
  updates: Partial<Memory>,
): Promise<void> {
  // 1. 加载现有记忆
  const memory = await loadMemory(memoryId);

  // 2. 更新字段
  const updated = {
    ...memory,
    ...updates,
    updatedAt: new Date(),
  };

  // 3. 保存更新
  await saveMemory(updated);

  // 4. 如果内容变化,重新生成嵌入
  if (updates.content) {
    const embedding = await generateEmbedding(updates.content);
    await saveEmbedding(memoryId, embedding);

    // 重新提取关键词
    const keywords = await extractKeywords(updates.content);
    await saveKeywords(memoryId, keywords);
  }
}

5.3 记忆删除

export async function deleteMemory(memoryId: string): Promise<void> {
  // 1. 删除记忆
  await sqliteDb.delete('memories', { id: memoryId });

  // 2. 删除嵌入
  await vectorDb.delete({ memoryId });

  // 3. 删除关键词
  await sqliteDb.delete('keywords', { memoryId });
}

5.4 记忆清理

export async function cleanupMemories(options: CleanupOptions): Promise<CleanupResult> {
  const result: CleanupResult = {
    deleted: 0,
    archived: 0,
  };

  // 1. 删除低重要性记忆
  if (options.deleteLowImportance) {
    const lowImportance = await findLowImportanceMemories(options.threshold);
    for (const memory of lowImportance) {
      await deleteMemory(memory.id);
      result.deleted++;
    }
  }

  // 2. 归档旧记忆
  if (options.archiveOld) {
    const oldMemories = await findOldMemories(options.days);
    for (const memory of oldMemories) {
      await archiveMemory(memory.id);
      result.archived++;
    }
  }

  return result;
}

六、核心代码文件索引

文件路径 功能 重要性
src/memory/hybrid.ts 混合检索 ⭐⭐⭐⭐⭐
src/memory/vector-search.ts 向量搜索 ⭐⭐⭐⭐⭐
src/memory/keyword-search.ts 关键词搜索 ⭐⭐⭐⭐⭐
src/memory/embedding-provider.ts 嵌入提供者 ⭐⭐⭐⭐
src/memory/embedding-cache.ts 嵌入缓存 ⭐⭐⭐⭐
src/memory/memory-manager.ts 记忆管理器 ⭐⭐⭐⭐⭐
src/memory/memory-store.ts 记忆存储 ⭐⭐⭐⭐

七、下一步

恭喜你完成了记忆系统的学习!接下来建议:


通过理解记忆系统的工作原理,你已经掌握了 OpenClaw 的长期记忆管理!

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐