🌟 LangChain 30 天保姆级教程 · Day 7|对话太长怎么办?用 ConversationSummaryMemory 让 AI “总结记忆”

1 阅读4分钟

系列目标: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 对比

特性ConversationBufferMemoryConversationSummaryMemory
存储内容原始对话全文自动总结的摘要
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