AI Agent 的「记忆压缩术」:LangChain Summarization 中间件完全指南
当 Agent 对话越来越长,模型开始"记不住"早先聊过什么——这时候,Summarization 中间件就是你的救命稻草。
本文将带你从概念、创建、触发流程、规则制定到参数调优,彻底掌握 LangChain Summarization 中间件。
📑 目录
- 什么是 Summarization 中间件
- 从零创建一个带 Summarization 的 Agent
- 四步拆解:参数详解
- 触发机制:before_model 钩子全流程
- 全景视角:消息在系统中的流转
- 规则制定的 4 种姿势
- 必知必会:其他参数配置
- 一图总结:知识图谱
1. 什么是 Summarization 中间件
核心概念:在接近令牌限制或其他条件时,自动总结对话记录,保留近期消息的同时压缩较早的上下文,为 Agent 在更复杂的长时序环境中的任务执行提供便利。
适用场景
| 场景 | 英文标识 | 描述 |
|---|---|---|
| 长文本 | Long-context | 超出上下文窗口的长期对话任务 |
| 多轮次 | Multi-turn | 具有丰富历史记录的多轮对话 |
| 高冗余 | High-redundancy | 需要完整保留对话上下文的应用场景 |
工作原理
💡 核心价值:扩展 Agent 的"有效记忆",让模型在长时序任务中不丢失关键信息。
2. 从零创建一个带 Summarization 的 Agent
Step 1:定义工具
from langchain.tools import tool
@tool
def internet_search(...):
"""
Search the internet for information using Tavily search engine
"""
search_docs = tavily_client.search(...)
return search_docs
@tool
def calculate(expression: str) -> str:
"""
Perform mathematical calculations and return the result.
Args:
expression: A mathematical expression string.
Returns:
The result of the calculation as a string.
"""
result = str(eval(expression))
return result
Step 2:创建 Agent 并挂载 Summarization
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
agent = create_agent(
model=model,
tools=[internet_search, calculate],
middleware=[
SummarizationMiddleware(
model=model,
trigger=("messages", 5), # 消息数达到 5 时触发
keep=("messages", 3), # 保留最近 3 条
),
],
)
3. 四步拆解:参数详解
关键参数
| 参数 | 示例值 | 含义 |
|---|---|---|
model | model | 用于执行摘要的 LLM |
trigger | ("messages", 5) | 触发条件:消息数达 5 时启动摘要 |
keep | ("messages", 3) | 保留策略:摘要后保留最近 3 条消息 |
4. 触发机制:before_model 钩子全流程
Summarization 中间件属于 before_model 类型钩子,在每次模型调用之前,依据用户拟定条件检查是否触发。
实际运行观察
初始状态(4 条历史消息):
from langchain.messages import HumanMessage, AIMessage, ToolMessage
status = {"messages": [
HumanMessage(content='deepseek公司最近有什么最新的资讯?', ...),
AIMessage(content='', ...),
ToolMessage(content='{"query": "deepseek 最新资讯", ...}'),
AIMessage(content='最近,DeepSeek 公司推出了其最新的数学推理模型 DeepSeek-Math...'),
]}
追加新询问(消息数达到 5 条 → 触发阈值):
status["messages"].append(
HumanMessage("deepseek的新模型有哪些特点与突破?")
)
result = agent.invoke(status)
观察 Agent 回复(首条消息已被替换为摘要):
[HumanMessage(content='Here is a summary of the conversation...'), # 🆕 摘要(自动注入)
HumanMessage(content='deepseek的新模型有哪些特点与突破?', ...),
AIMessage(content='', ...),
ToolMessage(content='{"query": "DeepSeek Math-V2 模型 特点 ...}', ...),
AIMessage(content='DeepSeek的最新数学推理模型DeepSeek-Math-V2...')]
触发流程图
5. 全景视角:消息在系统中的流转
关键洞察
| 维度 | 说明 |
|---|---|
| 介入时机 | 不在用户输入时,而在工具返回后(消息实际膨胀时) |
| 压缩对象 | 仅压缩历史消息,不压缩当下任务相关消息 |
| 保留策略 | 严格保留最近 3 条(高信息密度的内容优先) |
| 摘要注入位置 | 消息列表最前面,作为上下文背景 |
6. 规则制定的 4 种姿势
方式 1:消息数量
trigger=("messages", 5)
keep=("messages", 3)
适合:简单轮次控制,原型开发
方式 2:Token 计数
agent2 = create_agent(
model=model,
tools=[internet_search, calculate],
middleware=[
SummarizationMiddleware(
model="gpt-4o-mini",
trigger=("tokens", 4000),
keep=("tokens", 2000),
),
],
)
适合:精确控制上下文成本
方式 3:模型上下文长度比值
agent3 = create_agent(
model=model,
tools=[internet_search, calculate],
middleware=[
SummarizationMiddleware(
model="gpt-4o-mini",
trigger=("fraction", 0.8),
keep=("fraction", 0.3),
),
],
)
适合:跨模型自适应,换模型无需重新调参
方式 4:混合配置(OR 关系)
agent4 = create_agent(
model=model,
tools=[internet_search, calculate],
middleware=[
SummarizationMiddleware(
model="gpt-4o-mini",
trigger=[
("tokens", 5000),
("messages", 3),
],
keep=("messages", 20),
),
],
)
满足任一条件即触发,方便多维度兜底
对比维度
7. 必知必会:其他参数配置
完整参数表
| 参数 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
model | string | BaseChatModel | — | ✅ | 摘要所用模型 |
trigger | ContextSize | list[ContextSize] | — | ✅ | 触发条件(支持多条件 OR) |
keep | ContextSize | ("messages", 20) | ❌ | 保留策略 |
summary_prompt | string | LangChain 预设 | ❌ | 自定义摘要提示词 |
参数细节
model:与 Agent 创建相同,可以利用字符串配置模型,也可直接传入模型对象。
model="gpt-4o-mini" # ✅ 字符串
model=ChatOpenAI(...) # ✅ 模型对象
trigger:可接受单一元组或元组列表(多条件触发,OR 关系)。
trigger=("messages", 5) # 单条件
trigger=[("tokens", 5000), ("messages", 3)] # 多条件
keep:只能接收单一元组,不配置时默认 ("messages", 20)。
keep=("messages", 20) # ✅ 唯一合法写法
summary_prompt:LangChain 预设了系统提示词,可重写以替换。
⚠️ 注意:自行拟定的提示词中必须包含
{messages}占位符。
summary_prompt="请将以下对话历史压缩为简洁摘要:\n{messages}\n保留关键信息:"
8. 一图总结:知识图谱
🎯 一句话总结
Summarization 中间件 = 在
before_model钩子位置、按trigger配置触发、按keep配置保留、自动用 LLM 压缩早期消息的"上下文管家"。
📝 实战建议
| 场景 | 推荐配置 |
|---|---|
| 🎮 原型开发 | trigger=("messages", 5) + keep=("messages", 3) |
| 💰 生产部署 | trigger=("tokens", 4000) + keep=("tokens", 2000) |
| 🔄 多模型适配 | trigger=("fraction", 0.8) + keep=("fraction", 0.3) |
| 🛡️ 复杂生产 | trigger=[("tokens", 5000), ("messages", 3)] + keep=("messages", 20) |
💡 写在最后
当你下次遇到 Agent"聊到失忆"时,记得试试 Summarization 中间件——它可能是你的 Agent 走向生产可用的关键一步。