AI Town项目架构深度解析:从游戏引擎到智能体系统
2025-07-07 01:11:48作者:尤辰城Agatha
项目概述
AI Town是一个结合了游戏引擎与AI智能体的创新项目,它构建了一个虚拟世界,人类玩家和AI智能体可以在其中进行交互。本文将深入剖析该项目的整体架构设计,帮助开发者理解其核心组件和工作原理。
整体架构分层
AI Town采用分层架构设计,主要分为以下几个关键层次:
- 服务端游戏逻辑层:位于
convex/aiTown
目录下,负责维护游戏状态、处理用户输入以及推进游戏世界演化 - 客户端UI层:使用
pixi-react
框架构建,负责将游戏状态渲染到浏览器 - 游戏引擎层:位于
convex/engine
目录,提供通用的游戏引擎功能 - 智能体系统层:位于
convex/agent
目录,处理AI智能体的决策和行为
核心数据模型
世界与玩家
AI Town的数据模型围绕几个核心概念构建:
- 世界(World):代表一个包含多个玩家互动的游戏地图
- 玩家(Player):游戏中的核心角色,包含可读名称、描述信息以及与人类用户的关联
- 对话(Conversation):由玩家创建并具有生命周期的交流会话
- 对话成员(ConversationMembership):记录玩家参与对话的状态
数据表分类
项目中的数据表分为三大类:
- 引擎表:维护引擎内部状态
- 游戏表:存储游戏状态数据
- 智能体表:专为智能体状态设计
输入处理系统
AI Town通过输入系统修改数据模型,输入由玩家和智能体提交,由游戏引擎处理。主要输入类型包括:
- 加入/离开游戏
- 玩家移动指令
- 对话相关操作(开始、接受邀请、拒绝邀请、离开)
- 智能体特定输入(记忆对话、决策等)
每个输入处理都会检查相关约束条件并更新游戏状态,确保系统的一致性。
游戏引擎设计
输入处理流程
游戏引擎采用专门的输入处理机制:
- 用户通过
insertInput
函数提交输入 - 输入被分配唯一递增的编号和时间戳
- 引擎处理输入并将结果写回
- 客户端可以通过
inputStatus
查询订阅输入状态
时间推进机制
游戏引擎通过tick
方法推进时间:
tick(now)
将模拟推进到指定时间戳- 默认以60次/秒的频率运行
- 将多个tick批处理为一个"step",实际以1次/秒的频率执行
这种设计既保证了游戏动画的流畅性,又避免了过高的数据库操作频率。
状态管理
游戏状态管理遵循以下流程:
- 加载当前游戏状态到内存
- 解析数据库表示到内存对象
- 运行模拟,修改内存中的游戏对象
- 计算状态差异并写回数据库
- 继续运行后续步骤
客户端UI实现
AI Town的客户端UI遵循以下原则:
- 使用常规的
useQuery
钩子加载状态 - 通过
useHistoricalValue
处理历史数据以实现平滑动画 - 使用
useSendInput
封装输入提交逻辑
这种设计使得UI层尽可能接近常规的Convex应用开发模式。
智能体系统架构
智能体工作循环
智能体的行为执行遵循特定流程:
Agent.tick
读取和修改游戏状态- 需要长时间操作时调用
startOperation
- 操作函数可以读取游戏状态和其他表数据
- 通过提交输入来修改游戏状态
- 操作完成后删除
inProgressOperation
记录
对话系统
对话层实现了与GPT的交互逻辑,包括:
- 开始对话(
startConversation
) - 继续对话(
continueConversation
) - 礼貌离开对话(
leaveConversation
)
记忆系统
记忆系统的工作流程:
- 对话结束后,GPT总结消息历史
- 计算总结文本的嵌入向量并存入向量数据库
- 新对话时查询相关记忆并注入提示
设计考量与限制
AI Town的设计遵循几个核心原则:
- 尽可能接近常规Convex应用模式
- 采用常见的
tick()
模型便于理解 - 解耦智能体行为与游戏引擎
这些设计选择带来了一些固有限制:
- 所有数据需在每一步加载到内存
- 输入需通过数据库表传递
- 输入延迟约为1个RTT加上半步长时间
总结
AI Town项目通过清晰的架构分层和精心设计的数据模型,构建了一个支持人类玩家与AI智能体共同参与的虚拟世界。其游戏引擎的设计平衡了性能与开发便利性,而智能体系统则展示了如何将LLM集成到游戏环境中。理解这些架构设计对于定制和扩展项目功能至关重要。