跳到主要内容

记忆系统

问题

Agent 的记忆系统如何设计?短期记忆和长期记忆有什么区别?

答案

记忆让 Agent 能够跨轮对话保留上下文从历史经验中学习

一、记忆分类

类型存储位置生命周期示例
短期记忆Context Window单次会话对话历史
工作记忆Scratchpad单次任务中间计算结果、执行状态
长期记忆外部存储(DB/向量库)永久用户偏好、历史总结

二、短期记忆管理

Context Window 有限,需要策略管理对话历史:

滑动窗口

def sliding_window(messages: list, max_messages: int = 20):
"""保留最近 N 条消息"""
system_msg = messages[0] # 保留 System Prompt
recent = messages[-max_messages:]
return [system_msg] + recent

摘要压缩

def summarize_history(messages: list, llm, threshold: int = 4000):
"""当历史过长时,用 LLM 总结旧消息"""
total_tokens = count_tokens(messages)
if total_tokens < threshold:
return messages

# 将旧消息压缩为摘要
old_messages = messages[1:-10] # 保留系统消息和最近10条
summary = llm.invoke(
f"请将以下对话历史总结为简洁的摘要:\n{format_messages(old_messages)}"
)

return [
messages[0], # system
{"role": "system", "content": f"历史对话摘要:{summary.content}"},
*messages[-10:] # 最近10条保留原文
]

三、长期记忆实现

from openai import OpenAI

class LongTermMemory:
def __init__(self, vectorstore, llm):
self.vectorstore = vectorstore
self.llm = llm

def save(self, content: str, metadata: dict):
"""将重要信息存入长期记忆"""
self.vectorstore.add_texts(
texts=[content],
metadatas=[metadata]
)

def recall(self, query: str, k: int = 5) -> list:
"""根据当前上下文检索相关记忆"""
return self.vectorstore.similarity_search(query, k=k)

def extract_and_save(self, conversation: list):
"""从对话中自动提取值得记住的信息"""
response = self.llm.invoke(
"从以下对话中提取用户偏好、重要事实等值得长期记住的信息。"
"如果没有值得记住的内容,返回空。\n"
f"{format_messages(conversation)}"
)
if response.content.strip():
self.save(response.content, {"type": "extracted", "timestamp": now()})

四、记忆在 Agent 循环中的位置


常见面试问题

Q1: 为什么不能直接把所有对话历史都放进 Context Window?

答案

  1. Token 限制:Context Window 有上限(4K-1M Token)
  2. 成本:每次请求都发送全部历史,Token 成本线性增长
  3. 性能:长上下文 Prefill 变慢,可能出现 Lost in the Middle 问题
  4. 解决:滑动窗口 + 摘要压缩 + 长期记忆外部存储

Q2: 长期记忆用什么存储?

答案

存储方案适用数据示例
向量数据库语义内容(对话摘要、用户偏好)Pinecone、Chroma
关系数据库结构化数据(用户资料、操作记录)PostgreSQL
KV 存储简单键值(用户设置、偏好)Redis

相关链接