10月 19, 2024
在 3 月份的 Sequoia AI Ascent 会议上,我谈到了Agent的三个限制:规划、UX 和记忆。在这里查看该演讲。在这篇文章中,我将更深入地研究内存。请在此处查看之前关于规划的文章,以及之前关于 UX 的文章。
如果 agent 是 2024 年 LLM 应用程序开发的最大流行语,那么
记忆可能是第二大流行语。但什么是记忆呢?
在高层次上,
记忆只是一个记住以前交互内容的系统。这对于建立良好的agent 体验至关重要。想象一下,如果你有一个同事从来不记得你告诉他们什么,强迫你不断重复这些信息 - 那将是非常令人沮丧的!
人们通常希望 LLM 系统天生就有内存,可能是因为 LLM 感觉已经很像人类了。但是,LLM 本身并不天生记住事物 — 因此您需要有意识地添加
记忆。但是,您究竟应该如何考虑这样做呢?
记忆
是特定于应用程序的
我们一直在考虑
记忆问题,我们相信
记忆是特定于应用程序的。
Replit 的编码代理可能选择记住的有关给定用户的信息与 Unify 的研究代理可能记住的内容截然不同。Replit 可能会选择记住用户喜欢的 Python 库;Unify 可能会记住用户正在研究的公司的行业。
不仅 agent 记住的内容因应用程序而异,agent 的记忆方式也可能不同。正如在上一篇文章中所讨论的,agent 的一个关键方面是他们周围的 UX。不同的 UX 提供了不同的方法来相应地收集和更新反馈。
那么,我们在 LangChain 是如何看待内存的呢?
就像我们对 agent 的方法一样:我们的目标是让用户对记忆内存进行低级控制,并能够根据他们认为合适的方式对其进行自定义。
这一理念指导了我们开发 Memory Store 的大部分内容,我们上周将其添加到 LangGraph 中。
记忆
类型
虽然您的 agent 拥有的
记忆的确切类型可能因应用程序而异,但我们确实看到了不同的高级
记忆类型。这些类型的记忆并不是什么新鲜事 - 它们模仿人类记忆类型 .
将这些人类记忆类型映射到代理记忆方面,已经做了一些很棒的工作。我最喜欢的是 CoALA 论文。以下是我对每种类型的粗略解释,以及当今代理如何使用和更新这种
记忆类型的实用方法。
来自 CoALA 论文的决策程序图 (Sumers, Yao, Narasimhan, Griffiths 2024)
程序记忆
该术语是指有关如何执行任务的长期记忆,类似于大脑的核心指令集。
人类的程序记忆:记住如何骑自行车。
agent 中的程序
记忆:CoALA 论文将程序
记忆描述为 LLM 权重和 agent 代码的组合,它们从根本上决定了代理的工作方式。
在实践中,我们没有看到很多(任何)agent 系统会自动更新其 LLM 的权重或重写其代码。但是,我们确实看到了一些 agent 更新自己的系统提示的示例。虽然这是最接近的实际例子,但它仍然相对不常见。
语义记忆
这是某人的长期知识储备。
人类的语义记忆:它由信息片段组成,例如在学校学到的事实、概念的含义以及它们之间的关系。
agent 中的语义记忆:CoALA 论文将语义记忆描述为有关世界的事实存储库。
如今,agent 最常使用它来个性化应用程序。
实际上,我们看到这是通过使用 LLM 从 agent 的对话或交互中提取信息来实现的。此信息的确切类型通常是特定于应用程序的。然后,此信息将在将来的对话中检索并插入到系统提示中,以影响 agent 的响应。
情景记忆
这是指回忆特定的过去事件。
人类情景记忆:当一个人回忆起过去经历的特定事件(或“情节”)时。
a
ge
nt 中的情景记忆:CoALA 论文将情景记忆定义为存储
a
ge
nt 过去动作的序列。
这主要用于让 agent
按预期执行。
在实践中,情景记忆被实现为小样本提示。如果您收集了足够多的这些序列,那么这可以通过动态的 few-shot 提示来完成。如果有正确的方法来执行以前已经完成的特定操作,这通常非常适合指导代理。相反,如果不一定有正确的做事方式,或者如果代理不断做新的事情,那么语义记忆就更相关,所以前面的例子没有多大帮助。
如何更新记忆
除了考虑要在 Agent 中更新的内存类型外,我们还看到开发人员考虑如何更新 Agent 记忆。
更新 agent 记忆的一种方法是 “in the hot path” 。这是 agent 系统明确决定在响应之前记住事实(通常通过工具调用)的地方。这就是 ChatGPT 采取的方法。
更新记忆的另一种方法是 “in the background” .在这种情况下,后台进程会在会话期间或之后运行以更新内存。
比较这两种方法,“in the hot path” 方法的缺点是在传递任何响应之前引入一些额外的延迟。它还需要将 memory logic 与 agent logic相结合。
但是,在后台运行可以避免这些问题 - 不会增加延迟,并且内存逻辑保持独立。但是“在后台”运行也有其自身的缺点:内存不会立即更新,并且需要额外的逻辑来确定何时启动后台进程。
更新内存的另一种方法涉及用户反馈,这与情景记忆特别相关。例如,如果用户将交互标记为正面交互,您可以保存该反馈以备将来调用。
为什么我们关心代理的内存?
这对我们在 LangChain 构建的内容有何影响?嗯,内存极大地影响了代理系统的有用性,因此我们对尽可能轻松地将内存用于应用程序非常感兴趣
为此,我们在产品中构建了许多功能。这包括:
LangGraph 中内存存储的低级抽象,让您能够完全控制代理的内存
在 LangGraph 中 “in the hot path” 和 “in the background” 运行内存的模板
在 LangSmith 中动态选择少量样本,实现快速迭代
我们甚至构建了一些利用内存的应用程序!不过现在还为时过早,因此我们将继续了解代理内存以及它可以有效🙂使用的领域。