外观
AI Town:一个可运行的 Agent 世界
资料依据:
a16z-infra/ai-town开源仓库当前源码与ARCHITECTURE.md。本文关注它的运行逻辑,不复述页面功能。
1. 它不是聊天窗口
AI Town 的核心不是“让几个角色互相发消息”,而是维护一个持续推进的世界状态:
text
世界有时间
角色有位置
角色可以移动
角色可以相遇
相遇后形成对话
对话结果进入记忆
下一次行动再读取记忆这和普通 Chatbot 的区别是:
| 普通聊天 | AI Town |
|---|---|
| 用户发一句,模型回一句 | 世界循环持续运行 |
| 上下文主要在会话里 | 状态保存在服务端数据库 |
| 角色没有真实位置 | 玩家有位置、路径和当前活动 |
| 对话由用户触发 | Agent 可以自己行动 |
| 页面是聊天记录 | 页面是世界状态的可视化 |
AI Town 的浏览器画面只是表层。真正的系统在 Convex 服务端。
2. 四层结构
2.1 convex/engine:通用状态推进器
引擎维护固定步长的游戏循环。抽象接口包含:
text
tickDuration 一次 tick 的时间长度
stepDuration 一次 step 的执行窗口
tick(now) 游戏规则真正推进的位置一次推进大致是:
text
读取上一个时间点
↓
收集这一 tick 的输入
↓
按顺序处理输入
↓
tick(currentTs) 推进世界
↓
提交新状态输入先进入队列,再改变状态。 这比让每个 Agent 直接修改数据库更容易审计,也能避免多个角色同时写坏世界。
2.2 convex/aiTown:具体游戏规则
它定义 AI Town 自己的世界:
text
World 一张地图与一组角色
Player 角色、名字、描述、位置
Movement 路径与移动目标
Conversation 一次对话
ConversationMembership 角色加入对话的状态Conversation membership 有三个状态:
text
invited 已被邀请,但还没接受
walkingOver 已接受,正在走过去
participating 已经进入对话当前实现的一个重要约束是:一个对话通常只有两个成员。这让移动、接近和轮流发言的状态机变得简单,但也限制了多人群聊和复杂群戏。
2.3 convex/agent:让角色自己行动
Agent 不直接控制前端,而是作为异步任务运行:
text
agentDoSomething
↓
判断下一步动作
↓
移动 / 寻找角色 / 发起对话 / 继续活动
↓
agentGenerateMessage
↓
agentRememberConversationLLM 是 Agent 决策中的一个组件,不是整个游戏引擎。世界仍然由确定性的游戏规则维护。
2.4 src/:只负责看见世界
客户端使用 Pixi/React 渲染角色、地图、移动和对话状态。
text
服务端:世界事实
客户端:画面表现浏览器刷新后,画面可以根据服务端状态恢复。客户端不应该成为角色行为的事实来源。
3. 一次对话是怎样发生的
这个流程里有两个不同的事实:
| 类型 | 由谁保证 |
|---|---|
| 两个人是否真的靠近 | 游戏引擎 |
| 两个人说了什么 | Agent + LLM |
| 对话是否已经结束 | 游戏规则 |
| 角色以后记得什么 | 记忆层 |
这也是 AI Town 可持续运行的原因:LLM 只负责不确定的行为内容,位置、时间和状态转移仍由系统掌控。
4. AI Town 的记忆
源码中的 Agent 记忆以向量检索为主。对话结束后,系统把对话写入记忆,再根据后续情境生成 embedding,检索相关内容。
text
当前情境
↓ embedding
memory.searchMemories(player, embedding, topK)
↓
取回相似记忆
↓
放入下一轮 Agent 上下文它解决的是:
- 这个角色以前和谁聊过什么?
- 最近发生过哪些相关事情?
- 哪些历史记忆和当前行动最相似?
它不天然解决:
- 这个角色是否有资格知道某件事?
- 某条信息是自己看到的,还是别人告诉的?
- 两条记忆是否发生了事实冲突?
向量记忆回答“这段历史像不像当前问题”,不等于回答“这个角色有没有见过这件事”。
另外,AI Town 的对话记忆代码里明确把记忆当作不可信的历史内容,只作为上下文使用,不把记忆里的指令当成新的系统指令。这是实际产品中很重要的提示词注入防护。
5. 它为什么能让角色自己生活
AI Town 有三个关键闭环:
闭环一:行动闭环
text
角色状态 → Agent 决策 → 提交输入 → 世界推进 → 新状态闭环二:社会闭环
text
角色靠近 → 对话 → 关系变化 → 下一次行动受影响闭环三:记忆闭环
text
经历事件 → 写入记忆 → 未来检索 → 影响新决定如果只做第三个闭环,得到的是会记忆的聊天机器人;只有三个闭环同时存在,才会出现“角色在世界里生活”的感觉。
6. 它不适合直接做什么
AI Town 很适合:
- 角色长期生活;
- 自主移动和相遇;
- 日常关系发展;
- 可视化的世界状态;
- 观察 Agent 自己形成活动轨迹。
但它不天然适合:
- 多场景悬疑剧;
- 导演控制的镜头节奏;
- 复杂多人审讯;
- 每集固定开场和收尾;
- 直接导出短剧分镜;
- 以“主线 + 单元案”管理长篇叙事。
原因很直接:它的基本单位是世界 tick 和角色行动,不是“剧集 beat”。
text
AI Town 的问题:角色下一步在世界里做什么?
戏剧工坊的问题:这一集要把哪条冲突推到哪里?两者都使用 Agent,但调度目标不同。
7. 对我们的启发
我们没有直接复制 AI Town,而是吸收了三个设计:
7.1 服务端保存世界事实
戏剧工坊的剧本状态、记忆和项目进度不应该只留在浏览器上下文里。
7.2 Agent 负责行动,系统负责边界
角色可以自由说话,但场景、在场者、记忆权限、收尾条件由系统管理。
7.3 记忆是行为的一部分
角色不是每次重新读完整剧本,而是通过短期记忆、摘要和结构化事实恢复状态。
我们的改造方向是:
text
AI Town 的持续世界
+ MiroFish 的图谱与事件记忆
+ 导演-演员式戏剧调度
= 面向剧本生产的角色演化系统8. 一句话总结
AI Town 是一个有时间、有位置、有对话、有记忆的 Agent 世界;它的画面只是外壳,真正的核心是服务端固定步长状态机与异步角色决策。
它最值得借鉴的不是“小人会走路”,而是:
把 LLM 放进一个由系统掌控状态、输入和时间的世界里,而不是让 LLM 自己假装整个世界存在。