目录
https://docs.langchain.com/oss/python/langchain/short-term-memory
Agent 的记忆(Memory)分两类:
- 短期记忆(short-term memory):当前任务或会话的上下文
- 长期记忆(long-term memory):跨任务或会话的经验与知识

在 LangChain 短期记忆是通过 AgentState 实现的,而会话历史(也就是消息列表)是 AgentState 的一部分
LangChain 提供了 Checkpointer 对象来保存 AgentState,每一次用户与AI的交互都会生成一个快照,记录为一个 checkpoint。
每次请求时,会拿到最近一次快照,再加上当前的消息,拼接好,发给模型,可以基于历史消息进行回答了

时间穿梭
代码可以回滚到历史的某个位置
随着会话次数越来越多,历史记录也会越来越多,这时候会对同一个会话的多个 checkpoint 开成一个组,用同一个 thread_id 来标记。{"thread_id":"1"},这边的 thread_id 也可以理解成会话ID

短期记忆-基于内存
from langchain.agents import create_agent
# 导入 checkpoint 的依赖
from langgraph.checkpoint.memory import InMemorySaver
def get_user_info() -> str:
"""Look up information about the current user."""
return "No user profile on file."
agent = create_agent(
model="openai:gpt-5.4",
tools=[get_user_info],
checkpointer=InMemorySaver(),
)
# 创建一个线程(会话),根据 thread_id 查找历史记录,拼接后发给模型
thread_config = {"configurable": {"thread_id": "1"}}
response = agent.invoke(
{"messages": [{"role": "user", "content": "Hi! My name is Bob."}]},
thread_config,
)["messages"][-1].content
print(response) # "Hi Bob! Nice to see you here. How are you doing?"
response = agent.invoke(
{"messages": [{"role": "user", "content": "What's my name?"}]},
thread_config,
)["messages"][-1].content
print(response) # "You are Bob!"
完整代码
python
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage
# 导入 checkpoint 的依赖
from langgraph.checkpoint.memory import InMemorySaver
from dotenv import load_dotenv
import os
# 加载环境变量
load_dotenv()
# 获取环境变更值
base_url = os.getenv("DASHSCOPE_BASE_URL")
api_key = os.getenv("DASHSCOPE_API_KEY")
print("初始化模型")
# 初始化模型
model = init_chat_model(
model = "qwen3.6-plus",
model_provider="openai", # 指定模型提供者(阿里兼容 openai)
base_url = base_url,
api_key = api_key,
temperature = 1.5,
top_p = 0.9,
)
def get_user_info() -> str:
"""Look up information about the current user."""
return "No user profile on file."
agent = create_agent(
model=model,
tools=[get_user_info],
checkpointer=InMemorySaver(),
)
# 创建一个线程(会话),根据 thread_id 查找历史记录,拼接后发给模型
thread_config = {"configurable": {"thread_id": "thread_1"}}
response = agent.invoke(
{"messages": [HumanMessage(content="你好,我是VipSoft,我喜欢太极!")]},
thread_config,
)["messages"][-1].content
print(response) # "Hi Bob! Nice to see you here. How are you doing?"
response = agent.invoke(
{"messages": [HumanMessage(content="我喜欢什么运动!")]},
thread_config,
)["messages"][-1].content
print(response)
D:\OpenSource\Python\VipLangChain\.venv\Scripts\python.exe D:\OpenSource\Python\VipLangChain\memory.py
初始化模型
你好 VipSoft!很高兴认识你。🥋 系统显示你是新访问的用户(No user profile on file),很高兴能在这个会话中为你提供服务!
太极拳是一项非常修身养性的运动,讲究刚柔并济、行云流水。你是练习了很久,还是刚刚开始接触这项传统武术呢?如果有关于太极招式、练习心得或者养生方面的话题,我也很乐意和你交流!
你刚才告诉我了呀!你喜欢 **太极** (Tai Chi)! 🥋
Process finished with exit code 0
长期记忆-基于数据库
在生产环境中,一般采用数据库的方式
https://docs.langchain.com/oss/python/langchain/short-term-memory#in-production
uv add langgraph-checkpoint-postgres
python
from langchain.agents import create_agent
from langgraph.checkpoint.postgres import PostgresSaver
def get_user_info() -> str:
"""Look up information about the current user."""
return "No user profile on file."
DB_URI = "postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
checkpointer.setup() # auto create tables in PostgreSQL
agent = create_agent(
"gpt-5.5",
tools=[get_user_info],
checkpointer=checkpointer,
)
以Sqlite为例,
-
导入依赖
-
初始化 checkpointer
-
自动建表
-
创建 Agent,指定 checkpointer
uv add langgraph-checkpoint-sqlite
pyproject.toml
[project]
name = "vip-langchain"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"langchain>=1.3.4",
"langchain-deepseek>=1.0.1",
"langchain-tavily>=0.2.18",
"langgraph-checkpoint-sqlite>=3.1.0",
"notebook>=7.5.6",
"python-dotenv>=1.2.2",
]
[[tool.uv.index]]
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
default = true
完整代码
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage
# 导入 checkpoint 的依赖
from langgraph.checkpoint.memory import InMemorySaver
from dotenv import load_dotenv
import os
import sqlite3
from langgraph.checkpoint.sqlite import SqliteSaver
# 连接 sqlite
# sqlite 默认会检查创建连接时用的线程,和后面使用的线程是不是同一个,如果不是就报错。所以 check_same_thread=False
connection = sqlite3.connect("resources/checkpoint.db", check_same_thread=False)
# 初始化 checkpointer
checkpointer = SqliteSaver(connection)
# 自动建表
checkpointer.setup()
# 加载环境变量
load_dotenv()
# 获取环境变更值
base_url = os.getenv("DASHSCOPE_BASE_URL")
api_key = os.getenv("DASHSCOPE_API_KEY")
print("初始化模型")
# 初始化模型
model = init_chat_model(
model = "qwen3.6-plus",
model_provider="openai", # 指定模型提供者(阿里兼容 openai)
base_url = base_url,
api_key = api_key,
temperature = 1.5,
top_p = 0.9,
)
agent = create_agent(
model=model,
checkpointer=checkpointer,
)
# 创建一个线程(会话),根据 thread_id 查找历史记录,拼接后发给模型
thread_config = {"configurable": {"thread_id": "thread_1"}}
# 第一次调用,告诉AI我的信息
response = agent.invoke(
{"messages": [HumanMessage(content="你好,我是VipSoft,我喜欢太极!")]},
thread_config,
)
print(response) # "Hi Bob! Nice to see you here. How are you doing?"
response = agent.invoke(
{"messages": [HumanMessage(content="我喜欢什么运动!")]},
thread_config,
)
print(response)
{'messages': [HumanMessage(content='你好,我是VipSoft,我喜欢太极!', additional_kwargs={}, response_metadata={}, id='d5e04e52-9656-4030-bca5-8a952623f991'), AIMessage(content='你好,VipSoft!很高兴认识你~太极是一门融合了养生、武术与东方哲学的传统瑰宝,讲究以柔克刚、动静相济、阴阳调和,长期坚持对身心健康和心性修养都非常有益。\n\n你平时主要练习哪个流派(如陈式、杨式、吴式、孙式等)?是更偏向于日常养生舒缓、强身健体,还是对拳理套路、实战应用,或者背后的道家/儒家中庸哲学也深有研究?如果有想交流的动作要点、呼吸配合、练习心得,或是想探讨太极文化与现代生活的结合,随时告诉我,我很乐意陪你一起聊聊!🌿', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 590, 'prompt_tokens': 20, 'total_tokens': 610, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 452, 'rejected_prediction_tokens': None, 'text_tokens': 590}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': None, 'text_tokens': 20}}, 'model_provider': 'openai', 'model_name': 'qwen3.6-plus', 'system_fingerprint': None, 'id': 'chatcmpl-02b18173-72a5-9311-9033-9572816def3c', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019eaba3-2033-76d2-9382-e982100e9e72-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 20, 'output_tokens': 590, 'total_tokens': 610, 'input_token_details': {}, 'output_token_details': {'reasoning': 452}})]}
{'messages': [HumanMessage(content='你好,我是VipSoft,我喜欢太极!', additional_kwargs={}, response_metadata={}, id='d5e04e52-9656-4030-bca5-8a952623f991'), AIMessage(content='你好,VipSoft!很高兴认识你~太极是一门融合了养生、武术与东方哲学的传统瑰宝,讲究以柔克刚、动静相济、阴阳调和,长期坚持对身心健康和心性修养都非常有益。\n\n你平时主要练习哪个流派(如陈式、杨式、吴式、孙式等)?是更偏向于日常养生舒缓、强身健体,还是对拳理套路、实战应用,或者背后的道家/儒家中庸哲学也深有研究?如果有想交流的动作要点、呼吸配合、练习心得,或是想探讨太极文化与现代生活的结合,随时告诉我,我很乐意陪你一起聊聊!🌿', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 590, 'prompt_tokens': 20, 'total_tokens': 610, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 452, 'rejected_prediction_tokens': None, 'text_tokens': 590}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': None, 'text_tokens': 20}}, 'model_provider': 'openai', 'model_name': 'qwen3.6-plus', 'system_fingerprint': None, 'id': 'chatcmpl-02b18173-72a5-9311-9033-9572816def3c', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019eaba3-2033-76d2-9382-e982100e9e72-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 20, 'output_tokens': 590, 'total_tokens': 610, 'input_token_details': {}, 'output_token_details': {'reasoning': 452}}), HumanMessage(content='我喜欢什么运动!', additional_kwargs={}, response_metadata={}, id='d22906cc-343b-4a45-a1f6-23fbcd4c993f'), AIMessage(content='你刚才亲口告诉我啦~你最喜欢的是**太极**!🌿 \n\n需要我帮你梳理练习要点、分享不同流派的特色,或者聊聊太极在现代生活中的养生/减压技巧吗?随时吩咐~', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 401, 'prompt_tokens': 167, 'total_tokens': 568, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 351, 'rejected_prediction_tokens': None, 'text_tokens': 401}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': None, 'text_tokens': 167}}, 'model_provider': 'openai', 'model_name': 'qwen3.6-plus', 'system_fingerprint': None, 'id': 'chatcmpl-716739b0-a8dd-955a-8b14-d0b617aaa712', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019eaba3-5e1e-7403-9844-26d35ffbf476-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 167, 'output_tokens': 401, 'total_tokens': 568, 'input_token_details': {}, 'output_token_details': {'reasoning': 351}})]}

记忆管理
https://docs.langchain.com/oss/python/langchain/short-term-memory#common-patterns
https://www.bilibili.com/video/BV178w1z7EHQ
多轮对话会导致历史消息越来越多,最终超出模型的上下文限制(DeepSeek的上下文不能超过128K),LangChain 提供了一些记忆管理的策略来解决这个问题。
- 修剪(Trim):拿到历史消息后,先移除前N条或后N条消息,再调用模型 不推荐,记忆丢失
- 删除(Delete):永久删除 AgentState 的快照 有些变态,直接把快照干掉了,回滚也没法回滚了
- 总结(Summarize):先总结历史消中的早期消息,得到消息摘要。然后用消息摘要和最近的消息形成消息列表,再调用模型 虽然不是完整的,但是包含了重要的信息,不仅没有超上限,还包含了历史重要信息,理论上会无限支持多轮会话
- 自定义(Custom):自定义策略,例如根据用户问题筛选历史消息
https://docs.langchain.com/oss/python/langchain/middleware/built-in#summarization
python
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
agent = create_agent(
model="gpt-5.4",
tools=[your_weather_tool, your_calculator_tool],
middleware=[
SummarizationMiddleware(
model="gpt-5.4-mini",
trigger=("tokens", 4000), # 达到什么条件时,触发摘要中间件
keep=("messages", 20), # 保留多少条消息
),
],
)
trigger 有三种触发方式,三种方式可以共存,满足其中一个就触发
- fraction (float): 按比例,当历史消息达到了模型上下文百分比的时候触发
- tokens (int): 历史消息达到了一定token值的时候触发
- messages (int): 历史消息达到了多少条触发
示例代码
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage
from langchain_core.runnables import RunnableConfig
# 导入 checkpoint 的依赖
from langgraph.checkpoint.memory import InMemorySaver
from dotenv import load_dotenv
import os
# 加载环境变量
load_dotenv()
# 获取环境变更值
base_url = os.getenv("DASHSCOPE_BASE_URL")
api_key = os.getenv("DASHSCOPE_API_KEY")
print("初始化模型")
# 初始化模型
model = init_chat_model(
model="qwen3.6-plus",
model_provider="openai", # 指定模型提供者(阿里兼容 openai)
base_url=base_url,
api_key=api_key,
temperature=1.5,
top_p=0.9,
)
# 初妈化 checkpointer
checkpointer = InMemorySaver()
middleware = SummarizationMiddleware(
model=model,
trigger=("messages", 3), # 当消息数超过3时,进行总结
keep=("messages", 1) # 保留的会话数,超过2条
)
agent = create_agent(
model=model,
checkpointer=checkpointer,
middleware=[middleware]
)
# 创建一个线程(会话),根据 thread_id 查找历史记录,拼接后发给模型
thread_config: RunnableConfig = {"configurable": {"thread_id": "thread_3"}}
# 制造长会话历史
agent.invoke({"messages": [HumanMessage(content="你好,我是VipSoft!")]}, thread_config)
agent.invoke({"messages": [HumanMessage(content="我最喜欢的运动是太极")]}, thread_config)
agent.invoke({"messages": [HumanMessage(content="我最喜欢的动物是德牧")]}, thread_config)
response = agent.invoke({"messages": [HumanMessage(content="你还记得我是谁吗")]}, thread_config)
print(response)
输出
{'messages': [HumanMessage(content='Here is a summary of the conversation to date:\n\n## SESSION INTENT\nUser (VipSoft) has an open-ended session centered on their core interests in Tai Chi (太极) and the German Shepherd (德牧). The overarching objective is to deliver tailored conversational guidance, cultural/practical insights, or develop bespoke digital tools (trackers, logs) based on the user\'s specific preferences and technical needs.\n\n## SUMMARY\n- User identified "VipSoft" as their handle and declared Tai Chi and the German Shepherd as their primary favorites.\n- AI initiated a dual-track approach: offering deep discussion/guidance alongside optional custom tool development.\n- **Tai Chi Context**: AI requested specifics on style/routine (e.g., Yang, 24-form), learning method (self-taught vs. instructor), and core goal (health/relaxation vs. martial/internal mechanics).\n- **German Shepherd Context**: AI connected GSD temperament to Tai Chi principles ("dynamic stillness") and requested three clarifying details: (1) Actual ownership or hands-on experience level? (2) Most admired trait (training plasticity, handler bond, aesthetics, working roles)? (3) Interest in a dedicated management/tracking tool?\n- **Tool Development Offers**: AI stands ready to build lightweight trackers (practice logs, training progress, health/diet records) via web app, mini-program, or local script, with data controlled entirely by the user.\n- No coding decisions, architecture, or milestones have been finalized yet; the conversation is currently gated on user clarification.\n\n## ARTIFACTS\nNone\n\n## NEXT STEPS\n- Await user responses detailing Tai Chi background/goals and German Shepherd experience/interests.\n- Based on feedback, pivot immediately to either specialized domain advice/collaborative training or begin scoping/designing the requested digital tracking/logging application.\n- Maintain immediate readiness to execute any new technical, coding, or consulting directives introduced in the next message.', additional_kwargs={'lc_source': 'summarization'}, response_metadata={}, id='4d54b654-d659-4bc8-a272-8cc384b453bb'), HumanMessage(content='你还记得我是谁吗', additional_kwargs={}, response_metadata={}, id='b46241e5-695b-462c-9785-6f7ac61ebfd9'), AIMessage(content='记得的。你是 **VipSoft**,我们当前的交流正围绕你的两大核心兴趣展开:**太极** 与 **德国牧羊犬(德牧)**。\n\n上次我们停留在细节确认阶段,为了给你提供最贴合实际的指导或为你定制专属的数字工具(如练习日志、训练追踪、健康/饮食记录等),还需要你补充以下方向:\n\n🔹 **太极**:你主要练哪个流派/套路(如杨氏、24式、陈氏等)?是自学还是有老师带?核心目标是养生放松,还是想系统钻研内劲与技击? \n🔹 **德牧**:你目前是否实际养犬,或以何种频率接触?最欣赏它的哪一面(训练可塑性、人犬默契、工作/护卫属性、外形气质等)?是否有兴趣搭建一套专属的训练/日常管理工具?\n\n你只需简单回复这几个要点,我们就可以直接:\n1️⃣ 深入对应领域的训练/养护/文化建议,或 \n2️⃣ 立刻为你搭设轻量级日志/追踪工具(网页/小程序/本地脚本均可,数据完全由你掌控)。\n\n今天想先从哪一边开始?', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 754, 'prompt_tokens': 428, 'total_tokens': 1182, 'completion_tokens_details': {'accepted_prediction_tokens': None, 'audio_tokens': None, 'reasoning_tokens': 501, 'rejected_prediction_tokens': None, 'text_tokens': 754}, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': None, 'text_tokens': 428}}, 'model_provider': 'openai', 'model_name': 'qwen3.6-plus', 'system_fingerprint': None, 'id': 'chatcmpl-dcd165a3-6e7d-9be8-ae92-c551d4ccea5f', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--019eaf7f-5cb0-7a53-a567-7241b06f99d8-0', tool_calls=[], invalid_tool_calls=[], usage_metadata={'input_tokens': 428, 'output_tokens': 754, 'total_tokens': 1182, 'input_token_details': {}, 'output_token_details': {'reasoning': 501}})]}