一、前言
LangChain 的记忆组件发挥着至关重要的作用,其旨在协助大语言模型(LLM)有效地留存历史对话信息。通过这一功能,使得大语言模型在对话过程中能够更出色地维持上下文的连贯性和一致性,进而能够像人类的记忆运作方式那样,进行更为自然、流畅且智能化的交互。
它仿佛是为大语言模型赋予了一种类似人类记忆的能力,让其在处理对话时,不仅能够清晰地记住之前交流的内容,还能依据这些历史信息做出更贴合语境、更富有逻辑和更具有针对性的回应,极大地提升了交互的质量和效果。
本篇学习如何正确使用ConversationBufferMemory组件。
二、术语
2.1.记忆组件
记忆组件是一种用于帮助大语言模型(LLM)记住历史对话信息的工具。大语言模型本身是无状态的,不会记住之前的对话内容,而记忆组件通过存储和管理历史对话的相关信息,让 LLM 在对话中能够更好地保持上下文,从而进行更自然和智能的交互。
2.2.ConversationBufferMemory
存储对话的所有消息,并能将这些消息抽取到一个变量中。它会如实记录所有历史消息,但随着对话延长,所需存储量会增大,向 LLM 发送的 token 成本也可能增加。
2.3.load_memory_variables方法
用于获取当前存储在该记忆组件中的对话历史信息。通过调用这个方法,可以以特定的格式返回之前保存的对话内容。默认情况下,它可能会返回一个包含对话历史的变量字典,其中有一个名为"history"的变量存储了具体的对话记录。这些对话历史信息可以作为上下文提供给大语言模型,使其在生成回答时能够参考之前的对话内容,从而实现更自然和智能的交互,就像人类在对话中能够记住之前的讨论内容一样。
2.4.save_context方法
用于将对话的上下文信息保存到记忆组件对象中。
三、前提条件
3.1. 基础环境
- 操作系统:不限
3.2. 安装虚拟环境
conda create --name langchain python=3.10
conda activate langchain
pip install langchain langchain-openai langchain-community
四、技术实现
4.1.ConversationBufferMemory基础示例
import os
from langchain.chains.conversation.base import ConversationChain
from langchain.memory import ConversationBufferMemory
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
if __name__ == '__main__':
memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("你好,我叫蜘蛛侠")
memory.chat_memory.add_ai_message("很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?")
variables = memory.load_memory_variables({})
print(variables)
llm = ChatOpenAI(model_name='gpt-3.5-turbo-1106', temperature=0.7, max_tokens=512)
# 创建一个对话链
conversation = ConversationChain(
llm=llm,
memory=memory,
verbose=True
)
print(conversation.predict(input="Hi, 你还记得我叫什么名字吗?"))
调用结果:
说明:
ConversationBufferMemory类中的human_prefix、ai_prefix和memory_key属性分别对应到
- history: 'Human: 你好,我叫蜘蛛侠\nAI: 很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?'
- Human: 你好,我叫蜘蛛侠
- AI: 很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?
4.2.ConversationBufferMemory进阶示例
指定memory_key属性
import os
from langchain.chains.conversation.base import ConversationChain
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
if __name__ == '__main__':
memory = ConversationBufferMemory(memory_key="chat_history")
memory.chat_memory.add_user_message("你好,我叫蜘蛛侠")
memory.chat_memory.add_ai_message("很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?")
variables = memory.load_memory_variables({})
print(variables)
llm = ChatOpenAI(model_name='gpt-3.5-turbo-1106', temperature=0.7, max_tokens=512)
template = ''' 仅根据以下上下文回答问题:
{chat_history}
问题: {input}
'''
prompt = ChatPromptTemplate.from_template(template)
# 创建一个对话链
conversation = ConversationChain(
llm=llm,
memory=memory,
prompt=prompt,
verbose=True
)
print(conversation.predict(input="Hi, 你还记得我叫什么名字吗?",chat_history = variables['chat_history']))
调用结果:
说明:
1. 为什么ConversationBufferMemory指定memory_key属性后,ConversationChain调用predict方法要显示指定chat_history?
在未显示指定memory_key时,默认以history来存储历史对话内容,符合PromptTemplate的输入变量,如下图所示:
在predict方法中,未显示指定历史对话存储的key时,将提示以下异常:
langchain Got unexpected prompt input variables. The prompt expects ['history', 'input'], but got ['chat_history'] as inputs from memory, and input as the normal input key. (type=value_error)
4.3.save_context使用示例
import os
from langchain.chains.conversation.base import ConversationChain
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
os.environ["OPENAI_API_KEY"] = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
if __name__ == '__main__':
memory = ConversationBufferMemory(memory_key="chat_history")
# memory.chat_memory.add_user_message("你好,我叫蜘蛛侠")
# memory.chat_memory.add_ai_message("很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?")
memory.save_context({"input":"你好,我叫蜘蛛侠"},{"output":"很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?"})
variables = memory.load_memory_variables({})
print(variables)
llm = ChatOpenAI(model_name='gpt-3.5-turbo-1106', temperature=0.7, max_tokens=512)
template = ''' 仅根据以下上下文回答问题:
{chat_history}
问题: {input}
'''
prompt = ChatPromptTemplate.from_template(template)
# 创建一个对话链
conversation = ConversationChain(
llm=llm,
memory=memory,
prompt=prompt,
verbose=True
)
print(conversation.predict(input="Hi, 你还记得我叫什么名字吗?",chat_history = variables['chat_history']))
调用结果:
说明:
memory.save_context({"input":"你好,我叫蜘蛛侠"},{"output":"很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?"})
等价于
memory.chat_memory.add_user_message("你好,我叫蜘蛛侠")
memory.chat_memory.add_ai_message("很高兴认识你,蜘蛛侠!作为一名人工助理,我会尽我所能为你提供帮助。你有什么需要我协助的吗?")