LangChain Memory模块完全指南:从 ChatMessageHistory 到滑动窗口
·
LangChain 记忆模块完全指南:从 ChatMessageHistory 到滑动窗口
版本:Python 3.9+、LangChain ≥ 0.1
目标:一篇文章掌握所有「记忆」组件,复制即可运行
0. 统一环境(仅需一次)
pip install -U langchain langchain-openai python-dotenv
.env 文件(同目录)
OPENAI_API_KEY=sk-xxx
OPENAI_BASE_URL=https://api.openai.com/v1
# 0_env.py
import os, dotenv
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
下面所有代码均默认已 from 0_env import llm,不再重复。
1. ChatMessageHistory:最原始的消息列表
文件:1_raw_history.py
from langchain.memory import ChatMessageHistory
history = ChatMessageHistory()
history.add_user_message("你好,我是小明")
history.add_ai_message("很高兴认识你,我是人工智能助手")
history.add_user_message("帮我解释一下 1 + 2 * 3 = ?")
print(history.messages) # List[BaseMessage]
print(llm.invoke(history.messages).content)
终端打印:
[SystemMessage(content='你好,我是小明'),
AIMessage(content='很高兴认识你,我是人工智能助手'),
HumanMessage(content='帮我解释一下 1 + 2 * 3 = ?')]
结果是 7,因为先乘除后加减。
2. ConversationBufferMemory:自动拼接历史字符串
文件:2_buffer_str.py
from langchain.memory import ConversationBufferMemory
from langchain.chains import LLMChain
from langchain_core.prompts import PromptTemplate
template = """
历史对话:{history}
当前问题:{question}
"""
prompt = PromptTemplate.from_template(template)
memory = ConversationBufferMemory(memory_key="history") # 默认 return_messages=False
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
print(chain.invoke({"question": "1 + 3 = ?"})["text"])
print(chain.invoke({"question": "我刚才问了什么?"})["text"])
输出:
1 + 3 等于 4。
你刚才问的是“1 + 3 = ?”。
3. 使用 ChatPromptTemplate + MessagesPlaceholder(推荐)
文件:3_buffer_messages.py
from langchain.memory import ConversationBufferMemory
from langchain.chains import LLMChain
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "你是人工智能助手,可以详细回答问题"),
MessagesPlaceholder(variable_name="history"),
("human", "{question}"),
])
memory = ConversationBufferMemory(
memory_key="history",
return_messages=True # 必须 True,才能喂给 MessagesPlaceholder
)
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
print(chain.invoke({"question": "太阳为什么发光?"})["text"])
print(chain.invoke({"question": "我上一个问题是什么?"})["text"])
4. ConversationBufferWindowMemory:只记最近 k 轮
文件:4_window_memory.py
from langchain.memory import ConversationBufferWindowMemory
from langchain.chains import LLMChain
from langchain_core.prompts import PromptTemplate
template = """
历史最近 3 轮:{history}
当前问题:{question}
"""
prompt = PromptTemplate.from_template(template)
memory = ConversationBufferWindowMemory(k=3) # 只保留最近 3 轮
chain = LLMChain(llm=llm, prompt=prompt, memory=memory)
chain.invoke({"question": "你好,我的名字叫小明"})
chain.invoke({"question": "今天适合做啥?"})
chain.invoke({"question": "我考了 681,不去北大,去福耀科大"})
reply = chain.invoke({"question": "我的名字叫啥?"})
print(reply["text"])
当 k=1 时模型会“失忆”,k=3 能记住“小明”。
5. 记忆选型速查表
| 类 | 是否保留全部历史 | 是否支持 MessagesPlaceholder | 适用场景 |
|---|---|---|---|
| ChatMessageHistory | 是(手动) | 手动 | 调试、最小 demo |
| ConversationBufferMemory | 是 | ✔ | 通用对话,历史不长 |
| ConversationBufferWindowMemory | 否(只留 k 轮) | ✔ | 长对话、控制 token |
6. 最佳实践小结
- 新代码优先用
ChatPromptTemplate + MessagesPlaceholder + return_messages=True - 历史太长 → 改用
WindowMemory或后续SummaryMemory - 一条链即可同时支持 sync / async / stream,无需改代码:
async for chunk in chain.astream({"question": "讲个笑话"}):
print(chunk, end="", flush=True)
复制以上文件即可直接 python xxx.py 运行,把你的 LangChain 应用加上“记忆”吧!
点赞 + 收藏,下篇带你用 LCEL 重构记忆链,再会!
更多推荐

所有评论(0)