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

 

本文深入探讨了前端环境模拟中的Replay功能,重点介绍了基于Django框架的前端服务。通过启动服务、访问URL、以及对页面组成部分的分析,详细解析了Replay功能的核心逻辑。文章还阐述了代码实现,包括URL解析、Django视图函数,以及Phaser 3.0在地图展示中的应用。此外,文章还涉及了Agent数据结构,为理解整个模拟系统的运作提供了关键线索。

🚀 Replay 功能启动流程:前端环境服务基于Django框架,通过`python manage.py runserver`启动。访问`http://localhost:8000/replay/July1_the_ville_isabella_maria_klaus-step-3-20/1/`可以进行Replay,其中URL包含了模拟文件名和步骤。

🎭 Replay 页面组成:Replay页面分为三部分,包括基于Phaser 3.0的地图及角色动画展示,时间和回放控制,以及角色列表和角色详情,用于核心信息的展示。

⚙️ Django 核心代码解析:`urls.py`文件配置了URL路由,将`/replay/`请求转发至`translator.views.replay`函数处理。该函数读取存储的JSON文件,包含角色初始位置等信息,并将数据传递给模板进行渲染。

🌐 前后端数据交互:`main_script.html`脚本负责游戏界面处理,并通过XMLHttpRequest与Django服务通信。`process_environment`接口接收前端世界信息并写入文件,`update_environment`接口读取后端计算的行动信息并返回给前端。

上一篇文章对项目的核心文件的功能做了单独介绍。接下来我们就具体看看各个模块的功能实现。这一篇先看前端环境模拟部分。

之前介绍编译运行的文章中提到,启动和常用功能大概有下面几项:

    🚀 启动 environment 服务启动 simulation 服务运行和保存 Simulation重放之前保存的 simulation演示 simulation

以上 5 点可以分为两类。一部分是真正调用 LLM 大模型生成对话和记忆,然后检索规划,最终保存整个过程。另一部分是把前面运行的过程保存下来的场景,进行重放和演示。

功能介绍

今天重点学习重放 replay,启动 environment 前端服务。前端环境是一个基于 Django 框架的应用。

cd environment/frontend_serverpython manage.py runserver

打开 http://localhost:8000/浏览器显示"Your environment server is up and running,"说明运行成功了。

打开 http://localhost:8000/replay/July1_the_ville_isabella_maria_klaus-step-3-20/1/开始 replay。

整个页面分为三部分:

    地图及角色动画展示,基于 Phaser 3.0 实现。这部分后面有时间单独介绍。时间和回放控制👯 角色列表和角色详情,核心信息展示。

代码

# http://localhost:8000/replay/July1_the_ville_isabella_maria_klaus-step-3-20/1/# 拆解http://localhost:8000/# base urlreplay/# commandJuly1_the_ville_isabella_maria_klaus-step-3-20/# simulation 文件1/# 步骤,可以手动指定第几步

启动 django 服务,指定默认配置文件目录为 frontend_server.settings

def main():    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'frontend_server.settings')    try:        from django.core.management import execute_from_command_line    execute_from_command_line(sys.argv)if __name__ == '__main__':    main()

环境配置文件

# 需要跟随 django 启动的模块INSTALLED_APPS = [    # ...    'translator',    'corsheaders',    'storages',]# 项目的 URL 路由入口模块ROOT_URLCONF = 'frontend_server.urls'# 静态资源与媒体文件STATIC_URL = '/static/'STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_root")STATICFILES_DIRS = (    os.path.join(BASE_DIR, "static_dirs"),)MEDIA_URL = '/media/'MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "media_root")

解析刚才的 url,匹配到 replay/,转到 translator.replay方法

from translator import views as translator_viewsurlpatterns = [    url(r'^$', translator_views.landing, name='landing'),    url(r'^simulator_home$', translator_views.home, name='home'),    url(r'^demo/(?P<sim_code>[\w-]+)/(?P<step>[\w-]+)/(?P<play_speed>[\w-]+)/$', translator_views.demo, name='demo'),    url(r'^replay/(?P<sim_code>[\w-]+)/(?P<step>[\w-]+)/$', translator_views.replay, name='replay'),    url(r'^replay_persona_state/(?P<sim_code>[\w-]+)/(?P<step>[\w-]+)/(?P<persona_name>[\w-]+)/$', translator_views.replay_persona_state, name='replay_persona_state'),    url(r'^process_environment/$', translator_views.process_environment, name='process_environment'),    url(r'^update_environment/$', translator_views.update_environment, name='update_environment'),    url(r'^path_tester/$', translator_views.path_tester, name='path_tester'),    url(r'^path_tester_update/$', translator_views.path_tester_update, name='path_tester_update'),    path('admin/', admin.site.urls),]

解析

def replay(request, sim_code, step):     persona_names_set = set()# 人物角色列表    for i in find_filenames(f"storage/{sim_code}/personas", ""): # 遍历存储的 replay 文件,找到人物角色            persona_names_set.add(x)    for i in find_filenames(f"storage/{sim_code}/environment", ".json"):            file_count += [int(x.split(".")[0])]    curr_json = f'storage/{sim_code}/environment/{str(max(file_count))}.json'    with open(curr_json) as json_file:          persona_init_pos_dict = json.load(json_file)        for key, val in persona_init_pos_dict.items():             if key in persona_names_set:                 persona_init_pos += [[key, val["x"], val["y"]]]    context = {"sim_code": sim_code,# 模拟文件名:July1_the_ville_isabella_maria_klaus-step-3-20               "step": step,# 对应 environment/ 下面的 *.json 文件,游戏里面的 10 秒代表一步,也就是 10s 一个 json 文件               "persona_names": persona_names,# 对应 personas 目录下的名字               "persona_init_pos": persona_init_pos, # 角色 初始的 位置               "mode": "replay"}# 控制是否显示 play/pause 按钮    template = "home/home.html"    return render(request, template, context)

replay函数读取的 json 文件:

July1_the_ville_isabella_maria_klaus-step-3-20├── environment│   ├── 0.json# 角色坐标文件│   ├── 1.json│   ├── 10.json│   ├── 100.json│   ├── 1000.json│   ├── 1001.json│   ├── ...├── personas│   ├── Isabella\ Rodriguez# 角色文件│   │   └── bootstrap_memory│   │       ├── associative_memory# 关联记忆│   │       │   ├── embeddings.json# embedding 矢量存储│   │       │   ├── kw_strength.json#?│   │       │   └── nodes.json# 记忆节点│   │       ├── scratch.json# 角色的基础信息│   │       └── spatial_memory.json# 空间环境记忆│   ├── Klaus\ Mueller│   │   └── bootstrap_memory│   │       ├── associative_memory│   │       │   ├── embeddings.json│   │       │   ├── kw_strength.json│   │       │   └── nodes.json│   │       ├── scratch.json│   │       └── spatial_memory.json│   └── Maria\ Lopez│       └── bootstrap_memory│           ├── associative_memory│           │   ├── embeddings.json│           │   ├── kw_strength.json│           │   └── nodes.json│           ├── scratch.json│           └── spatial_memory.json└── reverie    └── meta.json# simulator 基本信息

接下来 render 开始渲染界面 home/home.html,并且引入了 phaser 和 main_script.html脚本。

<script src='https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js'></script>{% include 'home/main_script.html' %}

main_script.html主要负责游戏界面处理,同时负责和 django 服务通信。

function preload() {}function create() {}function update(time, delta) {  if (phase == "process") {    var retrieve_xobj = new XMLHttpRequest();    retrieve_xobj.overrideMimeType("application/json");    retrieve_xobj.open('POST', "{% url 'process_environment' %}", true);    retrieve_xobj.send(json);       // Finally, we update the phase variable to start the "udpate" process.     // Now that we sent all persona locations to the backend server, we need    // to wait until the backend determines what the personas will do next.     phase = "update";  } else if (phase == "update") {  var update_xobj = new XMLHttpRequest();    update_xobj.overrideMimeType("application/json");    update_xobj.open('POST', "{% url 'update_environment' %}", true);    update_xobj.send(JSON.stringify({"step": step, "sim_code": sim_code }));       phase = "execute";  } else {    phase = "process";  }}

调用 process_environmentupdate_environment接口处理数据

def process_environment(request):     """    <FRONTEND to BACKEND>     This sends the frontend visual world information to the backend server.     It does this by writing the current environment representation to     "storage/environment.json" file.     """    data = json.loads(request.body)    step = data["step"]    sim_code = data["sim_code"]    environment = data["environment"]    with open(f"storage/{sim_code}/environment/{step}.json", "w") as outfile:        outfile.write(json.dumps(environment, indent=2))    return HttpResponse("received")def update_environment(request):     """  <BACKEND to FRONTEND>   This sends the backend computation of the persona behavior to the frontend  visual server.   It does this by reading the new movement information from   "storage/movement.json" file.  """    data = json.loads(request.body)    step = data["step"]    sim_code = data["sim_code"]    response_data = {"<step>": -1}    if (check_if_file_exists(f"storage/{sim_code}/movement/{step}.json")):        with open(f"storage/{sim_code}/movement/{step}.json") as json_file:             response_data = json.load(json_file)            response_data["<step>"] = step    return JsonResponse(response_data)

Agent 数据结构

关于一个 Agent 的描述

Fish AI Reader

Fish AI Reader

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

FishAI

FishAI

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

联系邮箱 441953276@qq.com

相关标签

前端环境模拟 Django Phaser 3.0 Replay
相关文章