第6章 记忆系统(Memory)

第6章 记忆系统(Memory)

本章目标:理解短期记忆和长期记忆的区别,掌握各种记忆实现的使用方法


6.1 记忆系统概述

6.1.1 为什么需要记忆

没有记忆的智能体就像"金鱼"——每次对话都是全新的开始:

无记忆:                          有记忆:
用户: 我叫张三                    用户: 我叫张三
助手: 你好张三!                  助手: 你好张三!
用户: 我叫什么?                  用户: 我叫什么?
助手: 抱歉,你没告诉我...         助手: 你叫张三呀!

6.1.2 记忆的类型

AgentScope 提供两种类型的记忆:

┌─────────────────────────────────────────────────────────────┐
│                      记忆系统架构                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                   短期记忆 (Memory)                   │   │
│  │                                                      │   │
│  │  - 存储当前会话的对话历史                             │   │
│  │  - 每次调用 LLM 时作为上下文发送                      │   │
│  │  - 会话结束后可选择持久化                             │   │
│  │                                                      │   │
│  │  实现:InMemoryMemory, AutoContextMemory             │   │
│  └─────────────────────────────────────────────────────┘   │
│                            │                                │
│                            │ 可选:持久化                   │
│                            ▼                                │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                  长期记忆 (LongTermMemory)            │   │
│  │                                                      │   │
│  │  - 存储跨会话的用户偏好和知识                         │   │
│  │  - 通过语义搜索召回相关记忆                           │   │
│  │  - 独立于对话历史                                    │   │
│  │                                                      │   │
│  │  实现:Mem0LongTermMemory, ReMeLongTermMemory        │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

6.2 短期记忆

6.2.1 InMemoryMemory - 基础实现

最简单的记忆实现,在内存中存储对话历史:

import io.agentscope.core.memory.InMemoryMemory;

// ========================================
// 【创建内存记忆】
// ========================================
InMemoryMemory memory = new InMemoryMemory();

// 在智能体中使用
ReActAgent agent = ReActAgent.builder()
        .name("Assistant")
        .model(model)
        .memory(memory)
        .build();

// 对话
agent.call(Msg.builder().textContent("我叫张三").build()).block();
agent.call(Msg.builder().textContent("我喜欢吃火锅").build()).block();

// ========================================
// 【查看对话历史】
// ========================================
List<Msg> history = memory.getMessages();
for (Msg msg : history) {
    System.out.println(msg.getRole() + ": " + msg.getTextContent());
}
// 输出:
// SYSTEM: 你是一个有帮助的助手...
// USER: 我叫张三
// ASSISTANT: 你好张三!很高兴认识你...
// USER: 我喜欢吃火锅
// ASSISTANT: 火锅是很棒的选择!...

// ========================================
// 【手动操作记忆】
// ========================================

// 添加消息
memory.addMessage(Msg.builder()
        .role(MsgRole.SYSTEM)
        .textContent("额外的系统指令...")
        .build());

// 清空记忆
memory.clear();

6.2.2 AutoContextMemory - 智能压缩

当对话历史过长时,自动压缩上下文:

import io.agentscope.extensions.autocontext.AutoContextMemory;
import io.agentscope.extensions.autocontext.AutoContextConfig;

// ========================================
// 【配置自动压缩】
// ========================================
AutoContextConfig config = AutoContextConfig.builder()
        .msgThreshold(30)
        // 消息数量阈值
        // - 超过此数量时触发压缩
        
        .lastKeep(10)
        // 保留最近 N 条消息
        // - 压缩后保留最近的对话
        // - 确保上下文连贯性
        
        .tokenRatio(0.3)
        // Token 比例阈值
        // - 当 Token 超过模型上下文的 30% 时触发压缩
        
        .build();

// 创建自动压缩记忆
AutoContextMemory memory = new AutoContextMemory(config, model);

// ========================================
// 【使用示例】
// ========================================
ReActAgent agent = ReActAgent.builder()
        .name("Assistant")
        .model(model)
        .memory(memory)
        .build();

// 进行长对话...
for (int i = 0; i < 50; i++) {
    agent.call(Msg.builder()
            .textContent("第 " + i + " 轮对话内容...")
            .build()).block();
}

// 记忆会自动压缩,保持在合理大小
// 压缩时会:
// 1. 用 LLM 总结旧对话的关键信息
// 2. 保留最近的消息
// 3. 释放 Token 空间

6.2.3 短期记忆持久化

结合 Session 系统,可以持久化短期记忆:

import io.agentscope.core.session.JsonSession;
import io.agentscope.core.session.Session;

// ========================================
// 【持久化短期记忆】
// ========================================

// 创建 Session
Path sessionPath = Path.of("./sessions");
Session session = new JsonSession(sessionPath);

// 创建智能体
InMemoryMemory memory = new InMemoryMemory();
ReActAgent agent = ReActAgent.builder()
        .name("Assistant")
        .model(model)
        .memory(memory)
        .build();

String sessionId = "user-001";

// 加载已有会话
if (agent.loadIfExists(session, sessionId)) {
    System.out.println("继续上次对话...");
} else {
    System.out.println("开始新对话...");
}

// 对话
agent.call(Msg.builder().textContent("...").build()).block();

// 保存会话
agent.saveTo(session, sessionId);
// 下次启动时可以恢复对话历史

6.3 长期记忆

6.3.1 长期记忆的作用

长期记忆存储跨会话的信息,实现"记住用户":

会话 1(1月1日):
用户: 我对花生过敏
助手: 好的,我记住了!以后推荐食物时会避开花生。

... 一个月后 ...

会话 N(2月1日):
用户: 给我推荐一款零食
助手: 这款巧克力饼干很不错!
      (注:它不含花生,我记得你对花生过敏)
      ↑ 从长期记忆中召回

6.3.2 Mem0LongTermMemory

基于 Mem0 服务的长期记忆实现:

import io.agentscope.extensions.mem0.Mem0LongTermMemory;

// ========================================
// 【配置 Mem0 长期记忆】
// ========================================
Mem0LongTermMemory longTermMemory = Mem0LongTermMemory.builder()
        .agentName("CustomerService")
        // 智能体名称
        // - 用于区分不同智能体的记忆
        
        .userId("user-001")
        // 用户 ID
        // - 每个用户有独立的记忆空间
        
        .apiBaseUrl("https://api.mem0.ai")
        // Mem0 API 地址
        // - 可以使用 Mem0 云服务
        // - 也可以自建服务
        
        .apiKey(System.getenv("MEM0_API_KEY"))
        // API 密钥
        
        .build();

// ========================================
// 【在智能体中使用】
// ========================================
ReActAgent agent = ReActAgent.builder()
        .name("CustomerService")
        .model(model)
        .memory(new InMemoryMemory())
        .longTermMemory(longTermMemory)
        .longTermMemoryMode(LongTermMemoryMode.STATIC_CONTROL)
        // 记忆模式:
        // - STATIC_CONTROL: 框架自动在推理前召回、回复后记录
        // - AGENT_CONTROL: 通过工具让 Agent 自主决定
        // - BOTH: 两者兼用
        .build();

6.3.3 LongTermMemoryMode

// ========================================
// 【STATIC_CONTROL 模式】
// 框架自动控制,对智能体透明
// ========================================
// 工作流程:
// 1. 用户发送消息
// 2. 框架从长期记忆召回相关内容
// 3. 召回内容注入到系统提示
// 4. 智能体生成回复
// 5. 框架将对话存入长期记忆

ReActAgent staticAgent = ReActAgent.builder()
        .longTermMemory(longTermMemory)
        .longTermMemoryMode(LongTermMemoryMode.STATIC_CONTROL)
        .build();

// ========================================
// 【AGENT_CONTROL 模式】
// 智能体通过工具自主控制
// ========================================
// 智能体获得两个工具:
// - recall_memories: 主动召回记忆
// - record_memory: 主动存储记忆

ReActAgent agentControlled = ReActAgent.builder()
        .longTermMemory(longTermMemory)
        .longTermMemoryMode(LongTermMemoryMode.AGENT_CONTROL)
        .build();

// ========================================
// 【BOTH 模式】
// 两种机制同时生效
// ========================================
ReActAgent bothAgent = ReActAgent.builder()
        .longTermMemory(longTermMemory)
        .longTermMemoryMode(LongTermMemoryMode.BOTH)
        .build();

6.3.4 ReMeLongTermMemory

ReMe 是另一种长期记忆实现:

import io.agentscope.extensions.reme.ReMeLongTermMemory;

ReMeLongTermMemory remeMemory = ReMeLongTermMemory.builder()
        .agentName("Assistant")
        .userId("user-001")
        // ReMe 特有配置...
        .build();

6.4 记忆的最佳实践

6.4.1 选择合适的记忆类型

// ========================================
// 【场景一】简单聊天机器人
// 只需要单会话记忆
// ========================================
ReActAgent simpleChatBot = ReActAgent.builder()
        .name("ChatBot")
        .model(model)
        .memory(new InMemoryMemory())  // 基础记忆足够
        .build();

// ========================================
// 【场景二】客服助手
// 需要长对话 + 用户偏好
// ========================================
ReActAgent customerService = ReActAgent.builder()
        .name("CustomerService")
        .model(model)
        .memory(new AutoContextMemory(config, model))  // 自动压缩长对话
        .longTermMemory(mem0Memory)  // 记住用户偏好
        .longTermMemoryMode(LongTermMemoryMode.STATIC_CONTROL)
        .build();

// ========================================
// 【场景三】私人助理
// 需要完整的记忆能力
// ========================================
ReActAgent personalAssistant = ReActAgent.builder()
        .name("PersonalAssistant")
        .model(model)
        .memory(new AutoContextMemory(config, model))
        .longTermMemory(mem0Memory)
        .longTermMemoryMode(LongTermMemoryMode.BOTH)  // 完整控制
        .build();

6.4.2 记忆容量管理

// ========================================
// 【监控记忆使用】
// ========================================

public class MemoryMonitor {
    
    public static void checkMemoryUsage(Memory memory, ChatModel model) {
        List<Msg> messages = memory.getMessages();
        
        // 统计消息数量
        System.out.println("消息数量: " + messages.size());
        
        // 估算 Token 数量(简单估算)
        int estimatedTokens = messages.stream()
                .mapToInt(m -> m.getTextContent().length() / 2)
                .sum();
        System.out.println("估算 Token: " + estimatedTokens);
        
        // 警告阈值
        if (estimatedTokens > 10000) {
            System.out.println("警告: Token 数量较高,建议使用 AutoContextMemory");
        }
    }
}

6.4.3 敏感信息处理

// ========================================
// 【过滤敏感信息】
// 不要将敏感信息存入长期记忆
// ========================================

public class SafeMemoryFilter {
    
    private static final List<String> SENSITIVE_PATTERNS = List.of(
            "\\d{16,19}",           // 信用卡号
            "\\d{11}",              // 手机号
            "[A-Z0-9]{10,}"         // API Key 模式
    );
    
    public static String filterSensitive(String content) {
        String filtered = content;
        for (String pattern : SENSITIVE_PATTERNS) {
            filtered = filtered.replaceAll(pattern, "[已过滤]");
        }
        return filtered;
    }
}

6.5 本章小结

本章我们学习了:

  1. 记忆类型

- 短期记忆:当前会话的对话历史 - 长期记忆:跨会话的用户信息

  1. 短期记忆实现

- InMemoryMemory:基础内存存储 - AutoContextMemory:智能压缩

  1. 长期记忆实现

- Mem0LongTermMemory:Mem0 服务 - ReMeLongTermMemory:ReMe 服务

  1. 记忆模式

- STATICCONTROL:框架自动控制 - AGENTCONTROL:智能体工具控制 - BOTH:两者兼用

  1. 最佳实践

- 根据场景选择记忆类型 - 监控记忆容量 - 过滤敏感信息


练习

  1. 实现对话持久化:使用 Session 保存和恢复对话
  2. 测试自动压缩:创建长对话,观察 AutoContextMemory 的行为
  3. 配置长期记忆:使用 Mem0 实现跨会话的用户偏好记忆
  4. 自定义记忆过滤:实现敏感信息过滤器

下一章 → 第7章 工具系统基础

← 返回目录