记忆 (Memory)
大语言模型本质上是无状态的。为了进行连续的对话,我们需要手动将之前的聊天记录(History)作为上下文传递给模型。LangChain 提供了 RunnableWithMessageHistory 来简化这一过程。
核心组件
- ChatMessageHistory: 用于存储消息的容器(可以是内存、Redis、SQL 等)。
- RunnableWithMessageHistory: 一个包装器,负责在调用链之前读取历史记录,并在调用后自动保存新消息。
实战:构建带记忆的聊天机器人
python
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
# 1. 定义基础链
model = ChatOpenAI()
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个热情的助手。"),
MessagesPlaceholder(variable_name="history"), # 关键:预留位置给历史记录
("human", "{input}")
])
chain = prompt | model | StrOutputParser()
# 2. 定义历史记录存储 (这里使用内存存储)
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
# 3. 包装链
with_message_history = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key="input",
history_messages_key="history",
)
# 4. 调用 (需提供 session_id)
config = {"configurable": {"session_id": "user_123"}}
# 第一轮
response1 = with_message_history.invoke(
{"input": "你好,我是小明。"},
config=config
)
print(response1)
# AI: 你好小明!很高兴见到你。
# 第二轮 (模型记住了名字)
response2 = with_message_history.invoke(
{"input": "我叫什么名字?"},
config=config
)
print(response2)
# AI: 你叫小明。生产环境建议
在生产环境中,不要使用简单的内存字典 store。请使用持久化的存储方案,例如:
RedisChatMessageHistoryPostgresChatMessageHistory
这些类通常位于 langchain_community 或专门的集成包中。
解决了记忆问题,接下来我们解决“知识”问题。进入最实用的章节:检索增强生成 (RAG)。
LangChain中文文档