【LangChain】langchain.memory 模块:对话或链(Chain)中存储和检索上下文信息

langchain.memory 模块,这是 LangChain 库中用于管理对话记忆(memory)的工具集,旨在存储和检索对话历史或上下文,以支持多轮对话和上下文感知的交互。

本文基于 LangChain 0.3.x,详细介绍 langchain.memory 模块的结构、核心类及其功能,并提供一个独立示例,展示如何使用 ConversationBufferMemory 结合 ChatOpenAI 实现人工智能主题的多轮对话,示例突出模块的对话记忆管理能力。

如果你在运行代码时遇到以下提示信息,代表memory 模块已经弃用,需要迁移到新的技术实现。请按提示中的链接中的内容进行迁移。
LangChainDeprecationWarning:
Please see the migration guide at: https://python.langchain.com/docs/versions/migrating_memory/


langchain.memory 模块概览

langchain.memory 模块是 LangChain 库的核心组成部分,提供一系列记忆类,用于在对话或链(Chain)中存储和检索上下文信息。这些类帮助模型记住之前的交互内容,支持多轮对话、上下文感知的问答和复杂任务的连续性。模块中的记忆类通常与 langchain_core.chat_history.BaseChatMessageHistory 或其他存储后端集成,适用于聊天机器人、问答系统等场景。

核心功能

  • 存储对话历史(用户输入和模型响应)。
  • 支持多种记忆类型(如缓冲区、摘要、知识图谱)。
  • 提供灵活的上下文注入方式,适配不同链。
  • 支持持久化存储(如内存、数据库)。

适用场景

  • 构建多轮对话的聊天机器人,需保留上下文。
  • 实现 RAG(Retrieval-Augmented Generation)系统,结合历史和检索内容。
  • 管理复杂任务的中间状态或上下文。
  • 测试 LLM 的长上下文处理能力。

模块位置


模块中的主要类

以下是 langchain.memory 模块中的核心类(基于 LangChain 0.3.x),包括功能和典型用法。

1. ConversationBufferMemory
  • 功能:存储完整的对话历史(用户和 AI 消息),按时间顺序保留所有消息。
  • 参数
    • memory_keystr,默认 "history"):上下文注入的键。
    • input_keystr,默认 None):用户输入的键。
    • output_keystr,默认 None):模型输出的键。
    • chat_memoryBaseChatMessageHistory,默认 ChatMessageHistory):消息存储后端。
  • 使用场景:简单的多轮对话,需完整历史。
  • 示例
    from langchain.memory import ConversationBufferMemory
    memory = ConversationBufferMemory(memory_key="history")
    memory.save_context({"input": "什么是 AI?"}, {"output": "AI 是人工智能的缩写。"})
    
2. ConversationBufferWindowMemory
  • 功能:仅存储最近的 k 条对话消息,限制上下文长度。
  • 参数
    • kint):保留的消息对数。
    • memory_keystr):上下文键。
    • chat_memoryBaseChatMessageHistory):存储后端。
  • 使用场景:控制上下文长度,节省 tokens。
  • 示例
    from langchain.memory import ConversationBufferWindowMemory
    memory = ConversationBufferWindowMemory(k=2, memory_key="history")
    
3. ConversationSummaryMemory
  • 功能:使用 LLM 总结对话历史,生成简洁的上下文摘要。
  • 参数
    • llmBaseLLM):用于生成摘要的模型。
    • memory_keystr):上下文键。
    • promptPromptTemplate):摘要生成提示。
  • 使用场景:长对话中压缩历史,适合大模型。
  • 示例
    from langchain.memory import ConversationSummaryMemory
    from langchain_openai import ChatOpenAI
    memory = ConversationSummaryMemory(llm=ChatOpenAI(), memory_key="history")
    
4. ConversationSummaryBufferMemory
  • 功能:结合缓冲区和摘要,保留近期消息并总结早期对话。
  • 参数
    • llmBaseLLM):摘要模型。
    • max_token_limitint):触发摘要的 token 阈值。
    • memory_keystr):上下文键。
  • 使用场景:平衡完整性和效率的长对话。
  • 示例
    from langchain.memory import ConversationSummaryBufferMemory
    memory = ConversationSummaryBufferMemory(llm=ChatOpenAI(), max_token_limit=1000)
    
5. ConversationKGMemory
  • 功能:从对话中提取知识图谱(实体和关系),存储结构化上下文。
  • 参数
    • llmBaseLLM):提取实体的模型。
    • memory_keystr):上下文键。
  • 使用场景:需要结构化知识的对话(如问答、推理)。
  • 示例
    from langchain.memory import ConversationKGMemory
    memory = ConversationKGMemory(llm=ChatOpenAI())
    
其他类
  • VectorStoreRetrieverMemory:使用向量存储检索相关历史。
  • CombinedMemory:组合多个记忆类,灵活定制。
  • MotorheadMemory:基于 Motorhead 的外部记忆服务。

基类

  • 所有记忆类继承自 langchain.memory.BaseMemory,提供标准接口:
    • save_context:保存输入和输出。
    • load_memory_variables:加载上下文。
    • clear:清除记忆。

使用方式

以下是使用 langchain.memory 模块的通用步骤。

1. 安装依赖
pip install --upgrade langchain langchain-openai langchain-community
2. 设置 OpenAI API 密钥
export OPENAI_API_KEY="your-api-key"

或在代码中:

import os
os.environ["OPENAI_API_KEY"] = "your-api-key"
3. 初始化记忆
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(memory_key="history", return_messages=True)
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 import RunnablePassthrough
chain_with_memory = RunnablePassthrough.assign(
    history=lambda x: memory.load_memory_variables({})["history"]
) | prompt | llm
6. 调用链并保存历史
response = chain_with_memory.invoke({"input": "什么是人工智能?"})
memory.save_context({"input": "什么是人工智能?"}, {"output": response.content})
print(response.content)

使用 langchain.memory 的示例

以下是一个独立示例,展示如何使用 langchain.memory 模块中的 ConversationBufferMemory 结合 ChatOpenAI 实现人工智能主题的多轮对话,保留完整对话历史。示例使用 LCEL 和 RunnableWithMessageHistory 简化历史管理,突出记忆模块的集成。

准备环境

  • 获取 OpenAI API 密钥:OpenAI Platform
  • 设置环境变量:
    export OPENAI_API_KEY="your-api-key"
    
  • 安装依赖:
    pip install --upgrade langchain langchain-openai langchain-community
    

代码

from langchain.memory import ConversationBufferMemory
from langchain_community.chat_message_histories import ChatMessageHistory
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

# 初始化 ConversationBufferMemory
memory = ConversationBufferMemory(
    memory_key="history",
    return_messages=True,
    chat_memory=ChatMessageHistory()
)

# 定义会话历史获取函数
def get_session_history(session_id: str):
    return memory.chat_memory

# 初始化 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=get_session_history,
    input_messages_key="input",
    history_messages_key="history"
)

# 测试 ConversationBufferMemory 和对话链
print("测试 ConversationBufferMemory 和对话链:")
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}")
    
    # 显示消息历史
    print("\n消息历史:")
    history = memory.load_memory_variables({})["history"]
    for i, msg in enumerate(history):
        print(f"消息 {i+1} ({msg.__class__.__name__}): {msg.content}")
except Exception as e:
    print(f"错误: {e}")

输出示例(实际输出取决于模型和 API 响应):

测试 ConversationBufferMemory 和对话链:
问题 1: 什么是人工智能?
回答 1: 人工智能(AI)是计算机科学的一个分支,旨在模拟人类智能,如学习、推理和问题解决。

问题 2: 它有哪些应用?
回答 2: 人工智能的应用包括医疗诊断、自动驾驶、语音识别、推荐系统和金融分析等领域。

消息历史:
消息 1 (HumanMessage): 什么是人工智能?
消息 2 (AIMessage): 人工智能(AI)是计算机科学的一个分支,旨在模拟人类智能,如学习、推理和问题解决。
消息 3 (HumanMessage): 它有哪些应用?
消息 4 (AIMessage): 人工智能的应用包括医疗诊断、自动驾驶、语音识别、推荐系统和金融分析等领域。
代码说明
  1. ConversationBufferMemory
    • 初始化 ConversationBufferMemory,使用 ChatMessageHistory 作为后端。
    • 设置 memory_key="history"return_messages=True
  2. 会话历史
    • 定义 get_session_history 返回 memory.chat_memory
  3. LLM 初始化
    • 使用 ChatOpenAI 调用 gpt-3.5-turbo,设置 temperature=0.7
  4. 提示模板
    • ChatPromptTemplate 包含系统消息、历史占位符和用户输入。
    • MessagesPlaceholder 注入历史消息。
  5. 对话链
    • 使用 LCEL 组合 promptllmparser
    • RunnableWithMessageHistory 包装链,自动管理历史。
  6. 测试
    • 进行两轮对话:定义 AI 和询问应用。
    • 使用 session_id="ai_chat_001" 跟踪会话。
    • 显示历史消息,展示上下文保留。
  7. 错误处理
    • 使用 try-except 捕获 API 或链错误。
  8. 主题
    • 示例聚焦 AI 多轮对话,突出记忆管理。
  9. 独立性
    • 不涉及 RunnableWithMessageHistory 或其他上下文。

运行要求

  • 有效的 OpenAI API 密钥:
    export OPENAI_API_KEY="your-api-key"
    
  • 安装依赖:
    pip install --upgrade langchain langchain-openai langchain-community
    
  • 网络连接:访问 https://api.openai.com.

注意事项

  1. API 密钥
    • 确保 OPENAI_API_KEY 已设置:
      echo $OPENAI_API_KEY
      
    • 或在代码中设置:
      llm = ChatOpenAI(api_key="your-api-key")
      
  2. 记忆选择
    • 完整历史ConversationBufferMemory):适合短对话。
      memory = ConversationBufferMemory()
      
    • 窗口历史ConversationBufferWindowMemory):控制长度。
      memory = ConversationBufferWindowMemory(k=2)
      
    • 摘要ConversationSummaryMemory):压缩长对话。
      memory = ConversationSummaryMemory(llm=ChatOpenAI())
      
  3. 持久化存储
    • 使用 RedisChatMessageHistory
      from langchain_community.chat_message_histories import RedisChatMessageHistory
      memory = ConversationBufferMemory(
          chat_memory=RedisChatMessageHistory(session_id="ai_chat_001", redis_url="redis://localhost:6379/0")
      )
      
  4. 性能优化
    • 异步调用:使用 ainvoke
      result = await chain_with_history.ainvoke(input, config)
      
    • 限制历史长度:避免上下文溢出:
      max_messages = 10
      memory.chat_memory.messages = memory.chat_memory.messages[-max_messages:]
      
    • 缓存摘要:加速 ConversationSummaryMemory
      memory = ConversationSummaryBufferMemory(llm=ChatOpenAI(), max_token_limit=1000)
      
  5. 错误调试
    • 历史未注入
      • 检查 memory_key
        print(memory.memory_key)
        
      • 验证历史:
        print(memory.load_memory_variables({}))
        
    • API 错误
      • 检查密钥:
        print(os.environ.get("OPENAI_API_KEY"))
        
      • 增加超时:
        llm = ChatOpenAI(timeout=30)
        
    • 会话错误
      • 检查 session_id
        print(config)
        
      • 验证历史实例:
        print(get_session_history("ai_chat_001"))
        

常见问题

Q1:如何选择合适的记忆类?
A:根据需求:

  • 短对话:ConversationBufferMemory
  • 控制长度:ConversationBufferWindowMemory
  • 长对话压缩:ConversationSummaryMemoryConversationSummaryBufferMemory
  • 结构化知识:ConversationKGMemory

Q2:如何持久化记忆?
A:使用持久化后端:

from langchain_community.chat_message_histories import SQLChatMessageHistory
memory = ConversationBufferMemory(
    chat_memory=SQLChatMessageHistory(session_id="ai_chat_001", connection_string="sqlite:///chat_history.db")
)

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: memory.load_memory_variables({})["history"], "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=get_session_history,
    input_messages_key="input",
    history_messages_key="history"
)

总结

langchain.memory 模块是 LangChain 中管理对话上下文的核心工具集,包含以下关键类:

  • ConversationBufferMemory:存储完整历史。
  • ConversationBufferWindowMemory:限制近期消息。
  • ConversationSummaryMemory:生成历史摘要。
  • ConversationSummaryBufferMemory:结合缓冲和摘要。
  • ConversationKGMemory:提取结构化知识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬彬侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值