AI-town:用 JavaScript 构建 AI 驱动的虚拟世界
开源项目展示多 agents 交互设计,通过仿真演示 agents 协作与涌现现象。
开源项目展示多 agents 交互设计,通过仿真演示 agents 协作与涌现现象。
加入我们的社区 Discord:AI Stack Devs
AI Town 是一座虚拟小镇,AI 角色在这里生活、聊天和社交。
本项目是一套可部署的入门套件,可帮助你轻松构建并定制自己的 AI Town。其灵感来自研究论文《Generative Agents: Interactive Simulacra of Human Behavior》。
除了开发过程本身非常有趣之外,本项目的首要目标是提供一个基础扎实、便于扩展的平台。后端原生支持共享全局状态、事务和模拟引擎,既适用于简单的实验项目,也适用于可扩展的多人游戏。次要目标是提供一个 JS/TS 框架,因为这一领域的大多数模拟器(包括上述原始论文中的模拟器)都是用 Python 编写的。
🧠 安装(云端、本地、Docker、自托管、Fly.io 等)
💻️ Windows 前置要求
🤖 配置你选择的 LLM(Ollama、OpenAI、Together.ai 等)
👤 自定义——你自己的模拟世界
👩💻 部署到生产环境
游戏引擎、数据库和向量搜索:Convex
身份验证(可选):Clerk
默认聊天模型为 llama3,嵌入模型为 mxbai-embed-large。
本地推理:Ollama
可配置为使用其他云端 LLM:Together.ai,或任何兼容 OpenAI API 的服务。欢迎提交 PR,添加对更多云服务提供商的支持。
背景音乐生成:通过 Replicate 使用 MusicGen
像素画生成:Replicate、Fal.ai
项目组件中的所有交互、背景音乐和渲染均由 PixiJS 提供支持。
图块集:https://opengameart.org/content/16x16-game-assets,作者 George Bailey;https://opengameart.org/content/16x16-rpg-tileset,作者 hilau
https://opengameart.org/content/16x16-game-assets,作者 George Bailey
https://opengameart.org/content/16x16-rpg-tileset,作者 hilau
本项目最初的概念验证使用了 https://github.com/pierpo/phaser3-simple-rpg。此后我们已经重写了整个应用,但仍然非常感谢它提供了一个易于上手的起点。
原始素材由 ansimuz 创作。
UI 基于 Mounir Tohami 创作的原始素材。
整体步骤如下:
在 Convex(后端)之上运行此应用有几种方式。
标准的 Convex 配置允许你在本地或云端进行开发。这需要一个免费的 Convex 账户。这是将应用部署到云端并进行正式开发最简单的方式。
如果你只是想试用,不想注册账户,并且可以接受使用 Docker,那么 Docker Compose 配置是一个不错且完全自包含的选择。
这个项目还有一个社区分支,为只想运行而不打算修改项目的用户提供了通过 Pinokio 一键安装的方式 😎。
你也可以将其部署到 Fly.io。有关说明,请参阅 ./fly。
注意:如果你使用 Windows,请参阅下文。
git clone https://github.com/a16z-infra/ai-town.git
cd ai-town
npm install
如果你尚未登录 Convex 账户,此过程会要求你登录。
npm run dev
现在可以访问 http://localhost:5173。
如果你希望分别运行前端和后端(这样后端函数在保存时会同步),可以在两个终端中分别运行:
npm run dev:frontend
npm run dev:backend
详情请参阅 package.json。
你也可以使用自托管 Docker 容器运行 Convex 后端。这里我们将通过 Docker Compose 同时运行前端、后端和控制面板。
docker compose up --build -d
如果传入 -d,容器将持续在后台运行。首次执行完成后,你可以停止和启动这些服务。
前端将在 http://localhost:5173 上运行。
后端将在 http://localhost:3210 上运行(HTTP API 使用端口 3211)。
控制面板将在 http://localhost:6791 上运行。
要登录控制面板并通过 Convex CLI 进行部署,需要生成一个管理员密钥。
docker compose exec backend ./generate_admin_key.sh
将其添加到 .env.local 文件中。注意:如果执行 down 后再执行 up,你必须重新生成密钥并更新 .env.local 文件。
# in .env.local
CONVEX_SELF_HOSTED_ADMIN_KEY="<admin-key>" # Ensure there are quotes around it
CONVEX_SELF_HOSTED_URL="http://127.0.0.1:3210"
然后设置 Convex 后端(只需执行一次):
npm run predev
要持续向后端部署新代码并输出日志,请运行:
npm run dev:backend
要查看控制面板,请访问 http://localhost:6791,并提供此前生成的管理员密钥。
如果你准备使用 Ollama 进行本地推理,需要配置 Docker 以连接到 Ollama。
npx convex env set OLLAMA_HOST http://host.docker.internal:11434
启动 Ollama 后,可以使用以下命令测试连接:
docker compose exec backend /bin/bash curl http://host.docker.internal:11434
如果显示 "Ollama is running",说明连接正常!否则,请查看“故障排除”部分。
注意:如果你希望在云端运行后端,可以使用 OpenAI 或 Together.ai 等基于云的 LLM API,也可以将来自云端的流量代理到本地 Ollama。相关说明请参阅下文。
默认情况下,应用会尝试使用 Ollama,以便完全在本地运行。
下载并安装 Ollama。
打开应用,或者在终端中运行 ollama serve。如果应用已经在运行,ollama serve 会发出警告。
运行 ollama pull llama3 下载 llama3。
使用 ollama run llama3 进行测试。
Ollama 的模型选项可在此处查看。
如果要自定义所使用的模型,请调整 convex/util/llm.ts,或者运行 npx convex env set OLLAMA_MODEL # model。如果要修改嵌入模型:
修改 convex/util/llm.ts 中的 OLLAMA_EMBEDDING_DIMENSION,并确保:
export const EMBEDDING_DIMENSION = OLLAMA_EMBEDDING_DIMENSION;
运行 npx convex env set OLLAMA_EMBEDDING_MODEL # model。
注意:如果运行速度较慢,可以考虑将 constants.ts 中的 NUM_MEMORIES_TO_SEARCH 设置为 1,以减小对话提示词的大小。
要使用 OpenAI,你需要:
// In convex/util/llm.ts change the following line:
export const EMBEDDING_DIMENSION = OPENAI_EMBEDDING_DIMENSION;
设置 OPENAI_API_KEY 环境变量。如果还没有密钥,请访问 https://platform.openai.com/account/api-keys。
npx convex env set OPENAI_API_KEY 'your-key'
可选:通过 OPENAI_CHAT_MODEL 和 OPENAI_EMBEDDING_MODEL 选择模型。
要使用 Together.ai,你需要:
// In convex/util/llm.ts change the following line:
export const EMBEDDING_DIMENSION = TOGETHER_EMBEDDING_DIMENSION;
设置 TOGETHER_API_KEY 环境变量。如果还没有密钥,请访问 https://api.together.xyz/settings/api-keys。
npx convex env set TOGETHER_API_KEY 'your-key'
可选:通过 TOGETHER_CHAT_MODEL 和 TOGETHER_EMBEDDING_MODEL 选择模型。嵌入模型的维度必须与 EMBEDDING_DIMENSION 一致。
你可以使用任何兼容 OpenAI API 的服务,例如 Anthropic、Groq 或 Azure。
修改 convex/util/llm.ts 中的 EMBEDDING_DIMENSION,使其与所用嵌入模型的维度一致。
编辑 llm.ts 中的 getLLMConfig,或者设置以下环境变量:
npx convex env set LLM_API_URL 'your-url'
npx convex env set LLM_API_KEY 'your-key'
npx convex env set LLM_MODEL 'your-chat-model'
npx convex env set LLM_EMBEDDING_MODEL 'your-embedding-model'
注意:如果不需要 LLM_API_KEY,请不要设置它。
关于更换 LLM 服务提供商或嵌入模型的注意事项:
如果更换了 LLM 服务提供商或嵌入模型,应删除现有数据并重新开始。用于记忆的嵌入向量取决于你选择的嵌入模型,而且向量数据库的维度必须与嵌入模型的维度一致。有关操作方法,请参阅下文。
注意:每次修改角色数据后,都应该重新运行 npx convex run testing:wipeAllTables,然后运行 npm run dev,将所有内容重新上传到 Convex。这是因为角色数据会在首次加载时发送到 Convex。但请注意,npx convex run testing:wipeAllTables 会清除你的全部数据。
创建你自己的角色和故事:所有角色、故事及其精灵图引用都存储在 characters.ts 中。你可以先从修改角色描述开始。
创建你自己的角色和故事:所有角色、故事及其精灵图引用都存储在 characters.ts 中。你可以先从修改角色描述开始。
更新精灵图:在 data/characters.ts 中,你会看到以下代码:export const characters = [ { name: 'f1', textureUrl: '/assets/32x32folk.png', spritesheetData: f1SpritesheetData, speed: 0.1, }, ... ]; 你需要为角色找到一张精灵图,并在对应文件中定义精灵动画和素材(在上述示例中,f1SpritesheetData 定义在 f1.ts 中)。
更新精灵图:在 data/characters.ts 中,你会看到以下代码:
export const characters = [
{
name: 'f1',
textureUrl: '/assets/32x32folk.png',
spritesheetData: f1SpritesheetData,
speed: 0.1,
},
...
];
你应该为你的角色找到一个精灵表单,并在对应的文件中定义精灵运动/资源(在上面的例子中,f1SpritesheetData 在 f1.ts 中定义)
地图在 convex/init.ts 中从 data/gentle.js 加载。要更新地图,请按照以下步骤操作:
使用 Tiled 将瓦片地图导出为 JSON 文件(包含 2 个名为 bgtiles 和 objmap 的图层)
使用 convertMap.js 脚本将 JSON 转换为引擎可以使用的格式。
node data/convertMap.js <mapDataPath> <assetPath> <tilesetpxw> <tilesetpxh>
<mapDataPath>:Tiled JSON 文件的路径。
<assetPath>:瓦片集图像的路径。
<tilesetpxw>:瓦片集宽度(像素)。
<tilesetpxh>:瓦片集高度(像素)。生成 converted-map.js,你可以像使用 gentle.js 一样使用它。
要实现每日背景音乐生成,请创建一个 Replicate 账户并在你的个人资料的 API Token 页面中创建一个令牌。
npx convex env set REPLICATE_API_TOKEN # token
这仅在你能从 Replicate 接收 webhook 时有效。如果在普通 Convex 云上运行,默认会有效。如果你是自托管,你需要配置它以在 /http 上访问你应用的 url。如果你使用 Docker Compose,它将是 http://localhost:3211,但你需要将流量代理到本地机器。
注意:如果窗口空闲 5 分钟后,模拟将暂停。加载页面将恢复运行。你也可以通过 UI 中的按钮手动冻结和解冻世界。如果你想在没有浏览器的情况下运行世界,可以注释掉 convex/crons.ts 中的"停止不活跃的世界" cron。通过修改 convex/music.ts 中的提示来改变背景音乐。通过修改 convex/crons.ts 中的"生成新背景音乐"任务来改变生成新音乐的频率。
这将停止运行引擎和智能体。你仍然可以运行查询和函数来调试。
npx convex run testing:stop
npx convex run testing:resume
npx convex run testing:kick
如果你想重置世界并从头开始,可以归档当前世界:
npx convex run testing:archive
然后,你仍然可以在仪表板中查看世界的数据,但引擎和智能体将不再运行。
之后,你可以用 init 创建一个全新的世界。
npx convex run init
你可以进入仪表板的部署设置来暂停和取消暂停你的部署。这将停止所有函数,无论是从客户端、计划任务还是 cron 作业调用的。将此视为最后的手段,因为上面有更温和的停止方式。
首先,你需要安装 WSL2。按照本指南在你的 Windows 机器上设置 WSL2。我们建议使用 Ubuntu 作为 Linux 发行版。
打开你的 WSL 终端(Ubuntu)并更新你的软件包:
sudo apt update
NVM(Node 版本管理器)帮助管理多个版本的 Node.js。安装 NVM 和 Node.js 18(稳定版本):
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
source ~/.bashrc
nvm install 18
nvm use 18
某些依赖需要 Python。安装 Python 和 Pip:
sudo apt-get install python3 python3-pip sudo ln -s /usr/bin/python3 /usr/bin/python
此时,你可以按照上面的说明进行操作。
在运行应用之前,你需要确保 Convex 函数部署到其生产环境。注意:这是假设你使用的是默认的 Convex 云产品。
运行 npx convex deploy 将 convex 函数部署到生产环境
运行 npx convex run init --prod
要将本地数据传输到云,可以运行 npx convex export,然后用 npx convex import --prod 导入。
如果你有想要清除的现有数据,可以运行 npx convex run testing:wipeAllTables --prod
你可以用 git revert b44a436 重新添加 clerk auth。或者只查看该 diff 来了解移除它的改动。
进入 https://dashboard.clerk.com/ 并点击"Add Application"
命名你的应用并选择你想向用户提供的登录方式
将 VITE_CLERK_PUBLISHABLE_KEY 和 CLERK_SECRET_KEY 添加到 .env.local
VITE_CLERK_PUBLISHABLE_KEY=pk_***
CLERK_SECRET_KEY=sk_***
进入 JWT Templates 并创建一个新的 Convex Template。
复制 JWKS 端点 URL 供下面使用。
npx convex env set CLERK_ISSUER_URL # 例如 https://your-issuer-url.clerk.accounts.dev/
在 Vercel 上注册账户,然后安装 Vercel CLI。
如果你使用 Github Codespaces:你需要安装 Vercel CLI 并通过运行 vercel login 从 codespaces cli 进行身份验证。
用 vercel --prod 将应用部署到 Vercel。
我们支持使用 Ollama 进行对话生成。要使其可从网络访问,你可以使用 Tunnelmole 或 Ngrok 或类似工具,以便云后端可以向运行在本地机器上的 Ollama 发送请求。
设置 Tunnelmole 或 Ngrok。
将 Ollama 端点添加到 Convex
npx convex env set OLLAMA_HOST # 上一步中你的 tunnelmole/ngrok 唯一 url
更新 Ollama 域名 Ollama 有一个接受的域名列表。添加 ngrok 域名以便它不会拒绝流量。详见 ollama.ai。
Tunnelmole 是一个开源隧道工具。
你可以使用以下选项之一安装 Tunnelmole:
NPM: npm install -g tunnelmole
Linux: curl -s https://tunnelmole.com/sh/install-linux.sh | sudo bash
Mac: curl -s https://tunnelmole.com/sh/install-mac.sh --output install-mac.sh && sudo bash install-mac.sh
Windows:通过 NPM 安装,或者如果你还没有安装 NodeJS,可以从这里下载 Windows 的 exe 文件,并将其放在 PATH 的某个位置。
安装完 Tunnelmole 后,运行以下命令:
tmole 11434
Tunnelmole 运行此命令后应该会输出一个唯一的 URL。
Ngrok 是一个流行的闭源隧道工具。
安装并验证 ngrok 后,运行以下命令:
ngrok http http://localhost:11434
Ngrok 运行此命令后应该会输出一个唯一的 URL。
你可以通过运行以下命令来清除数据库:
npx convex run testing:wipeAllTables
npx convex run init
如果在应用启动时在 convex 服务器上遇到 node 版本错误,请使用 node 18 版本,这是最稳定的。一种方法是安装 nvm 并运行 nvm install 18 和 nvm use 18。
如果你在后端与 Ollama 的通信方面遇到问题,调试方法取决于你的设置:
如果你直接在 Windows 上运行,请参阅 Windows Ollama 连接问题。
如果你使用 Docker,请参阅 Docker 到 Ollama 连接问题。
如果你在本地运行,可以尝试以下方法:
npx convex env set OLLAMA_HOST http://localhost:11434
默认情况下,主机设置为 http://127.0.0.1:11434。某些系统更喜欢 localhost ¯(ツ)/¯。
如果按照 windows 和常规安装说明进行操作后上述方法仍然不起作用,你可以尝试以下方法,假设你不使用 Docker。
如果你使用 Docker,请参阅下一部分了解 Docker 故障排查。
对于直接在 Windows 上运行,你可以尝试以下方法:
安装 unzip 和 socat:sudo apt install unzip socat
安装 unzip 和 socat:
sudo apt install unzip socat
运行以下命令来桥接端口:
socat TCP-LISTEN:11434,fork TCP:$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):11434 &
测试是否有效:
curl http://127.0.0.1:11434
如果响应 OK,Ollama API 应该可以访问。
如果你在后端与 Ollama 的通信方面遇到问题,有几个方面需要检查:
Docker 是否至少是 18.03 版本?这样你可以使用 host.docker.internal 主机名从容器内连接到主机。
Ollama 是否在运行?你可以通过在容器外运行 curl http://localhost:11434 来检查。
Ollama 是否可以从容器内访问?你可以通过运行 docker compose exec backend curl http://host.docker.internal:11434 来检查。
如果 1 和 2 都有效,但 3 无效,你可以使用 socat 将流量从容器内桥接到主机上运行的 Ollama。
用主机的 IP 地址(不是 Docker IP)配置 socat。
docker compose exec backend /bin/bash
HOST_IP=YOUR-HOST-IP
socat TCP-LISTEN:11434,fork TCP:$HOST_IP:11434
然后从容器外部:
npx convex env set OLLAMA_HOST http://localhost:11434
测试是否有效:
docker compose exec backend curl http://localhost:11434
如果响应 OK,Ollama API 是可访问的。否则,尝试将之前的两个改为 http://127.0.0.1:11434。
如果你想在容器内进行调查,你可以为前端、后端或仪表盘服务启动一个交互式 Docker 终端:
docker compose exec frontend /bin/bash
要退出容器,运行 exit。
docker compose exec frontend npx update-browserslist-db@latest
Convex 是一个托管的后端平台,具有内置数据库,让你可以用 TypeScript 编写数据库架构和服务器函数。服务器端数据库查询会自动缓存和订阅数据,为我们的 React 客户端提供实时 useQuery hook。还有适用于 Python、Rust、ReactNative 和 Node 的客户端,以及一个简单的 HTTP API。
数据库支持 NoSQL 风格的文档,具有可选的架构验证、关系和自定义索引(包括嵌套对象中的字段)。
查询和变更服务器函数具有事务性、低延迟的数据库访问权限,并利用我们的 v8 运行时和确定性护栏来提供市场上最强的 ACID 保证:立即一致性、可序列化隔离和通过乐观多版本并发控制(OCC / MVCC)的自动冲突解决。
Action 服务器函数可以访问外部 API,并在我们优化的 v8 运行时或更灵活的 node 运行时中启用其他副作用和非确定性。
函数可以通过调度和 cron 作业在后台运行。
开发是云优先的,通过 CLI 支持服务器函数编辑的热重载、预览部署、日志和异常报告集成。有一个仪表盘 UI 来浏览和编辑数据、编辑环境变量、查看日志、运行服务器函数等。
There ar