Langchain核心模块Memory


大多数LLM应用都具有对话界面。对话的一个重要组成部分是能够引用先前在对话中介绍过的信息。至少,一个对话系统应该能够直接访问一些过去消息的窗口。更复杂的系统将需要拥有一个不断更新的世界模型,使其能够保持关于实体及其关系的信息。

我们将存储过去交互信息的能力称为“记忆(Memory)”。

LangChain提供了许多用于向应用/系统中添加 Memory 的实用工具。这些工具可以单独使用,也可以无缝地集成到链中。

一个记忆系统(Memory System)需要支持两个基本操作:读取(READ)和写入(WRITE)。

每个链都定义了一些核心执行逻辑,并期望某些输入。其中一些输入直接来自用户,但有些输入可能来自 Memory。

在一个典型 Chain 的单次运行中,将与其 Memory System 进行至少两次交互:

  1. 在接收到初始用户输入之后,在执行核心逻辑之前,链将从其 Memory 中读取并扩充用户输入。
  2. 在执行核心逻辑之后但在返回答案之前,一个链条将把当前运行的输入和输出写入 Memory ,以便在未来的运行中可以引用它们。
    在这里插入图片描述

BaseMemory Class 基类

类继承关系:

适用于简单的语言模型

BaseMemory --> BaseChatMemory --> Memory # Examples: ZepMemory, MotorheadMemory
代码实现:memory.py

# 定义一个名为BaseMemory的基础类
class BaseMemory(Serializable, ABC):
    """用于Chains中的内存的抽象基类。
    
    这里的内存指的是Chains中的状态。内存可以用来存储关于Chain的过去执行的信息,
    并将该信息注入到Chain的未来执行的输入中。例如,对于会话型Chains,内存可以用来
    存储会话,并自动将它们添加到未来的模型提示中,以便模型具有必要的上下文来连贯地
    响应最新的输入。"""

    # 定义一个名为Config的子类
    class Config:
        """为此pydantic对象配置。
    
        Pydantic是一个Python库,用于数据验证和设置管理,主要基于Python类型提示。
        """
    
        # 允许在pydantic模型中使用任意类型。这通常用于允许复杂的数据类型。
        arbitrary_types_allowed = True
    
    # 下面是一些必须由子类实现的方法:
    
    # 定义一个属性,它是一个抽象方法。任何从BaseMemory派生的子类都需要实现此方法。
    # 此方法应返回该内存类将添加到链输入的字符串键。
    @property
    @abstractmethod
    def memory_variables(self) -> List[str]:
        """获取此内存类将添加到链输入的字符串键。"""
    
    # 定义一个抽象方法。任何从BaseMemory派生的子类都需要实现此方法。
    # 此方法基于给定的链输入返回键值对。
    @abstractmethod
    def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
        """根据给链的文本输入返回键值对。"""
    
    # 定义一个抽象方法。任何从BaseMemory派生的子类都需要实现此方法。
    # 此方法将此链运行的上下文保存到内存。
    @abstractmethod
    def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:
        """保存此链运行的上下文到内存。"""
    
    # 定义一个抽象方法。任何从BaseMemory派生的子类都需要实现此方法。
    # 此方法清除内存内容。
    @abstractmethod
    def clear(self) -> None:
        """清除内存内容。"""

BaseChatMessageHistory Class 基类

类继承关系:

适用于聊天模型

BaseChatMessageHistory --> ChatMessageHistory # Example: ZepChatMessageHistory

# 定义一个名为BaseChatMessageHistory的基础类
class BaseChatMessageHistory(ABC):
    """聊天消息历史记录的抽象基类。"""

    # 在内存中存储的消息列表
    messages: List[BaseMessage]

    # 定义一个add_user_message方法,它是一个方便的方法,用于将人类消息字符串添加到存储区。
    def add_user_message(self, message: str) -> None:
        """为存储添加一个人类消息字符串的便捷方法。

        参数:
            message: 人类消息的字符串内容。
        """
        self.add_message(HumanMessage(content=message))

    # 定义一个add_ai_message方法,它是一个方便的方法,用于将AI消息字符串添加到存储区。
    def add_ai_message(self, message: str) -> None:
        """为存储添加一个AI消息字符串的便捷方法。

        参数:
            message: AI消息的字符串内容。
        """
        self.add_message(AIMessage(content=message))

    # 抽象方法,需要由继承此基类的子类来实现。
    @abstractmethod
    def add_message(self, message: BaseMessage) -> None:
        """将Message对象添加到存储区。

        参数:
            message: 要存储的BaseMessage对象。
        """
        raise NotImplementedError()

    # 抽象方法,需要由继承此基类的子类来实现。
    @abstractmethod
    def clear(self) -> None:
        """从存储中删除所有消息"""

ConversationChain and ConversationBufferMemory

ConversationBufferMemory 可以用来存储消息,并将消息提取到一个变量中。

from langchain.llms import OpenAI
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory

llm = OpenAI(temperature=0)
conversation = ConversationChain(
    llm=llm, 
    verbose=True, 
    memory=ConversationBufferMemory()
)
conversation.predict(input="你好呀!")

ConversationBufferWindowMemory

ConversationBufferWindowMemory 会在时间轴上保留对话的交互列表。它只使用最后 K 次交互。这对于保持最近交互的滑动窗口非常有用,以避免缓冲区过大。

from langchain.memory import ConversationBufferWindowMemory

conversation_with_summary = ConversationChain(
    llm=OpenAI(temperature=0, max_tokens=1000), 
    # We set a low k=2, to only keep the last 2 interactions in memory
    memory=ConversationBufferWindowMemory(k=2), 
    verbose=True
)
conversation_with_summary.predict(input="嗨,你最近过得怎么样?")
  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值