记忆系统
问题
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?
答案:
- Token 限制:Context Window 有上限(4K-1M Token)
- 成本:每次请求都发送全部历史,Token 成本线性增长
- 性能:长上下文 Prefill 变慢,可能出现 Lost in the Middle 问题
- 解决:滑动窗口 + 摘要压缩 + 长期记忆外部存储
Q2: 长期记忆用什么存储?
答案:
| 存储方案 | 适用数据 | 示例 |
|---|---|---|
| 向量数据库 | 语义内容(对话摘要、用户偏好) | Pinecone、Chroma |
| 关系数据库 | 结构化数据(用户资料、操作记录) | PostgreSQL |
| KV 存储 | 简单键值(用户设置、偏好) | Redis |