如何让你的LLM能跟操作系统一样可以持久化记忆?

好久没更新论文的分享了,今天来给大家分享一篇最近阅读的个人感觉非常有价值的一篇:MEMGPT: TOWARDS LLMS AS OPERATING SYSTEMS。我们都知道无论是ChatGPT、LLaMA、Claude等等大模型,虽然支持结合上下文进行对话,但这个对话长度实际是受限的,尤其是如果想进行长文档处理的时候就更头疼了,那么对于大模型这种记忆能力薄弱的问题要如何解决呢?这篇论文从操作系统的存储设计上得到灵感,从而尝试让大模型拥有了"无限"的记忆能力。

我们都知道,操作系统的数据存储包括磁盘、内存、甚至CPU,真正能持久化数据的只有磁盘,但要弄数据的读写速度,CPU和内存显然比磁盘要快得多,因此有L1,L2缓存技术、内存映射技术等提升操作系统对于数据的操作性能。那么对于大模型,我们是不是也可以参考这个设计,将上下文内容也进行分层存储呢?

如何分层?

在MemGPT中,作者将上下文分成了主上下文(Main Context,类似RAM)和外部上下文(External Context,类似磁盘)。主上下文是现代语言模型中的标准固定上下文窗口,而外部上下文则是LLM固定上下文窗口之外的任何信息。这些“不在上下文中”的数据必须明确地移动到主上下文中,以便将其传递给LLM处理器进行推理。

在MemGPT中,哪些上下文应该放在主上下文和哪些应该放在外部上下文通常是由几个因素决定的:

  1. 当前任务或目标:根据当前的任务或用户查询,MemGPT可能会决定将与这些任务或查询最相关的信息移动到主上下文中。
  2. 上下文窗口大小:由于主上下文有一个固定的token限制,因此需要仔细管理哪些信息应该保留在主上下文中。当主上下文接近其最大容量时,可能需要将一些不太重要或不太相关的信息移动到外部上下文。
  3. 用户或系统触发的事件:某些特定事件(如用户输入或系统消息)可能会触发将信息从一个上下文移动到另一个上下文。这些事件通常会通过LLM处理器生成相应的函数调用来处理。
  4. 自主决策:MemGPT具有一定程度的自主性,可以根据其对当前目标和责任的理解,自行决定如何管理其内存。

比如下面就是源码中针对记忆长度来进行判断是否要进行记忆修改:

# Check the memory pressure and potentially issue a memory pressure warning  
current_total_tokens = response['usage']['total_tokens']  
active_memory_warning = False  
if current_total_tokens > MESSAGE_SUMMARY_WARNING_TOKENS:  
    printd(f"WARNING: last response total_tokens ({current_total_tokens}) > {MESSAGE_SUMMARY_WARNING_TOKENS}")  
    # Only deliver the alert if we haven't already (this period)  
    if not self.agent_alerted_about_memory_pressure:  
        active_memory_warning = True  
        self.agent_alerted_about_memory_pressure = True  # it's up to the outer loop to handle this  
else:  
    printd(f"last response total_tokens ({current_total_tokens}) < {MESSAGE_SUMMARY_WARNING_TOKENS}")

在LLM进行推理的时候,实际使用的内容是主上下文中的内容,它是LLM可以直接访问和处理的数据区域。外部上下文更像是磁盘存储,在这里可以存储更多的数据,但这些数据不会直接用于LLM的推理。外部上下文的数据必须首先被移动到主上下文中,才能被LLM处理。因此,可以将外部上下文视为一种“存档”或“备份”机制,它允许系统在需要时检索旧数据或额外信息。

数据移动

那么既然数据分层好了,操作系统进行读写的时候数据可能是会在RAM和DISK之间来回转移的,MemGPT显然也是要做一样的事情。MemGPT通过函数调用来协调主上下文和外部上下文之间的数据移动。这些内存编辑和检索都是自主完成的:MemGPT根据当前上下文自主地更新和搜索其自己的内存。例如,它可以决定何时在上下文之间移动项目,并修改其主上下文,以更好地反映其对当前目标和责任的不断发展的理解。

因此就像操作系统的虚拟内存一样,操作系统的虚拟内存对应的物理内存其实不是连续的,只是让应用程序进程误以为自己拥有一片连续的内存而已。对于LLM而言,它的主上下文的内容其实也不是连续的,它里面的信息可以是来自不同时间点或不同会话的。例如,如果用户在一个长对话中多次提到某个特定主题,这些相关的信息片段可能会被聚集在主上下文中,即使它们在原始对话中是不连续的。同样地,如果有一个长文档需要处理,MemGPT可能会从文档中提取出最关键的部分并将其放入主上下文,而不是连续地处理整个文档。下面是源码agent.py里面拷贝出来的代码片段,就是用来重建记忆或者说更新记忆用的。

def rebuild_memory(self):  
    """Rebuilds the system message with the latest memory object"""  
    curr_system_message = self.messages[0]  # this is the system + memory bank, not just the system prompt  
    new_system_message = initialize_message_sequence(  
        self.model,  
        self.system,  
        self.memory,  
        archival_memory=self.persistence_manager.archival_memory,  
        recall_memory=self.persistence_manager.recall_memory,  
    )[0]  
  
    diff = united_diff(curr_system_message['content'], new_system_message['content'])  
    printd(f"Rebuilding system with new memory...\nDiff:\n{diff}")  
  
    # Store the memory change (if stateful)  
    self.persistence_manager.update_memory(self.memory)  
  
    # Swap the system message out  
    self.swap_system_message(new_system_message)

这种灵活性允许MemGPT更有效地管理其有限的上下文窗口,以便在多个任务和长期互动中表现得更好。因此,主上下文是一个动态的、可变的数据结构,其内容会根据当前任务、用户输入和其他因素而变化。

控制流

此外,MemGPT还包含了控制流(Control Flow)和函数链(Function Chaining)的功能。在MemGPT中,事件触发LLM推理:事件是MemGPT的一般化输入,可以包括用户消息(在聊天应用中)、系统消息(例如,主上下文容量警告)、用户交互(例如,用户刚刚登录的警报,或者他们完成了文档上传的警报)以及定时事件(允许MemGPT在没有用户干预的情况下运行)。当MemGPT生成一个函数调用时,它可以提前请求控制权以将函数链接在一起。当暂停(yielding)时,处理器会暂停,直到下一个外部事件。

对于Function Chaining,许多实际任务需要按顺序调用多个函数,例如,从单个查询中浏览多页结果或从主上下文中的不同文档中整合数据,MemGPT中,函数可以用一个特殊标志进行调用,该标志请求在请求的函数完成执行后立即将控制权返回给处理器。如果这个标志存在,MemGPT会将函数输出添加到主上下文中,并继续执行处理器。如果这个标志不存在(即为yield),MemGPT将不会运行LLM处理器,直到下一个外部事件触发,这种设计允许在单个任务期间进行重复的上下文修改,使代理能够更有效地利用其有限的上下文。

MemGPT对于AI-Agent的研究意义

目前LLM的选择已经非常多了,无论是开源的LLaMA2、ChatGLM还是闭源的ChatGPT、Claude,我们普通人或者小公司也许无法去进行大模型的的开发,有的可能针对特定场景进行fine-tuning,也有的可能基于这些大模型进行应用开发(当然也有可能两者同时进行)。AI-Agent(人工智能代理)是一个自动执行任务或做出决策的软件实体。它通常具有一定程度的自主性、智能和适应性,能够在复杂、动态或不确定的环境中工作,因此进行大模型应用开发可少不了它的身影。AI-Agent可以是简单的,如基于规则的聊天机器人,也可以是复杂的,如自动驾驶汽车或高级游戏AI。它们通常使用各种AI技术,包括机器学习、自然语言处理、计算机视觉和强化学习,以实现其功能。

MemGPT对于Agent的开发有着重要的意义,传统的大型语言模型(LLMs)在处理长期多会话互动方面有局限性。MemGPT通过引入持久性内存和事件系统,为AI-Agent提供了一种有效的长期记忆和上下文管理机制。此外,MemGPT具有一定程度的自主性,能够自行决定如何管理其内存。这为AI-Agent的自主性和智能决策提供了新的可能性。通过函数链(Function Chaining)机制,MemGPT能够执行一系列复杂的任务,这对于需要多步骤和长期规划的AI-Agent非常有用。

MemGPT的代码是开源的,感兴趣的同学可以自己去阅读一下源码或自己尝试使用一下,它是支持直接调用ChatGPT的API的,或使用Azure OpenAI。而且它还支持本地LLM服务的,因此各位也可以尝试使用其他开源模型来玩一下MemGPT,不过操作起来相对要麻烦一点: 首先需要为该模型实现一个封装类 ,封装类需要实现两个函数:

  • 一个是从聊天完成消息/函数模式到提示字符串
  • 一个是从原始 LLM 输出到聊天完成响应
    然后将该模型放在服务器后面(例如使用 WebUI),并设置 OPENAI_API_BASE。
class LLMChatCompletionWrapper(ABC):
    @abstractmethod
    def chat_completion_to_prompt(self, messages, functions):
        """Go from ChatCompletion to a single prompt string"""
        pass

    @abstractmethod
    def output_to_chat_completion_response(self, raw_llm_output):
        """Turn the LLM output string into a ChatCompletion response"""
        pass

具体指导教程可以看官方给的指导说明

除了MemGPT,其实最近我还略读了另一篇关于Agent的论文,叫做AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation,后面抽空我仔细看完之后再分享一下。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇