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

推荐订阅源

S
Security @ Cisco Blogs
H
Hacker News: Front Page
P
Privacy International News Feed
N
News and Events Feed by Topic
T
Threatpost
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
K
Kaspersky official blog
S
Secure Thoughts
V2EX - 技术
V2EX - 技术
Security Latest
Security Latest
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
L
Lohrmann on Cybersecurity
Jina AI
Jina AI
P
Proofpoint News Feed
AI
AI
雷峰网
雷峰网
T
Tailwind CSS Blog
Engineering at Meta
Engineering at Meta
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 叶小钗
Webroot Blog
Webroot Blog
Apple Machine Learning Research
Apple Machine Learning Research
SecWiki News
SecWiki News
罗磊的独立博客
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
Google DeepMind News
Google DeepMind News
Cyberwarzone
Cyberwarzone
MongoDB | Blog
MongoDB | Blog
博客园 - Franky
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
S
Security Affairs
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
月光博客
月光博客
D
Docker
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
S
Securelist
W
WeLiveSecurity
T
Troy Hunt's Blog
A
Arctic Wolf
博客园 - 司徒正美

博客园 - 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] 管理短期记忆 [LangGraph] 自定义checkpointer [LangGraph] 时间旅行 [LangGraph] checkpoint常用API [LangGraph] 元数据标记 [LangGraph] 流 [Vitest] mockClear, mockReset, mockRestore [LangGraph] 将子图添加为节点
[LangGraph] 短期记忆
Zhentiw · 2026-03-08 · via 博客园 - Zhentiw

这节课我们来介绍一下记忆。在 langgraph 中,记忆分为两种:

  • 短期记忆:Short-term Memory
  • 长期记忆:Long-term Memory

基本概念

所谓短期记忆,指的就是在某一个 thread 内持续演化的 State。只要 State 在同一个 thread_id 下被反复传入和更新,agent 就具备了多轮对话的能力。

举个例子,假设我们在 StateGraph 里定义了一个 State

type State = {
  messages: Message[];
  topic?: string;
  plan?: string;
}

State 里装的内容,本身就是短期记忆。多轮对话能成立,靠的是这三件事一起配合:

  1. State 会在同一个 thread_id 下持续存在
  2. 每一轮执行,都会把上一次的 State 传进来
  3. 新节点在旧 State 的基础上继续改

例如:

// 第 1 轮
State.messages = ["你好"]

// 第 2 轮
State.messages = ["你好", "你是谁"]

// 第 3 轮
State.messages = ["你好", "你是谁", "我们刚刚聊了什么"]

另外,这里一定要注意,短期记忆是和 thread 绑定的,也就是说:

  • thread_id = A 有一份独立的 State
  • thread_id = B 是另一份完全不同的 State

只要 thread 不同:短期记忆就不共享。这也是为什么官网说它是 short-term,因为它的生命周期是:

从 thread 开始 → 到 thread 结束

而不是:

  • 跨会话
  • 跨线程
  • 跨用户

快速上手

下面我们通过一个快速上手示例来验证:

  • 不同用户 → 不同 thread
  • 切换用户 → 短期记忆立即切换
  • 不使用 Store(长期记忆)
  • 只使用 State + MemorySaver

用户设计

用户名 密码 thread_id
aaa 111 thread-aaa
bbb 222 thread-bbb

每个用户固定使用一个 thread_id

import "dotenv/config";
import { ChatOpenAI } from "@langchain/openai";
import {
  MemorySaver,
  StateGraph,
  START,
  END,
  MessagesZodMeta,
} from "@langchain/langgraph";
import { z } from "zod/v4";
import readline from "readline-sync";
import { HumanMessage, BaseMessage } from "@langchain/core/messages";
import { registry } from "@langchain/langgraph/zod";

// 用户系统
const users = {
  aaa: { password: "111", thread_id: "thread-aaa" },
  bbb: { password: "222", thread_id: "thread-bbb" },
};

const Schema = z.object({
  messages: z.array(z.custom<BaseMessage>()).register(registry, {
    ...MessagesZodMeta,
    default: () => [],
  }),
});

type TState = z.infer<typeof Schema>;

const model = new ChatOpenAI({
  model: "gpt-4o",
  temperature: 0.5,
});

// 聊天的节点
async function chatNode(state: TState): Promise<Partial<TState>> {
  const res = await model.invoke(state.messages);

  return {
    messages: [res],
  };
}

const checkpointer = new MemorySaver();

// 图
const graph = new StateGraph(Schema)
  .addNode("chatNode", chatNode)
  .addEdge(START, "chatNode")
  .addEdge("chatNode", END)
  .compile({ checkpointer });

async function main() {
  while (true) {
    console.log("\n--- 登录 ---");
    const username = readline.question("请输入用户名:");
    const password = readline.question("请输入密码:", {
      hideEchoBack: true,
    });

    const user = users[username];

    if (!user || user.password !== password) {
      console.log("登录失败☹️");
      continue;
    }

    // 登录成功
    console.log(`✅ 登录成功,当前用户:${username}`);
    console.log("输入 /switch 可切换用户\n");

    const config = {
      configurable: {
        thread_id: user.thread_id, // 这个非常重要,这个保证了不同的用户拥有不同的state
      },
    };

    // 处理用户的对话
    while (true) {
      const input = readline.question(`${username}>`);

      if (input === "/switch") {
        console.log("切换用户中...");
        break;
      }

      // 这里只需要传入当前这一轮的输入消息
      const result = await graph.invoke(
        {
          messages: [new HumanMessage(input)],
        },
        config,
      );

      // 返回的结果就是完整的状态
      const aiMsg = result.messages.at(-1);

      console.log(`AI> ${aiMsg?.content}`);
    }
  }
}
main();


-EOF-