想看一群 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 能看到每一句对话。



实测踩坑
- 国内/代理环境
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)。 - 11434 端口冲突:官方 compose 给 backend 映射了 11434,和宿主机 Ollama 抢端口,删掉即可。
- admin key 会失效:
docker compose down再up后经常要重新generate_admin_key.sh并改.env.local;key 不加引号也会解析出错。 - 控制台刷新就掉登录:dashboard 直接访问子路径会回到登录页,重新填 key 即可。
- 地图初始视野里看不到人:角色出生点在地图中右侧,拖动地图就能找到。
- 1B 小模型会”拒答”:llama3.2:1b 偶尔回一句 “I can’t help with that”,对话质量明显不如 8B,但流程完整;内存够的话建议用默认 llama3。
- 换模型/嵌入维度后要清库:
npx convex run testing:wipeAllTables后再npx convex run init,否则向量维度不一致会报错。 - 闲置会暂停:页面没人看约 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














暂无评论内容