langchain_community.chat_message_histories.SQLChatMessageHistory
类是 LangChain 社区库中用于将聊天消息历史存储到 SQL 数据库的工具类,适合持久化管理和多轮对话的上下文跟踪。
本文基于 LangChain 0.3.x ,详细介绍 SQLChatMessageHistory
的定义、参数、方法和典型场景,并提供一个独立示例,展示如何使用 SQLChatMessageHistory
结合 ChatOpenAI
和 SQLite 数据库实现人工智能主题的多轮对话,示例突出消息历史的持久化存储和上下文保留。
langchain_community.chat_message_histories.SQLChatMessageHistory
简介
SQLChatMessageHistory
是 LangChain 社区库中的消息历史存储类,通过 SQL 数据库(支持 SQLite、PostgreSQL 等)持久化存储对话消息(HumanMessage
、AIMessage
等)。它适合需要长期保存对话历史或多用户会话管理的场景,相比内存存储的 ChatMessageHistory
,它提供数据持久化和跨会话访问能力。
核心功能:
- 将对话消息存储到 SQL 数据库,支持持久化。
- 按会话 ID(
session_id
)组织消息,支持多用户或多会话。 - 支持添加、获取、清除消息。
- 集成到对话链,实现上下文感知的多轮对话。
适用场景:
- 构建生产级聊天机器人,需持久化对话历史。
- 多用户应用,跟踪每个用户的会话。
- 需要跨设备或会话恢复对话的场景。
- 与 LLM 链结合,提供长期上下文支持。
与其他消息历史类对比:
ChatMessageHistory
:内存存储,临时使用,非持久化。RedisChatMessageHistory
:基于 Redis,适合高并发但需额外部署。SQLChatMessageHistory
:基于 SQL 数据库,持久化且易于集成。
类定义和初始化
以下是 SQLChatMessageHistory
的定义,基于 LangChain 社区库源码(langchain_community/chat_message_histories/sql.py
)和官方文档(SQLChatMessageHistory)。
类签名
class SQLChatMessageHistory(BaseChatMessageHistory):
def __init__(
self,
session_id: str,
connection_string: str,
table_name: str = "message_store",
session_id_field_name: str = "session_id",
created_at_field_name: str = "created_at",
custom_message_to_dict: Optional[Callable[[BaseMessage], Dict[str, Any]]] = None,
custom_dict_to_message: Optional[Callable[[Dict[str, Any]], BaseMessage]] = None
) -> None
- 参数:
session_id
(str
):会话标识符,区分不同对话。connection_string
(str
):SQL 数据库连接字符串(如"sqlite:///chat_history.db"
)。table_name
(str
,默认"message_store"
):存储消息的表名。session_id_field_name
(str
,默认"session_id"
):会话 ID 列名。created_at_field_name
(str
,默认"created_at"
):创建时间列名。custom_message_to_dict
(Optional[Callable]
,默认None
):自定义消息转字典函数。custom_dict_to_message
(Optional[Callable]
,默认None
):自定义字典转消息函数。
- 功能:
- 自动创建数据库表(包含
session_id
、message
等列)。 - 按
session_id
存储和查询消息。 - 支持 SQLite、PostgreSQL 等数据库。
- 自动创建数据库表(包含
初始化示例
from langchain_community.chat_message_histories import SQLChatMessageHistory
history = SQLChatMessageHistory(
session_id="ai_chat_001",
connection_string="sqlite:///chat_history.db",
table_name="message_store"
)
数据库表结构
SQLChatMessageHistory
自动创建以下表结构(以 table_name="message_store"
为例):
CREATE TABLE message_store (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
- 字段:
id
:消息唯一标识,自增。session_id
:会话 ID,区分对话。message
:消息内容(序列化为 JSON,包含类型和内容)。created_at
:消息创建时间。
常用方法
SQLChatMessageHistory
继承自 langchain_core.chat_history.BaseChatMessageHistory
,提供以下核心方法。
1. add_message
def add_message(self, message: BaseMessage) -> None
- 功能:添加单条消息到数据库。
- 输入:
message
(BaseMessage
),如HumanMessage
或AIMessage
。 - 示例:
from langchain_core.messages import HumanMessage, AIMessage history.add_message(HumanMessage(content="什么是人工智能?")) history.add_message(AIMessage(content="人工智能是计算机科学的一个分支。"))
2. add_user_message
def add_user_message(self, message: str) -> None
- 功能:添加用户消息(
HumanMessage
)。 - 输入:
message
(str
),用户输入文本。 - 示例:
history.add_user_message("AI 有哪些应用?")
3. add_ai_message
def add_ai_message(self, message: str) -> None
- 功能:添加 AI 消息(
AIMessage
)。 - 输入:
message
(str
),模型响应文本。 - 示例:
history.add_ai_message("AI 应用于医疗、自动驾驶等领域。")
4. clear
def clear(self) -> None
- 功能:删除当前
session_id
的所有消息。 - 示例:
history.clear() print(len(history.messages)) # 0
5. messages
属性
- 功能:从数据库查询当前
session_id
的消息列表。 - 输出:
List[BaseMessage]
,所有消息。 - 示例:
for msg in history.messages: print(f"{msg.__class__.__name__}: {msg.content}")
6. 异步方法
- 功能:异步版本方法(如
aclear
、aadd_message
)。 - 使用场景:高并发场景。
- 示例:
import asyncio await history.aclear()
使用方式
以下是使用 SQLChatMessageHistory
的步骤。
1. 安装依赖
pip install --upgrade langchain langchain-openai langchain-community sqlalchemy
2. 设置 OpenAI API 密钥
export OPENAI_API_KEY="your-api-key"
或在代码中:
import os
os.environ["OPENAI_API_KEY"] = "your-api-key"
3. 初始化 SQLChatMessageHistory
from langchain_community.chat_message_histories import SQLChatMessageHistory
history = SQLChatMessageHistory(
session_id="ai_chat_001",
connection_string="sqlite:///chat_history.db"
)
4. 构建对话链
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
llm = ChatOpenAI(model="gpt-3.5-turbo")
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个人工智能专家,回答用户问题。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | llm
5. 调用链并存储历史
from langchain_core.runnables.history import RunnableWithMessageHistory
chain_with_history = RunnableWithMessageHistory(
runnable=chain,
get_session_history=lambda session_id: SQLChatMessageHistory(
session_id=session_id,
connection_string="sqlite:///chat_history.db"
),
input_messages_key="input",
history_messages_key="history"
)
response = chain_with_history.invoke(
{"input": "什么是人工智能?"},
config={"configurable": {"session_id": "ai_chat_001"}}
)
使用 SQLChatMessageHistory
的示例
以下是一个独立示例,展示如何使用 SQLChatMessageHistory
结合 ChatOpenAI
和 SQLite 数据库实现人工智能主题的多轮对话,持久化存储消息历史并保留上下文。示例使用 RunnableWithMessageHistory
简化对话管理。
准备环境:
- 获取 OpenAI API 密钥:OpenAI Platform。
- 设置环境变量:
export OPENAI_API_KEY="your-api-key"
- 安装依赖:
pip install --upgrade langchain langchain-openai langchain-community sqlalchemy
代码:
from langchain_community.chat_message_histories import SQLChatMessageHistory
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables.history import RunnableWithMessageHistory
# 初始化 ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)
# 定义提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个人工智能专家,回答用户问题。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
# 定义输出解析器
parser = StrOutputParser()
# 创建对话链
chain = prompt | llm | parser
# 包装链以支持消息历史
chain_with_history = RunnableWithMessageHistory(
runnable=chain,
get_session_history=lambda session_id: SQLChatMessageHistory(
session_id=session_id,
connection_string="sqlite:///chat_history.db"
),
input_messages_key="input",
history_messages_key="history"
)
# 测试 SQLChatMessageHistory 和对话链
print("测试 SQLChatMessageHistory 和对话链:")
try:
session_id = "ai_chat_001"
# 第一轮对话
question1 = "什么是人工智能?"
result1 = chain_with_history.invoke(
{"input": question1},
config={"configurable": {"session_id": session_id}}
)
print(f"问题 1: {question1}")
print(f"回答 1: {result1}")
# 第二轮对话(依赖上下文)
question2 = "它有哪些应用?"
result2 = chain_with_history.invoke(
{"input": question2},
config={"configurable": {"session_id": session_id}}
)
print(f"\n问题 2: {question2}")
print(f"回答 2: {result2}")
# 显示消息历史
history = SQLChatMessageHistory(session_id=session_id, connection_string="sqlite:///chat_history.db")
print("\n消息历史:")
for i, msg in enumerate(history.messages):
print(f"消息 {i+1} ({msg.__class__.__name__}): {msg.content}")
except Exception as e:
print(f"错误: {e}")
输出示例(实际输出取决于模型和 API 响应):
测试 SQLChatMessageHistory 和对话链:
问题 1: 什么是人工智能?
回答 1: 人工智能(AI)是计算机科学的一个分支,旨在模拟人类智能,如学习、推理和问题解决。
问题 2: 它有哪些应用?
回答 2: 人工智能的应用包括医疗诊断、自动驾驶、语音识别、推荐系统和金融分析等领域。
消息历史:
消息 1 (HumanMessage): 什么是人工智能?
消息 2 (AIMessage): 人工智能(AI)是计算机科学的一个分支,旨在模拟人类智能,如学习、推理和问题解决。
消息 3 (HumanMessage): 它有哪些应用?
消息 4 (AIMessage): 人工智能的应用包括医疗诊断、自动驾驶、语音识别、推荐系统和金融分析等领域。
代码说明
- SQLChatMessageHistory:
- 使用 SQLite 数据库(
sqlite:///chat_history.db
)存储消息。 - 设置
session_id="ai_chat_001"
区分会话。
- 使用 SQLite 数据库(
- LLM 初始化:
- 使用
ChatOpenAI
调用gpt-3.5-turbo
,设置temperature=0.7
。
- 使用
- 提示模板:
ChatPromptTemplate
包含系统消息、历史占位符和用户输入。MessagesPlaceholder
注入历史消息。
- 对话链:
- 使用 LCEL 组合
prompt
、llm
和parser
。 RunnableWithMessageHistory
包装链,动态加载SQLChatMessageHistory
。
- 使用 LCEL 组合
- 测试:
- 进行两轮对话:定义 AI 和询问应用。
- 使用
session_id
确保上下文一致。 - 显示数据库中的消息历史。
- 错误处理:
- 使用
try-except
捕获 API 或数据库错误。
- 使用
运行要求:
- 有效的 OpenAI API 密钥:
export OPENAI_API_KEY="your-api-key"
- 安装依赖:
pip install --upgrade langchain langchain-openai langchain-community sqlalchemy
- SQLite 无需额外安装(Python 内置支持)。
- 网络连接:访问
https://api.openai.com
.
注意事项
- API 密钥:
- 确保
OPENAI_API_KEY
已设置:echo $OPENAI_API_KEY
- 或在代码中设置:
llm = ChatOpenAI(api_key="your-api-key")
- 确保
- 数据库配置:
- SQLite:简单,无需服务器:
connection_string="sqlite:///chat_history.db"
- PostgreSQL:生产环境:
connection_string="postgresql://user:password@localhost:5432/dbname"
- 确保数据库可写:
touch chat_history.db chmod 666 chat_history.db
- SQLite:简单,无需服务器:
- 会话 ID:
- 唯一
session_id
区分对话:session_id="ai_chat_001"
- 重复使用
session_id
加载历史:history = SQLChatMessageHistory(session_id="ai_chat_001", connection_string="sqlite:///chat_history.db")
- 唯一
- 性能优化:
- 限制历史长度:避免上下文过长:
max_messages = 10 history.messages = history.messages[-max_messages:]
- 异步调用:使用
ainvoke
:result = await chain_with_history.ainvoke(input, config)
- 数据库索引:为
session_id
添加索引:CREATE INDEX idx_session_id ON message_store (session_id);
- 限制历史长度:避免上下文过长:
- 错误调试:
- 数据库错误:
- 检查连接:
import sqlalchemy engine = sqlalchemy.create_engine("sqlite:///chat_history.db") engine.connect()
- 验证表结构:
sqlite3 chat_history.db "SELECT * FROM message_store LIMIT 1"
- 检查连接:
- API 错误:
- 检查密钥:
print(os.environ.get("OPENAI_API_KEY"))
- 增加超时:
llm = ChatOpenAI(timeout=30)
- 检查密钥:
- 消息丢失:
- 检查历史:
print(history.messages)
- 验证
session_id
:print(session_id)
- 检查历史:
- 数据库错误:
常见问题
Q1:如何使用 PostgreSQL 替代 SQLite?
A:修改 connection_string
:
history = SQLChatMessageHistory(
session_id="ai_chat_001",
connection_string="postgresql://user:password@localhost:5432/chat_db"
)
安装 PostgreSQL 驱动:
pip install psycopg2
Q2:如何清理特定会话历史?
A:调用 clear
:
history.clear()
或直接删除数据库记录:
DELETE FROM message_store WHERE session_id = 'ai_chat_001';
Q3:如何与 RAG 结合?
A:添加检索上下文:
from langchain.vectorstores import FAISS
vectorstore = FAISS.from_documents(docs, OpenAIEmbeddings())
retriever = vectorstore.as_retriever()
prompt = ChatPromptTemplate.from_messages([
("system", "根据上下文和历史回答:\n{context}"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = {"context": retriever, "history": lambda x: history.messages, "input": lambda x: x["input"]} | prompt | llm
Q4:如何支持开源模型?
A:使用 ChatOllama
:
from langchain_ollama import ChatOllama
llm = ChatOllama(model="llama3")
chain = prompt | llm | parser
chain_with_history = RunnableWithMessageHistory(
runnable=chain,
get_session_history=lambda session_id: SQLChatMessageHistory(
session_id=session_id,
connection_string="sqlite:///chat_history.db"
),
input_messages_key="input",
history_messages_key="history"
)
总结
langchain_community.chat_message_histories.SQLChatMessageHistory
是 LangChain 中持久化对话历史的核心工具,核心功能包括:
- 定义:通过 SQL 数据库存储消息历史。
- 初始化:配置
session_id
和connection_string
。 - 常用方法:
add_message
、add_user_message
、add_ai_message
、clear
。 - 适用场景:多轮对话、持久化存储、生产级应用。