系列目标:30 天从 LangChain 入门到企业级部署
今日任务:理解长对话的 token 限制 → 掌握ConversationSummaryMemory→ 构建能处理多轮复杂对话的 AI 助手!
⏳ 一、为什么需要 Summary Memory?
在 Day 5 中,我们用了 ConversationBufferMemory —— 它把全部对话历史塞进 prompt。
但问题来了:
- 模型有上下文长度限制(Qwen:7b 约 32K token,但越长越慢越贵)
- 对话超过 10 轮后,prompt 可能爆掉 ❌
- 无关历史会干扰当前回答
解决方案:不要记“所有话”,而是记“核心摘要”!
✅
ConversationSummaryMemory就是 LangChain 提供的“AI 记忆压缩器”——它用另一个 LLM 把历史对话自动总结成一段文字,作为上下文传给主模型。
🧠 二、工作原理(图解)
用户: 我叫小明。
AI: 你好,小明!
用户: 我喜欢编程。
AI: 编程很棒!
用户: 我用 Python。
│
▼
[ConversationSummaryMemory]
调用 LLM 总结历史 → "用户叫小明,喜欢用 Python 编程。"
│
▼
下一轮提问时,prompt 变成:
System: 你是一个助手。
Summary: 用户叫小明,喜欢用 Python 编程。
Human: 你能推荐一个 Python 库吗?
🔁 每次新对话,都会基于旧摘要 + 最新交互,生成新摘要。
🛠️ 三、动手实践:构建长对话友好的聊天机器人
步骤 1:安装依赖(如果还没装)
pip install langchain-ollama
💡 注意:
ConversationSummaryMemory需要两个 LLM:
- 一个用于总结历史(
memory_llm)- 一个用于回答问题(
llm)为节省资源,我们可以复用同一个本地模型!
步骤 2:编写带 Summary Memory 的 Chain
# day7_summary_memory.py
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.chains import ConversationChain
from langchain.memory import ConversationSummaryMemory
# 1. 初始化本地模型(同时用于回答 + 总结)
llm = ChatOllama(model="qwen:7b", temperature=0)
# 2. 创建 Summary Memory
memory = ConversationSummaryMemory(
llm=llm, # 用于生成摘要的 LLM
memory_key="history", # 在 prompt 中引用的变量名
return_messages=True # 返回 Message 对象
)
# 3. 定义 Prompt 模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个贴心的个人助理,会参考对话摘要提供帮助。"),
("human", "对话摘要:{history}\n\n当前问题:{input}")
])
# 4. 构建 ConversationChain
chain = ConversationChain(
llm=llm,
memory=memory,
prompt=prompt,
verbose=True # 查看摘要生成过程
)
# 5. 模拟多轮对话
inputs = [
"我叫王芳。",
"我在杭州工作。",
"我是一名数据分析师。",
"我常用 pandas 和 SQL。",
"最近在学大模型。",
"你能总结一下我的背景吗?"
]
print("🤖 开始对话...\n")
for user_input in inputs:
print(f"👤 用户:{user_input}")
response = chain.invoke({"input": user_input})
print(f"🤖 AI:{response['response']}\n")
▶️ 关键输出示例(verbose 模式):
> Entering new ConversationChain chain...
Prompt after formatting:
你是一个贴心的个人助理...
对话摘要:
用户叫王芳,在杭州工作,是一名数据分析师,常用 pandas 和 SQL,最近在学大模型。
当前问题:你能总结一下我的背景吗?
🤖 AI:当然!你是王芳,杭州的数据分析师,熟练使用 pandas 和 SQL,目前正在学习大模型技术。👏
✅ 即使对话很长,AI 依然精准记住关键信息!
🔍 四、与 BufferMemory 对比
| 特性 | ConversationBufferMemory | ConversationSummaryMemory |
|---|---|---|
| 存储内容 | 原始对话全文 | 自动总结的摘要 |
| Token 消耗 | 随对话线性增长 ❌ | 基本恒定 ✅ |
| 适合场景 | 短对话(<5 轮) | 长对话、复杂任务 |
| 是否需要额外 LLM | 否 | 是(但可复用主模型) |
| 信息保真度 | 100%(但可能超限) | 有损压缩(但够用) |
📌 建议:
- 简单聊天 → 用
BufferMemory- 专业助手/客服 → 用
SummaryMemory
🔄 五、性能优化技巧
1. 使用更小模型做摘要(节省资源)
python
编辑
summary_llm = ChatOllama(model="qwen:1.8b", temperature=0)
main_llm = ChatOllama(model="qwen:7b", temperature=0.7)
memory = ConversationSummaryMemory(llm=summary_llm, ...)
chain = ConversationChain(llm=main_llm, memory=memory, ...)
2. 控制摘要长度
通过 system prompt 引导摘要简洁:
# 在 memory 初始化时无法直接控制,但可在 LLM 调用时加约束
# 更高级方案:自定义 Memory 类(Day 21 讲)
⚠️ 六、注意事项
| 问题 | 建议 |
|---|---|
| 摘要丢失关键细节 | 在用户输入中强调重点:“请记住:我过敏花生!” |
| 本地模型总结能力弱 | Qwen 对中文摘要效果较好;避免用太小的模型(如 phi3)做 summary |
| 第一次对话就问“之前说了啥” | 初始摘要为空,需在 prompt 中处理空值情况 |
| 想要混合方案? | 后续可学 SummaryBufferMemory(保留最近几轮 + 摘要) |
📦 七、配套代码结构
langchain-30-days/
└── day7/
└── summary_memory_chatbot.py # 支持长对话的 AI 助手
📝 八、今日小结
- ✅ 理解了长对话的 token 限制问题
- ✅ 学会了
ConversationSummaryMemory工作原理 - ✅ 实现了能自动总结历史的 AI 助手
- ✅ 掌握了主模型与摘要模型的复用技巧
- ✅ 知道了何时用 Buffer vs Summary Memory