LangChain 16 通过Memory记住历史对话的内容

LangChain系列文章

  1. LangChain 实现给动物取名字
  2. LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字
  3. LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄
  4. LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索Indexes for information retrieve
  5. LangChain 5易速鲜花内部问答系统
  6. LangChain 6根据图片生成推广文案HuggingFace中的image-caption模型
  7. LangChain 7 文本模型TextLangChain和聊天模型ChatLangChain
  8. LangChain 8 模型Model I/O:输入提示、调用模型、解析输出
  9. LangChain 9 模型Model I/O 聊天提示词ChatPromptTemplate, 少量样本提示词FewShotPrompt
  10. LangChain 10思维链Chain of Thought一步一步的思考 think step by step
  11. LangChain 11实现思维树Implementing the Tree of Thoughts in LangChain’s Chain
  12. LangChain 12调用模型HuggingFace中的Llama2和Google Flan t5
  13. LangChain 13输出解析Output Parsers 自动修复解析器
  14. LangChain 14 SequencialChain链接不同的组件
  15. LangChain 15根据问题自动路由Router Chain确定用户的意图
    在这里插入图片描述

1. Memory 记忆

在这里插入图片描述
大多数LLM应用程序都有对话界面。对话的一个重要组成部分是能够引用先前在对话中介绍的信息。最基本的是,对话系统应该能够直接访问某些过去的信息窗口。更复杂的系统将需要具有一个世界模型,它不断更新,这使它能够维护有关实体及其关系的信息。

我们称这种存储关于过去交互的信息的能力为“记忆”。LangChain为系统添加记忆提供了许多实用工具。这些实用工具可以单独使用,也可以无缝地整合到链中。

记忆系统需要支持两个基本操作:读取和写入。请记住,每个链定义了一些核心执行逻辑,期望某些输入。其中一些输入直接来自用户,但一些输入可以来自记忆。链将在给定运行中两次与其记忆系统交互。

  1. 在接收到初始用户输入但在执行核心逻辑之前,链将从其记忆系统中读取并增强用户输入。
  2. 在执行核心逻辑但在返回答案之前,链将把当前运行的输入和输出写入记忆中,以便在将来的运行中可以引用它们。

2. 将内存构建到系统中

在任何内存系统中的两个核心设计决策是:

  • 状态如何存储
  • 状态如何查询

2.1 存储:聊天消息列表

任何记忆的基础都是所有聊天互动的历史。即使这些并非全部直接使用,也需要以某种形式存储。LangChain记忆模块的关键部分之一是一系列用于存储这些聊天消息的集成,从内存列表到持久性数据库。

2.2 查询:在聊天消息之上的数据结构和算法

保留聊天消息列表相当简单。不太简单的是建立在聊天消息之上的数据结构和算法,以便提供最有用的消息视图。

一个非常简单的记忆系统可能只返回每次运行最近的消息。一个稍微复杂一点的记忆系统可能会返回过去K条消息的简明总结。一个更复杂的系统可能会从存储的消息中提取实体,并且只返回当前运行中涉及的实体信息。

每个应用程序对于如何查询记忆都可能有不同的要求。记忆模块应该让简单的记忆系统易于入门,并且如果需要,也能够编写自定义系统。

3. 代码实现

让我们来看看LangChainMemory实际上是什么样子。在这里,我们将介绍与任意记忆类互动的基础知识。

让我们来看看如何在链中使用ConversationBufferMemoryConversationBufferMemory是记忆的一种极其简单的形式,它只是在缓冲区中保留聊天消息的列表,并将其传递到提示模板中。

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()
memory.chat_memory.add_user_message("hi!")
memory.chat_memory.add_ai_message("what's up?")

在使用链式内存时,有一些关键概念需要理解。请注意,这里我们涵盖了对大多数类型的内存都有用的一般概念。每种个别的内存类型可能都有自己必须理解的参数和概念。

3.1 从内存中返回哪些变量

在进入链之前,会从内存中读取各种变量。这些变量有特定的名称,需要与链期望的变量相匹配。您可以通过调用memory.load_memory_variables({})来查看这些变量是什么。请注意,我们传入的空字典只是真实变量的占位符。如果您使用的内存类型依赖于输入变量,您可能需要传入一些变量。

print(memory.load_memory_variables({}))

输出结果

    {'history': "Human: hi!\nAI: what's up?"}

在这种情况下,您可以看到load_memory_variables返回一个名为history的key。这意味着您的链条(很可能是您的提示)应该期望一个名为history的输入。通常您可以通过内存类的参数来控制这个变量。例如,如果您希望将内存变量返回到键chat_history中,您可以这样做:

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(memory_key="chat_history")
memory.chat_memory.add_user_message("hi!")
memory.chat_memory.add_ai_message("what's up?")

print(memory.load_memory_variables({}))

输出结果

    {'chat_history': "Human: hi!\nAI: what's up?"}

这些键的控制参数名称可能因内存类型而异,但重要的是要明白:(1)这是可控的,(2)如何控制它。

3.2 Memory是string字符串还是chat list消息列表

最常见的记忆类型之一涉及返回聊天消息列表。这些可以作为单个字符串返回,全部连接在一起(当它们将被传递到LLMs时很有用),或者作为ChatMessages列表返回(当它们被传递到ChatModels时很有用)。

默认情况下,它们作为单个字符串返回。为了返回消息列表,您可以设置return_messages=True

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
memory.chat_memory.add_user_message("hi!")
memory.chat_memory.add_ai_message("what's up?")

print(memory.load_memory_variables({}))

输出结果

 {'chat_history': [HumanMessage(content='hi!', additional_kwargs={}, example=False),
  AIMessage(content='what's up?', additional_kwargs={}, example=False)]}

3.3 什么Keys保存在内存中

通常情况下,链条会接收或返回多个输入/输出键。在这种情况下,我们如何知道要保存哪些键到聊天消息历史记录中?这通常可以通过内存类型的input_keyoutput_key参数来控制。这些参数默认为None-如果只有一个输入/输出键,则可以直接使用它。但是,如果有多个输入/输出键,则必须指定要使用哪一个的名称。

最后,让我们来看看如何在一个链中使用这个。我们将使用LLMChain,并展示如何同时使用LLM和ChatModel。

# 导入 Langchain 库的 ChatOpenAI 类,用于与 OpenAI 聊天模型进行交互。
from langchain.chat_models import ChatOpenAI

# 导入 Langchain 库的不同提示模板类,用于构建会话提示。
from langchain.prompts import (
    ChatPromptTemplate,
    MessagesPlaceholder,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

# 导入 Langchain 的 LLMChain 类,用于创建语言模型链。
from langchain.chains import LLMChain

# 导入 Langchain 的 ConversationBufferMemory 类,用于存储和管理会话记忆。
from langchain.memory import ConversationBufferMemory

# 导入 dotenv 库,用于从 .env 文件加载环境变量,管理敏感数据,如 API 密钥。
from dotenv import load_dotenv  

# 调用 load_dotenv 函数来加载 .env 文件中的环境变量。
load_dotenv()  

# 创建 ChatOpenAI 的实例。
llm = ChatOpenAI()

# 创建聊天提示模板,包含一个系统消息、一个聊天历史占位符和一个人类消息模板。
prompt = ChatPromptTemplate(
    messages=[
        SystemMessagePromptTemplate.from_template(
            "You are a nice chatbot having a conversation with a human."
        ),
        MessagesPlaceholder(variable_name="chat_history"),
        HumanMessagePromptTemplate.from_template("{question}")
    ]
)

# 创建一个会话记忆,用于存储和返回会话中的消息。
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

# 创建一个 LLMChain 实例,包括语言模型、提示、详细模式和会话记忆。
conversation = LLMChain(
    llm=llm,
    prompt=prompt,
    verbose=True,
    memory=memory
)

# 使用会话链处理第一个问题,并打印回应。
response = conversation({"question": "hi"})
print(response)

# 使用相同的会话链处理第二个问题,并打印回应。
response = conversation({"question": "how are you?"})
print(response)

输出

zgpeace at zgpeaces-MBP in ~/Workspace/LLM/langchain-llm-app (develop●) (.venv) 
$ python Memory/memory_theory.py


> Entering new LLMChain chain...
Prompt after formatting:
System: You are a nice chatbot having a conversation with a human.
Human: hi

> Finished chain.
{'question': 'hi', 'chat_history': [HumanMessage(content='hi'), AIMessage(content='Hello! How can I assist you today?')], 'text': 'Hello! How can I assist you today?'}


> Entering new LLMChain chain...
Prompt after formatting:
System: You are a nice chatbot having a conversation with a human.
Human: hi
AI: Hello! How can I assist you today?
Human: how are you?

> Finished chain.
{'question': 'how are you?', 'chat_history': [HumanMessage(content='hi'), AIMessage(content='Hello! How can I assist you today?'), HumanMessage(content='how are you?'), AIMessage(content="Thank you for asking! As an AI, I don't have feelings, but I'm here to help you. How can I assist you today?")], 'text': "Thank you for asking! As an AI, I don't have feelings, but I'm here to help you. How can I assist you today?"}

在这里插入图片描述

代码
https://github.com/zgpeace/pets-name-langchain/tree/develop

参考

https://python.langchain.com/docs/modules/memory/

  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
16-entry memory management unit是一种内存管理单元,其设计目的是为了提高计算机的数据访问效率和保护内存资源。它是计算机系统中至关重要的组成部分之一,在操作系统和应用程序的支持下,为计算机的内存管理提供关键的支持。 一个16-entry memory management unit通常包括一个硬件单元和一个管理单元。硬件单元负责将内存地址转换为物理地址,并确保在内存访问期间对内存资源进行保护,以免其他进程或应用程序进行非法操作。这个过程中,硬件单元使用一个表格来维护虚拟内存地址到物理内存地址的映射关系。这个表格由管理单元进行管理,管理单元可以根据操作系统的需求对表格进行修改,或者运行时动态地修改表格中的映射关系。 16-entry memory management unit的优点有很多。首先,它可以有效地提高计算机的内存访问效率。通过使用虚拟内存和物理内存的映射关系,16-entry memory management unit可以在内存访问时自动完成地址转换,消除了程序和硬件之间的中间过程,从而提高了计算机内存访问的速度。其次,它可以有效地管理内存资源,保护内存资源免受非法操作。通过使用内存映射表,16-entry memory management unit可以有效地管理和监控内存资源,并防止其他进程或应用程序对内存资源进行非法操作。 总之,16-entry memory management unit是一种重要的内存管理单元。它可以提高计算机的内存访问效率,并有效地管理和保护内存资源。通过使用16-entry memory management unit,操作系统和应用程序可以更加高效地使用计算机的内存资源,提高了计算机的性能和安全性。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值