Skip to content

记忆 (Memory)

大语言模型本质上是无状态的。为了进行连续的对话,我们需要手动将之前的聊天记录(History)作为上下文传递给模型。LangChain 提供了 RunnableWithMessageHistory 来简化这一过程。

核心组件

  1. ChatMessageHistory: 用于存储消息的容器(可以是内存、Redis、SQL 等)。
  2. 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。请使用持久化的存储方案,例如:

  • RedisChatMessageHistory
  • PostgresChatMessageHistory

这些类通常位于 langchain_community 或专门的集成包中。


解决了记忆问题,接下来我们解决“知识”问题。进入最实用的章节:检索增强生成 (RAG)

LangChain中文文档