第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 本章小结
本章我们学习了:
- 记忆类型
- 短期记忆:当前会话的对话历史 - 长期记忆:跨会话的用户信息
- 短期记忆实现
- InMemoryMemory:基础内存存储 - AutoContextMemory:智能压缩
- 长期记忆实现
- Mem0LongTermMemory:Mem0 服务 - ReMeLongTermMemory:ReMe 服务
- 记忆模式
- STATICCONTROL:框架自动控制 - AGENTCONTROL:智能体工具控制 - BOTH:两者兼用
- 最佳实践
- 根据场景选择记忆类型 - 监控记忆容量 - 过滤敏感信息
练习
- 实现对话持久化:使用 Session 保存和恢复对话
- 测试自动压缩:创建长对话,观察 AutoContextMemory 的行为
- 配置长期记忆:使用 Mem0 实现跨会话的用户偏好记忆
- 自定义记忆过滤:实现敏感信息过滤器
下一章 → 第7章 工具系统基础