极客时间已完结课程限时免费阅读

21|提示语工程(三):如何帮助智能体更好地管理记忆?

21|提示语工程(三):如何帮助智能体更好地管理记忆?-AI大模型系统实战-极客时间
下载APP

21|提示语工程(三):如何帮助智能体更好地管理记忆?

讲述:Tyler

时长15:11大小13.87M

你好,我是 Tyler。
第 2 节课的时候,我们第一次提到智身具能的概念。随着课程的学习,相信你已经有了新的感悟和判断,再次回顾第 2 节课中的 ReAct 时,你也会发现这个 Langchain 和 AutoGPT 重度依赖的提示语方法虽然门槛低,人人都可以体验,但过于简单,是一个极为初级的方法。
具身智能这个词,原来是机器人相关学科的术语,不过由于机器人研究的速度限制了具身智能研究的发展。所以,为了提高研究实验的效率,目前大多的具身智能研究都会在一个虚拟或数字孪生的世界中进行。
在众多基于生成式 AI 大模型的具身智能研究中,最有代表性的当属斯坦福的 Generative Agents(我们在第 10 节课里埋过彩蛋)。不过那个时候这篇论文对应的代码还没有开源,你也没有储备好大语言模型和上下文学习的相关知识,直接看论文会感觉云里雾里。
但现在我们再来学习这篇论文就会事半功倍。接下来的几节课,我不但会为你深度解析这篇论文的技术原理与方案,还会带你综合各种提示语工程方法,动手构建一个真实的具身智能“应用”——一个属于你自己的“西部世界”。

西部世界

如果你看过《西部世界》这部科幻剧的话,会发现斯坦福研究人员在做的实验,正是构建一个像西部世界一样的乐园,作为“造物主”,为智能体植入“意识”。总之就是构建一个未来世界中的机器人主题乐园,其中机器人可以像人类一样思考和行动,每天他们都在相同的时间地点醒来,进入乐园管理者为他设定的剧本情节。
在这场社会实验中,研究人员会观测自己设计的“生命”,观察它们是否拥有稳定的“人格”,是否有能力应对社会上的各种问题。
有趣的是,研究者还会对小镇中的各个角色进行“采访”,得到智能体对这个世界和它们自己的看法。这和西部世界里,开头那句询问机器人的台词“你是否曾经怀疑过这个世界的真实性”是不是很像呢?
接下来,就让我充当导游,带你进入斯坦福 AI 小镇的世界,看看小镇的运行规则。这些规则也会对我们后面自己设计的智能体系统带来启发。
这是一个拥有 25 个智能体的小型社会,各个智能体拥有不同的工作、兴趣和社交对象。它们会使用这个虚拟世界中的各种设施度过每一天的日常生活,并在兴之所至时,在镇中的各个场所举行各种社交活动。
小镇的一切都发生在一个类似虚拟人生的游戏引擎上,这个游戏引擎维持了小镇中所有基础设施以及智能体们的“肉体”。智能体可以通过和游戏引擎的交互,控制这个虚拟世界的各种设施,比如点燃炉具,或者上床睡觉。
每个智能体都有自己独特的剧本,也就是种子记忆,其中记录了他们的出身和成长经历,下图就是其中的一个例子。
对应的中文简要翻译如下。主要描述的就是药剂师 John Lin 的人物设定和社会关系。
John Lin 是 Willow Market and Pharmacy 药房的药剂师,乐于助人,一直在寻找让顾客更容易获得药物的方法。他与妻子 Mei Lin(大学教授)和儿子 Eddy Lin(学习音乐理论的学生)一家三口幸福地生活在一起。
John Lin 非常爱他的家人,与隔壁的老夫妇 Sam Moore 和 Jennifer Moore 相识多年。他认为 Sam Moore 是一个善良的好人,还认识 Yuriko Yamamoto 等邻居。John Lin 与同事 Tom Moreno 是朋友,喜欢一起讨论当地的政治。他对 Moreno 一家有一些了解,知道他们夫妻分别是丈夫 Tom Moreno 和妻子 Jane Moreno。
基于自己的剧本,智能体就能通过游戏引擎做出各种行动。那问题来了,这些行动怎么体现呢?
例如,Isabella Rodriguez 可能会说“我正在撰写杂志文章”或“我正在查看我的邮箱”。这种陈述会被转换成影响虚拟世界的具体动作,例如“撰写文章”或“查看邮箱”。为了让观察者清楚这些行动发生在什么时间,这个虚拟世界的时间会抽象成一个个时间点,说得专业一些就是这个世界的时间是离散化的。
除了单个智能体的行动。智能体还会知道周围存在着哪些其他智能体,它可以自己决定无视对方还是进行对话。对话的方式跟人一样,也是通过自然语言沟通。
后面是智能体 Isabella Rodriguez 和 Tom Moreno 之间关于即将到来的选举的一个讨论。
Isabella: 我还在考虑,但我一直在和 Sam Moore 讨论选举。你对他有什么看法?
Tom: 说实话,我对 Sam Moore 不太感冒。我感觉他有点脱离实际,也不太关心我们的利益。
了解了这些设定以后,是不是觉得这个镇子非常逼真,就像这个世界上的一个真实小镇一样?
其实,在你每天工作回到家以后,听听你智能体之间的八卦也挺解压的,是不是?如果你足够“无聊”,你甚至可以把你办公室中的甲乙丙丁的设定放入智能体的种子记忆,让他们在这个世界中一起生活,看看他们会聊些什么。
书归正传,我们继续学习技术。
刚刚在一开始的时候,我们提到了,你不但可以通过观察智能体之间的对话内容来分析它们的行为特点,你还可以通过采访的方式,得知智能体的真实想法。这个方法在论文中被称为“inner voice”,这里我们可以理解成“内心的声音”。

记忆能力

从这里开始,我们就跟随论文的脚步,把自己当成智能体社会的总设计师,推演一下构建真实的多智能体系统要解决的具体问题了。这里第一个关键的问题是如何让你创造的生命拥有“记忆”。
我们在之前也提到过,大语言模型作为智能体的最大的问题在于它本身是一个无状态的“生物”,也就是说它记不得历史上发生了什么。一切关于它的历史都需要一个外部记忆来辅助记录,这样智能体之间对话时,才不会彼此玩“失忆”。
当然,这个外部记忆的实现是很有讲究的。比如,在问智能体 Isabella “你这些天都在热衷于哪件事?”时,最直接的实现方法是把它这些天的种种活动都放入到大语言模型的提示语中,让模型作答。
不过,这时我们大概率会得到一个没什么信息量的答复,因为它根本不知道哪些发生过的事情才是重点。
为了解决这个问题,论文中提出了一种叫做记忆流的方案。记忆流保存了智能体的完整经历,是一个记忆对象的列表,每个对象包含自然语言的描述、创建的时间戳以及最近访问的时间戳。记忆流中最基本的元素是记忆事件,这是每个智能体直接感知到的事件,你可以理解成这是智能体的生活日记。
记忆流的检索方法将时近性、重要性和相关性三个因素作为记忆对象的得分,并加权求和作为最终得分。
我把这三个因素的意思稍微给你解释一下。
时近性:为最近访问的记忆对象分配一个更高的分,这和人类的记忆习惯一样,能让刚才或今早发生的事情留在智能体的意识内。
重要性:为智能体觉得重要的记忆对象赋予更高的得分,将关键记忆和普通记忆区分开。
相关性:为与当前情况紧密相关的记忆对象分配一个更高的得分,具体方案可以是用当前情况和记忆事件的高维空间距离来描述其相似性。
这里我放了一张图,图里描述的是记忆流的存储内容和检索方法,你可以边看文稿边听我继续讲解。
其实,只要相信很多同学都已经想到了,这其实你和学过的注意力机制很像,这里确实利用了近似的思想。
这里我们来看一下论文里检索过程的实现代码,可以通过文稿里的超链接看到完整代码,课程里我只挑选重要的部分做讲解。
其实有了刚才的背景知识之后很容易看懂。这段代码的实现思路可以这样概括:根据给定的当前人物(persona)和焦点事件(focal points),从记忆流中检索相关记忆事件,并将结果返回放入一个字典。
实现这个记忆流检索的具体函数,在稍后的代码解读环节我再带你看,你这里先了解它需要接受的参数有哪些即可。
persona:代表当前人物的对象,其中包含了关联记忆。
focal_points:一个包含了焦点事件或思维的字符串描述的列表,表示需要检索的内容。
n_count:一个可选参数,默认值为 30,表示要返回的检索结果的最大数量。
可以看出每个角色相关的记忆都被存储在了一个叫 a_mem 的实例变量中,这个变量中的数据结构 AssociativeMemory 便是上图中的记忆流结构。
self.a_mem = AssociativeMemory(f_a_mem_saved)
在检索的过程中,提示引擎会通过参数 recency_w、relevance_w、importance_w 加权计算出与查询内容 focal_points 相关的每个记忆的分数,并择优录取。
接下来,我带你梳理一下更具体的步骤。首先,为了存储检索结果,我们要创建一个空字典 retrieved。
def new_retrieve(persona, focal_points, n_count=30):
retrieved = dict()
随后遍历 focal_points 列表中的每个焦点事件。
for focal_pt in focal_points:
接着获取所有节点,包括事件和反思节点,从角色的记忆中检索,然后按照它们的创建时间来做排序。至于反思节点是什么,这里你可以先当它与事件节点没有什么区别,下节课中我将详细介绍它。
nodes = [[i.last_accessed, i]
for i in persona.a_mem.seq_event + persona.a_mem.seq_thought
if "idle" not in i.embedding_key]
nodes = sorted(nodes, key=lambda x: x[0])
nodes = [i for created, i in nodes]
下一步,我们调用 extract_recency、extract_importance 和 extract_relevance 函数来计算每个节点的新旧程度、重要性和相关性得分,并对这些得分进行归一化。
# Calculating the component dictionaries and normalizing them.
recency_out = extract_recency(persona, nodes)
recency_out = normalize_dict_floats(recency_out, 0, 1)
importance_out = extract_importance(persona, nodes)
importance_out = normalize_dict_floats(importance_out, 0, 1)
relevance_out = extract_relevance(persona, nodes, focal_pt)
relevance_out = normalize_dict_floats(relevance_out, 0, 1)
之后计算最终的综合分数,将新旧程度、相关性和重要性得分按照一组权重进行组合,得到每个节点的最终得分。当然, 这里可以从注释看得出,斯坦福的研究人员在下一步,计划用强化学习的方法,来自动学习这个权重。
# Computing the final scores that combines the component values.
# Note to self: test out different weights. [1, 1, 1] tends to work
# decently, but in the future, these weights should likely be learned,
# perhaps through an RL-like process.
# gw = [1, 1, 1]
# gw = [1, 2, 1]
gw = [0.5, 3, 2]
master_out = dict()
for key in recency_out.keys():
master_out[key] = (persona.scratch.recency_w*recency_out[key]*gw[0]
+ persona.scratch.relevance_w*relevance_out[key]*gw[1]
+ persona.scratch.importance_w*importance_out[key]*gw[2])
master_out = top_highest_x_values(master_out, len(master_out.keys())
接下来,我们会从所有节点中选取分数最高的节点,数量不超过 n_count。
# Extracting the highest x values.
# <master_out> has the key of node.id and value of float. Once we get the
# highest x values, we want to translate the node.id into nodes and return
# the list of nodes.
master_out = top_highest_x_values(master_out, n_count)
master_nodes = [persona.a_mem.id_to_node[key]
for key in list(master_out.keys())]
然后,更新选中节点的 last_accessed 属性,这个属性是每个记忆事件最后一次被访问的时间。
for n in master_nodes:
n.last_accessed = persona.scratch.curr_time
接着,我们将选中的记忆事件列表,跟对应的焦点事件关联起来,并且把结果给存储在 retrieved 字典中,这里面的 key 是焦点事件的描述,value 是选中的记忆事件列表。
retrieved[focal_pt] = master_nodes
最后 retrieved 字典中得到的,就是所有检索到的记忆事件内容了。
return retrieved
这种方法可以有效地将相关的记忆呈现给语言模型,提高生成式智能体的表现。例如,一个智能体可以使用记忆流来回答问题“这些天你都热衷于干什么?”。如果使用前面提到的简单粗暴方法,很可能会得到一个泛泛的回答。
我最近一直在忙于工作和学习。
这种回答是没有意义的,几乎没有什么信息量。如果使用记忆流的方法,可能会得到这样的回答。
我最近一直在策划情人节派对。我希望能让大家感到受欢迎和被接纳。
这种回答是更有意义和具体的,因为它直接呈现了智能体的具体记忆。这本质上是一种对长提示词压缩的方法,在很多 AI 大模型系统的场景中都会使用,希望你能理解并记住这个重要思想。

总结

学到这里,我带你做个总结吧。
真实世界中的智能体环境远比那些玩具教程要复杂得多,如果不经过专业的训练,在面对真实的多智能体博弈需求时,孩子们将只能向恶龙挥舞自己手中的儿童木剑(在 Langchain 和 AutoGPT 使用的 ReAct),让人哭笑不得。
为了武装我们的模型,今天我们学习了记忆流这个构建具身智能的关键方法。记忆流可以用于保存智能体经历的记忆事件列表,其中包括自然语言描述和时间戳等信息。
记忆流的检索过程类似于人类的回忆过程,会利用时近性、重要性和相关性等因素来计算记忆对象的得分,然后选择与当前情境最相关的记忆。
通过记忆流可以帮助智能体理解和适应复杂的情境。通过回顾过去的经历,智能体可以更好地理解当前的情境,并做出更合理的决策。同时提高智能体的性能,更有效地管理记忆信息。
在这节课中,我们赋予了智能体人类一样的记忆能力,让它像人类一样可以回顾过去,学习和成长。下节课,我们将继续深入学习这篇论文里的其他提示语工程算法。我们将会根据今天学到的记忆方法,为我们创造的“生命”设计“反思”和“计划”的能力,让它能够像人类一样生活和“思考”。

思考题

如果让你用前几节课学到的提示语工程方法构建一个智能体,让它融入这个社会,你有什么思路吗?
恭喜完成我们第 21 次打卡学习,期待你在留言区和我交流互动。如果你觉得有收获,也欢迎你分享给你身边的朋友,邀 TA 一起讨论。

本文介绍了一种新的技术,记忆流,旨在帮助智能体更好地管理记忆。通过斯坦福的Generative Agents项目和AI小镇的运行规则,展现了智能体管理记忆的技术特点。记忆流可以有效地将相关的记忆呈现给语言模型,提高智能体的表现和生成的内容的质量。文章内容涉及了具体的技术实现细节,对于对智能体技术感兴趣的读者来说,具有很高的参考价值。记忆流的检索过程类似于人类的回忆过程,会利用时近性、重要性和相关性等因素来计算记忆对象的得分,然后选择与当前情境最相关的记忆。通过回顾过去的经历,智能体可以更好地理解当前的情境,并做出更合理的决策。这种方法能够帮助智能体理解和适应复杂的情境,提高智能体的性能,更有效地管理记忆信息。文章通过引入记忆流的方案,解决了智能体记忆管理的问题,提高了生成式智能体的表现。

分享给需要的人,Ta购买本课程,你将得18
生成海报并分享
2023-09-27

赞 8

提建议

上一篇
20|提示语工程(二):LLM的护卫舰队有哪些?
下一篇
国庆策划|赛程过半,检验一下你的学习成果吧!
unpreview
 写留言

全部留言(5)

  • 最新
  • 精选
  • 大尾巴老猫
    2023-10-03 来自北京
    真实世界中的智能体环境远比那些玩具教程要复杂得多,如果不经过专业的训练,在面对真实的多智能体博弈需求时,孩子们将只能向恶龙挥舞自己手中的儿童木剑(在 Langchain 和 AutoGPT 使用的 ReAct),让人哭笑不得。 Langchian有那么的不堪吗?不过好像也没看到此文中介绍的内容超越或者颠覆LangChain多少...保持技术的中立性和客观性

    作者回复: 你好,大尾巴老猫!感谢你的问题,课程还在持续更新,希望你在完成提示语工程系列的完整学习后,能够自己得出这个问题的答案。那时如果还有疑惑,我们再继续交流。

    6
  • 顾琪瑶
    2023-09-27 来自上海
    1. 设定基础信息, 如姓名, 年龄, 职业, 家庭等等 2. 背景故事 3. 行为准则 4. 环境信息(如所处的地方, 工作场地等等) 不过还是有点不太明白, 多个agent是如何互相互动起来的, 类似是应用启动时给每个agent发一条指令, "现在你们可以和小镇里的居民们交流了"吗?

    作者回复: 你好,顾琪瑶!很好的问题,在下一节课中,我们给出了整体的实现方法,你可以去看一下。

    4
  • aLong
    2024-02-07 来自北京
    目前确实没看懂为什么一直觉得langchain是玩具。
    2
  • l_j_dota_1111
    2024-02-04 来自天津
    在虚拟构建的世界里, 会有多个智能体,每个智能体都会不断产生新事件,这些事件都会当做记忆流的一部分进行存储。那么在新的交互过程中,面对如此大体量的记忆流,如何保证查询效率。记忆流是如何存储的?(记忆流是按照时间尺度进行存储,还是按照关键事件存储。如果是时间尺度,多长时间存储一个记忆,如果是按照事件存储,如何定义这个事件值不值得存储)
    2
  • l_j_dota_1111
    2024-02-05 来自天津
    每个节点的新旧程度、重要性和相关性得分,其中新旧程度可以很容易计算出来,那么重要性和相关性是如何计算出来的,用大模型吗
    1