LangChain 入门 Memory 会话记忆

目录

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}})]}
相关推荐
眠りたいです3 小时前
LangChainv1:agent快速上手与中间件认识
人工智能·python·中间件·langchain·langgraph
阳区欠15 小时前
【LangChain】LLM基础介绍
开发语言·python·langchain
动能小子ohhh17 小时前
DocForge平台的设计与开发--文件上传接口的实现
开发语言·人工智能·python·langchain·ocr·fastapi
颜酱18 小时前
LangChain LCEL Chain 零基础入门指南
langchain
颜酱20 小时前
LangChain调用向量模型,存入向量数据库
python·langchain
wuhen_n21 小时前
RAG 核心:向量嵌入与本地向量数据库实战
前端·langchain·ai编程
冷小鱼21 小时前
LangChain 系统性科普:从入门到架构设计
langchain
wuhen_n21 小时前
RAG 关键环节:文本分块策略与最优参数配置
前端·langchain·ai编程
矩阵科学1 天前
Langchain.js 实战四:工具的使用
langchain·node.js