🔥 AI Agent 记忆系统深度解析:从短期记忆到长期记忆的工程实践

10 阅读6分钟

引言

本文约 2500 字,阅读时间 8 分钟。建议收藏后阅读。

如果你正在开发 AI Agent,一定会遇到这个灵魂拷问:"为什么我的 Agent 聊着聊着就忘了前面说过什么?"

这正是记忆系统的价值所在。作为 AI Agent 的核心组件之一,记忆系统决定了 Agent 能否像人类一样保持对话连贯性、积累经验和持续学习。

今天,我将从工程实践角度,深度解析 AI Agent 记忆系统的设计与实现。


一、为什么 Agent 需要记忆?

1.1 LLM 的本质局限

大语言模型(LLM)本质上是无状态的文本生成器。每次 API 调用都是独立的,模型不会自动记住之前的对话内容。

# 伪代码:LLM 的调用方式
response = llm.generate("你好")  # 模型不知道你是谁
response = llm.generate("我叫小明")  # 模型依然不知道
response = llm.generate("我叫什么?")  # 模型:我不知道

1.2 记忆系统的价值

能力无记忆 Agent有记忆 Agent
多轮对话❌ 每轮独立✅ 上下文连贯
用户偏好❌ 重复询问✅ 自动记住
任务进度❌ 容易中断✅ 持续追踪
经验积累❌ 从零开始✅ 越用越聪明

二、记忆系统的三层架构

2.1 感知记忆(Sensory Memory)

作用:临时存储当前对话的原始输入

特点

  • 生命周期极短(通常一次请求)
  • 存储原始文本、图像、音频等多模态数据
  • 用于即时理解和响应
class SensoryMemory:
    """感知记忆:存储当前输入的原始信息"""
    
    def __init__(self):
        self.current_input = None
        self.timestamp = None
    
    def store(self, input_data):
        self.current_input = input_data
        self.timestamp = time.time()
    
    def retrieve(self):
        return self.current_input

2.2 短期记忆(Short-term Memory)

作用:维护当前对话的上下文窗口

核心问题:LLM 的上下文长度有限(通常 4K-128K tokens),如何高效利用?

解决方案

方案 A:滑动窗口(Sliding Window)

class SlidingWindowMemory:
    """滑动窗口记忆:保留最近 N 轮对话"""
    
    def __init__(self, max_turns=10):
        self.messages = []
        self.max_turns = max_turns
    
    def add(self, role, content):
        self.messages.append({"role": role, "content": content})
        # 只保留最近 N 轮
        if len(self.messages) > self.max_turns * 2:
            self.messages = self.messages[-self.max_turns * 2:]
    
    def get_context(self):
        return self.messages

方案 B:摘要压缩(Summarization)

当对话过长时,对早期内容进行摘要:

class SummarizationMemory:
    """摘要记忆:对历史对话进行压缩"""
    
    def __init__(self, llm, max_tokens=2000):
        self.llm = llm
        self.raw_messages = []
        self.summary = ""
        self.max_tokens = max_tokens
    
    def add(self, message):
        self.raw_messages.append(message)
        
        # 检查是否需要摘要
        if self._estimate_tokens() > self.max_tokens:
            self._compress()
    
    def _compress(self):
        # 使用 LLM 生成摘要
        prompt = f"""请对以下对话进行摘要,保留关键信息:
        {self.raw_messages[:-5]}  # 保留最近 5 条不摘要
        """
        self.summary = self.llm.generate(prompt)
        self.raw_messages = self.raw_messages[-5:]

2.3 长期记忆(Long-term Memory)

作用:跨会话持久化存储用户信息和知识

技术选型对比

存储方案适用场景优点缺点
关系型数据库结构化用户数据事务支持、查询灵活不适合语义检索
Redis会话缓存高性能、TTL 支持内存限制
向量数据库语义记忆相似度检索需要 Embedding
图数据库关系记忆关系推理学习成本高

向量记忆实现示例

import numpy as np
from typing import List, Dict

class VectorMemory:
    """向量记忆:基于语义相似度的长期记忆"""
    
    def __init__(self, embedding_model, vector_store):
        self.embedder = embedding_model
        self.store = vector_store
    
    def memorize(self, content: str, metadata: Dict = None):
        """存储记忆"""
        embedding = self.embedder.encode(content)
        self.store.add(
            ids=[f"mem_{time.time()}"],
            embeddings=[embedding],
            documents=[content],
            metadatas=[metadata or {}]
        )
    
    def recall(self, query: str, top_k: int = 5) -> List[str]:
        """检索相关记忆"""
        query_embedding = self.embedder.encode(query)
        results = self.store.query(
            query_embeddings=[query_embedding],
            n_results=top_k
        )
        return results['documents'][0]

三、记忆系统的进阶设计

3.1 记忆分层检索策略

class HierarchicalMemory:
    """分层记忆系统:按优先级检索"""
    
    def __init__(self):
        self.sensory = SensoryMemory()
        self.short_term = SlidingWindowMemory()
        self.long_term = VectorMemory()
    
    def retrieve(self, query: str) -> str:
        """分层检索记忆"""
        context_parts = []
        
        # 1. 感知记忆(最高优先级)
        sensory_data = self.sensory.retrieve()
        if sensory_data:
            context_parts.append(f"当前输入: {sensory_data}")
        
        # 2. 短期记忆
        recent_context = self.short_term.get_context()
        context_parts.append("近期对话:\n" + 
                           "\n".join([f"{m['role']}: {m['content']}" 
                                     for m in recent_context]))
        
        # 3. 长期记忆(语义检索)
        relevant_memories = self.long_term.recall(query)
        if relevant_memories:
            context_parts.append("相关历史:\n" + 
                               "\n".join(relevant_memories))
        
        return "\n\n".join(context_parts)

3.2 记忆的重要性评分

不是所有记忆都同等重要,需要设计遗忘机制:

class ScoredMemory:
    """带重要性评分的记忆"""
    
    def __init__(self, content: str, importance: float = 1.0):
        self.content = content
        self.importance = importance  # 1.0 - 10.0
        self.created_at = time.time()
        self.access_count = 0
    
    def calculate_retention_score(self) -> float:
        """计算记忆保留分数"""
        time_decay = 1 / (1 + 0.1 * (time.time() - self.created_at) / 86400)
        access_boost = 1 + 0.1 * self.access_count
        return self.importance * time_decay * access_boost
    
    def access(self):
        """访问记忆,增加访问计数"""
        self.access_count += 1

3.3 记忆的类型化设计

from enum import Enum

class MemoryType(Enum):
    FACT = "fact"           # 事实性记忆
    PREFERENCE = "preference"  # 用户偏好
    EVENT = "event"         # 事件记忆
    SKILL = "skill"         # 技能记忆

class TypedMemory:
    """类型化记忆系统"""
    
    def __init__(self):
        self.memories = {t: [] for t in MemoryType}
    
    def add(self, content: str, mem_type: MemoryType, 
            importance: float = 1.0):
        memory = ScoredMemory(content, importance)
        self.memories[mem_type].append(memory)
    
    def recall_by_type(self, query: str, mem_type: MemoryType):
        """按类型检索记忆"""
        candidates = self.memories[mem_type]
        # 按保留分数排序
        candidates.sort(key=lambda m: m.calculate_retention_score(), 
                       reverse=True)
        return candidates[:5]

四、生产环境的最佳实践

4.1 隐私与安全

class PrivacyAwareMemory:
    """隐私感知的记忆系统"""
    
    SENSITIVE_PATTERNS = [
        r'\b\d{16,19}\b',  # 银行卡号
        r'\b\d{18}\b',     # 身份证号
        r'password[:\s]+\S+',  # 密码
    ]
    
    def sanitize(self, content: str) -> str:
        """敏感信息脱敏"""
        for pattern in self.SENSITIVE_PATTERNS:
            content = re.sub(pattern, '[REDACTED]', content)
        return content
    
    def memorize(self, content: str, **kwargs):
        safe_content = self.sanitize(content)
        return super().memorize(safe_content, **kwargs)

4.2 记忆同步与并发

import asyncio
from contextlib import asynccontextmanager

class AsyncMemory:
    """异步记忆系统"""
    
    def __init__(self):
        self._lock = asyncio.Lock()
        self._cache = {}
    
    @asynccontextmanager
    async def _transaction(self):
        async with self._lock:
            yield
    
    async def memorize(self, key: str, value: str):
        async with self._transaction():
            self._cache[key] = value
            await self._persist(key, value)
    
    async def _persist(self, key: str, value: str):
        """持久化到存储"""
        # 异步写入数据库或缓存
        pass

4.3 性能优化

优化策略实现方式效果
缓存热点记忆Redis减少 90% 数据库查询
批量写入异步队列优化策略实现方式效果
------------------------
缓存热点记忆Redis减少 90% 数据库查询
批量写入异步队列降低 I/O 压力
索引优化向量索引 + 倒排索引检索速度提升 10x
分层存储热/温/冷数据分层降低存储成本

五、实战案例:构建一个带记忆的客服 Agent

class CustomerServiceAgent:
    """带记忆系统的客服 Agent"""
    
    def __init__(self):
        self.memory = HierarchicalMemory()
        self.llm = OpenAI()
    
    async def handle(self, user_id: str, message: str):
        # 1. 加载用户长期记忆
        user_profile = await self.load_user_profile(user_id)
        
        # 2. 检索相关历史对话
        relevant_history = self.memory.long_term.recall(message)
        
        # 3. 构建上下文
        context = self.build_context(
            user_profile=user_profile,
            history=relevant_history,
            recent_chat=self.memory.short_term.get_context()
        )
        
        # 4. 生成回复
        response = await self.llm.chat(context + message)
        
        # 5. 更新记忆
        self.memory.short_term.add("user", message)
        self.memory.short_term.add("assistant", response)
        
        # 6. 提取重要信息存入长期记忆
        await self.extract_and_memorize(message, response)
        
        return response
    
    async def extract_and_memorize(self, user_msg: str, assistant_msg: str):
        """从对话中提取重要信息"""
        extraction_prompt = f"""
        从以下对话中提取需要记住的关键信息(偏好、事实、事件):
        用户: {user_msg}
        助手: {assistant_msg}
        
        只输出 JSON 格式:{{"facts": [], "preferences": [], "events": []}}
        """
        
        extracted = await self.llm.generate(extraction_prompt)
        data = json.loads(extracted)
        
        # 存入长期记忆
        for fact in data.get("facts", []):
            self.memory.long_term.memorize(
                fact, 
                metadata={"type": "fact", "timestamp": time.time()}
            )

六、总结与展望

6.1 核心要点回顾

  1. 记忆分层:感知记忆 → 短期记忆 → 长期记忆,每层解决不同问题
  2. 检索策略:分层检索 + 语义相似度 + 重要性评分
  3. 工程实践:隐私保护、并发控制、性能优化缺一不可

6.2 未来趋势

  • 多模态记忆:不仅存储文本,还包括图像、音频、视频
  • 个性化记忆:基于用户画像的个性化记忆权重
  • 联邦记忆:在保护隐私前提下,跨 Agent 共享知识
  • 自适应记忆:Agent 自主决定记住什么、遗忘什么

参考资料

  1. LangChain Memory 模块文档
  2. MemGPT: Towards LLMs as Operating Systems
  3. Vector Database Comparison

💡 思考题:你在开发 Agent 时遇到过哪些记忆相关的问题?欢迎在评论区分享讨论!

如果这篇文章对你有帮助,请点赞 👍 收藏 ⭐ 关注,我会持续输出更多 AI 工程实践干货!