LLM历史记忆(Memory)
大多数基于LLM的应用程序都有一个类似微信的聊天对话界面。AI对话过程的一个重要功能是能够引用先前在对话中讲过的信息,就像人类对话过程,不需要把前面讲过的内容在复述一遍,人类会自动联想历史信息。
对于存储历史对话信息的能力,在LLM领域通常称为“记忆”(Memory),就像人一样有记忆能力。LangChain封装了多种记忆功能组件,这些记忆组件可以单独使用,也可以无缝地集成到链(Chain)中。
记忆组件需要实现两个基本操作:读取和写入。
LangChain的各类chain任务组件,如果你打开记忆(Memory)功能,他会执行下面类似的逻辑
- 接收初始用户输入的时候,Chain任务会尝试从记忆组件中查询相关的历史信息,然后把历史信息和用户的输入拼接到提示词中传给LLM。
- 在接受llm返回内容的时候,会自动把结果存储到记忆组件,方便下次查询。
LangChain实现记忆能力的流程如下图:
将记忆组件集成到系统中
在使用记忆组件之前需要思考下面两个问题
- 怎么存储历史消息数据
- 怎么查询历史消息数据
存储:聊天消息列表
如果使用Chat模型,对话数据就是一个聊天消息列表,LangChain支持多种存储引擎,存储历史消息数据,最简单的就是存储到内存中,实际业务最常用的还是存储到数据库。
查询:如何查询相关的历史对话消息
要实现LLM的记忆能力,核心就是把历史的消息内容作为背景信息拼接到提示词,这样LLM在回答问题的时候,就可以参考背景信息。
存储历史消息数据相对比较容易,比较有挑战的是如何查询跟当前对话内容相关的历史消息,为什么需要查询跟当前对话相关的历史消息,主要原因还是LLM有最大token限制,我们不能把所有历史对话内容全部塞进提示词里面丢给AI。
常见的历史消息查询策略如下:
- 仅查询最近的N条消息,作为提示词的背景信息
- 把历史消息丢给AI进行文本摘要,这个摘要作为提示词背景信息。
- 借助向量数据库,查询跟当前对话相似的历史消息,作为提示词的背景信息
LangChain组件使用例子
下面看看LangChain中的Memory组件实际上是什么样子的。这里会将介绍与记忆组件交互的基础知识。
下面看看如何在任务链中使用ConversationBufferMemory。ConversationBufferMemory是一种非常简单的记忆组件,只能在内存中保留聊天消息列表,并将其传递到新的对话提示模板中。
from langchain.memory import ConversationBufferMemory
# 定义memory组件
memory = ConversationBufferMemory()
# 添加用户消息
memory.chat_memory.add_user_message("hi!")
# 添加AI消息
memory.chat_memory.add_ai_message("whats up?")
- 提示:LangChain提供了多种Memory组件,用法类似。
下面看看如何在链(Chain)中使用记忆组件。下面分别介绍LangChain的LLM和ChatModel两种封装的模型如何使用记忆组件。
LLM使用记忆组件的例子
from langchain_openai import OpenAI
from langchain_core.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
# 使用openai模型
llm = OpenAI(temperature=0)
# 定义提示词模板
# 注意,我们使用*chat_history模板参数代表历史消息内容,下面记忆组件需要跟这个参数保持一致,才能把历史消息填充进来*
**template = """你是一个很好的聊天机器人,正在与人类对话。
之前的对话内容:
{chat_history}
新的问题: {question}
AI回答:"""
prompt = PromptTemplate.from_template(template)
# 定义记忆组件存储历史对话信息,这里指定了memory_key参数,需要保持跟前面的提示词模板历史消息模板参数一致,都使用chat_history
memory = ConversationBufferMemory(memory_key="chat_history")
# 通过memory参数指定我们定义的记忆组件(ps: langchain这种设计,很方便切换到其他的记忆组件)
conversation = LLMChain(
llm=llm,
prompt=prompt,
verbose=True,
memory=memory
)
# 执行AI对话
conversation({"question": "hi"})
ChatModel使用记忆组件的例子
from langchain_openai import ChatOpenAI
from langchain.prompts import (
ChatPromptTemplate,
MessagesPlaceholder,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
# 使用openai chat模型
llm = ChatOpenAI()
#定义消息提示词模板
prompt = ChatPromptTemplate(
messages=[
SystemMessagePromptTemplate.from_template(
"You are a nice chatbot having a conversation with a human."
),
# 设置历史消息的模板参数变量是chat_history
MessagesPlaceholder(variable_name="chat_history"),
HumanMessagePromptTemplate.from_template("{question}")
]
)
# `return_messages=True` 参数目的是返回langchain封装的对话消息格式
# memory_key的chat_history参数要跟前面的历史消息模板参数对应
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
# 通过memory参数指定记忆组件
conversation = LLMChain(
llm=llm,
prompt=prompt,
verbose=True,
memory=memory
)
# 执行对话任务
conversation({"question": "hi"})