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),其核心字段包括:
| 字段 | 类型 | 说明 |
|---|---|---|
id | UUID | 主键,消息唯一标识 |
session_id | TEXT | 会话标识,用于区分不同用户/会话 |
message | JSONB | 消息内容(含 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 会执行以下步骤:
- 从
memory中读取历史消息(此时数据来自 PostgreSQL); - 将历史消息格式化为字符串,拼接到 Prompt 的
history变量中; - 连同当前用户输入一起发送给 LLM;
- 拿到回复后,把「用户输入 + 模型回复」写回 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 记忆体系从原型走向生产的关键一步。在此基础上,你才能更合理地判断:什么时候用纯内存就够了,什么时候必须引入数据库持久化。

473

被折叠的 条评论
为什么被折叠?



