虽然 ConversationBufferMemory 通过存储每条消息提供完美的记忆,但随着对话增长,其效果会减弱。完整的历史记录会迅速超出 LLM 的上下文窗口限制,导致错误,并增加每次 API 调用的 token 成本。这种方式对于为长时间交互设计的应用来说是不可持续的。为解决此扩展问题,LangChain 提供了 ConversationSummaryMemory。它不保留逐字记录,而是使用语言模型创建交互的运行摘要。随着对话进行,摘要会持续更新,纳入新的交流,保持上下文简明且易于管理。摘要记忆如何运作核心机制包含一个额外的 LLM 调用,专门用于压缩对话历史。在每次用户-AI 交流后,记忆组件会获取现有摘要,附加最新消息。并请求 LLM 生成一个新的、更新后的摘要。这个新摘要随后会替换记忆缓冲区中的旧摘要。当链下次被调用时,传递给主 LLM 的将是这个精炼过的摘要,而非完整的聊天记录,同时伴随着新的用户输入。这一过程有效地用完美的记忆换取了可扩展性。它使得应用能够在非常长的对话中保持上下文感知,而不会触及 token 限制。digraph G { rankdir=TB; node [shape=box, style="rounded,filled", fontname="Arial", fontsize=10]; edge [fontname="Arial", fontsize=9]; subgraph cluster_0 { label="交互流程"; bgcolor="#e9ecef"; user_input [label="1. 用户输入\n(例如, '第一个话题是什么?')", fillcolor="#a5d8ff"]; chain [label="2. 对话链", fillcolor="#ced4da"]; memory [label="3. 从记忆中获取摘要", fillcolor="#ffec99"]; prompt [label="4. 构建提示", fillcolor="#bac8ff"]; llm [label="5. 主LLM调用", fillcolor="#b2f2bb"]; response [label="6. AI回应", fillcolor="#ced4da"]; user_output [label="7. 发送给用户", fillcolor="#a5d8ff"]; user_input -> chain; chain -> memory; memory -> prompt [label="当前摘要"]; user_input -> prompt [label="新输入"]; prompt -> llm; llm -> response; response -> user_output; } subgraph cluster_1 { label="记忆更新周期"; bgcolor="#e9ecef"; update_trigger [label="8. 交流后", fillcolor="#ced4da"]; prepare_summary [label="9. 为摘要器准备数据", fillcolor="#ffec99"]; summarizer_llm [label="10. 摘要器LLM调用", fillcolor="#fcc2d7"]; new_summary [label="11. 存储新摘要", fillcolor="#ffd8a8"]; response -> update_trigger [style=dashed]; update_trigger -> prepare_summary [label="旧摘要 + 新消息"]; prepare_summary -> summarizer_llm; summarizer_llm -> new_summary; } user_output -> update_trigger [style=invis]; }使用摘要记忆的应用流程。主交互之后会进行一次单独的 LLM 调用,以更新对话摘要。实现 ConversationSummaryMemory将此应用于实践与其他记忆类型的使用类似,但有一个主要的区别:你必须向记忆对象本身提供一个 LLM,因为它需要一个 LLM 来执行摘要。让我们设置一个使用 ConversationSummaryMemory 的 ConversationChain。我们将在每次交互后打印记忆缓冲区的内容,以观察摘要如何变化。import os from langchain_openai import ChatOpenAI from langchain.chains import ConversationChain from langchain.memory import ConversationSummaryMemory # 设置你的OpenAI API密钥 # os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY" # 初始化链和记忆摘要器所需的LLM # 使用如 gpt-4o 或 gpt-3.5-turbo 这样的聊天模型 llm = ChatOpenAI(model="gpt-4o", temperature=0) # 初始化 ConversationSummaryMemory # 需要 LLM 来生成摘要 summary_memory = ConversationSummaryMemory(llm=llm) # 创建 ConversationChain conversation_with_summary = ConversationChain( llm=llm, memory=summary_memory, verbose=True # 设置为 True 可以查看发送给 LLM 的提示 ) # 第一次交互 conversation_with_summary.predict(input="你好,我叫 Alex,我对机器学习感兴趣。") print(f"记忆缓冲区:\n{summary_memory.buffer}\n") # 第二次交互 conversation_with_summary.predict(input="我对强化学习特别感兴趣。你能推荐一个好的起点吗?") print(f"记忆缓冲区:\n{summary_memory.buffer}\n") # 第三次交互 conversation_with_summary.predict(input="听起来不错。我叫什么名字?") print(f"记忆缓冲区:\n{summary_memory.buffer}\n")运行此代码时,请密切关注链的 verbose 输出以及打印出的记忆缓冲区。第一次交互输出: 初始提示很简单。交流之后,记忆缓冲区包含了一个新的摘要。Memory Buffer: The human introduces themselves as Alex and expresses an interest in machine learning. The AI responds by offering to provide information on the topic.第二次交互输出: 请注意,发送给 LLM 的提示现在包含了第一次交互的摘要,而非原始文本。第二次交流后,摘要再次更新。Memory Buffer: The human, Alex, is interested in machine learning, specifically reinforcement learning. The AI suggests starting with the book "Reinforcement Learning: An Introduction" by Sutton and Barto.第三次交互输出: LLM 正确地记起了用户的名字,因为这个名字保存在运行中的摘要里。> 进入新的 ConversationChain 链... 格式化后的提示: 以下是人类与 AI 之间的友好对话。AI 健谈,并提供来自其上下文的许多具体细节。如果 AI 不知道问题的答案,它会如实说明。 当前对话: The human, Alex, is interested in machine learning, specifically reinforcement learning. The AI suggests starting with the book "Reinforcement Learning: An Introduction" by Sutton and Barto. 人类: 听起来不错。我叫什么名字? AI: > 链结束。 你的名字是 Alex。 Memory Buffer: The human, Alex, is interested in machine learning, specifically reinforcement learning. The AI suggests starting with the book "Reinforcement Learning: An Introduction" by Sutton and Barto. Alex then asks the AI to recall his name, which the AI correctly identifies as Alex.权衡ConversationSummaryMemory 虽然有效,但引入了两个主要的权衡:增加延迟: 由于每次对话轮次都需要额外的 LLM 调用来更新摘要,因此与使用简单缓冲区相比,用户的总体响应时间可能会略长。潜在信息丢失: 摘要过程本质上是有损的。LLM 可能无法捕获对话早期部分中一个不明显但有意义的细节。摘要的质量取决于用于摘要任务的 LLM 的能力。对于大多数使用场景,这是可以接受的,但对于需要高度还原特定细节的应用来说,这是一个需要考虑的因素。这种记忆类型非常适合客服机器人、长篇研究助手等应用,或者任何保持长对话总体上下文比记住每个单词更具优先性的场景。它为构建能够优雅处理长时间交互的有状态应用提供了一个实用方案。