一架梯子,一头程序猿,仰望星空!
LangChain教程(Python版本) > 内容正文

LangChain LLM记忆能力(Memory)


LLM历史记忆(Memory)

大多数基于LLM的应用程序都有一个类似微信的聊天对话界面。AI对话过程的一个重要功能是能够引用先前在对话中讲过的信息,就像人类对话过程,不需要把前面讲过的内在复述一遍,人类会自动联想历史信息。

对于存储历史对话信息的能力,在LLM领域通常称为“记忆”(Memory),就像人一样有记忆能力。LangChain封装了多种记忆功能组件,这些记忆组件可以单独使用,也可以无缝地集成到链(Chain)中。

记忆组件需要实现两个基本操作:读取和写入。

LangChain的各类chain任务组件,如果你打开记忆(Memory)功能,他会执行下面类似的逻辑

  1. 接收初始用户输入的时候,Chain任务会尝试从记忆组件中查询相关的历史信息,然后把历史信息和用户的输入拼接到提示词中传给LLM。
  2. 在接受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.llms import OpenAI
from langchain.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.chat_models 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"})


关联主题