LangChain Memory (记忆系统)
LLM 本身是无状态的。Memory 系统的作用就是存储、处理和提取之前的对话历史,并在新的请求中将其作为上下文发送给模型。
#1. 为什么需要 Memory?
如果没有 Memory,每次对话都是独立的:
- 用户:我叫小明。
- 模型:你好!
- 用户:我叫什么名字?
- 模型:对不起,我不记得了。
#2. 核心组件:ChatHistory
最基础的存储单元是 ChatMessageHistory,它简单地保存了 Message 对象的列表。
pythonfrom langchain.memory import ChatMessageHistory history = ChatMessageHistory() history.add_user_message("你好,我是小明。") history.add_ai_message("你好小明!很高兴见到你。") print(history.messages)
#3. 常用 Memory 类型
LangChain 提供了多种策略来处理历史记录,平衡“记忆长度”与“Token 消耗”。
#A. ConversationBufferMemory (全量记忆)
保存所有历史记录。最简单,但 Token 消耗增长极快。
#B. ConversationSummaryMemory (摘要记忆)
让 LLM 对之前的对话进行总结。适合超长对话。
#C. ConversationTokenBufferMemory (Token 限制记忆)
只保留最近的 N 个 Token,旧的记录会被丢弃。
#4. 在 Chain 中集成 Memory
在现代 LangChain 开发中,我们通常使用 RunnableWithMessageHistory 来包装我们的 Chain。
pythonfrom langchain_core.runnables.history import RunnableWithMessageHistory # 1. 定义 Chain 逻辑 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个友好的助手。"), ("placeholder", "{chat_history}"), # 历史记录占位符 ("user", "{input}"), ]) chain = prompt | llm # 2. 包装并关联存储 # 这里的 store 可以是内存中的字典,也可以是 Redis 数据库 store = {} def get_session_history(session_id: str): if session_id not in store: store[session_id] = ChatMessageHistory() return store[session_id] wrapped_chain = RunnableWithMessageHistory( chain, get_session_history, input_messages_key="input", history_messages_key="chat_history", ) # 3. 调用时传入 session_id wrapped_chain.invoke( {"input": "我叫小明"}, config={"configurable": {"session_id": "user_123"}} )
#5. 持久化存储
在生产环境中,你不能将历史存在内存里(重启就没了)。LangChain 支持多种数据库:
- Redis: 响应极快。
- MongoDB: 灵活的 JSON 存储。
- Postgres: 使用 SQL 数据库存储历史。
注意:随着 LangGraph 的普及,许多复杂的记忆逻辑现在可以通过 LangGraph 的 Checkpointer 实现,这提供了更强的状态持久化能力。