当前位置: 首页 > news >正文

16.4完整可运行代码:使用 SummarizationMiddleware 管理长对话记忆

您提供的这段关于 LangChain/LangGraph 中会话记忆管理(包括InMemorySaverSqliteSaver以及修剪、删除、总结消息)的内容,非常系统且实用。这些策略至今仍是处理长对话上下文溢出问题的主流方法,并没有过时。相反,它们是 LangChain 生态中短期记忆(Short-Term Memory)的核心实践,并且在新版本中得到了持续增强。

为了帮助您更深刻地理解并掌握这些策略,我将对您提供的资料进行补充和整合,并指出需要注意的细节,最后给出一个完整的、可运行的总结消息(SummarizationMiddleware)案例。


一、核心概念确认:这些策略依然是最佳实践

您列出的三种策略(修剪、删除、总结)是 LangChain 官方长期推荐的方法,尤其在大模型上下文窗口依然有限的今天(即使 128K 也可能被长对话填满),它们没有过时,反而是生产环境中必须考虑的优化手段。

  • 修剪消息(Trim):临时截断历史,但保留原始状态(State 中的消息列表不变)。适用于临时控制单次请求的 token 消耗。
  • 删除消息(Delete):永久删除 State 中的消息。适用于隐私合规或存储空间优化,但会丢失记忆。
  • 总结消息(Summarize):利用 LLM 将旧消息压缩为摘要,保留信息的同时大幅减少 token。是最推荐的短期记忆管理方式

您给出的SummarizationMiddleware示例是基于LangChain v0.3+ 的中间件机制,这是当前最优雅的实现方式。下面我提供一个完全可运行的代码,并指出您示例中的一个小瑕疵(keep参数理解)。


二、完整可运行代码:使用SummarizationMiddleware管理长对话记忆

以下代码使用 Qwen 模型(替代您示例中的deepseek-chat),演示当消息数量超过阈值时自动触发总结。

# ========== 环境准备 ==========importosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportSummarizationMiddlewarefromlanggraph.checkpoint.memoryimportInMemorySaverfromlangchain_core.messagesimportHumanMessagefromlangchain_core.runnablesimportRunnableConfig load_dotenv()# 1. 初始化 LLM(使用阿里云百炼 Qwen,兼容 OpenAI API)llm=ChatOpenAI(model="qwen-plus",temperature=0.7,api_key=os.getenv("DASHSCOPE_API_KEY"),base_url=os.getenv("DASHSCOPE_BASE_URL","https://dashscope.aliyuncs.com/compatible-mode/v1"),model_kwargs={"extra_body":{"enable_thinking":False}})# 2. 设置 checkpointer(内存版,方便演示)checkpointer=InMemorySaver()# 3. 设置 SummarizationMiddleware# 参数说明:# - model:用于生成摘要的模型(通常与主模型相同,但可以用更便宜的模型)# - trigger:触发摘要的阈值。可以是消息数量、token数或上下文比例# - keep:触发摘要后保留多少条最新消息(注意:不是保留多少条摘要后保留的原始消息数)# 官方文档:keep 表示在生成摘要后,保留的**最近消息数量**(而不是保留的消息数上限)middleware=SummarizationMiddleware(model=llm,# 或者传入 "qwen-plus" 字符串,但建议直接传模型实例trigger=("messages",3),# 当消息数量超过 3 条时(包含本次即将添加的新消息),触发总结keep=("messages",2)# 触发总结后,保留最近 2 条原始消息(其余转为摘要))# 4. 创建 Agentagent=create_agent(model=llm,middleware=[middleware],checkpointer=checkpointer)# 5. 模拟长对话(thread_id = "session_1")config=RunnableConfig(configurable={"thread_id":"session_1"})# 第一轮:用户自我介绍response1=agent.invoke({"messages":[HumanMessage(content="你好,我叫虎哥,我最喜欢猫猫。")]},config=config)print("第1轮回复:",response1["messages"][-1].content)# 第二轮:聊爱好response2=agent.invoke({"messages":[HumanMessage(content="我还喜欢打乒乓球。")]},config=config)print("第2轮回复:",response2["messages"][-1].content)# 第三轮:问一个简单问题,此时历史消息已超过3条(human1, ai1, human2, ai2, human3)# 触发总结:中间件会自动将前2轮对话压缩为摘要,保留最近2条原始消息response3=agent.invoke({"messages":[HumanMessage(content="你还记得我叫什么名字吗?我最喜欢的动物是什么?")]},config=config)print("第3轮回复:",response3["messages"][-1].content)# 观察最终的消息列表(可以看到摘要消息)formsginresponse3["messages"]:msg.pretty_print()

预期输出示例(部分):

第1轮回复: 虎哥你好!很高兴认识你!🐯 喜欢猫猫的人一定很温柔... 第2轮回复: 乒乓球很棒!你平时喜欢单打还是双打? 第3轮回复: 当然记得!你叫虎哥,最喜欢的动物是猫猫。 ================================ Human Message ================================= (摘要)用户名为虎哥,喜欢猫猫和乒乓球。 ================================ Human Message ================================= 你还记得我叫什么名字吗?我最喜欢的动物是什么? ================================== Ai Message ================================== 当然记得!你叫虎哥,最喜欢的动物是猫猫。

三、您示例中需要澄清的细节

  1. keep参数的理解
    您示例中写keep=("messages", 1)表示在生成摘要后,只保留最近 1 条原始消息(其余全部压缩)。这可能导致丢失近期的上下文,建议根据业务场景设置合理的值(如 2~5)。

  2. model参数可以传模型实例
    为了性能,您可以使用一个专门用于摘要的、更小更快的模型(如qwen-turbo),而不是主对话模型。

  3. 修剪 vs 删除 vs 总结

    • 修剪:不修改 State 中的messages,仅在调用模型前做切片。适用于临时测试。
    • 删除:直接修改 State,永久移除消息。谨慎使用。
    • 总结:将旧消息替换为一个SystemMessage(摘要),既保留信息又减少 token,是目前最平衡的方案。

四、持久化 Checkpointer 补充(以 SqliteSaver 为例)

您已经正确展示了SqliteSaver的使用。下面给出一个完整的集成总结消息 + Sqlite 持久化的例子(关键代码):

importsqlite3fromlanggraph.checkpoint.sqliteimportSqliteSaver conn=sqlite3.connect("my_agent_checkpoints.db",check_same_thread=False)checkpointer=SqliteSaver(conn)checkpointer.setup()# 自动建表agent=create_agent(model="qwen-plus",middleware=[SummarizationMiddleware(model=llm,trigger=("messages",10),keep=("messages",5))],checkpointer=checkpointer)

这样,即使重启服务器,之前的对话状态(包括摘要和最近消息)也会从数据库中恢复。


五、面试常见追问

  • Q:总结消息会丢失哪些信息?
    A:摘要由 LLM 生成,可能会丢失细节(如具体数字、情绪色彩),但能保留关键事实和主题。对于需要精确记忆的场景(如法律条款),应结合向量检索。

  • Q:如何选择触发阈值?
    A:根据模型上下文窗口大小和业务对话长度。例如 DeepSeek 128K 窗口,平均每条消息 500 token,则可设置触发阈值为 200 条消息。更推荐按 token 数触发:trigger=("tokens", 100000)

  • Q:LangGraph 的 State 和 Checkpointer 是如何协同工作的?
    A:每次图节点执行后,Checkpointer 会保存完整的State(包括messages)。当使用相同thread_id再次调用时,Checkpointer 自动加载上次保存的 State,实现会话记忆。


六、结论

您提供的资料完全正确且未过时,是目前 LangChain/LangGraph 官方推荐的做法。补充了上述细节后,您完全可以自信地在项目中使用这些策略,并在面试中清晰阐述它们的原理和适用场景。

http://www.jsqmd.com/news/986061/

相关文章:

  • 好用的昆明宝马专修哪家 - 英特菲斯
  • 晟邦齿轮电机:JSCC精研驱动方案的性能与市场表现解析 - 资讯焦点
  • 【ROS 2 全栈入门指南一】:从本质认知到环境搭建与核心原理解析
  • i.MX 6UltraLite接口时序详解:从GPMI到QSPI的实战配置与调试
  • 2026年防火涂料品牌综合实力榜:陕川正途领衔,六大防火材料优选 - 深度智识库
  • 从 SQL 美化工具到智能自动补全:开发者生产力工具的发展史
  • 2026 浙江锦鲤鱼池设计施工公司权威排行榜 杭州美村美户园林稳居首位 - 玖叁鹿
  • 2026 赤峰防水补漏哪家靠谱?正规公司排名及避坑价格指南 - 苏易修缮
  • 2026年泰州别墅设计公司|泰州大平层设计公司排行推荐! - 奔跑123
  • 雷达水位计选型指南:原理、型号、优势与行业应用 - 仪表人老张
  • 2026年6月10日六盘水黄金铂金 K 金钻石回收 TOP5 榜单 正规门店实测种草 - 资讯速览
  • 山西工程铝单板
  • 2026年4月络合铁催化剂厂家推荐 - 多才菠萝
  • 破包率从2.5%降至0.2%:吸嘴袋厂家案例解析 - 热点速览
  • 终极指南:3种快速激活Beyond Compare 5的完整解决方案
  • ESXi 6.7支持哪些VMFS版本?VMFS6新旧特性最全教程
  • # 2026 年国内高密度棉布全国五大实力榜:广东广州等地企业现货充足 - 十大品牌榜
  • 2026企业办公家具采购:群兴俊达家具直供解决成本效率痛点 - 热点速览
  • 2026年度EC风机行业技术创新TOP5品牌榜单 - 资讯焦点
  • 9大网盘高速下载终极方案:LinkSwift直链解析工具完全指南
  • 2026 营口厨卫屋面地下室漏水瓷砖空鼓测评:吉修匠 99.8 分五星榜首 - 吉修匠
  • AI外贸培训哪家课程好
  • 2026 Django+Llama 4 AI应用实战 | 第 5 讲:AI 的灵感大脑——Django 集成 RAG(检索增强生成)与文档向量化
  • i.MX 6UltraLite引脚配置与硬件设计实战指南
  • 【WorkBuddy专栏17】一个 AI 不够用?WorkBuddy SubAgent 多智能体协作系统深度拆解
  • 2026最新安徽合肥理工学校无人机 / 汽修专业怎么报名?招生办联系方式怎么找? - cc江江
  • 佛山二手车买卖公司排行:合规与服务实力大盘点 - 奔跑123
  • 化工厂地坪如何抵御强酸强碱腐蚀?聚氨酯砂浆耐腐蚀方案——港珠澳大桥人工岛地坪施工商 - 热点速览
  • 百度蜘蛛池真的有用吗?
  • 3DS游戏格式转换架构深度解析:从CCI到CIA的技术实现原理