LangChain 短期记忆:基于 PostgreSQL 的持久化实现详解

1. 引言

在 LangChain 的众多记忆机制中,短期记忆(Short-term Memory) 是最基础、也最常用的一类。它的核心特征是:基于内存(In-Memory)保存当前会话的上下文,随着对话推进不断更新,会话结束或程序重启后即丢失。

然而在实际生产环境中,我们往往需要让短期记忆跨进程、跨重启依然可用。这时,PostgreSQL 就是一个非常理想的持久化后端。本文将深入讲解如何用 PostgreSQL 实现 LangChain 短期记忆的持久化,涵盖核心机制、代码示例与多实例隔离等内容。

2. 为什么选择 PostgreSQL 作为记忆后端

很多初学者会困惑:短期记忆不是「基于内存」的吗?为什么还要用数据库?这里需要澄清一个概念:

  • 纯内存持久化:数据保存在进程的内存(RAM)中,只要程序进程存活,数据就一直存在;但进程重启后数据即丢失。
  • 数据库持久化:数据写入 PostgreSQL 等外部存储,程序重启后依然存在,可跨会话、跨实例共享。

LangChain 的短期记忆默认是前者,但通过 PostgresChatMessageHistory,我们可以把对话历史持久化到 PostgreSQL,从而获得「数据库级」的持久化能力。

# 数据库持久化的本质:消息写入 PostgreSQL,进程重启后依然可读
from langchain_community.chat_message_histories import PostgresChatMessageHistory

history = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/mydb",
    session_id="user_123",
)
history.add_user_message("你好")
history.add_ai_message("你好!有什么可以帮你?")

只要 PostgreSQL 服务在运行,即使应用进程重启,重新连接后仍能读到这条消息——这就是「基于 PostgreSQL 的持久化」。

3. 环境准备与依赖安装

在开始之前,需要安装必要的依赖包:

pip install langchain langchain-community langchain-openai psycopg2-binary

其中:

  • langchain:核心框架;
  • langchain-community:提供 PostgresChatMessageHistory 等社区集成;
  • langchain-openai:OpenAI 模型接口(示例中使用);
  • psycopg2-binary:PostgreSQL 的 Python 驱动。

同时,确保本地已启动 PostgreSQL 服务,并创建好数据库:

-- 创建数据库(如尚未创建)
CREATE DATABASE langchain_memory;

4. 核心组件:PostgresChatMessageHistory

PostgresChatMessageHistory 是 LangChain 提供的、基于 PostgreSQL 的消息历史存储类。它实现了与 ChatMessageHistory 相同的接口,但底层数据存储在 PostgreSQL 表中。

4.1 基本用法

from langchain_community.chat_message_histories import PostgresChatMessageHistory

# 连接 PostgreSQL,指定会话 ID
history = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/langchain_memory",
    session_id="user_123",
)

# 添加消息
history.add_user_message("我叫小明")
history.add_ai_message("你好,小明!")

# 读取全部消息
messages = history.messages
for msg in messages:
    print(f"{msg.type}: {msg.content}")

4.2 底层表结构

PostgresChatMessageHistory 会自动创建一张消息表(默认表名为 message_store),其核心字段包括:

字段类型说明
idUUID主键,消息唯一标识
session_idTEXT会话标识,用于区分不同用户/会话
messageJSONB消息内容(含 type、content 等)
-- 查看表结构
SELECT * FROM message_store WHERE session_id = 'user_123';

5. 与 ConversationBufferMemory 结合使用

PostgresChatMessageHistory 可以无缝嵌入 ConversationBufferMemory,让短期记忆获得数据库持久化能力:

from langchain.memory import ConversationBufferMemory
from langchain_community.chat_message_histories import PostgresChatMessageHistory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI

# 基于 PostgreSQL 的消息历史
history = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/langchain_memory",
    session_id="user_123",
)

# 将 PostgreSQL 历史注入内存记忆
memory = ConversationBufferMemory(chat_memory=history)

conversation = ConversationChain(
    llm=ChatOpenAI(model="gpt-4o-mini", temperature=0),
    memory=memory,
    verbose=True,
)

# 多次调用,历史消息持久化到 PostgreSQL
conversation.predict(input="你好,我叫小明。")
conversation.predict(input="我叫什么名字?")  # 模型能答出「小明」

5.1 数据如何注入 Prompt

每次调用时,ConversationChain 会执行以下步骤:

  1. memory 中读取历史消息(此时数据来自 PostgreSQL);
  2. 将历史消息格式化为字符串,拼接到 Prompt 的 history 变量中;
  3. 连同当前用户输入一起发送给 LLM;
  4. 拿到回复后,把「用户输入 + 模型回复」写回 PostgreSQL。
# 查看 memory 中保存的内容(来自 PostgreSQL)
print(memory.load_memory_variables({}))
# {'history': 'Human: 你好,我叫小明。\nAI: 你好,小明!'}

6. 进程重启后的数据恢复

基于 PostgreSQL 的持久化,最大的优势在于进程重启后记忆依然存在

from langchain_community.chat_message_histories import PostgresChatMessageHistory

# 模拟程序重启:重新创建连接
def create_session(session_id: str):
    return PostgresChatMessageHistory(
        connection_string="postgresql://user:password@localhost:5432/langchain_memory",
        session_id=session_id,
    )

# 第一次运行:写入消息
history_a = create_session("user_123")
history_a.add_user_message("我叫小明")
history_a.add_ai_message("你好,小明!")

# 模拟程序重启:重新连接
history_b = create_session("user_123")
# 历史消息依然存在!
print(history_b.messages)
# [HumanMessage(content='我叫小明'), AIMessage(content='你好,小明!')]

这就是「数据库持久化」与「纯内存持久化」的本质区别:数据不依赖进程存活,而是存储在独立的数据库服务中

7. 多用户场景下的会话隔离

在生产环境中,应用通常需要同时服务多个用户。使用 PostgreSQL 后,只需通过 session_id 即可天然实现会话隔离:

from langchain_community.chat_message_histories import PostgresChatMessageHistory

# 用户 A 的会话
history_a = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/langchain_memory",
    session_id="user_a",
)
history_a.add_user_message("我叫小明")

# 用户 B 的会话(独立记忆,互不影响)
history_b = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/langchain_memory",
    session_id="user_b",
)
history_b.add_user_message("我叫小红")

# 各自读取,互不干扰
print(history_a.messages)  # 只有 user_a 的消息
print(history_b.messages)  # 只有 user_b 的消息

7.1 与内存方案对比

维度纯内存方案PostgreSQL 方案
数据存储位置进程内存(RAM)PostgreSQL 数据库
进程重启数据丢失数据保留
多实例共享不支持支持(多进程可共享)
会话隔离需手动维护字典通过 session_id 天然隔离
部署复杂度中(需维护数据库)

8. 结合滑动窗口与摘要压缩

PostgreSQL 持久化同样可以与其他记忆策略结合,实现更精细的控制:

8.1 滑动窗口 + PostgreSQL

from langchain.memory import ConversationBufferWindowMemory
from langchain_community.chat_message_histories import PostgresChatMessageHistory

# 只保留最近 2 轮对话,但历史仍持久化在 PostgreSQL
history = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/langchain_memory",
    session_id="user_123",
)

memory = ConversationBufferWindowMemory(
    chat_memory=history,
    k=2,  # 只保留最近 2 轮
)

8.2 摘要压缩 + PostgreSQL

from langchain.memory import ConversationSummaryMemory
from langchain_community.chat_message_histories import PostgresChatMessageHistory
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

history = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/langchain_memory",
    session_id="user_123",
)

memory = ConversationSummaryMemory(
    llm=llm,
    chat_memory=history,
)

9. 生产环境注意事项

9.1 连接池管理

在生产环境中,建议使用连接池避免频繁创建数据库连接:

from sqlalchemy import create_engine
from langchain_community.chat_message_histories import PostgresChatMessageHistory

# 使用 SQLAlchemy 连接池
engine = create_engine(
    "postgresql://user:password@localhost:5432/langchain_memory",
    pool_size=10,
    max_overflow=20,
)

# 通过 connection_string 传入 engine 的 URL
history = PostgresChatMessageHistory(
    connection_string="postgresql://user:password@localhost:5432/langchain_memory",
    session_id="user_123",
)

9.2 数据清理策略

长期运行后,message_store 表会不断增长。建议定期清理过期会话:

-- 删除 30 天前的会话消息
DELETE FROM message_store
WHERE session_id IN (
    SELECT session_id
    FROM message_store
    GROUP BY session_id
    HAVING MAX(created_at) < NOW() - INTERVAL '30 days'
);

9.3 安全建议

  • 使用环境变量管理数据库连接串,避免硬编码;
  • 最小权限原则:为应用创建专用数据库账号,仅授予必要的读写权限;
  • 启用 SSL:生产环境建议启用 PostgreSQL 的 SSL 加密连接。

10. 总结

LangChain 短期记忆的「基于 PostgreSQL 的持久化」,本质上是把对话历史从进程内存迁移到 PostgreSQL 数据库,通过 session_id 实现会话隔离,让记忆在进程重启后依然可用

核心要点回顾:

  • 数据库持久化 ≠ 内存持久化:数据存储在 PostgreSQL 中,重启不丢失;
  • PostgresChatMessageHistory 是关键:它实现了与内存版相同的接口,可无缝替换;
  • session_id 实现隔离:天然支持多用户、多会话场景;
  • 可组合使用:滑动窗口、摘要压缩等策略均可与 PostgreSQL 结合;
  • 生产需注意:连接池、数据清理、安全配置缺一不可。

理解 PostgreSQL 持久化的机制,是掌握 LangChain 记忆体系从原型走向生产的关键一步。在此基础上,你才能更合理地判断:什么时候用纯内存就够了,什么时候必须引入数据库持久化。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值