113.Agent-LangChain核心组件-大模型Short-term_memory短期记忆和PostgreSQL记忆存储

内容参考于:图灵AI大模型全栈

记忆在人工智能体中是很重要的,跟你们人类的记忆一样,如果你们人类没有记忆相比较于有记忆的人类会很不智能,所以人工智能体也是需要记忆才能更加的智能,短期记忆通常是聊天记录,现在对于大篇幅的聊天记录大模型没办法做到百分百记住完整的聊天记录,会存在丢失的情况,就跟你们人类记的东西多了,最早记的东西可能就会忘记,这就会有策略来压缩聊天记录

短期记忆它实际上是State状态,也就是把State状态存储起来

这里的短期记忆是线程级别的,相当于一次对话,在LangChain中它是checkpointer检查点

效果图:前两次使用同一个线程id,它是记得我是谁的,第三次更换的线程id,它就不记得我是谁了

如下图红框,第二次提问时,会带着第一次提问的问题和回复一起发给大模型

代码:下方的代码记忆都是保存在内存中,代码结束就没了,生产环境是要持久化(保存)到硬盘上的

python 复制代码
# =============================================================================
# 【文件说明】
# 这段代码演示了如何使用 LangChain 1.x + LangGraph 构建一个"带记忆能力的 Agent"。
# 核心亮点:
#   1) 用 create_agent 一行代码创建智能体(替代了旧版的 initialize_agent / AgentExecutor)
#   2) 用 InMemorySaver 做"会话记忆持久化",让 Agent 能跨多轮对话记住上下文
#   3) 用 thread_id 区分不同用户 / 不同会话,实现"同人多轮共享记忆,不同人记忆隔离"
# =============================================================================

# create_agent:LangChain 1.x 提供的"快速创建 Agent"的工厂函数
# 它内部会自动帮我们装配好:模型、工具、提示词、ReAct 循环、状态管理
from langchain.agents import create_agent

# InMemorySaver:LangGraph 提供的一种"内存检查点存储器"
# 作用是把每一轮对话的状态(messages、工具调用记录等)快照保存下来,
# 让 Agent 在多轮对话中"记得住"之前的上下文。
# 注意:它保存在内存里,程序重启后记忆就没了(生产环境一般换成 Redis / Postgres 等持久化方案)
from langgraph.checkpoint.memory import InMemorySaver

# ChatOpenAI:LangChain 对 OpenAI 协议模型的封装
# 因为通义千问 DashScope 提供了兼容 OpenAI 的接口,所以可以直接用它来调用 qwen 模型
from langchain_openai import ChatOpenAI

# dotenv:从 .env 文件读取环境变量,避免把 API Key 硬编码在代码里
from dotenv import load_dotenv

# os:用于读取环境变量
import os


# =============================================================================
# 【第一步】加载 .env 中的环境变量
# 比如 .env 内容:
#   DASHSCOPE_API_KEY=sk-xxxxxxxx
#   DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
# =============================================================================
load_dotenv()


# =============================================================================
# 【第二步】初始化大模型
# 通过 ChatOpenAI 封装层调用 qwen 模型(利用了 DashScope 的 OpenAI 兼容接口)
# =============================================================================
llm = ChatOpenAI(
    model="qwen3.7-flash",                     # 模型名称
    api_key=os.getenv("DASHSCOPE_API_KEY"),    # 从环境变量读取 API Key
    base_url=os.getenv("DASHSCOPE_BASE_URL")   # 从环境变量读取 API 基础地址
)


# =============================================================================
# 【第三步】创建 Agent 实例
# create_agent 会把 model + checkpointer(+ 后续可选的 tools/prompt 等) 组装成一个可调用的 Agent。
#
# 参数说明:
#   - model:指定底层使用的大模型
#   - checkpointer:检查点存储器,决定 Agent 的"记忆"能力
#       * 传入 InMemorySaver() 后,LangGraph 会在每次 invoke 前后自动保存/恢复状态
#       * 不传的话,Agent 就是"无记忆"的,每次对话都是全新开始
# =============================================================================
agent = create_agent(
    model=llm,
    checkpointer=InMemorySaver(),  # 用内存方式保存对话状态,同一线程内的多轮对话可以共享上下文
)


# =============================================================================
# 【第四步】定义线程配置
# LangGraph 中,状态是按 thread_id 隔离的:
#   - 同一个 thread_id:多轮对话共享同一份历史(Agent 记得住)
#   - 不同 thread_id:各自独立,互不影响(相当于不同用户的会话)
# 这里用 "user_1" 作为线程 ID,代表"当前用户"。
# =============================================================================
thread_config1 = {"configurable": {"thread_id": "user_1"}}
thread_config2 = {"configurable": {"thread_id": "user_2"}}


# =============================================================================
# 【第五步】第一轮对话:告诉 Agent 用户的名字
# 注意:
#   - invoke 的入参是 {"messages": [...]},一个 messages 列表
#   - 第二个参数 thread_config 会把这次对话挂到 "user_1" 线程下
#   - 返回值是一个状态字典,["messages"][-1].content 取出最后一条 AI 消息的文本内容
# =============================================================================
response = agent.invoke(
    {"messages": [{"role": "user", "content": "你好,我的名字叫做计算机王!"}]},
    thread_config1,   # 把这次对话写到 user_1 这条线程下
)["messages"][-1].content  # 取最后一条消息(即模型的回复)的文本
print("第一次")
print(response)  # 示例输出:"你好,计算机王!很高兴认识你!"


# =============================================================================
# 【第六步】第二轮对话:验证 Agent 是否记住了上一轮的信息
# 因为我们传的是同一个 thread_id="user_1",
# Agent 会从 InMemorySaver 中恢复上一轮的历史消息,
# 因此它能够看到"用户之前说自己叫计算机王"这个信息,并正确回答。
# =============================================================================
response = agent.invoke(
    {"messages": [{"role": "user", "content": "我的名字是什么?"}]},
    thread_config1,   # 同一个 thread_id,因此共享上一轮的记忆
)["messages"][-1].content
print("第二次")
print(response)  # 示例输出:"你的名字是计算机王!"


response = agent.invoke(
    {"messages": [{"role": "user", "content": "我的名字是什么?"}]},
    thread_config2,   # 同一个 thread_id,因此共享上一轮的记忆
)["messages"][-1].content

print("第三次") 
print(response)  # 示例输出:"你的名字是计算机王!"

# =============================================================================
# 【补充说明 · 关于记忆机制】
# 1. InMemorySaver 只在内存中保存,进程一退出就清空。
#    生产中常用:
#      - langgraph.checkpoint.sqlite.SqliteSaver  → 本地 SQLite 持久化
#      - langgraph.checkpoint.postgres.PostgresSaver → 生产级关系数据库
#      - langgraph.checkpoint.redis.RedisSaver → 高性能缓存持久化
#
# 2. 想"开始一段新对话"时,只需换一个 thread_id 即可,例如:
#      new_config = {"configurable": {"thread_id": "user_1_session_2"}}
#    Agent 就会以"空白记忆"重新开始。
#
# 3. 想查看当前线程下的完整消息历史,可以这样取:
#      state = agent.get_state(thread_config)
#      state.values["messages"]   # 所有历史消息
#
# 4. create_agent 还支持传入 tools=[...]、system_prompt=... 等参数,
#    让 Agent 具备调用函数工具、设定角色人设等能力,用法与 OpenAI Function Calling 类似,
#    但循环(Thought → Action → Observation → Answer)由 LangGraph 自动调度,
#    无需像裸调 OpenAI SDK 那样手写 "第一次调用 → 执行工具 → 第二次调用"。
# =============================================================================

它的持久化使用的数据库是 postgres,一般都使用postgres(全称postgresql)

下方链接是LangChain关于持久化检查点的说明和可用数据库

https://docs.langchain.com/oss/python/langgraph/checkpointers#checkpointer-libraries

postgres是需要下载安装的

首先安装库

复制代码
uv add langgraph-checkpoint-postgres "psycopg[binary]"

然后使用Docker安装postgres 数据库,如下图红框,点击pull就会安装了

点击下图红框就可以运行了,注意下图蓝框,它是postgres 的版本不是上图里的Latest版本,这里下载的是apline版本它的体积小

点击上图红框后添加下图的内容,输入完点击Run,它们的说明放在后方了

Container name:容器名称,对应命令 --name=postgresql

Ports:端口映射,对应命令:-p 5432:5432

Volumes:数据卷挂载,它又分 Host path(主机路径)和 Container path(容器路径)对应命令:-v postgre-data:/var/lib/postgresql

Environment variables:环境变量,POSTGRES_PASSWORD是密码,对应命令:-e POSTGRES_PASSWORD=123456 -e LANG=C.UTF-8

出了上方的界面版本还有命令版本,通过上图和下方命令做的事情都是一样的

dockerfile 复制代码
# 1.使用docker下载对应镜像
docker pull postgres:alpine # 这边使用的是体积更小的镜像

# 2.运行对应镜像
docker run -id --name=postgresql -v postgre-data:/var/lib/postgresql -p 5432:5432 -e POSTGRES_PASSWORD=123456 -e LANG=C.UTF-8 postgres:alpine

命令说明

然后点击下图红框运行,如果使用命令的话,使用docker run的就会运行了,不需要再点击下图红框了

如下图红框postgre正在运行

到这就安装完成了,然后连接postgresql数据库

第一次会缺少驱动文件,这里直接点击下载就可以了

如下图默认用户是postgres,密码就是上方使用Docker安装postgresql是设置的密码,这里是123456,也就是POSTGRES_PASSWORD它的值,输入完点击确定就可以了,点击确定直接可以点击下图里的测试连接看看是否正常,如果不正常就根据错误信息问ai

实例

首先创建一个数据库,如下图鼠标右键单击第一步,然后剩下的都是鼠标左键单击

如下图红框,它就可以创建一个数据库了

它要选择一个架构,这里选择默认的

如下图红框选择完架构就正常了,上图选择架构的实例是langchain_agent3数据库,但是都是一样的操作,langchain_agent数据库选择架构时忘记截图了

执行下图红框的代码就会创建下图蓝框里的四张表,如果重复运行下图红框代码不会重复创建表,下图蓝框的4张表就是LangChain用保存记忆的核心表,但是里面都加密了看不出都是些什么内容,它存储了所有聊天记录,每次提问是它都会查询出当前thread_id下所有的记录

效果图:可以看出它查询出了所有聊天记录

完整代码:

python 复制代码
# =============================================================================
# 【文件说明】
# 这个版本和之前用 InMemorySaver 的版本几乎一样,唯一的区别是:
#   把"内存记忆"换成了"Postgres 数据库记忆"。
#
# 好处:
#   - 进程退出后记忆不会丢,重启程序还能接着之前的状态继续对话
#   - 多个实例 / 多台机器可以共享同一份会话状态
#   - 支持按 thread_id 长期保存、查询、回放历史
#
# 核心流程仍然是:
#   创建模型 → 创建 Postgres checkpointer → 用 with 打开连接并 setup → 创建 Agent → 多轮对话共享记忆
# =============================================================================

# create_agent:LangChain 1.x 提供的工厂函数,用来快速创建一个带工具/记忆能力的 Agent
from langchain.agents import create_agent

# 下面这行被注释掉了,因为本示例不再使用"内存存储"
# from langgraph.checkpoint.memory import InMemorySaver

# PostgresSaver:LangGraph 提供的 Postgres 检查点存储器
# 作用:把每一轮对话的状态(messages、工具调用记录等)持久化到 Postgres 里,
#       这样即使程序重启,只要 thread_id 相同,Agent 依然能"记得住"之前的对话。
from langgraph.checkpoint.postgres import PostgresSaver

# ChatOpenAI:LangChain 对 OpenAI 协议模型的封装
# 由于 DashScope 提供了 OpenAI 兼容接口,可以用它来调用 qwen 模型
from langchain_openai import ChatOpenAI

# dotenv:从 .env 文件读取环境变量,避免把密钥硬编码到代码里
from dotenv import load_dotenv

# os:读取环境变量
import os


# =============================================================================
# 【第一步】加载 .env 中的环境变量
# 例如 .env 内容:
#   DASHSCOPE_API_KEY=sk-xxxxxxxx
#   DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
# =============================================================================
load_dotenv()


# =============================================================================
# 【第二步】初始化大模型
# 通过 ChatOpenAI 封装层调用 qwen 模型(利用 DashScope 的 OpenAI 兼容接口)
# =============================================================================
llm = ChatOpenAI(
    model="qwen3.7-flash",                    # 模型名称
    api_key=os.getenv("DASHSCOPE_API_KEY"),   # 从环境变量读取 API Key
    base_url=os.getenv("DASHSCOPE_BASE_URL")  # 从环境变量读取 Base URL
)


# =============================================================================
# 【第三步】数据库连接 URI
# 格式:postgresql://用户名:密码@主机地址:端口号/数据库名称?参数
#
# 这里的含义:
#   - 用户名:postgres
#   - 密码:123456
#   - 主机:localhost(本地)
#   - 端口:5432(Postgres 默认端口)
#   - 数据库:langchain_agent
#   - sslmode=disable:关闭 SSL 加密连接(本地开发一般关闭;生产建议开启)
#
# 使用前提:
#   1) 本机已启动 Postgres 服务
#   2) 已经创建好名为 langchain_agent 的数据库
#      例如:CREATE DATABASE langchain_agent;
#   3) 驱动依赖已安装:pip install langgraph-checkpoint-postgres psycopg[binary]
# =============================================================================
DB_URI = "postgresql://postgres:123456@localhost:5432/langchain_agent?sslmode=disable"


# =============================================================================
# 【第四步】创建 Agent 并执行多轮对话
#
# 关键点:使用 with 语句打开 PostgresSaver 连接(上下文管理器会自动关闭连接)。
# =============================================================================
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:

    # ⚠️ setup() 是必须的一步:
    # 它会在目标数据库里自动创建 LangGraph 所需的表(如 checkpoints、checkpoint_writes 等)。
    # 首次运行必须调用;重复调用也没关系,它是幂等的(已存在就跳过)。
    checkpointer.setup()

    # 创建 Agent 实例,把 Postgres checkpointer 挂上去,
    # 从此 Agent 的每一轮对话状态都会被自动写入 Postgres。
    agent = create_agent(
        llm,
        checkpointer=checkpointer
    )

    # 定义线程配置:
    # LangGraph 中状态按 thread_id 隔离:
    #   - 同一个 thread_id:共享同一份历史消息(Agent 记得住)
    #   - 不同 thread_id:彼此隔离(相当于不同用户的会话)
    thread_config = {"configurable": {"thread_id": "user_1"}}

    # -------- 第一轮对话:告诉 Agent 用户的名字 --------
    # invoke 返回整个状态字典,我们这里直接把整个 response 打印出来观察结构。
    # response 里通常包含 "messages" 字段,记录了本线程下所有历史消息。
    response = agent.invoke(
        {"messages": [{"role": "user", "content": "你好,我的名字叫做计算机王!"}]},
        thread_config,
    )
    print("第一次")
    print(response)

    # -------- 第二轮对话:验证 Agent 是否记住了上一轮的信息 --------
    # 因为 thread_id 相同,Agent 会从 Postgres 中恢复上一轮的状态,
    # 所以它能"看到"用户之前说自己叫计算机王。
    # 即使中途程序重启过,只要数据库没被清空、thread_id 一致,记忆依然存在。
    response = agent.invoke(
        {"messages": [{"role": "user", "content": "我的名字是什么?"}]},
        thread_config,
    )
    print("第二次")
    print(response)

# =============================================================================
# 【补充说明 · Postgres 版记忆机制】
#
# 1. 与 InMemorySaver 的区别:
#      InMemorySaver          → 只在内存里存,程序一退出记忆全丢,多实例无法共享
#      PostgresSaver          → 持久化到 Postgres,重启不丢,多实例可共享(生产推荐)
#
# 2. 打印 response 时你会看到什么?
#      response 是一个 dict,典型结构:
#        {
#          "messages": [
#             HumanMessage(...),      # 第一轮用户消息
#             AIMessage(...),         # 第一轮 AI 回复
#             HumanMessage(...),      # 第二轮用户消息
#             AIMessage(...),         # 第二轮 AI 回复
#          ]
#        }
#      所以第二次打印的 messages 会比第一次多两条,说明状态被累积保存了。
#
# 3. 常见报错及排查:
#      - "connection refused"         → Postgres 服务没启动
#      - "database does not exist"    → 没有创建 langchain_agent 数据库
#      - "password authentication"    → 用户名/密码不对
#      - "relation ... does not exist"→ 忘了调用 checkpointer.setup()
#
# 4. 换成其它持久化后端也很简单:
#      SqliteSaver       → 单文件本地持久化,适合小型部署
#      RedisSaver        → 高性能、支持过期策略
#      PostgresSaver     → 关系型、便于审计与查询(本示例)
#
# 5. 想开新会话只需换个 thread_id,例如:
#      {"configurable": {"thread_id": "user_1_session_2"}}
#    这样 Agent 就会以空白记忆重新开始。
# =============================================================================

相关推荐
用户283209679371 小时前
Function Calling 只是开始:Agent 工具系统到底难在哪
agent
海盗12341 小时前
AI 新闻日报 2026-09-12:Agents API 公测、AI Agent 军团攻击事件、龙猫 2.0 万亿开源
人工智能·开源
仙魁XAN1 小时前
【WorkBuddy·基础入门】第五篇 :模型、权限和工作空间:让 WorkBuddy 做得好,也做得安全
人工智能·安全·workbuddy·workbuddy 基础入门
jimmyleeee1 小时前
大模型安全之十三:威胁建模
人工智能·安全
Rocky Ding*1 小时前
一文读懂LLM Agent Skills 的运行时本质:从能力路由到渐进式披露
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·agent skills
知几蜗牛1 小时前
图片一多首字就慢?用EPD拆开多模态推理三段路
人工智能
桃西西呀2 小时前
体检报告上一堆箭头看不懂?背后的逻辑就是随机森林:一群树投票,比一棵树靠谱
人工智能·机器学习·llm
知几蜗牛2 小时前
AI能写无人机控制代码后,安全边界不能只守提示词
人工智能
知几蜗牛2 小时前
机器人动作误差降近九成,真正该先看数据切分
人工智能