惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
雷峰网
雷峰网
J
Java Code Geeks
G
Google Developers Blog
博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
L
LangChain Blog
人人都是产品经理
人人都是产品经理
GbyAI
GbyAI
Vercel News
Vercel News
S
SegmentFault 最新的问题
Engineering at Meta
Engineering at Meta
H
Hackread – Cybersecurity News, Data Breaches, AI and More
云风的 BLOG
云风的 BLOG
F
Fortinet All Blogs
Y
Y Combinator Blog
博客园_首页
Last Week in AI
Last Week in AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
A
About on SuperTechFans
B
Blog
Microsoft Security Blog
Microsoft Security Blog

博客园 - Zhentiw

[GenAI] Migration Plan: Flat API → Layered Architecture [Skill] Frontend Design Skill Claude Code Hooks: Complete Guide [GenAI] Pre-retieval overview [GenAI] About Indexing [GenAI] Indexing overview [Vibe Coding] 降低大模型幻觉 - 重试机制 [Vibe coding] 降低大模型幻觉 - JSON 安全输出提示词 [Node.js] WebSocket基础知识 [LangGraph] 应用结构 [LangGrpah] Unit testing [LangGraph] Functional API [LangGraph] 中断注意事项 [LangGraph] 中断相关细节 [LangGrpah] 静态断点 [LangGrpah] 非阻塞式中断 [LangGraph] 阻塞式中断 [LangGraph] 语义搜索 [LangGraph] 长期记忆 [LangGraph] 自定义checkpointer [LangGraph] 短期记忆 [LangGraph] 时间旅行 [LangGraph] checkpoint常用API [LangGraph] 元数据标记 [LangGraph] 流 [Vitest] mockClear, mockReset, mockRestore [LangGraph] 将子图添加为节点
[LangGraph] 管理短期记忆
Zhentiw · 2026-03-11 · via 博客园 - Zhentiw

随着对话会随着轮数不断增长。

这时候,一个非常现实的问题就会出现:对话越聊越长,最终可能会超出大模型的上下文窗口限制。

这并不是 langgraph 独有的问题,而是所有基于大模型的长对话系统都会遇到的限制。

为了解决这个问题,通常有几种常见的处理思路。

  1. 裁剪消息
  2. 永久删除消息
  3. 总结消息
  4. 自定义策略

1. 裁剪消息

最简单的做法是:在每次调用 LLM 之前,只保留一部分对话消息。

例如:

  • 只保留最近的 N 轮对话
  • 或者删除最早的几条消息

这种方式的优点是实现简单、成本低;但缺点也很明显:被裁掉的内容,大模型就“彻底不知道了”。

因此,它更适合用于对历史依赖不强的聊天场景。

2. 永久删除消息

和裁剪类似,但更加彻底:

  • 不是“这一次不用”
  • 而是直接从 langgraph 的 State 中删除

一旦删除,这些消息就不会再参与后续的流程,也不会被 checkpoint 记录。

这种方式适合那些:

  • 明确已经“失去价值”的历史消息
  • 或者只对当前流程阶段有意义的临时信息

3. 总结消息

相比简单裁剪,更合理的一种方式是:把早期对话“压缩成一段总结”。

做法通常是:

  1. 将较早的对话内容交给 LLM
  2. 生成一段摘要
  3. 用这段摘要,替换原本冗长的消息列表

这样一来:

  • 大模型仍然能“知道之前发生了什么”
  • 但上下文占用大幅减少

这也是实际项目中最常见、最平衡的一种方案。

// 这是图里面的一个节点:用于对对话进行压缩总结的
import type { TState } from "./state.ts";
import { KEEP_LAST_N_MESSAGES } from "./config.ts";
import { model } from "./model.ts";
import { AIMessage } from "@langchain/core/messages";

export async function summarizeNode(state: TState): Promise<Partial<TState>> {
  console.log("📝 正在对早期对话进行总结...");

  // 拿出需要被总结的旧消息
  const messagesToSummarize = state.messages.slice(
    0,
    state.messages.length - KEEP_LAST_N_MESSAGES,
  );

  // 构造总结 Prompt
  const summaryPrompt = `
  请将以下对话内容总结成一段简短的中文摘要,
  保留关键信息和上下文,不要逐条列举:
  
  ${messagesToSummarize.map((m) => `${m.type}: ${m.content}`).join("\n")}
  `;

  // 调用大模型得到摘要结果
  const summaryResponse = await model.invoke(summaryPrompt);

  const summaryContent =
    typeof summaryResponse.content === "string"
      ? summaryResponse.content
      : JSON.stringify(summaryResponse.content);

  // 输出总结后的内容
  console.log("\n" + "=".repeat(50));
  console.log("🧹 触发历史消息总结 (Summarization)");
  console.log(`📝 摘要内容: ${summaryContent}`);
  console.log("=".repeat(50) + "\n");

  // 这个相当于就是一条信息
  const summaryMessage = new AIMessage(`【对话摘要】${summaryContent}`);

  // 上面的这一条 AIMessage 就需要去替换原来对话历史里面对应条数的对话
  const newMessages = [
    summaryMessage,
    ...state.messages.slice(-KEEP_LAST_N_MESSAGES),
  ];

  return {
    messages: newMessages,
  };
}

4. 自定义策略

在真实业务中,往往不会只用上述某一种方法,而是组合使用。例如:

  • messages 里,只保留「最近的 + 必要的」
  • 早期对话,压缩成摘要
  • 无关内容直接过滤
  • 关键事实,单独写入长期记忆

这样混合使用,可以取各种策略的优点。总之,自定义策略的核心目标只有一个:让模型在不超出上下文限制的前提下,依然能“知道自己在干什么”。