摘要

本文深入探讨Deep Agents框架中的Memory(记忆)系统,该系统借鉴人类认知心理学模型,将记忆分为短期记忆和长期记忆两种类型。文章详细介绍了两种记忆的概念、代码实现、使用场景,并通过对比分析帮助读者理解各自的优缺点。最后,提供了设计抉择指南、混合记忆架构示例以及最佳实践建议,为开发者在实际项目中构建高效的Memory系统提供全面指导。

目录

Deep Agents中Memory的介绍和作用

在人工智能代理(Agents)系统中,Memory(记忆)是一个核心组件,它决定了代理如何存储、检索和利用历史交互信息。Deep Agents框架中的Memory系统借鉴了人类认知心理学中的记忆模型,将记忆分为短期记忆和长期记忆两种类型,每种类型都有其独特的作用和适用场景。
在这里插入图片描述

Memory在Deep Agents中的主要作用包括:

  1. 状态保持:在对话或多轮交互中保持上下文一致性
  2. 经验积累:存储历史交互经验以供后续决策参考
  3. 个性化适应:根据用户历史行为调整代理行为
  4. 知识扩展:通过长期记忆构建领域知识库

一个设计良好的Memory系统能够显著提升代理的智能水平,使其能够进行更复杂的推理和更自然的交互。

短期记忆

介绍

短期记忆(Short-term Memory)在Deep Agents中负责处理当前会话或近期交互的上下文信息。它类似于人类的工作记忆,容量有限但访问速度快,主要用于维持对话的连贯性和处理即时任务。

短期记忆的特点:

  • 容量有限:通常只保留最近N轮对话或特定时间窗口内的信息
  • 访问快速:数据存储在内存中,检索延迟低
  • 会话相关:与当前用户会话紧密绑定
  • 临时性:会话结束后通常会被清除或归档

在Deep Agents框架中,短期记忆通常实现为基于窗口的缓冲区或最近最少使用(LRU)缓存。

代码实现

以下是Deep Agents中短期记忆的典型实现示例:

from typing import List, Dict, Any
from datetime import datetime
from collections import deque

class ShortTermMemory:
    """短期记忆实现类"""
    
    def __init__(self, max_size: int = 10):
        """
        初始化短期记忆
        
        Args:
            max_size: 最大记忆容量(对话轮数)
        """
        self.memory_buffer = deque(maxlen=max_size)
        self.current_session_id = None
        self.session_start_time = None
        
    def start_new_session(self, session_id: str):
        """开始新会话"""
        self.current_session_id = session_id
        self.session_start_time = datetime.now()
        self.memory_buffer.clear()
        
    def add_interaction(self, user_input: str, agent_response: str, metadata: Dict[str, Any] = None):
        """添加一次交互记录"""
        interaction = {
            "timestamp": datetime.now().isoformat(),
            "user_input": user_input,
            "agent_response": agent_response,
            "metadata": metadata or {}
        }
        self.memory_buffer.append(interaction)
        
    def get_recent_interactions(self, n: int = None) -> List[Dict[str, Any]]:
        """获取最近的交互记录"""
        if n is None:
            return list(self.memory_buffer)
        return list(self.memory_buffer)[-n:] if n <= len(self.memory_buffer) else list(self.memory_buffer)
        
    def get_context(self) -> str:
        """获取当前会话的上下文摘要"""
        if not self.memory_buffer:
            return "无历史对话"
            
        context_parts = []
        for i, interaction in enumerate(self.memory_buffer, 1):
            context_parts.append(f"[第{i}轮]")
            context_parts.append(f"用户: {interaction['user_input']}")
            context_parts.append(f"代理: {interaction['agent_response']}")
            
        return "\n".join(context_parts)
        
    def clear(self):
        """清空短期记忆"""
        self.memory_buffer.clear()

使用场景

短期记忆适用于以下场景:

  1. 对话式代理:在聊天机器人中维持对话上下文,理解指代和省略
  2. 多步任务执行:在复杂任务分解中保持步骤间的连贯性
  3. 实时决策:需要快速访问最近状态的应用
  4. 会话管理:跟踪当前会话的状态和进度

例如,在客服机器人中,短期记忆可以记住用户最近提到的订单号、问题描述等信息,避免用户重复说明。

长期记忆

介绍

长期记忆(Long-term Memory)负责存储跨越多个会话的持久化信息,包括用户偏好、历史交互模式、学习到的知识等。它类似于人类的长期记忆,容量大但访问速度相对较慢,需要设计有效的检索机制。

长期记忆的特点:

  • 持久化存储:数据保存在数据库或文件系统中
  • 容量大:可以存储海量历史数据
  • 检索复杂:需要索引和搜索机制
  • 结构化组织:通常按主题、时间或相关性组织

在Deep Agents中,长期记忆通常结合向量数据库、关系数据库或图数据库实现,支持相似性搜索和复杂查询。

代码实现

以下是Deep Agents中长期记忆的典型实现示例:

import json
import hashlib
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta
import sqlite3
from dataclasses import dataclass, asdict
from enum import Enum

class MemoryType(Enum):
    """记忆类型枚举"""
    FACT = "fact"          # 事实性知识
    PREFERENCE = "preference"  # 用户偏好
    INTERACTION = "interaction" # 交互记录
    LEARNED = "learned"    # 学习到的模式

@dataclass
class MemoryItem:
    """记忆项数据类"""
    id: str
    content: str
    memory_type: MemoryType
    user_id: str
    session_id: Optional[str]
    timestamp: datetime
    metadata: Dict[str, Any]
    embedding: Optional[List[float]] = None
    importance: float = 1.0  # 重要性权重
    
class LongTermMemory:
    """长期记忆实现类"""
    
    def __init__(self, db_path: str = "memory.db"):
        """初始化长期记忆数据库"""
        self.db_path = db_path
        self._init_database()
        
    def _init_database(self):
        """初始化数据库表结构"""
        with sqlite3.connect(self.db_path) as conn:
            conn.execute("""
                CREATE TABLE IF NOT EXISTS memories (
                    id TEXT PRIMARY KEY,
                    content TEXT NOT NULL,
                    memory_type TEXT NOT NULL,
                    user_id TEXT NOT NULL,
                    session_id TEXT,
                    timestamp TEXT NOT NULL,
                    metadata TEXT NOT NULL,
                    importance REAL DEFAULT 1.0,
                    access_count INTEGER DEFAULT 0,
                    last_accessed TEXT
                )
            """)
            conn.execute("CREATE INDEX IF NOT EXISTS idx_user_id ON memories(user_id)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_memory_type ON memories(memory_type)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_timestamp ON memories(timestamp)")
            
    def _generate_id(self, content: str, user_id: str) -> str:
        """生成记忆项ID"""
        unique_string = f"{content}_{user_id}_{datetime.now().isoformat()}"
        return hashlib.sha256(unique_string.encode()).hexdigest()[:16]
        
    def store(self, memory_item: MemoryItem) -> str:
        """存储记忆项"""
        memory_item.id = self._generate_id(memory_item.content, memory_item.user_id)
        
        with sqlite3.connect(self.db_path) as conn:
            conn.execute("""
                INSERT INTO memories (id, content, memory_type, user_id, session_id, 
                                    timestamp, metadata, importance, access_count, last_accessed)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, ?)
            """, (
                memory_item.id,
                memory_item.content,
                memory_item.memory_type.value,
                memory_item.user_id,
                memory_item.session_id,
                memory_item.timestamp.isoformat(),
                json.dumps(memory_item.metadata),
                memory_item.importance,
                datetime.now().isoformat()
            ))
            
        return memory_item.id
        
    def retrieve_by_user(self, user_id: str, limit: int = 10) -> List[MemoryItem]:
        """按用户ID检索记忆"""
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.execute("""
                SELECT * FROM memories 
                WHERE user_id = ? 
                ORDER BY timestamp DESC 
                LIMIT ?
            """, (user_id, limit))
            
            memories = []
            for row in cursor.fetchall():
                memory = MemoryItem(
                    id=row[0],
                    content=row[1],
                    memory_type=MemoryType(row[2]),
                    user_id=row[3],
                    session_id=row[4],
                    timestamp=datetime.fromisoformat(row[5]),
                    metadata=json.loads(row[6]),
                    importance=row[7]
                )
                memories.append(memory)
                
        return memories
        
    def retrieve_by_type(self, user_id: str, memory_type: MemoryType, 
                        days: int = 30) -> List[MemoryItem]:
        """按类型和时间范围检索记忆"""
        cutoff_date = datetime.now() - timedelta(days=days)
        
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.execute("""
                SELECT * FROM memories 
                WHERE user_id = ? AND memory_type = ? AND timestamp >= ?
                ORDER BY importance DESC, timestamp DESC
            """, (user_id, memory_type.value, cutoff_date.isoformat()))
            
            memories = []
            for row in cursor.fetchall():
                memory = MemoryItem(
                    id=row[0],
                    content=row[1],
                    memory_type=MemoryType(row[2]),
                    user_id=row[3],
                    session_id=row[4],
                    timestamp=datetime.fromisoformat(row[5]),
                    metadata=json.loads(row[6]),
                    importance=row[7]
                )
                memories.append(memory)
                
        return memories
        
    def update_importance(self, memory_id: str, importance: float):
        """更新记忆项的重要性权重"""
        with sqlite3.connect(self.db_path) as conn:
            conn.execute("""
                UPDATE memories 
                SET importance = ?, last_accessed = ?
                WHERE id = ?
            """, (importance, datetime.now().isoformat(), memory_id))
            
    def delete_old_memories(self, days: int = 365):
        """删除过期的记忆项"""
        cutoff_date = datetime.now() - timedelta(days=days)
        
        with sqlite3.connect(self.db_path) as conn:
            conn.execute("""
                DELETE FROM memories 
                WHERE timestamp < ? AND importance < 0.5
            """, (cutoff_date.isoformat(),))

使用场景

长期记忆适用于以下场景:

  1. 个性化推荐系统:存储用户历史偏好和行为模式
  2. 知识库构建:积累领域知识和常见问题解决方案
  3. 用户画像构建:基于长期交互数据构建用户模型
  4. 跨会话学习:在不同会话间传递学习成果
  5. 历史分析:分析用户行为趋势和模式变化

例如,在教育辅导代理中,长期记忆可以存储学生的学习进度、薄弱知识点、偏好学习方式等,实现个性化的学习路径推荐。

两者的对比和抉择

对比分析

特性短期记忆长期记忆
存储容量有限(通常10-100条)几乎无限
访问速度快(内存访问)较慢(需要I/O)
持久性临时(会话级)持久(跨会话)
数据结构简单(列表/队列)复杂(数据库/索引)
检索方式顺序/时间戳关键词/向量/关系
适用场景实时交互、上下文维持个性化、知识积累

设计抉择指南

在实际的Deep Agents系统设计中,如何选择和使用记忆系统?

  1. 纯短期记忆方案

    • 适用:简单的对话机器人、一次性任务代理
    • 优点:实现简单、响应快速、无数据持久化负担
    • 缺点:无法个性化、每次会话从零开始
  2. 纯长期记忆方案

    • 适用:知识库系统、历史数据分析
    • 优点:知识积累、个性化能力强
    • 缺点:响应慢、实现复杂、需要数据管理
  3. 混合记忆方案(推荐)

    • 架构:短期记忆作为缓存层,长期记忆作为持久层
    • 数据流:重要信息从短期记忆同步到长期记忆
    • 检索策略:先从短期记忆查找,未命中则查询长期记忆

混合记忆架构示例

class HybridMemorySystem:
    """混合记忆系统"""
    
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.short_term = ShortTermMemory(max_size=20)
        self.long_term = LongTermMemory()
        self.short_term.start_new_session(f"session_{datetime.now().timestamp()}")
        
    def add_interaction(self, user_input: str, agent_response: str):
        """添加交互到混合记忆"""
        # 添加到短期记忆
        self.short_term.add_interaction(user_input, agent_response)
        
        # 判断是否值得长期存储
        if self._should_store_long_term(user_input, agent_response):
            memory_item = MemoryItem(
                id="",
                content=f"用户: {user_input}\n代理: {agent_response}",
                memory_type=MemoryType.INTERACTION,
                user_id=self.user_id,
                session_id=self.short_term.current_session_id,
                timestamp=datetime.now(),
                metadata={"type": "conversation"}
            )
            self.long_term.store(memory_item)
            
    def _should_store_long_term(self, user_input: str, agent_response: str) -> bool:
        """判断交互是否值得长期存储的启发式规则"""
        # 规则1:包含重要关键词
        important_keywords = ["偏好", "喜欢", "不喜欢", "经常", "总是", "从不"]
        if any(keyword in user_input for keyword in important_keywords):
            return True
            
        # 规则2:交互长度超过阈值
        if len(user_input) > 50 or len(agent_response) > 100:
            return True
            
        # 规则3:包含问题解决或知识传授
        solution_indicators = ["如何", "怎么", "步骤", "方法", "教程", "解释"]
        if any(indicator in user_input for indicator in solution_indicators):
            return True
            
        return False
        
    def get_context(self, include_long_term: bool = True) -> str:
        """获取完整的上下文"""
        short_term_context = self.short_term.get_context()
        
        if not include_long_term:
            return short_term_context
            
        # 从长期记忆中获取相关历史
        long_term_memories = self.long_term.retrieve_by_user(self.user_id, limit=5)
        if not long_term_memories:
            return short_term_context
            
        long_term_context = "\n\n[历史记忆]\n"
        for memory in long_term_memories:
            long_term_context += f"- {memory.content[:100]}...\n"
            
        return short_term_context + long_term_context

选择建议

  1. 根据应用类型选择

    • 客服机器人:侧重短期记忆,辅以长期记忆存储常见问题
    • 个性化助手:侧重长期记忆,建立完整的用户画像
    • 教育代理:混合方案,短期记忆跟踪当前课程,长期记忆记录学习历史
  2. 根据资源约束选择

    • 资源有限:从短期记忆开始,逐步添加长期记忆
    • 数据敏感:考虑隐私保护,谨慎设计长期记忆存储
  3. 根据性能要求选择

    • 实时性要求高:优化短期记忆,异步更新长期记忆
    • 准确性要求高:加强长期记忆的检索和推理能力

总结

Deep Agents中的Memory系统是构建智能代理的核心组件,短期记忆和长期记忆各有其独特价值和应用场景:

关键要点

  1. 短期记忆是代理的"工作记忆",负责维持会话连贯性和处理即时任务,适合实时交互场景。

  2. 长期记忆是代理的"知识库",负责存储跨会话的持久化信息,支持个性化和知识积累。

  3. 混合架构通常是最佳实践,通过短期记忆提供快速响应,通过长期记忆实现深度个性化。

  4. 设计选择需要平衡性能、复杂性、隐私和用户体验等多方面因素。

最佳实践建议

  1. 渐进式实现:从简单的短期记忆开始,根据需求逐步引入长期记忆
  2. 隐私保护:对敏感信息进行脱敏处理,提供记忆清除机制
  3. 性能优化:对长期记忆建立合适的索引,实现缓存机制
  4. 可解释性:让用户了解代理记住了什么,提供记忆管理界面
  5. 持续评估:定期评估记忆系统的效果,调整存储和检索策略

未来发展方向

随着大语言模型和向量数据库技术的发展,Deep Agents的Memory系统也在不断演进:

  1. 向量化记忆:使用嵌入向量实现语义检索
  2. 图结构记忆:构建知识图谱式的关系记忆
  3. 分层记忆:实现从瞬时记忆到长期记忆的多层次结构
  4. 联邦记忆:在保护隐私的前提下实现跨设备记忆共享

通过合理设计和实现Memory系统,Deep Agents能够更好地理解用户需求,提供更加智能、个性化和连贯的服务体验。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐