工具部署|AI Town · 像素 AI 小镇,角色会自己社交

想看一群 AI 角色在像素小镇里自己走动、碰面、聊天、记住彼此?这篇整理的是一个可以完全本地跑起来的「生成式智能体小镇」:后端用自托管 Convex(Docker Compose),大模型用本机 Ollama,前端 Vite + React + PixiJS 渲染像素地图。不需要任何云 API Key,断网(模型已下载后)也能玩。

本机已实跑:小镇画面正常、5 个角色自动走动并两两搭话,对话面板实时滚动,Convex 控制台里可以看到消息表持续增长。下面是部署步骤和实测踩过的坑。本帖免费。

小镇全景

能玩什么

  • 自动社交:角色有各自的人设(科学家、园丁、爱吃奶酪的探险家……),会自己决定去找谁聊天、聊什么、聊完记进”记忆”
  • 对话面板:点地图上任意角色,右侧显示人设与当前/上一段对话,正在生成时显示 typing…
  • 记忆与向量检索:聊天结束后生成记忆摘要并做嵌入,下次见面会回忆相关内容
  • 亲自下场:点 Interact 可以作为玩家加入小镇,和角色对话
  • Freeze/解冻:一键暂停模拟;闲置约 5 分钟也会自动暂停,刷新页面即恢复
  • 可换模型:默认 Ollama,也支持 OpenAI、Together 或任意 OpenAI 兼容接口

角色对话

对话面板实时生成

技术栈

层级 技术
前端 Vite、React、TypeScript、PixiJS(像素地图与动画)
后端 Convex(自托管 backend + dashboard,Docker Compose)
模型 Ollama:对话模型(llama3 系列)+ 嵌入模型 mxbai-embed-large(1024 维)
运行环境 Node 18+(本机 Node 24 正常)、Docker / Compose

资源与硬件提醒

  • 默认 llama3(8B)至少要 5–6 GB 空闲内存;本机空闲只有约 4 GB、且无 GPU,所以换成了 llama3.2:1b,CPU 上一句话 2–10 秒
  • 嵌入模型 mxbai-embed-large 约 670 MB,不能省,否则记忆/对话会报错
  • 端口:前端 5173、Convex 3210/3211、控制台 6791、Ollama 11434
  • 模拟每秒都在跑函数和写库,长时间开着会持续吃 CPU;不玩时点 Freeze 或停容器

部署步骤(本机已跑通)

1. 准备 Ollama 和模型

# 宿主机直接装 Ollama,或者用容器(本机用的是容器 + host 网络)
docker run -d --name aitown-ollama --network host \
  -v aitown-ollama:/root/.ollama ollama/ollama:latest

docker exec aitown-ollama ollama pull llama3            # 内存够就用默认
# docker exec aitown-ollama ollama pull llama3.2:1b    # 内存紧张时
docker exec aitown-ollama ollama pull mxbai-embed-large
curl http://127.0.0.1:11434    # 返回 Ollama is running

2. 拉代码、装依赖

cd ai-town          # 解压/克隆后的项目目录
npm install

3. 起 Convex 后端与控制台

项目自带 docker-compose.yml(frontend + backend + dashboard)。注意 backend 默认还映射了 11434 端口,宿主机已有 Ollama 时会冲突,要删掉这行映射或改 OLLAMA_PORT。

本机 Docker 没有默认网桥,所以写了一份 host 网络版(只起 backend 和 dashboard,前端用 npm 起):

services:
  backend:
    image: ghcr.io/convex/convex-backend:latest
    network_mode: host
    volumes: [ "data:/convex/data" ]
    environment:
      - CONVEX_CLOUD_ORIGIN=http://127.0.0.1:3210
      - CONVEX_SITE_ORIGIN=http://127.0.0.1:3211
    healthcheck:
      test: curl -f http://localhost:3210/version
      interval: 5s
  dashboard:
    image: ghcr.io/convex/convex-dashboard:latest
    network_mode: host
    environment:
      - NEXT_PUBLIC_DEPLOYMENT_URL=http://127.0.0.1:3210
    depends_on:
      backend: { condition: service_healthy }
volumes:
  data:
docker compose -f docker-compose.host.yml up -d
docker compose -f docker-compose.host.yml exec backend ./generate_admin_key.sh

4. 写 .env.local

CONVEX_SELF_HOSTED_ADMIN_KEY="<上一步生成的 admin key,务必加引号>"
CONVEX_SELF_HOSTED_URL="http://127.0.0.1:3210"

5. 告诉 Convex 去哪找模型

# host 网络下直接用 127.0.0.1;bridge 网络则用 http://host.docker.internal:11434
npx convex env set OLLAMA_HOST http://127.0.0.1:11434
# 换了小模型才需要这行
npx convex env set OLLAMA_MODEL llama3.2:1b

6. 初始化并启动

npm run predev          # 推函数、建表、初始化地图和角色
npm run dev:frontend    # 前端
# 改了 convex/ 下代码时另开终端:npm run dev:backend

浏览器打开 http://127.0.0.1:5173/ai-town,地图可以拖动,角色在中右侧区域。等 1–2 分钟就会出现对话气泡。

7. Convex 控制台

打开 http://127.0.0.1:6791,填 admin key 登录,Data → messages 能看到每一句对话。

控制台健康页

messages 表

容器与模型

实测踩坑

  1. 国内/代理环境 ollama pull 失败:报 redirect target not allowed ... resolves to non-public。原因是模型文件跳转到 CDN,被解析成了代理的保留地址,Ollama 出于安全拒绝。解决:从 HuggingFace 下载 GGUF,写一行 FROM ./xxx.gguf 的 Modelfile,ollama create 模型名 -f Modelfile。嵌入模型名要叫 mxbai-embed-large(或设 OLLAMA_EMBEDDING_MODEL)。
  2. 11434 端口冲突:官方 compose 给 backend 映射了 11434,和宿主机 Ollama 抢端口,删掉即可。
  3. admin key 会失效:docker compose down 再 up 后经常要重新 generate_admin_key.sh 并改 .env.local;key 不加引号也会解析出错。
  4. 控制台刷新就掉登录:dashboard 直接访问子路径会回到登录页,重新填 key 即可。
  5. 地图初始视野里看不到人:角色出生点在地图中右侧,拖动地图就能找到。
  6. 1B 小模型会”拒答”:llama3.2:1b 偶尔回一句 “I can’t help with that”,对话质量明显不如 8B,但流程完整;内存够的话建议用默认 llama3。
  7. 换模型/嵌入维度后要清库:npx convex run testing:wipeAllTables 后再 npx convex run init,否则向量维度不一致会报错。
  8. 闲置会暂停:页面没人看约 5 分钟后模拟暂停,截图或演示前刷新一下;也可用 npx convex run testing:resume。

常用调试命令

npx convex run testing:stop          # 停模拟
npx convex run testing:resume        # 恢复
npx convex run testing:wipeAllTables # 清空
npx convex run init                  # 重新初始化

安全与合规提醒

  • admin key 等同数据库最高权限,别截图外传、别提交到仓库;公网部署要给 6791/3210 加访问控制
  • 本地 Ollama 免费但吃 CPU/内存;改用云 API 后每句对话和嵌入都会持续计费,记得设额度
  • 背景音乐生成(Replicate)需要额外 token 和公网回调,本文未开启
  • 本项目代码为 MIT 协议,二次分发需保留原版权与许可声明

像素素材署名

小镇的地图、角色与 UI 素材来自以下作者,使用和再分发请遵守各自原协议并保留署名:

  • Tilesheet:OpenGameArt「16×16 Game Assets」by George Bailey;「16×16 RPG Tileset」by hilau
  • 原始素材:OpenGameArt「Tiny RPG Forest」by ansimuz
  • UI:itch.io「Pixel Art GUI Elements」by Mounir Tohami
  • 渲染与交互:PixiJS
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容