Files
iven aa6a9cbd84
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
feat: 新增技能编排引擎和工作流构建器组件
refactor: 统一Hands系统常量到单个源文件
refactor: 更新Hands中文名称和描述

fix: 修复技能市场在连接状态变化时重新加载
fix: 修复身份变更提案的错误处理逻辑

docs: 更新多个功能文档的验证状态和实现位置
docs: 更新Hands系统文档

test: 添加测试文件验证工作区路径
2026-03-25 08:27:25 +08:00

7.9 KiB
Raw Permalink Blame History

Agent 记忆系统 (Agent Memory)

分类: 智能层 优先级: P0 - 决定性 成熟度: L4 - 生产 最后更新: 2026-03-24 验证状态: 代码已验证


一、功能概述

1.1 基本信息

Agent 记忆系统实现了跨会话的持久化记忆,支持 5 种记忆类型,通过关键词搜索和相关性排序提供上下文增强。后端已迁移至 Rust 实现。

属性
分类 智能层
优先级 P0
成熟度 L4
依赖 Tauri Runtime, SQLite
存储后端 Rust + SQLite
存储位置 {app_data_dir}/memory/memories.db
加密支持 AES-256-GCM (可选)

1.2 相关文件

文件 路径 用途
前端客户端 desktop/src/lib/intelligence-client.ts 统一记忆客户端
后端适配器 desktop/src/lib/intelligence-backend.ts Tauri 命令封装
Rust 命令 desktop/src-tauri/src/memory_commands.rs 记忆 Tauri 命令
图谱 Store desktop/src/store/memoryGraphStore.ts 记忆图谱状态
UI 组件 desktop/src/components/MemoryPanel.tsx 记忆列表面板
图谱组件 desktop/src/components/MemoryGraph.tsx 记忆关系图谱

二、设计初衷

2.1 问题背景

用户痛点:

  1. 每次对话都要重复说明背景
  2. Agent 无法记住用户偏好
  3. 经验教训无法积累

系统缺失能力:

  • 缺乏跨会话的记忆保持
  • 缺乏记忆的智能提取
  • 缺乏记忆的有效检索

为什么需要: 记忆是 Agent 智能的基础,没有记忆的 Agent 只能进行无状态对话,无法提供个性化服务。

2.2 设计目标

  1. 持久化: 记忆跨会话保存
  2. 分类: 5 种记忆类型 (fact, preference, lesson, context, task)
  3. 检索: 关键词 + 语义搜索
  4. 重要性: 自动评分和衰减

2.3 记忆类型设计

类型 描述 示例
fact 用户提供的客观事实 "我住在上海"
preference 用户偏好 "我喜欢简洁的回答"
lesson 经验教训 "上次因为...导致..."
context 上下文信息 "当前项目使用 React"
task 待办任务 "下周需要检查..."

2.4 设计约束

  • 存储约束: localStorage 有 5MB 限制
  • 性能约束: 检索不能阻塞对话
  • 质量约束: 记忆需要去重和清理

三、技术设计

3.1 核心接口

interface Memory {
  id: string;
  type: MemoryType;
  content: string;
  keywords: string[];
  importance: number;     // 0-10
  accessCount: number;    // 访问次数
  lastAccessed: number;   // 最后访问时间
  createdAt: number;
  source: 'user' | 'agent' | 'extracted';
}

interface MemoryManager {
  save(memory: Omit<Memory, 'id' | 'createdAt'>): Memory;
  search(query: string, options?: SearchOptions): Memory[];
  getById(id: string): Memory | null;
  delete(id: string): void;
  prune(options: PruneOptions): number;
  export(): string;
}

3.2 检索算法

function search(query: string, options: SearchOptions): Memory[] {
  const queryKeywords = extractKeywords(query);

  return memories
    .map(memory => ({
      memory,
      score: calculateScore(memory, queryKeywords, options)
    }))
    .filter(item => item.score > options.threshold)
    .sort((a, b) => b.score - a.score)
    .slice(0, options.limit)
    .map(item => item.memory);
}

function calculateScore(memory: Memory, queryKeywords: string[], options: SearchOptions): number {
  // 相关性得分 (60%)
  const relevanceScore = keywordMatch(memory.keywords, queryKeywords) * 0.6;

  // 重要性加成 (25%)
  const importanceScore = (memory.importance / 10) * 0.25;

  // 新鲜度加成 (15%)
  const recencyScore = calculateRecency(memory.lastAccessed) * 0.15;

  return relevanceScore + importanceScore + recencyScore;
}

3.3 去重机制

function isDuplicate(newMemory: Memory, existing: Memory[]): boolean {
  const similarity = calculateSimilarity(newMemory.content, existing.map(m => m.content));
  return similarity > 0.8;  // 80% 以上认为是重复
}

3.4 清理策略

interface PruneOptions {
  maxAge?: number;           // 最大保留天数
  minImportance?: number;    // 最低重要性
  maxCount?: number;         // 最大数量
  dryRun?: boolean;          // 预览模式
}

function prune(options: PruneOptions): number {
  let toDelete = memories;

  if (options.maxAge) {
    const cutoff = Date.now() - options.maxAge * 24 * 60 * 60 * 1000;
    toDelete = toDelete.filter(m => m.createdAt > cutoff);
  }

  if (options.minImportance) {
    toDelete = toDelete.filter(m => m.importance >= options.minImportance);
  }

  if (options.maxCount) {
    // 按重要性排序,保留前 N 个
    toDelete = memories
      .sort((a, b) => b.importance - a.importance)
      .slice(options.maxCount);
  }

  return toDelete.length;
}

四、预期作用

4.1 用户价值

价值类型 描述
效率提升 无需重复说明背景
体验改善 Agent 记住用户偏好
能力扩展 经验积累带来持续改进

4.2 系统价值

价值类型 描述
架构收益 解耦的记忆管理层
可维护性 单一职责,易于测试
可扩展性 支持向量搜索升级

4.3 成功指标

指标 基线 目标 当前
记忆命中率 0% 80% 75%
检索延迟 - <100ms 50ms
用户满意度 - 4.5/5 4.3/5

五、实际效果

5.1 已实现功能

  • 5 种记忆类型
  • 关键词提取
  • Rust 后端存储 (SQLite) - 通过 Tauri 命令
  • 统一客户端接口 - 自动选择 Tauri 后端或 localStorage
  • 相关性排序
  • 重要性评分
  • 访问追踪
  • 去重机制
  • 清理功能
  • 导入/导出
  • UI 面板 (MemoryPanel)
  • 记忆图谱可视化 (MemoryGraph)
  • Tauri 命令: memory_init, memory_store, memory_get, memory_search, memory_delete, memory_stats

5.2 测试覆盖

  • 单元测试: 42 项 (agent-memory.test.ts)
  • 集成测试: 完整流程测试
  • 覆盖率: ~95%

5.3 已知问题

问题 严重程度 状态 计划解决
大量记忆时检索变慢 待处理 Q2
向量搜索需要 OpenViking 可选 -

5.4 历史问题修复

问题 原因 解决方案 日期
Memory tab 为空 useLLM: false 默认禁用 LLM 提取 启用 LLM 提取,降低阈值到 2 条消息 2026-03-18
Graph UI 与系统不一致 使用深色主题 #1a1a2e 统一为浅色/暗色双主题支持 2026-03-18
agentId 不一致 MemoryPanel'zclaw-main'MemoryGraph'default' 统一 fallback 为 'zclaw-main' 2026-03-18
GatewayLLMAdapter 端点不存在 调用不存在的 /api/llm/complete 改用 /api/agents/{id}/message 2026-03-18

5.4 用户反馈

记忆系统有效减少了重复说明,希望提高自动提取的准确性。


六、演化路线

6.1 短期计划1-2 周)

  • 优化关键词提取算法
  • 添加记忆分类统计

6.2 中期计划1-2 月)

  • 集成向量搜索 (VectorMemory)
  • 记忆可视化时间线

6.3 长期愿景

  • 记忆共享(跨 Agent
  • 记忆市场(导出/导入)

七、头脑风暴笔记

7.1 待讨论问题

  1. 是否需要支持用户手动编辑记忆?
  2. 如何处理冲突的记忆?

7.2 创意想法

  • 记忆图谱:可视化记忆之间的关系
  • 记忆衰减:自动降低旧记忆的重要性
  • 记忆联想:基于语义自动关联相关记忆

7.3 风险与挑战

  • 技术风险: 记忆提取的准确性
  • 隐私风险: 敏感信息的存储
  • 缓解措施: 用户可控的记忆管理