07 - 记忆(Memory):对话上下文管理
约 1096 字大约 4 分钟
LangChainMemory对话管理
2026-03-08
第 07 课:记忆(Memory)- 对话上下文管理
课程目标
通过本节课,你将学到:
- ✅ 为什么需要对话记忆
- ✅ 常用 Memory 类型
- ✅ 向量存储记忆
- ✅ 记忆持久化
一、为什么需要对话记忆?
1.1 问题场景
# ❌ 没有记忆:每次对话都是独立的
user: "我叫张三"
AI: "你好张三!"
user: "我叫什么名字?"
AI: "抱歉,我不知道你的名字" # ❌ 忘记了1.2 解决方案
使用 Memory 组件保存对话历史:
# ✅ 有记忆:AI 记住上下文
user: "我叫张三"
AI: "你好张三!"
user: "我叫什么名字?"
AI: "你叫张三!" # ✅ 记住了二、常用 Memory 类型
2.1 ConversationBufferMemory
特点:保存所有对话历史
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI
# 创建记忆
memory = ConversationBufferMemory()
# 创建对话链
conversation = ConversationChain(
llm=ChatOpenAI(),
memory=memory,
verbose=True # 打印详细日志
)
# 对话
response1 = conversation.predict(input="我叫张三")
print(response1) # "你好张三!"
response2 = conversation.predict(input="我叫什么名字?")
print(response2) # "你叫张三!"
# 查看记忆
print(memory.load_memory_variables({}))
# {"history": "Human: 我叫张三\nAI: 你好张三!\nHuman: 我叫什么名字?\nAI: 你叫张三!"}2.2 ConversationBufferWindowMemory
特点:只保留最近 N 轮对话
from langchain.memory import ConversationBufferWindowMemory
# 只保留最近 2 轮对话
memory = ConversationBufferWindowMemory(k=2)
conversation = ConversationChain(
llm=ChatOpenAI(),
memory=memory
)
# 多轮对话
conversation.predict(input="第一轮")
conversation.predict(input="第二轮")
conversation.predict(input="第三轮")
# 此时只保留第2、3轮,第1轮被丢弃2.3 ConversationTokenBufferMemory
特点:根据 token 数量限制记忆
from langchain.memory import ConversationTokenBufferMemory
# 最多保留 1000 个 token
memory = ConversationTokenBufferMemory(
llm=ChatOpenAI(),
max_token_limit=1000
)2.4 ConversationSummaryMemory
特点:自动总结历史对话
from langchain.memory import ConversationSummaryMemory
# 自动总结
memory = ConversationSummaryMemory(
llm=ChatOpenAI()
)
conversation = ConversationChain(
llm=ChatOpenAI(),
memory=memory
)
# 长对话后,自动生成总结
conversation.predict(input="我想学习Python")
conversation.predict(input="推荐一些学习资源")
conversation.predict(input="如何入门")
# 查看总结
print(memory.load_memory_variables({}))
# {"history": "用户想学习Python,我推荐了学习资源,并指导如何入门。"}三、向量存储记忆
3.1 VectorStoreRetrieverMemory
特点:使用向量搜索相关历史
from langchain.memory import VectorStoreRetrieverMemory
from langchain_openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
# 创建向量存储
vectorstore = Chroma(
embedding_function=OpenAIEmbeddings(),
persist_directory="./chroma_db"
)
# 创建记忆
memory = VectorStoreRetrieverMemory(
retriever=vectorstore.as_retriever(search_kwargs={"k": 3})
)
# 添加记忆
memory.save_context(
{"input": "我最喜欢的颜色是蓝色"},
{"output": "好的,我记住了你喜欢蓝色"}
)
memory.save_context(
{"input": "我有一只猫叫小橘"},
{"output": "小橘是个可爱的名字"}
)
# 查询相关记忆
result = memory.load_memory_variables({"prompt": "我的宠物是什么?"})
print(result) # 返回相关的对话3.2 对比总结
| Memory 类型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Buffer | 完整保留 | 占用空间大 | 短对话 |
| Window | 固定长度 | 丢失早期信息 | 中等对话 |
| Token | 精确控制 | 需要计算 token | 长对话 |
| Summary | 压缩信息 | 丢失细节 | 超长对话 |
| Vector | 语义搜索 | 需要向量库 | 混合场景 |
四、记忆持久化
4.1 保存到文件
import json
# 保存记忆
memory_json = json.dumps(memory.load_memory_variables({}))
with open("memory.json", "w") as f:
f.write(memory_json)
# 加载记忆
with open("memory.json", "r") as f:
memory_data = json.load(f)
memory.save_context(memory_data)4.2 保存到数据库
from langchain.memory import SQLChatMessageHistory
# 使用 SQLite 存储
message_history = SQLChatMessageHistory(
session_id="user_123",
connection="sqlite:///memory.db"
)
# 添加消息
message_history.add_user_message("你好")
message_history.add_ai_message("你好!有什么可以帮你的?")
# 查询历史
messages = message_history.messages五、实战案例
5.1 多用户对话系统
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
class MultiUserChat:
def __init__(self):
self.memories = {} # 用户ID -> Memory
def get_memory(self, user_id):
if user_id not in self.memories:
self.memories[user_id] = ConversationBufferMemory()
return self.memories[user_id]
def chat(self, user_id, message):
memory = self.get_memory(user_id)
conversation = ConversationChain(
llm=ChatOpenAI(),
memory=memory
)
return conversation.predict(input=message)
# 使用
chat_system = MultiUserChat()
# 用户1
response1 = chat_system.chat("user_001", "我叫张三")
# 用户2
response2 = chat_system.chat("user_002", "我叫李四")
# 用户1再次对话
response3 = chat_system.chat("user_001", "我叫什么名字?")
print(response3) # "你叫张三!" ✅ 记住了六、本课小结
核心要点
Memory 类型:
- Buffer:完整保留
- Window:固定窗口
- Token:token 限制
- Summary:自动总结
- Vector:语义搜索
选择建议:
- 短对话:Buffer
- 长对话:Token/Summary
- 多主题:Vector
持久化:
- 文件存储
- 数据库存储
下节预告
下一课,我们将学习 检索增强(RAG),包括:
- 文档加载器
- 向量数据库
- 检索策略
🎯 课后练习
- 基础练习:创建一个带 Window Memory 的对话系统。
- 进阶练习:实现一个多用户对话系统,每个用户独立记忆。
- 挑战练习:使用 VectorStoreRetrieverMemory 实现语义搜索记忆。