您的位置:首页 > 文旅 > 旅游 > 建网站广州_海安网页设计_博客seo怎么做_在线发外链工具

建网站广州_海安网页设计_博客seo怎么做_在线发外链工具

2024/12/23 9:53:48 来源:https://blog.csdn.net/AIBigModel/article/details/144406081  浏览:    关键词:建网站广州_海安网页设计_博客seo怎么做_在线发外链工具
建网站广州_海安网页设计_博客seo怎么做_在线发外链工具

知乎:何枝
地址:https://zhuanlan.zhihu.com/p/9096314010

Live Demo(网站在进入前可能会加载一段时间,需要等一等)

  • 人物观测:Agent Life Live Demo[1]

  • 行为统计:Agent Life Action Logging Board[2]

Code:GitHub - HarderThenHarder/AgentLife: A small open source 3D agent simulator based on LLM.
Video:https://www.bilibili.com/video/BV1f

去年第一次看到 斯坦福小镇[3] 时,大概是骨子里喜欢模拟类游戏的原因,当时激动了好久好久,

后来 AI Town[4]出现,允许注册玩家进入到虚拟小镇里和里面的 NPC 对话,又把这类玩法拔了一个高度。

图片

斯坦福小镇(图左)& AI Town(图右)

但受限于当时自己薄弱的技术功底,因为不会做游戏,让我不得不放弃亲手圆梦的计划,

直到不久前,我无意中刷到 6个AI合租[5]视频时,内心的燥热再也按耐不住,

不会做,那就学!

所以在将近一个月里所有零零散散的时间拼拼凑凑后,终于堆完了第一个版本的 demo[6](也可以看 视频[7]):

图片

Agent Life Demo(因为需要用到 Qwen-2.5 进行决策,所以 demo 网站将持续至账户 quota 用光为止)

和原版相比,主要做了以下一些改动:

  1. 2D -> 3D:虽然 2D 像素也能做出艺术品(我很喜欢《星露谷》),但为了观测起来更 “真” 一点,我们还是决定一步到位切 3D 引擎。

  2. Multi -> Single:「斯坦福小镇」和「AI Town」亮点在于 Multi-Agent,我们可以在里面看到非常有趣的 Agent 之间的对话内容。但 —— 我总感觉有些看不太过来,一个地图上同时存在非常多对人在对话,即便作为 “上帝” 的我也只有一双眼睛。为此,我们想暂时砍掉 Multi,先只 Focus 到一个 Agent 上。

  3. 建立与 Agent 与真实世界之间的联系: 我一直在想,如果能让 Agent 和现实世界里的真实信息产生联系,说不定会有趣起来。所以我给了 Agent 一个微博,它能够通过发布、回复微博,来和物理世界里的我交互;同时我们允许他查看当前最新的热点新闻,由他自己选择将感兴趣的内容存放到“记忆”里。

  4. 可视化 Agent 一天的日程:对 Agent 每一次的行为选择进行可视化,通过赋予 Agent 不同的人设,统计 Agent 在行为选择上是否会有所不同。

  5. 动态编辑游戏世界,制造新的事件:比如移除床后无法睡觉,破坏灶台后无法做饭,查看 AI 在突发情况下做出什么决策。(目前还不完善)

图片

日程可视化:八卦人设(左)更喜欢看娱乐新闻 & 极客人设(右)更喜欢看稀土掘金

秉承着「一起学习,共同进步」的基本原则,我将我实现这个项目中用到的所有技术在这里梳理出来,

文章的最后会给出源码,希望能对那些想 try 一把虚拟世界的朋友们有一点帮助。

PS:相信我,其实没有那么难。

1. 项目框架

整个项目分为两部分:客户端(渲染引擎)+ 服务端(行为决策):

图片

Agent Life 系统框架图

1.1 客户端(Client)

因为是一个 3D 的渲染引擎,所以首先从 three.js[8] 开始学习,

Three.js Journey[9] 是我看过最好的教程,它会从很多基础的概念开始讲解和剖析。

不过想要扎实基本功,时间短了是肯定搞不定的,所以整套教程很长(一共 67 个视频,每个 0.5~2 小时)。

图片

Three.js Journey 教程视频

three.js 算是稍微底层的代码,最后在实现项目时用开源框架,之前几十行的代码其实一行就搞定了。

就好比:一大段 Transformer Model 用一句 from transformers import xxx 就能解决一样。

所以,如果不想从头看起也可以直接跳转学习 React Three Fiber(R3F)[10]。

React & React Three Fiber

React[11] 是 Javascript 的一个三方库(类似于 Python 里 pip install 的那些三方库一样),

从写法上来讲,最大的特点事允许我们同时在一个文件里面同时写 html tag 和 js 的代码。

PS:「状态管理」是 React 更核心的特点,但是这不是一篇科普 React 的文章(我自己也只是个小白),所以主要讲一讲写法上的特点,便于之后阅读源码。

如果 js 比较陌生,我们可以想象成 python,如果我们要用 python 来构建一个能进行逻辑计算的前端页面,

因为 html 本身不支持计算逻辑,所以我们需要 2 个文件:

  • 1 个 index.html 来负责定义网页长什么样(几个按钮,几个输入框)。

  • 1 个 calculate.py 来负责逻辑计算,然后再传递给 index.html。

PS:所以现在比较受欢迎的 python 做 web 的框架:streamlit[12] & gradio[13]都变成纯 python 写网页,不用我们亲自写 html & css,但带来的问题就是局限性比较大,无法实现一些自己想实现的样式。

但这样很麻烦,我们能不能直接把「计算逻辑」和「页面布局」同时写在一个文件里呢?

当然可以,使用 React 这种实现就方便了很多,以下是一个例子:

图片

React 示例(将计算逻辑 & html 逻辑写在同一个文件下)

上面的例子是 React(.jsx) 中常用的写法,所有计算逻辑都在前面写好(a = 3 + 2),

然后在 return 里写上需要的 html 组件(<button>),结束!

React Three Fiber[14] 是在将 Three.js 融合在 React 框架里面的一个三方库,

它能够极大的简化 three.js 代码,并转换成 <tag> 的形式,在 React 的 return 部分导入 3D 模型。

举一个创建立方体的例子:

// three.js 写法(js 形式)
const geometry = new THREE.BoxGeometry(1, 1, 1);                   // 创建立方体几何体
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建绿色材质
const mesh = new THREE.Mesh(geometry, material);                   // 使用几何体和材质创建网格    // R3F 写法(tag 形式)
<mesh><boxGeometry args={[1, 1, 1]} /><meshBasicMaterial color='green' />
</mesh>

完整的示例代码如下:

图片

R3F 示例,将 Three.js 融入到 React 中使用

可以在 R3F官网[15] 里查看详细的说明,也可以在 sandbox[16] 里面在线尝试运行/调试代码。

Tailwind CSS

tailwind css[17] 是一个非常非常非常方便快速美化 web 页面的库,

可以简单理解为:这个库已经提前实现了很多常用的 css 效果,我们只需要填对应的 className 就能快速应用:

图片

tailwind css 使用示例

更直观的来看,我们的项目中底层使用 R3F 进行 3D 世界的渲染,而所有上层的信息框都是通过 tailwind css 来实现(比如人物的状态信息栏、内心想法、搜索网页效果等):

图片

tailwind css 的实现效果

例如,右上角的状态栏对应实现代码如下:

const InfoBox = ({characters,selectedAvatar
}) => {return (// 通过设置 className 来使用 tailwind css 的样式(注:在 React 中使用 className 而不是 class)<div className="fixed right-5 top-5 w-80 h-2/5 flex flex-col items-start space-y-2 p-0 bg-opacity-30 shadow-lg rounded-lg text-xs overflow-y-auto backdrop-blur-sm duration-500"...>{characters?.find(character => character.id === selectedAvatar) ? (<table className="table-auto"><tbody>{Object.entries(characters.find(character => character.id === selectedAvatar)).map(([key, value], index) => (<tr key={key} className={index % 2 === 0 ? 'bg-gray-600 bg-opacity-30' : 'bg-gray-0 bg-opacity-50'}><td className="px-4 py-2 text-sky-100">{key}</td><td className="px-4 py-2 text-sky-100">{JSON.stringify(value)}</td></tr>))}</tbody></table>) : (<div className="p-2 text-red-400">角色信息不可用</div>)}</div>)
}

人物模型 & 动画资源

项目中用到的人物模型是在 Ready Player Me[18] 上捏的,这是一个免费的捏人网站,

你可以在上面选择肤色、发型、衣服等,然后把捏好的人物下载到本地使用(可能是因为国外网站的原因,用起来很卡):

图片

Ready Player Me,捏完之后点击「Next」再保存到本地

动画则是在 mixamo[19] 上找到的,这个网站可以支持上传自己的人物模型,

然后挑选对应的动画(animations),在线预览后下载到本地即可:

图片

点击左侧预设动画,调节好参数后 download 到本地

参考原型

这个客户端的原型是 Youtube 博主 Wawa sensei[20] 的 SIMS ONLINE[21],

我们是基于这个非常棒的开源项目进行的修改,配套的视频教程中有博主亲自一步一步敲代码教学(很推荐):

  • 视频教程:https://www.youtube.com/watch?v=uLv1Zu8GyUw&t=14s

  • 代码链接:GitHub - wass08/r3f-sims-online

图片

讲的很好,强推一键三连

1.2 服务端(Server)

服务端用 python 实现,看起来应该就比较轻松啦,这里主要挑几个我认为比较核心功能的部分讲一讲。

Function Calls

为了定义 agent 可以执行哪些 action,以及在什么时间、什么场合,哪些行为是合法的,

我们将这些定义都实现在了一个叫 function_calls.py 的文件中。

我们期望有一种方便的实现方式,它能够同时具备:

  1. 能够「根据工具的实现函数」自动转换成「自然语言」,并自动添加到 prompt 中。

  2. 只有「当前满足被使用条件的工具」才能加入到 agent 的待选列表中。

关于第 1 点,我们通过实现一个装饰器@register_function_call_class来完成自动生成 prompt 的功能,

python function 的函数名、函数注释(doc string)、输入变量来自动生成对应的 prompt。

举例来讲,我们实现一个AddMemory的工具,并带上该装饰器:

@register_function_call_class
class AddMemory(BaseFunctionCall):def call(agent_object: object, memory_content: str):"""添加一条记忆信息,通常发生在获取了新的信息之后。Args:agent_object (object): agent 对象,通常传入 self 即可。memory_content (str): 需要添加的记忆内容,一条概括性的关键信息。"""agent_object.character['memories'].append(memory_content)...

之后只需要调用 generate_all_function_calls_prompts() 方法,就会生成对应的 prompt:

当前所有可使用的函数以及对应的解释如下:* AddMemory.call(agent_object, memory_content): 添加一条记忆信息,通常发生在获取了新的信息之后。Args:agent_object (object): agent 对象,通常传入 self 即可。memory_content (str): 需要添加的记忆内容,一条概括性的关键信息。* (其他所有带了装饰器的函数)...

在函数注释中需要写清楚函数作用、输入参数的明确含义,这样能帮助 Agent 更容易做出正确的选择。

关于第 2 点,由于我们并不希望所有的 function 在所有时刻都输入给 Agent 做选择,

因此每一个 function_call 类中会定义 validate_func() 方法(默认返回 True),在每一步生成 function_call prompt 之前,env 会将当前的状态传入 validate_func() 方法中,并将返回值为 True 的 function 加入到当前的 prompt 中。

比如:只有当 Agent 在床的附近才允许选择「睡觉」这个行为。

@register_function_call_class
class Sleep(BaseFunctionCall):...@staticmethoddef validate_func(agent_object,room):"""用于根据当前状态判断,是否需要被加入 agent 当前的行为空间中,若返回 False,则不会被加入,默认返回 True。"""return distance(agent_object.character['position'],room['bed']) < 0.1

Extensions(获取新闻、发布微博等)

项目里使用到的「微博发布」、「新闻热点」这些获取真实世界信息的函数,都被放在了 extensions 目录下,

一共有 2 种进行信息获取:cookie 抓取、html tag 解析。

  • cookie:发布/回复微博、稀土掘金新闻、leetcode。

  • html tag 解析:搜索结果。

对于一些比较好解析的页面,比如搜索页面(项目中使用 搜狗搜索),直接抓取 html 后使用 bs4 进行解析:

图片

找到每个 item 对应的 div 进行内容解析即可

from bs4 import BeautifulSoupresponse = requests.get(url, headers=headers, verify=False)
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'html.parser'
)all_search_results = []
div_contents = soup.find_all(class_='vrwrap')         # 找到内容所在的对应 divfor div_content in div_contents:cur_result = {}a_tag = div_content.find('a')if a_tag:cur_result['title'] = a_tag.get_text().strip()span_tag = div_content.find('p', class_='star-wiki')if span_tag:cur_result['body'] = span_tag.get_text().strip().replace('最佳答案', '').strip()if 'title' in cur_result and 'body' in cur_result:all_search_results.append(cur_result)

而对于另一部分内容「需要多次数据交互」才能获得结果的页面就稍微麻烦一些,

我们需要使用 cookie 的方式来模拟 post/get 请求,来获得服务器的响应结果。

以 leetcode 为例,我们需要经过:获取题目、输入代码、验证代码结果这几个步骤,

为此,我们需要明确找到每一步对应的请求接口,这里以「验证代码结果」为例:

图片

通过抓取网络请求,找到正确调用的实际接口,并按照需要的格式请求获得结果

当填写完 ./extensions 目录下的所有的 COOKIE 后,可以通过一键脚本测试:

(base)>>> python -m extensions.test_all_cookies[❌ Unpassed] GeekNewsFetcher.test_fetch_geek_news
[✅ Passed] GeekNewsFetcher.test_fetch_hot_list
[✅ Passed] NewsFetcher.test_fetch_dongfang_news
[✅ Passed] NewsFetcher.test_fetch_toutiao_news
[✅ Passed] SearchFetcher.test_fetch_sougou_zhihu_results
[❌ Unpassed] LeetCodeFetcher.test_get_leetcode_hot_list
[✅ Passed] LeetCodeFetcher.test_get_question_details
[✅ Passed] LeetCodeFetcher.test_run_code_and_get_result
[✅ Passed] WeiBoTools.test_get_all_my_post_weibo
Testing cookies...: 100%|██████████████████████████████████████████████████████████| 5/5 [00:09<00:00,  1.87s/it]
Pass Rate: 80.00%(8/10).

通过 pass 结果来判断当前哪些 cookie 已过期失效,需要重新获取。

自定义世界

通过修改 default_rooms.json 文件,我们可以自定义家具的位置,以及 agent 的爱好、性格、记忆等:

[{"id": 1,"name": "MAIN ROOM","password": "","items": [{"name": "厨房_燃气灶","size": [2, 2],"gridPosition": [2, 12],                        // 摆放位置"rotation": 2                                   // 旋转角度(x90)},...],"characters": [                                     // agent 属性设置{"id": 1,"session": 1,"name": "徐磊","gender": "male",...,"job": "程序员",                                 // 职业"hobby": ["刷新闻", "研究技术", "吃瓜"],           // 爱好"personality": "坦诚,喜欢分享,实事求是。",        // 人物性格"state": "","memories": []}]}
]
]

2. 一些有趣的观测现象

2.1 不同职业对行为选择的影响

我们尝试赋予 agent 2 种不同的职业:程序员 & 自媒体工作者。

如下图所示,职业的设定的确会对 agent 的行为分布产生较大影响:

  • 程序员:主要聚焦在「刷新闻(八卦)」、「搜索」、「leetcode」、「稀土掘金(一个技术论坛)」。

  • 自媒体工作者:「刷新闻(八卦)」、「搜索」、「查看自己的微博评论」。

图片

不同人设下的行为选择统计

进一步的,我们对 2 个职业选择查看的「所有新闻内容」进行词频统计:

图片

哪边是「程序员」应该不用备注了:)

此外,由于我们允许 agent 对自己好奇的内容进行搜索,所以我们也对两个 agent 的「搜索词」进行统计:

图片

自媒体工作者(左),不知道为什么这么痴迷做饭 & 程序员(右),什么都喜欢搜

2.2 不同人设对行为选择的影响

在同为「程序员」的职业下,我们赋予不同的细节人设:

  1. 佛系的吃货 1 号(对应人设统计图的第一行)。

  2. 热爱编程的极客 2 号(对应人设统计图的第二行)。

我们发现,相比之下极客 2 号搜索 query 会杂一些,而吃货 1 号就一直在搜附近的吃的(=-=)

图片

吃货程序员(左)和极客程序员(右)的搜索词

除了搜索词,我们还发现这两个程序员在选择 leetcode 时偏好的难度也不一样:

图片

佛系 1 号(左)和极客 2 号(右)

吃货程序员会更倾向选择简单(Easy)难度的题来做:选择最多的是 两数之和。

极客程序员会更倾向选择中等(Mdeium)难度的题来做:选择最多的是 两数相加,偶尔也会挑战一把 正数数组中位数(Hard 难度)。

好啦,以上就是全部内容啦,感谢观看~

参考资料

[1]

Agent Life Live Demo: http://192.144.228.48

[2]

Agent Life Action Logging Board: http://192.144.228.48:8901/

[3]

斯坦福小镇: https://arxiv.org/pdf/2304.03442v1

[4]

AI Town: https://www.convex.dev/ai-town

[5]

6个AI合租: https://www.bilibili.com/video/BV1MkxeeYEEb

[6]

第一个版本的 demo: http://192.144.228.48/

[7]

视频: https://www.bilibili.com/video/BV1fbz4YLEcA/

[8]

three.js: https://threejs.org/docs/#manual/zh/introduction/Installation

[9]

Three.js Journey: https://www.bilibili.com/video/BV1Ki4y1a72S

[10]

React Three Fiber(R3F): https://r3f.docs.pmnd.rs/getting-started/introduction

[11]

React: https://react.dev/learn

[12]

streamlit: https://streamlit.io/

[13]

gradio: https://www.gradio.app/

[14]

React Three Fiber: https://r3f.docs.pmnd.rs/getting-started/introduction

[15]

R3F官网: https://r3f.docs.pmnd.rs/getting-started/introduction

[16]

sandbox: https://codesandbox.io/p/sandbox/5g22g7

[17]

tailwind css: https://tailwindcss.com/

[18]

Ready Player Me: https://readyplayer.me/avatar

[19]

mixamo: https://www.mixamo.com/#/

[20]

Wawa sensei: https://www.youtube.com/@WawaSensei

[21]

SIMS ONLINE: https://github.com/wass08/r3f-sims-online

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com