构建赛博小镇
一句话
将智能体技术与游戏引擎结合,构建一个充满生命力的AI小镇,实现智能NPC对话、记忆系统和好感度系统。
什么时候翻这页
当你需要将AI技术与游戏开发结合,创建具有真实交互体验的虚拟世界时。
核心概念
- 智能NPC对话系统:玩家可以与NPC进行自然语言对话,NPC会根据角色设定和记忆做出回应。
- 记忆系统:NPC拥有短期记忆和长期记忆,能够记住与玩家的互动历史。
- 好感度系统:NPC对玩家的态度会随着互动而变化,从陌生到熟悉,从友好到亲密。
- 游戏化交互:玩家可以在2D像素风格的办公室场景中自由移动,与不同的NPC互动。
- 实时日志系统:所有对话和互动都会被记录,方便调试和分析。
- 批量对话生成:将多个NPC的对话请求合并成一次LLM调用,降低成本和延迟。
- 混合模式:结合批量生成和即时响应,既保证效率又保证交互质量。
怎么做
项目架构
赛博小镇采用游戏引擎+后端服务的分离架构,分为四个层次:
- 前端层:使用Godot 4.5游戏引擎,负责游戏渲染、玩家控制、NPC显示和对话UI。
- 后端层:使用FastAPI框架,负责API路由、NPC状态管理、对话处理和日志记录。
- 智能体层:使用HelloAgents框架,负责NPC智能、记忆管理和好感度计算。
- 外部服务层:提供LLM能力、向量存储和数据持久化,包括LLM API、Qdrant向量数据库和SQLite关系数据库。
NPC智能体系统
每个NPC都是一个独立的SimpleAgent实例,拥有独立的记忆和状态:
from hello_agents import SimpleAgent, HelloAgentsLLM
from hello_agents.memory import MemoryManager, WorkingMemory, EpisodicMemory
def create_npc_agent(npc_id: str, name: str, role: str, personality: str):
"""创建NPC Agent"""
# 构建系统提示词
system_prompt = f"""你是{name},一位{role}。
你的性格特点:{personality}
你在Datawhale办公室工作,与同事们一起推动开源社区的发展。
请根据你的角色和性格,自然地与玩家对话。
记住你们之前的对话内容,保持对话的连贯性。
"""
# 创建LLM实例
llm = HelloAgentsLLM()
# 创建记忆管理器
memory_manager = MemoryManager(
working_memory=WorkingMemory(capacity=10, ttl_minutes=120),
episodic_memory=EpisodicMemory(
db_path=f"memory_data/{npc_id}_episodic.db",
collection_name=f"{npc_id}_memories"
)
)
# 创建Agent
agent = SimpleAgent(
name=name,
llm=llm,
system_prompt=system_prompt,
memory_manager=memory_manager
)
return agent
NPC角色设定
设计了三个NPC,分别代表不同的职业和性格:
- 张三 - Python工程师:严谨、专业、喜欢分享技术知识。说话直接,注重代码质量。
- 李四 - 产品经理:外向、善于沟通、注重用户体验。喜欢从用户角度思考问题。
- 王五 - UI设计师:温和、富有创意、审美独特。注重视觉呈现和用户体验。
好感度系统
好感度分为五个等级:
- 陌生(0-20分):NPC刚认识玩家,态度礼貌但保持距离。
- 熟悉(21-40分):NPC开始记住玩家,愿意进行简单的交流。
- 友好(41-60分):NPC把玩家当作朋友,愿意分享更多信息。
- 亲密(61-80分):NPC非常信任玩家,愿意分享私人话题。
- 挚友(81-100分):NPC把玩家当作最好的朋友,无话不谈。
好感度计算使用LLM分析对话内容,判断玩家态度并调整分数:
class RelationshipManager:
"""好感度管理器"""
def analyze_sentiment(self, player_message: str, npc_reply: str) -> int:
"""分析对话情感,返回好感度变化值"""
prompt = f"""分析以下对话中玩家的态度:
玩家: {player_message}
NPC: {npc_reply}
请判断玩家的态度是:
1. 友好(+5分): 礼貌、热情、表示感谢或赞同
2. 中立(+2分): 普通的询问或陈述
3. 不友好(-3分): 粗鲁、冷漠、批评或否定
只返回数字,不要其他内容。"""
response = self.llm.think([{"role": "user", "content": prompt}])
try:
score_change = int(response.strip())
return max(-3, min(5, score_change)) # 限制在-3到5之间
except:
return 2 # 默认中立
批量对话生成
批量生成器将多个NPC的对话请求合并成一次LLM调用:
class NPCBatchGenerator:
"""批量生成NPC对话的生成器"""
def generate_batch_dialogues(self, context: Optional[str] = None) -> Dict[str, str]:
"""批量生成所有NPC的对话"""
# 构建批量生成提示词
prompt = self._build_batch_prompt(context)
# 一次LLM调用生成所有对话
response = self.llm.invoke([
{"role": "system", "content": "你是一个游戏NPC对话生成器,擅长创作自然真实的办公室对话。"},
{"role": "user", "content": prompt}
])
# 解析JSON响应
dialogues = json.loads(response)
return dialogues
前后端通信
使用HTTP REST API实现Godot前端与FastAPI后端的通信:
# api_client.gd
extends Node
# 信号定义
signal chat_response_received(npc_name: String, message: String)
signal chat_error(error_message: String)
# HTTP请求节点
var http_chat: HTTPRequest
func send_chat(npc_name: String, message: String) -> void:
"""发送对话请求"""
var data = {
"npc_name": npc_name,
"message": message
}
var json_string = JSON.stringify(data)
var headers = ["Content-Type: application/json"]
var error = http_chat.request(
Config.API_CHAT,
headers,
HTTPClient.METHOD_POST,
json_string
)
if error != OK:
print("[ERROR] 发送对话请求失败: ", error)
chat_error.emit("网络请求失败")
命令 / 代码速查
启动后端
# 1. 进入backend目录
cd Helloagents-AI-Town/backend
# 2. 安装依赖
pip install -r requirements.txt
# 3. 配置环境变量
cp .env.example .env
# 编辑.env文件,填写你的API密钥
# 4. 启动后端服务
python main.py
启动Godot
- 下载Godot引擎(Windows / Mac)
- 打开Godot引擎,点击"导入"按钮
- 浏览到
Helloagents-AI-Town/helloagents-ai-town/scenes/main.tscn,点击"导入并编辑" - 按F5或点击"运行"按钮启动游戏
查看日志
# 在backend目录下
python view_logs.py
与 Python / Claude Code 手册的联系
- 使用Python的FastAPI框架构建后端服务
- 使用Godot引擎的GDScript语言开发游戏前端
- 利用HelloAgents框架实现NPC智能体系统
- 使用向量数据库(Qdrant)存储长期记忆
- 使用SQLite关系数据库存储状态数据
初学者易错点
- CORS配置:确保FastAPI后端正确配置CORS,允许Godot前端访问
- 异步处理:Godot中的HTTP请求是异步的,需要正确处理回调函数
- 内存管理:NPC的短期记忆容量和TTL需要合理设置,避免内存泄漏
- 好感度计算:LLM的情感分析可能不稳定,需要设置合理的分数变化范围
- 批量生成限制:批量生成不适合与玩家的直接互动,仅适用于背景对话