欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 记忆模块概述

记忆模块概述

2025/2/13 5:32:46 来源:https://blog.csdn.net/weixin_43961909/article/details/145598501  浏览:    关键词:记忆模块概述

文章目录

    • 记忆模块概述
      • 记忆组件的定义
      • 记忆组件、链组件和Agent组件的关系
      • 设置第一个记忆组件
      • 内置记忆组件
      • 自定义记忆组件

    本文将LangChain框架内所有与记忆功能有关的组件统一称为“记忆模块”。简而言之,记忆模块是一个集合体,由多个不同的记忆组件构成。每个记忆组件都负责某一特定方面的记忆功能。在记忆模块(langchain.memory)下,有多种不同的类,每一个类都可以看作一个“记忆组件”。记忆组件是记忆模块的子元素,用于执行更具体的记忆任务。例如,如果你从记忆模块中导人ConversationBufferMemory类并对其进行实例化,你将得到一个名为ConversationBufferMemory的记忆组件。

记忆模块概述

    想一想,为什么需要记忆模块?大语言模型本质上是无记忆的。当与其交互时,它仅根据提供的提示生成相应的输出,而无法存储或记住过去的交互内容。因为是无记忆的,意味着它不能“学习”或“记住”用户的偏好、以前的错误或其他个性化信息,难以满足人们的期望。

    人们期待聊天机器人具有人的品质和回应能力。在现实的聊天环境中,人们的对话中充满了缩写和含蓄表达,他们会引用过去的对话内容,并期待对方能够理解和回应。例如,如果在聊天一开始时提到了某人的名字,随后仅用代词指代,那么人们就期望聊天机器人能够理解和记住这个指代关系。

    对聊天机器人的期待并不仅仅是它需要具备基础的回答功能,人们更希望聊天机器人能够在整个对话过程中,理解对话,记住交流内容,甚至理解情绪和需求。为了实现这个目标,需要赋予大语言模型一种“记忆”能力。记忆是一种基础的人类特性,是理解世界和与世界交流的基础。这是需要记忆模块的原因,将这种记忆能力赋予机器人,使机器人具备人类般的记忆能力。

    最后,需要强调,为什么在实际的大语言模型应用开发中,需要记忆能力。简单来说,同样作为提示词模板的外部数据,通过“记忆”能力形成的外部数据,与检索到的外部文档内容起到一样的作用。同样地,它可以确保大语言模型在处理信息时始终能够获取到最新、最准确的上下文数据。通过提供聊天信息,可以让大语言模型的输出更有据可查,多了一份“证据”,这也是一种低成本应用大语言模型的策略,不需要做参数训练等额外工作。

记忆组件的定义

    记忆组件是什么?记忆组件,实际上是一个聊天备忘录对象,像苹果手机备忘录程序一样,可以用它记录与大语言模型的聊天对话内容。那么,备忘录的作用是什么呢?试想在一个会议上,你有一位秘书在边上为你做备忘录。当你发言时,你可能会忘记先前的发言者都说过什么,这时你可以让秘书展示备忘录,通过查阅这些信息,你就能够清楚地整理自己的发言,从而赢得全场的赞许。而当你发言结束后,秘书又要做什么呢?他需要把你刚刚的精彩发言记录下来。

    这就是记忆组件的两大功能:读取和写人。因此,记忆组件的基本操作包括读取和写人。在链组件的每次运行中,都会有两次与记忆组件的交互:在链组件运行之前,记忆组件首先会从其存储空间中读取相关信息。这些信息可能包括先前的对话历史、用户设置或其他与即将执行的任务相关的数据。完成运行后,生成的输出或其他重要信息会被写人记忆组件中。这样,这些信息就可以在以后的运行或会话中被重新读取和使用。

    记忆组件的设计,旨在解决两个核心问题:一是如何写人,也就是存储状态;二是如何读取,即查询状态。存储状态一般通过程序的运行内存存储历史聊天记录实现。查询状态则依赖于在聊天记录上构建的数据结构和算法,它们提供了对历史信息的高效检索和解析。类似于一个聊天备忘录,记忆组件既可以帮助记录下聊天的每一条信息,也可以依据需求,搜索出相关的历史聊天记录。

    最难理解的是,如何在聊天记录上构建数据结构和算法?简单来说,数据结构和算法就是用来整理和检索聊天记录的。记忆组件会将处理过的聊天信息数据注人提示词模板中,最终通过模型平台的API接口获取大语言模型的响应,这样可以使响应更加准确。因为要决定哪些聊天记录需要保留,哪些聊天记录需要进一步处理,所以需要在聊天记录上构建数据结构和算法。

    主要采取以下两种方法整理和检索聊天记录。第一种方法是将聊天记录全部放人提示词模板中,这是一种比较简单的方法。具体是将聊天窗口中的上下文信息直接放在提示词中,作为外部数据注入提示词模板中,再提供给大语言模型。这种方法简单易行,但是因为结合信息的方式较为粗糙,所以可能无法达到精准控制的目的。而且由于模型平台的Max Tokens限制,这种方法要考虑如何截取聊天记录,如何压缩聊天记录,以适应模型平台底层的API要求。

    第二种方法是先压缩聊天记录,然后放入提示词模板中。这种方法的思路是利用LLM的总结和提取实体信息的能力压缩聊天记录,或者从数据库中提取相关的聊天记录、实体知识等,然后将这些文本拼接在提示词中,再提供给大语言模型,进行下一轮对话。

    在这个过程中,可以使用类似于图像压缩算法的方式对聊天记录进行压缩。比如,可以参考PEG图像压缩算法的原理,将原始的聊天记录(类比为图像的原始数据)进行压缩。PEG图像压缩算法在压缩过程中会舍弃一些人眼难以察觉的高频细节信息,从而达到压缩的效果,同时大部分重要信息被保留。这样,就可以将压缩后的聊天记录(类比为压缩后的图像)放入提示词模板中,用于生成下一轮对话。虽然这种压缩方式可能会丢失一些细节信息,但是由于这些信息对于聊天记录的总体含义影响较小,因此可以接受。通过这种方式,不仅可以在保证聊天记录的总体含义的同时,缩短提示词的长度,而且还可以提高大语言模型的运行效率和响应速度。

记忆组件、链组件和Agent组件的关系

    首先探讨记忆组件和链组件的关系。LangChain的记忆模块提供了各种类型的记忆组件,这些记忆组件可以独立使用,也可以集成到链组件中。换句话说,记忆组件可以作为链组件的一部分,是一个内部组件,用于保存状态和历史信息,以便链组件在处理输人和生成输出时使用。所以记忆组件和链组件的关系是,链组件是与大语言模型交互的主体,而记忆组件则是在这个过程中提供支持的角色。通过引人记忆组件,链组件调用大语言模型就能得到过去的对话,从而理解并确定当前谈论的主题和对象。这使得聊天机器人更接近人类的交流方式,从而更好地满足用户的期望。

    接下来探讨记忆组件和Agent组件的关系。将记忆组件放人Agent组件中,这使得Aget组件不仅能够处理和响应请求,而且还能够记住交流内容。这就是所谓的“让Agent拥有记忆”。Agent是一个更高级别的组件,它可能包含一个或多个链组件,以及与这些链组件交互的记忆组件。Agent通常代表一个完整的对话系统或应用,负责管理和协调其内部组件(包括链组件和记忆组件)以响应用户输人。

    具体来说,Aget组件在处理用户输人时,可能会使用其内部的链组件来执行各种逻辑,同时使用记忆组件来存储当前的交互信息和检索过去的交互信息。例如,聊天机器人可能会使用记忆组件中保存的聊天记录信息来增强模型响应。因此,可以说记忆组件是Agent组件的一个重要部分,帮助Agent组件维护状态和历史信息,使其能够处理复杂的对话任务。在构建Aget组件时,通常需要考虑如何选择和配置内存,以满足特定的应用需求和性能目标。以上就是记忆组件、链组件和Agent组件的关系。

设置第一个记忆组件

    下面使用代码演示如何实例化一个记忆组件,以及如何使用记忆组件的保存和加载方法来管理聊天记录。这是记忆组件通常的使用方式,但是在具体的实现细节上可能组件与组件之间会有所不同。首先,要引入ConversationTokenBufferMemory类,并创建一个OpenAI类的实例作为其参数。ConversationTokenBufferMemory是一个记忆组件,它将最近的交互信息保存在内存中,并使用最大标记(Token)数量来决定何时清除交互信息。使用一个OpenAI实例和一个max_token_limit参数来创建ConversationTokenBufferMemory的实例memory。max_token_limit=-l000指定了记忆组件中可以存储的最大标记数量为1000。这是一个上限数字,如果数字设置得过于小的话,可能最后打印的对象是空字符串,可以手动设置为10,再设置为100查看效果。memory key参数用于设置记忆组件存储对象的键名,默认是history,这里设置为session_chat。

from langchain.memory import ConversationTokenBufferMemory
from langchain.llms import OpenAI
openai_api_key="填人你的OpenAI密钥"
llm = OpenAI(openai_api_key=openai_api_key)
memory=ConversationTokenBufferMemory (llm=llm,max_token_limit=1000,memory_key="session chat")

    接下来,可以使用save context方法将聊天记录保存到记忆组件中。每次调用save context方法,都会将一次交互(包括用户输人和聊天机器人的回答)记录添加到记忆组件的缓冲区中。需要先后保存两次交互记录。在第一次交互中,用户输入的是“你好!我是李特丽,这是人类的第一个消息”;在第二次交互中,用户输人的是“今天心情怎么样”,大语言模型的输出是:“我很开心认识你”。

memory.save_context(("input":"你好!我是李特丽,这是人类的第一个消息"),
("output":"你好!我是AI助理的第一个消息")
memory.save_context(("input":"今天心情怎么样"),{"output":"我很开心认识你"))

    最后,可以使用load memory variables方法来加载记忆组件中的聊天记录。这个方法会返回一个字典,其中包含了记忆组件当前保存的所有聊天记录。

memory.load memory_variables(())
('session chat':'Human:你好!我是李特丽,这是人类的第一个消息\nAI:你好!我是AI助理的第一个消息\nHuman:今天心情怎么样nAI:我很开心认识你')

    以上就是如何使用ConversationTokenBufferMemory记忆组件的示例。

内置记忆组件

    LangChain的记忆模块提供了多种内置的记忆组件类,这些类的使用方法和ConversationTokenBufferMemory类基本一致,都提供了保存(save context)和加载(load_memory_variables)聊天记录的方法,只是在具体的实现和应用场景上有所不同。例如,ConversationBufferMemory ConversationBuffer WindowMemoryConversationTokenBufferMemory等类都是用于保存和加载聊天记录的记忆组件,但它们在保存聊天记录时所使用的数据结构和算法有所不同。ConversationBufferMemory类使用一个缓冲区来保存最近的聊天记录,而ConversationTokenBufferMemory类则使用Max Tokens长度来决定何时清除聊天记录。

    此外,有些记忆组件类还提供了额外的功能,如ConversationEntityMemory和ConversationKGMemory类可以用于保存和查询实体信息,CombinedMemory类可以用于组合多个记忆组件,而ReadOnlySharedMemory类则提供了一种只读的共享记忆模式。对于需要将聊天记录持久化保存的应用场景,LangChain的记忆模块还提供了多种与数据库集成的记忆组件类,如SQLChatMessageHistory、MongoDBChatMessageHistory、DynamoDBChatMessageHistory等。这些类在保存和加载聊天记录时,会将聊天记录保存在对应的数据库中。

    在选择记忆组件时,需要根据自己的应用需求来选择合适的记忆组件。例如,如果你需要处理大量的聊天记录,或者需要在多个会话中共享聊天记录,那么你需要选择一个与数据库集成的记忆组件。而如果你主要处理实体信息,那么你需要选择ConversationEntityMemory或ConversationKGMemory这样的记忆组件。无论选择哪种记忆组件,都需要理解其工作原理和使用方法,以便正确地使用它来管理你的聊天记录。

自定义记忆组件

    在上一节中,我们了解了LangChain的内置记忆组件。尽管这些记忆组件能够满足许多通用的需求,但每个具体的应用场景都有其独特的要求和复杂性。例如,某些应用可能需要使用特定的数据结构来优化查询性能,或者需要使用特别的存储方式来满足数据安全或隐私要求。在这些情况下,内置的记忆组件可能无法完全满足需求。

    LangChain通过允许开发者添加自定义的记忆类型,来提供更高的灵活性和扩展性,这使得开发者能够根据自己的需求定制和优化记忆组件。这对于高级的使用场景,如大规模的生产环境或特定的业务需求尤为重要。内置组件往往是框架开发者根据通用需求预先设计和封装好的,我们可以直接拿来使用,无须关心其内部实现细节。这无疑大大降低了使用组件的门槛,提高了开发效率。然而,这也意味着用户很可能对这些组件的内部构造和工作原理一无所知。

    而当你试图创建自定义组件时,需要深人理解和分析自己的特定需求,然后再在此基础上设计和实现符合需求的组件。这个过程迫使你深人了解内置组件的构造和工作原理,从而可以更好地理解框架的设计逻辑和工作方式。因此,尽管创建自定义组件的过程可能会有些复杂,但这无疑是深人理解和掌握框架的有效方式。下面向ConversationChain添加一个自定义的记忆组件。请注意,这个自定义的记忆组件相当简单且脆弱,可能在生产环境中并不实用。这里的目的是展示如何添加自定义记忆组件。

from langchain import OpenAI,ConversationChain
from langchain.schema import BaseMemory
from pydantic import BaseModel
from typing import List,Dict,Any

    然后编写一个SpacyEntityMemory类,它使用spacy方法来提取实体信息,并将提取到的信息保存在一个简单的哈希表中。然后,在对话中,检查用户输人,并提取实体信息,且将实体信息放人提示词的上下文中。

!pip install spacy
python -m spacy download en core web_1g
import spacy
nlp spacy.load("en core web 1g")
class SpacyEntityMemory(BaseMemory,BaseModel):"""Memory class for storing information about entities."""# Define dictionary to store information about entities.entities:dict ={}# Define key to pass information about entities into prompt.memory_key:str "entities"def clear(self):self.entities ={}@propertydef memory variables(self)->List(str]:"""Define the variables we are providing to the prompt."""return [self.memory_key]def load_memory_variables(self,inputs:Dict[str,Any])->Dict[str,str]:"""Load the memory variables,in this case the entity key."""# Get the input text and run through spacydoc = nlp(inputs[list (inputs.keys())[0]])# Extract known information about entities,if they exist.entities=[self.entities[str(ent)]for ent in doc.ents if str(ent)in self.entities]# Return combined information about entities to put into context.return (self.memory_key:"\n".join (entities))
def save_context (self,inputs:Dict[str,Any],outputs:Dict[str,str])->None:
"""Save context from this conversation to buffer."""# Get the input text and run through spacytext= inputs[list (inputs.keys())[0]]doc =nlp(text)# For each entity that was mentioned,save this information to thedictionary.for ent in doc.ents:ent str str(ent)if ent str in self.entities:self.entities[ent str]+=f"\n(text)"else:self.entities[ent_str]text

    下面定义一个提示词模板,它接受实体信息以及用户输人的信息。

from langchain.prompts.prompt import PromptTemplate
template="""
The following is a friendly conversation between a human and an AI.
The AI is talkative and provides lots of specific details from its
context.If the AI does not know the answer to a question,it truthfully
says it does not know.You are provided with information about entities
the Human mentions,if relevant.
Relevant entity information:
(entities)
Conversation:
Human:(input}
AI:
"""prompt=PromptTemplate (input variables=["entities","input"],template=template)

    然后把记忆组件和链组件组合在一起,放在ConversationChain链上运行,与模型交互。

llm =OpenAI(temperature=0)
conversation =ConversationChain(llm=llm,prompt=prompt,verbose=True,memory=SpacyEntityMemory ())

    第一次用户的输人是“Harrison likes machine learning”。由于对话中没有关于Harrison的先验知识,所以提示词模板中“Relevant entity information”(相关实体信息)部分是空的。

conversation.predict (input="Harrison likes machine learning")

    运行的结果是:

Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI.The
AI is talkative and provides lots of specific details from its context.If the
AI does not know the answer to a question,it truthfully says it does not know.
You are provided with information about entities the Human mentions,if relevant.
Relevant entity information:
Conversation:
Human:Harrison likes machine learning
AI:
> Finished ConversationChain chain.
"That's great to hear!Machine learning is a fascinating field of study.
It involves using algorithms to analyze data and make predictions.Have you ever
studied machine learning,Harrison?"

    对于第二次用户输人,可以看到聊天机器人回答了关于Harrison的信息,提示词模板中“Relevant entity information’”部分是“Harrison likes machine learning”。

conversation.predict(input="What do you think Harrison's favorite subject in college was?")

    运行的结果是:

Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI.The
AI is talkative and provides lots of specific details from its context.If the
AI does not know the answer to a question,it truthfully says it does not know.
You are provided with information about entities the Human mentions,if relevant.
Relevant entity information:
Harrison likes machine learning Conversation:
Human:What do you think Harrison's favorite subject in college was?
AI:
Finished ConversationChain chain.
'From what I know about Harrison,I believe his favorite subject in college
was machine learning.He has expressed a strong interest in the subject and has
mentioned it often.'

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com