掘金 人工智能 07月17日 19:08
Generative agents 代码分析 三
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

Reverie是模拟生成式智能体(Generative Agents)的核心框架,它通过一系列认知模块来驱动角色的行为。文章深入介绍了Reverie的启动流程、关键组件以及核心的Persona类。Persona类集成了感知(Perceive)、记忆检索(Retrieve)、规划(Plan)、反思(Reflect)和执行(Execute)等认知功能,模拟了智能体如何与环境互动、记忆信息并做出行动。通过详细解析Persona的各个方法,揭示了Reverie如何实现复杂的智能体行为模拟,为理解和构建更高级的AI代理提供了深入的视角。

✨ Reverie模拟框架是生成式智能体的核心,其主要组成部分包括角色(personas)、联想记忆(associative memory)和模拟框架(reverie)本身。启动Reverie服务通过`reverie.py`实现,并允许用户通过命令行指令控制模拟过程,如运行指定步数。

🧑‍💼 Persona类是Reverie系统中所有角色(智能体)的核心,它实现了生成式智能体的行为逻辑,包含感知、记忆、规划、执行和反思等认知模块。其核心认知流程为:Perceive → Retrieve → Plan → Reflect → Execute,最终通过`move`函数输出下一步动作。

🧠 Persona的初始化(init)涉及加载其空间记忆、联想记忆和临时记忆。其保存(save)机制则将这些记忆状态持久化到磁盘。感知(perceive)模块根据角色的注意力带宽和记忆保留时间来筛选周围事件。

💡 记忆检索(retrieve)模块根据感知到的事件,从联想记忆中找出相关的上下文信息。规划(plan)模块则基于地图、其他角色和检索到的记忆来制定角色目标动作。反思(reflect)机制用于回顾记忆并生成新的思考,更新联想记忆。

🚀 Persona的执行(execute)模块将抽象计划转化为具体动作,包括移动坐标、表情符号和动作描述。`move`函数是整个认知流程的主要入口,它协调了感知、记忆、规划、反思和执行等一系列步骤,最终驱动角色的行为。

经过之前的摸索学习,现在终于可以来看一下整个论文中描述的最核心的部分 reverie

三个关键词:

    personas: generative agents,角色associative memory: memory stream,联想记忆reverie: 整个模拟框架

启动 reverie

之前提到整个系统分为 5 个部分,今天我们来看 2、3 部分。

    启动 Environment 服务☕ 启动 Simulation 服务☕ 运行和保存 Simulation重放之前保存的 Simulation演示 Simulation

执行 pythone reverie.py启动 reverie,然后等待用户输入指令。

  origin = input("Enter the name of the forked simulation: ").strip()  target = input("Enter the name of the new simulation: ").strip()  rs = ReverieServer(origin, target)  rs.open_server()

初始化创建一个新的模拟实例,通常是从一个已有的模拟中派生。

# fs_storage = "../../environment/frontend_server/storage"# fs_temp_storage = "../../environment/frontend_server/temp_storage"def __init__(self,                fork_sim_code,               sim_code):    copyanything(fork_folder, sim_folder)        outfile.write(json.dumps(reverie_meta, indent=2))        for persona_name in reverie_meta['persona_names']:        persona_folder = f"{sim_folder}/personas/{persona_name}"        p_x = init_env[persona_name]["x"]        p_y = init_env[persona_name]["y"]        curr_persona = Persona(persona_name, persona_folder)        self.personas[persona_name] = curr_persona        self.personas_tile[persona_name] = (p_x, p_y)        self.maze.tiles[p_y][p_x]["events"].add(curr_persona.scratch                                        .get_curr_event_and_desc())    self.maze = Maze(reverie_meta['maze_name'])        with open(f"{fs_temp_storage}/curr_sim_code.json", "w") as outfile:       outfile.write(json.dumps(curr_sim_code, indent=2))        with open(f"{fs_temp_storage}/curr_step.json", "w") as outfile:       outfile.write(json.dumps(curr_step, indent=2))            
    复制源模拟的所有文件到新目录。修改 meta.json 文件记录来源。加载起始时间、地图名称、秒每步等全局配置。实例化地图对象 Maze。🧑‍💼构造所有人物(Persona),并初始化它们的位置信息。写入当前模拟代码和步数到临时文件,供前端识别。

初始化完成后启动 server 控制台,server 主要提供命令行方式控制模拟,方便一步步模拟执行和调试。

def open_server(self):     elif sim_command[:3].lower() == "run":           # Runs the number of steps specified in the prompt.          # Example: run 1000          int_count = int(sim_command.split()[-1])          rs.start_server(int_count)

支持命令:

命令功能
f
, fin
, finish
, save and finish
保存并退出模拟
start path tester mode进入路径测试模式(清空当前模拟)
exit退出不保存,删除当前模拟数据
save仅保存当前状态
run <steps>自动运行指定步数
print persona schedule <name>查看某个人物的日程安排
print all persona schedule查看所有人物的日程摘要
print hourly org persona schedule <name>查看原始日程安排(未分解)
print persona current tile <name>查看人物当前位置
print persona chatting with buffer <name>查看人物的聊天缓冲区
print persona associative memory (event/thought/chat) <name>查看人物的记忆流(事件/思考/对话)
print persona spatial memory <name>查看人物的空间记忆
print current time查看当前模拟时间
print tile event <x,y>查看某个瓦片上的事件
print tile details <x,y>查看某个瓦片的完整信息
call -- analysis <name>与人物开启一次分析会话(不保存记忆)
call -- load history <filename>从 CSV 文件加载历史记忆

我们输入run 100启动服务。主要用来模拟的核心运行逻辑,处理环境输入、人物行为推理、输出下一步动作。

def start_server(self, int_counter):  while (True):     # 1    curr_env_file = f"{sim_folder}/environment/{self.step}.json"    check_if_file_exists(curr_env_file)    # 5    self.maze.add_event_from_tile(persona.scratch                                         .get_curr_event_and_desc(), new_tile)        next_tile, pronunciatio, description = persona.move(# 这里移动就会触发感知 perceive              self.maze, self.personas, self.personas_tile[persona_name],               self.curr_time)
    等待前端环境文件更新(environment/.json)。清理上一轮添加的游戏对象事件(如床铺是否被使用)。更新人物位置:从环境文件中获取每个角色的新坐标。更新地图中的事件标记。驱动每个人物进行决策(调用 persona.move(...)):返回下一步目标位置、表情符号、描述文本、对话内容。写入下一步动作文件(movement/.json)供前端使用。更新时间与步数。循环直到指定步数完成。

核心 Persona

这是 Reverie 模拟系统中所有角色(智能体)的核心类。这个类实现了生成式智能体(Generative Agent)的行为逻辑,包含感知、记忆、规划、执行和反思等认知模块。

Perceive(感知) → Retrieve(检索) → Plan(计划) → Reflect(反思) → Execute(行动)

整体结构概览

模块描述
初始化 (init)加载或创建人物的记忆与状态
保存 (save)将当前状态保存到磁盘
感知 (perceive)获取周围环境事件
记忆检索 (retrieve)根据感知获取相关记忆
规划 (plan)制定长期与短期计划
执行 (execute)将计划转化为具体动作
反思 (reflect)更新记忆流中的深层思考
移动 (move)综合调用以上模块,返回下一步动作
对话会话 (open_convo_session)开启一个临时对话会话

另外可以通过 Maze 模块访问地图信息

详细分析

1. init 初始化

def __init__(self, name, folder_mem_saved=False):  f_s_mem_saved = f"{folder_mem_saved}/bootstrap_memory/spatial_memory.json"  self.s_mem = MemoryTree(f_s_mem_saved)  # <s_mem> is the persona's associative memory.   f_a_mem_saved = f"{folder_mem_saved}/bootstrap_memory/associative_memory"  self.a_mem = AssociativeMemory(f_a_mem_saved)  # <scratch> is the persona's scratch (short term memory) space.   scratch_saved = f"{folder_mem_saved}/bootstrap_memory/scratch.json"  self.scratch = Scratch(scratch_saved)
    folder_mem_saved="environment/frontend_server/storage/July1_the_ville_isabella_maria_klaus-step-3-20/personas/Isabella Rodriguez/"加载 spatial(空间) 记忆,associative(联想)记忆,scratch(暂时)记忆

2. save 保存记忆到文件

def save(self, save_folder):

将当前 Persona 的状态保存到指定目录。

    空间记忆树(JSON 文件)联想记忆(CSV 文件)临时记忆(JSON 文件)

3. perceive 感知环境

当角色移动的时候,调用 persona.move,然后就会调用 persona.perceive开始感知

def perceive(self, maze):

此函数获取当前 Maze,并返回角色周围发生的事件。重要的是,感知是由以下因素引导的

角色的两个关键超参数:

    att_bandwidth: 控制最多感知多少个事件。retention: 控制多久内不重复感知同一事件。

首先,<att_bandwidth> 决定了角色可以感知的附近事件的数量。假设有10个事件在角色的视野范围内——感知这10个事件可能太多了。因此,在事件太多的情况下,角色会感知到最接近 att_bandwidth 数量的事件。

其次,角色不想在每个时间步都感知和思考同一事件。这就是 发挥作用的地方——角色记忆的内容有时间顺序。因此,如果角色的记忆中包含了最近一次记忆中发生的当前周围事件,就没有必要再去感知。

4. retrieve 检索记忆

def retrieve(self, perceived):

作用:从联想记忆中检索与感知相关的记忆。

输入:感知到的事件列表。

输出:字典结构,包含每个事件相关的上下文记忆(包括事件、思考、对话等)。

5. plan 规划行为

def plan(self, maze, personas, new_day, retrieved):

作用:制定长期与短期计划。

输入:

    maze: 当前地图。personas: 所有人物字典。<font style="background-color:rgba(255, 255, 255, 0.04);">new_day</font>: 是否为新的一天(或第一天)。<font style="background-color:rgba(255, 255, 255, 0.04);">retrieved</font>: 检索到的相关记忆。

输出:目标动作地址(如 <font style="background-color:rgba(255, 255, 255, 0.04);">"Isabella Rodriguez is idle"</font>)。

6. execute 执行计划

def execute(self, maze, personas, plan):

作用:将抽象计划转化为具体动作(如移动坐标、使用的对象等)。

输入

    maze: 地图。personas: 所有人物。plan: 目标动作地址。

输出

    下一步位置(<font style="background-color:rgba(255, 255, 255, 0.04);">(x, y)</font> 坐标)表情符号(emoji)动作描述(如 <font style="background-color:rgba(255, 255, 255, 0.04);">"writing her next novel @ sofa"</font>

7. reflect 反思机制

def reflect(self):

作用:回顾记忆并生成新的思考。

机制:

    如果记忆中有未处理的事件,则触发“反思”过程。生成新的思想节点,并加入联想记忆中。

8. move 主行为函数 认知流程的主要入口

执行 run 100会触发 persona 执行 move
动作。move
动作就是整个思考链条的起点。也是首页思考流程图的具体实现。

def move(self, maze, personas, curr_tile, curr_time):    """    This is the main cognitive function where our main sequence is called.     INPUT:       maze: The Maze class of the current world.       personas: A dictionary that contains all persona names as keys, and the                 Persona instance as values.       curr_tile: A tuple that designates the persona's current tile location                  in (row, col) form. e.g., (58, 39)      curr_time: datetime instance that indicates the game's current time.     OUTPUT:       execution: A triple set that contains the following components:         <next_tile> is a x,y coordinate. e.g., (58, 9)        <pronunciatio> is an emoji.        <description> is a string description of the movement. e.g.,         writing her next novel (editing her novel)         @ double studio:double studio:common room:sofa    """    # Updating persona's scratch memory with <curr_tile>.     self.scratch.curr_tile = curr_tile    # We figure out whether the persona started a new day, and if it is a new    # day, whether it is the very first day of the simulation. This is     # important because we set up the persona's long term plan at the start of    # a new day.     new_day = False    if not self.scratch.curr_time:         new_day = "First day"    elif (self.scratch.curr_time.strftime('%A %B %d')          != curr_time.strftime('%A %B %d')):        new_day = "New day"    self.scratch.curr_time = curr_time    # Main cognitive sequence begins here.     perceived = self.perceive(maze)    retrieved = self.retrieve(perceived)    plan = self.plan(maze, personas, new_day, retrieved)    self.reflect()    # <execution> is a triple set that contains the following components:     # <next_tile> is a x,y coordinate. e.g., (58, 9)    # <pronunciatio> is an emoji. e.g., "\ud83d\udca4"    # <description> is a string description of the movement. e.g.,     #   writing her next novel (editing her novel)     #   @ double studio:double studio:common room:sofa    return self.execute(maze, personas, plan)

作用:综合调用上述模块,完成一次完整的认知循环。

流程:

    更新当前时间与位置。判断是否为新一天。调用 perceive 感知环境。感知 perceive 的输入是地图 maze调用 retrieve 检索记忆。检索 retrieve 的输入是感知 perceive调用 plan 制定计划。计划 plan 的输入是地图 maze、角色 persona、时间 curr_time、检索 retrieve调用 reflect 进行反思。调用 execute 执行计划,返回下一步动作。

名词

    Congitive,形容词,认知的。侧重智力层面的认知能力或相关研究领域(如认知科学),不涉及感官感知Perceive,动词,感知/察觉。包含更广泛的意义,既包含感官感知(如视觉、听觉),也包含对抽象概念的认知(如理解理论、情感)。Retrieve,检索,取回Reflect,反射,反映,反思

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Reverie 生成式智能体 认知架构 AI行为模拟
相关文章