赛博小镇:基于 HelloAgents 与 Godot 的多智能体 AI NPC 对话系统实战解析
2026/9/19 1:55:36 网站建设 项目流程

赛博小镇:基于 HelloAgents 与 Godot 的多智能体 AI NPC 对话系统实战解析

【免费下载链接】hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/datawhalechina/hello-agents

本篇技术指南聚焦《从零开始构建智能体》教程第 15 章的配套开源案例——赛博小镇(Helloagents-AI-Town),一个将 HelloAgents 多智能体框架与 Godot 游戏引擎结合的 2D 像素风 AI 小镇模拟项目。文中将从项目架构、环境搭建、NPC 智能体构建、记忆与好感度系统、批量自主行为、日志体系到前后端通信,完整还原每个模块的源码实现与配置细节,读完你即可在本地跑起一个"会记忆、有感情、能自主生活"的 AI 小镇,并掌握把多智能体系统接入游戏引擎的通用套路。

项目概览:三个会"生活"的 AI NPC

赛博小镇基于 HelloAgents 框架构建,展示多智能体系统在游戏中的落地应用。项目在 Datawhale 办公室场景中部署了3 个拥有独立人格的 AI NPC:Python 工程师张三、产品经理李四和 UI 设计师王五。每个 NPC 都是一个独立的SimpleAgent实例,具备以下核心能力:

  • 智能对话系统:玩家可以用自然语言与任意 NPC 交流,NPC 根据角色设定与互动历史做出回应;
  • 记忆系统:短期(工作记忆)+ 长期(情景记忆)两级记忆,能够记住与玩家的互动历史;
  • 好感度系统:5 个关系等级,NPC 对玩家的态度随互动动态变化;
  • NPC 自主行为:闲逛、工作等背景对话,让小镇"活"起来;
  • 完整日志系统:所有对话与互动被完整记录,便于调试与分析。

项目的完整工程位于仓库 code/chapter15/Helloagents-AI-Town 目录,其中backend/为 Python 后端,helloagents-ai-town/为 Godot 游戏工程。

技术栈与四层架构

项目采用游戏引擎 + 后端服务的分离式架构,技术栈如下:

层次技术选型职责
前端层Godot 4.x(推荐 4.2+)游戏渲染、玩家控制、NPC 显示、对话 UI
后端层FastAPI + Python 3.10+API 路由、NPC 状态管理、对话处理、日志记录
智能体层HelloAgents 框架NPC 智能、记忆管理、好感度计算
外部服务层LLM API / Qdrant / SQLite对话生成、向量存储、数据持久化

整体数据流转为:玩家在 Godot 中按 E 键与 NPC 互动 → Godot 通过 HTTP API 将请求发送到 FastAPI 后端 → 后端调用 HelloAgents 的SimpleAgent处理对话(先检索记忆,再调用 LLM 生成回复)→ 后端更新好感度并写日志 → 返回回复给前端展示。架构图如下:

前端 Godot 工程中的场景与脚本组织可参考 scripts 目录说明:player.gd负责移动与交互、npc.gd负责巡逻与对话气泡、dialogue_ui.gd负责对话框、api_client.gd负责与后端通信、main.gd负责全局协调。

环境准备与 5 分钟快速启动

系统要求

  • 操作系统:Windows 10/11、macOS、Linux;
  • Godot:4.2+(推荐 4.3);
  • Python:3.10+;
  • Git(可选,用于克隆仓库)。

步骤 1:获取项目

git clone https://gitcode.com/datawhalechina/hello-agents # 进入本章案例目录 cd hello-agents/code/chapter15/Helloagents-AI-Town

也可以直接下载仓库 ZIP 包后解压到任意目录。

步骤 2:安装 Godot

从 Godot 官网下载 4.2+ 版本(Windows 提供.exe直开文件,macOS 提供.dmg文件),解压运行即可。之后在 Godot 中点击"导入",选择Helloagents-AI-Town/helloagents-ai-town/scenes/main.tscn,点击"导入并编辑"。

步骤 3:配置 Python 环境

cd backend python -m venv venv # Windows 激活虚拟环境 venv\Scripts\activate # macOS/Linux 激活虚拟环境 source venv/bin/activate # 安装依赖 pip install -r requirements.txt

依赖文件 backend/requirements.txt 中关键依赖包括fastapi>=0.104.0uvicorn[standard]>=0.24.0pydantic>=2.0.0python-dotenv,以及 HelloAgents 框架hello-agents>=0.2.4,<=0.2.9。随后安装 HelloAgents 框架:

cd ../HelloAgents pip install -e . cd ../backend

步骤 4:配置环境变量

cp .env.example .env

仓库提供的 backend/.env.example 默认推荐使用 ModelScope 平台:

# HelloAgents LLM配置(使用ModelScope API) LLM_MODEL_ID=Qwen/Qwen2.5-72B-Instruct LLM_API_KEY=your-modelscope-api-key-here LLM_BASE_URL=https://api-inference.modelscope.cn/v1/ # 其他可选模型 # LLM_MODEL_ID=Qwen/Qwen2.5-7B-Instruct # LLM_MODEL_ID=deepseek-ai/DeepSeek-V3 # 兼容 OpenAI 的服务也可用 # LLM_BASE_URL=https://api.deepseek.com/v1 # LLM_MODEL_ID=deepseek-chat

重要:请务必将LLM_API_KEY替换为你自己的实际密钥。若使用其他 LLM 服务,同时调整LLM_MODEL_IDLLM_BASE_URL

此外 backend/config.py 会自动加载.env文件,并提供以下配置项:

  • API_HOST = "0.0.0.0"API_PORT = 8000:后端监听地址;
  • NPC_UPDATE_INTERVAL = 30:NPC 状态批量更新间隔(秒);
  • LLM_MODEL_ID/LLM_API_KEY/LLM_BASE_URL:从环境变量读取;
  • CORS_ORIGINS = ["*"]:跨域配置(生产环境应限制具体域名)。

settings.validate()会在服务启动时检查LLM_API_KEY,若未配置会给出警告——此时系统自动降级为预设对话模式,基础功能仍可运行。

步骤 5:启动后端服务

cd backend python main.py

预期输出:

📝 对话日志文件: .../backend/logs/dialogue_2025-10-15.log 📂 日志目录: .../backend/logs ============================================================ 🎮 赛博小镇后端服务启动中... ============================================================ ... ✅ 所有服务已启动! 📡 API地址: http://0.0.0.0:8000 📚 API文档: http://0.0.0.0:8000/docs ============================================================

main.py中通过 FastAPI 的lifespan生命周期钩子完成初始化:验证配置 → 初始化 NPC 管理器(含记忆与好感度系统)→ 启动状态管理器定时任务 → 打印 API 地址。也可以使用 uvicorn 直接启动:uvicorn main:app --reload --host 0.0.0.0 --port 8000

步骤 6:运行游戏

在 Godot 编辑器中点击右上角"运行"按钮(或按 F5),游戏窗口打开后:

  • WASD:移动玩家;
  • E:与附近 NPC 交互(出现"按E交互"提示时);
  • Enter:发送消息;
  • ESC:关闭对话框。

游戏画面为一个像素风格的 Datawhale 办公室场景,NPC 头顶会浮现对话气泡:

提示:若游戏无法对话,请确认后端服务正在运行、后端地址正确(默认http://localhost:8000),并查看 Godot 控制台错误信息。后端可通过http://localhost:8000/docs访问 Swagger 交互式 API 文档。

NPC 智能体系统:从角色设定到对话循环

NPC 角色配置

三个 NPC 的角色定义集中在 backend/agents.py 的NPC_ROLES字典中,每个 NPC 包含职位、位置、活动、性格、专长、说话风格和爱好:

NPC_ROLES = { "张三": { "title": "Python工程师", "location": "工位区", "activity": "写代码", "personality": "技术宅,喜欢讨论算法和框架", "expertise": "多智能体系统、HelloAgents框架、Python开发、代码优化", "style": "简洁专业,喜欢用技术术语,偶尔吐槽bug", "hobbies": "看技术博客、刷LeetCode、研究新框架" }, "李四": { "title": "产品经理", "location": "会议室", "activity": "整理需求", "personality": "外向健谈,善于沟通协调", ... }, "王五": { "title": "UI设计师", "location": "休息区", "activity": "喝咖啡", "personality": "细腻敏感,注重美感", ... } }

create_system_prompt()函数将这些配置渲染成结构化系统提示词,包含角色设定、行为准则(第一人称、30-50 字简洁回复、可表达情绪、不说"我是 AI"等)和对话示例,确保 NPC 扮演真实的办公室同事。

NPCAgentManager 与对话流水线

NPCAgentManager负责统一管理所有 NPC:为每个 NPC 创建SimpleAgent实例与独立的MemoryManager,并在 LLM 不可用时自动切换到模拟模式。其核心chat()方法完整串联了六大步骤(日志系统全程埋点):

  1. 获取当前好感度:从RelationshipManager读取关系等级与对话风格修饰词,拼入上下文;
  2. 检索相关记忆:调用memory_manager.retrieve_memories(query=message, memory_types=["working", "episodic"], limit=5, min_importance=0.3)
  3. 构建增强提示词:将好感度上下文、历史记忆与当前玩家消息拼装为enhanced_message
  4. 生成回复agent.run(enhanced_message)调用 LLM;
  5. 分析并更新好感度:调用analyze_and_update_affinity(),将玩家消息与 NPC 回复交给情感分析 Agent;
  6. 保存对话到记忆:将玩家消息(importance=0.5)与 NPC 回复(importance=0.6)以working类型写入记忆,元数据中同时记录当时好感度、好感度变化量与情感倾向。
# agents.py 中记忆检索与保存的关键代码 relevant_memories = memory_manager.retrieve_memories( query=message, memory_types=["working", "episodic"], limit=5, min_importance=0.3 ) memory_manager.add_memory( content=f"玩家说: {player_message}", memory_type="working", importance=0.5, metadata={ "speaker": "player", "player_id": player_id, "affinity": affinity, "affinity_change": affinity_change, "sentiment": sentiment, "context": {"interaction_type": "dialogue", "npc_name": npc_name} } )

NPC 记忆系统:短期 + 长期两级记忆

核心功能

  • 工作记忆(Working Memory,短期):存储最近 10 条对话,约 2 小时后自动过期,用于当前对话上下文,检索快速;
  • 情景记忆(Episodic Memory,长期):持久化存储重要对话,基于 Qdrant 向量数据库进行语义检索,最多存 100 条记忆,重要性低于 0.3 的记忆自动被遗忘;
  • 记忆隔离:每个 NPC 拥有独立记忆系统(backend/memory_data/张三/李四/王五/三个目录),NPC 之间互不干扰,各玩家的对话也独立存储。

记忆系统配置参数

agents.py_create_memory_manager()展示了完整的MemoryConfig配置:

memory_config = MemoryConfig( storage_path=memory_dir, # 存储路径(按NPC隔离) working_memory_capacity=10, # 工作记忆容量(最近10条) working_memory_tokens=2000, # 工作记忆token限制 max_capacity=100, # 记忆总容量 importance_threshold=0.3, # 重要性阈值 decay_factor=0.95 # 时间衰减系数 ) memory_manager = MemoryManager( config=memory_config, user_id=npc_name, # 以NPC名字作为user_id enable_working=True, # 启用短期工作记忆 enable_episodic=True, # 启用长期情景记忆 enable_semantic=False, # 不需要语义记忆 enable_perceptual=False # 不需要感知记忆 )

各参数含义与建议范围:

参数默认值建议范围说明
working_memory_capacity105-20工作记忆容量,越大越占内存
working_memory_tokens20001000-4000Token 限制,影响上下文长度
max_capacity10050-500记忆总容量,越大越占磁盘
importance_threshold0.30.1-0.5重要性阈值,越高越偏向保留重要记忆
decay_factor0.950.8-0.99时间衰减系数,越低越强调近期记忆

记忆 API 接口

POST /chat Content-Type: application/json {"npc_name": "张三", "message": "你好,你是做什么的?"}
GET /npcs/张三/memories?limit=10 # 查看NPC记忆 DELETE /npcs/张三/memories?memory_type=working # 清空记忆(测试用)

其中GET响应返回记忆列表(id、content、type、importance、timestamp、metadata),DELETE支持按working/episodic类型定向清空,不传则清空全部(对应 backend/main.py 中clear_npc_memories的实现)。

NPC 好感度系统:LLM 情感分析驱动的五级关系

五级关系等级

好感度值域为 0-100,初始值为 50(友好),共分五个等级:

  • 陌生(0-20):冷淡疏离,不太愿意多说,回答简短;
  • 熟悉(20-40):礼貌但略显生疏,回答简洁;
  • 友好(40-60):礼貌友善,正常交流,保持专业;
  • 亲密(60-80):友好热情,愿意多聊,会主动关心对方;
  • 挚友(80-100):非常热情,像老朋友一样亲切,愿意分享私人话题。

好感度变化规则

好感度不靠固定加分,而是由情感分析 Agent 根据对话内容动态判定:

对话类型变化量示例
赞美、感谢、请教+3 到 +8"你真棒!" "谢谢你!" "能教教我吗?"
友好问候、正常交流+1 到 +3"你好!" "最近怎么样?"
普通闲聊、中性话题0"今天天气不错"
批评、质疑、不耐烦-3 到 -8"这个不太好" "真的吗?"
侮辱、攻击、恶意-8 到 -15"你太烂了!"

好感度被严格限制在 0-100 区间,等级跨越时会触发"关系等级提升/降低"事件(如 56→64 时"友好→亲密")。

RelationshipManager 源码实现

backend/relationship_manager.py 中,情感分析由一个独立的SimpleAgent(name="AffinityAnalyzer")承担,其系统提示词明确规定了分析维度(玩家态度、对话内容、互动质量、情感倾向)与 JSON 输出格式:

# 情感分析Agent的输出格式 { "should_change": true/false, "change_amount": -15到+10之间的整数, "reason": "简短说明原因(10字以内)", "sentiment": "positive/neutral/negative" }

analyze_and_update_affinity()的执行流程:构建"玩家消息 + NPC 回复"的分析提示 → 调用分析 Agent →_parse_analysis()解析 JSON(依次尝试直接解析、截取大括号内容、正则提取三个回退策略)→ 若should_change为 true 则更新好感度并判定新旧等级 → 返回包含old_affinitynew_affinitychange_amountreasonsentimentold_levelnew_level的完整结果。若解析失败或分析异常,系统会安全返回"不改变"的默认值,不会中断对话流程。

好感度最终通过get_affinity_modifier()生成的对话风格修饰词注入 NPC 的系统提示词,实现"好感度越高,回复越热情"的动态效果。

好感度 API 接口

GET /npcs/张三/affinity?player_id=player # 获取单个NPC好感度 GET /affinities?player_id=player # 获取所有NPC好感度 PUT /npcs/张三/affinity?affinity=80&player_id=player # 设置好感度(测试用)

PUT接口会校验好感度必须在 0-100 之间(越界返回 400),响应示例如:

{ "message": "已设置张三对玩家的好感度", "npc_name": "张三", "player_id": "player", "affinity": 80.0, "level": "挚友", "modifier": "非常热情友好,像老朋友一样亲切,愿意分享私人话题" }

若想调整好感度变化敏感度,可修改 relationship_manager.py 中的情感分析提示词:更敏感可将变化量范围调至 -20 到 +15,更保守可缩至 -5 到 +5,也可增加更多分析维度。

NPC 自主行为:批量生成 + 即时响应的混合模式

批量对话生成器

为了让 NPC 在无人交互时也"活着"(闲逛、工作、自言自语),项目实现了 backend/batch_generator.py。其核心思路是一次 LLM 调用生成全部 3 个 NPC 的对话,并要求严格按 JSON 格式返回:

{"张三": "这个bug真是见鬼了,已经调试两小时了...", "李四": "嗯,这个功能的优先级需要重新评估一下。", "王五": "这杯咖啡的拉花真不错,灵感来了!"}

提示词中会注入当前场景(由_get_current_context()根据本地时间自动推断:清晨/上午/午餐/下午/傍晚/夜晚)以及每个 NPC 的职位、位置、活动与性格描述。相比逐个调用,批量方式将每分钟 API 调用从 6 次降为 2 次(3 NPC × 每 30 秒一次 → 1 次批量调用/30 秒),成本降低约 66%(见 backend/README.md)。当 LLM 不可用时,系统自动降级使用按时间段划分的preset_dialogues预设对话库。

状态管理器

backend/state_manager.py 的NPCStateManager负责定时调度:启动时立即执行一次更新,随后以NPC_UPDATE_INTERVAL(默认 30 秒)为间隔运行后台循环_auto_update_loop(),将批量生成结果缓存到current_dialogues,并通过以下接口暴露给前端:

GET /npcs/status # 获取所有NPC当前状态与更新倒计时 POST /npcs/status/refresh # 强制刷新一次

混合模式的价值

  • 背景对话走批量生成:玩家靠近 NPC 但未交互时,NPC 显示"正在调试代码..."等背景对话,成本低;
  • 玩家交互走即时响应:按 E 键后立即调用该 NPC 专属 Agent,基于玩家的具体消息、历史记忆与好感度生成个性化回复,质量高。

这种"预制菜 + 现炒"的混合策略让 NPC 始终看起来生动,同时保障交互质量与成本可控,该思路可迁移到任何需要大量 AI 调用的场景。

日志系统:对话全程可视化

双重输出与按日归档

日志系统(backend/logger.py)使用 Pythonlogging标准库,同时挂载文件 handler控制台 handler,实现双重输出;日志按日期自动归档:

backend/logs/ ├── dialogue_2025-01-15.log ├── dialogue_2025-01-16.log └── dialogue_2025-01-17.log

它自动记录:对话开始/结束、玩家消息、当前好感度与关系等级、检索到的相关记忆、NPC 回复、好感度变化分析、关系等级变化、记忆保存确认。一次完整对话的日志形如:

14:30:25 - ============================================================ 14:30:25 - 💬 对话开始: 张三 <-> 玩家 14:30:25 - ============================================================ 14:30:25 - 📝 玩家消息: 你好,很高兴认识你! 14:30:25 - 💖 当前好感度: 50.0/100 (友好) 14:30:25 - 🧠 检索到0条相关记忆 14:30:26 - 🤖 正在生成回复... 14:30:28 - 💬 张三回复: 你好!我也很高兴认识你。我是Python工程师张三... 14:30:28 - 📊 正在分析好感度变化... 14:30:30 - 📈 好感度变化: 50.0 -> 56.0 (+6.0) 14:30:30 - 原因: 友好问候 14:30:30 - 情感: positive 14:30:30 - 💾 对话已保存到张三的记忆中 14:30:30 - ============================================================ 14:30:30 - ✅ 对话完成

日志查看工具

backend/view_logs.py 提供三种子命令:

cd backend python view_logs.py tail # 实时查看(类似 tail -f,Ctrl+C 停止) python view_logs.py view # 查看今天完整日志 python view_logs.py list # 列出所有日志文件(含大小与修改时间)

不传参数时默认进入tail实时查看模式。日志系统在教学与调试中的价值在于:完整呈现"玩家输入 → 记忆检索 → NPC 回复生成 → 好感度分析 → 记忆保存"的对话流水线,验证记忆与好感度系统是否按预期工作。

后端 API 全景

backend/main.py 使用 FastAPI + Pydantic(模型定义见 backend/models.py)暴露了完整的 REST API:

方法路径说明
GET/API 信息与端点列表
GET/health健康检查
POST/chat与 NPC 对话(核心接口)
GET/npcs获取全部 NPC 列表
GET/npcs/status获取 NPC 自主对话状态
POST/npcs/status/refresh强制刷新 NPC 状态
GET/npcs/{npc_name}获取单个 NPC 详情(含当前对话)
GET/npcs/{npc_name}/memories查看 NPC 记忆
DELETE/npcs/{npc_name}/memories清空 NPC 记忆
GET/npcs/{npc_name}/affinity获取单个 NPC 好感度
PUT/npcs/{npc_name}/affinity设置 NPC 好感度
GET/affinities获取所有 NPC 好感度

/chat接口的典型请求/响应:

POST /chat Content-Type: application/json {"npc_name": "张三", "message": "你好,你在做什么?"}
{ "npc_name": "张三", "npc_title": "Python工程师", "message": "你好!我正在写代码,调试一个多智能体系统的bug。", "success": true, "timestamp": "2024-01-15T10:30:00" }

Godot 前端实现要点

场景系统与脚本分工

游戏采用 Godot 场景系统模块化组织:main.tscn(主场景)、player.tscn(玩家)、npc.tscn(NPC 通用模板,三个 NPC 均为其实例,通过@export参数区分)、dialogue_ui.tscn(对话 UI)。GDScript 语法与 Python 高度相似,对 Python 开发者几乎零门槛。

玩家控制与交互

player.gd 使用CharacterBody2D实现 WASD 移动、四方向动画切换与碰撞检测;通过add_to_group("player")注册到组,NPC 的InteractionArea检测到玩家进出时调用set_nearby_npc(),玩家按 E 键触发interact_with_npc(),再通过get_tree().call_group("dialogue_system", "start_dialogue", npc_name)通知对话系统。对话期间set_interacting(true)禁用移动。

NPC 巡逻与对话气泡

npc.gd 实现了 NPC 的自主巡逻:在出生点wander_range(默认 200 像素)范围内随机选取目标,每隔wander_interval_min~wander_interval_max(3-8 秒)更换一次目标点;update_dialogue()接收主场景下发的背景对话并显示气泡(10 秒后自动隐藏)。

API 客户端与对话 UI

api_client.gd 使用HTTPRequest节点异步通信,为对话、状态、NPC 列表分别创建独立请求节点,通过信号(chat_response_receivednpc_status_received等)通知结果,避免阻塞游戏主循环;接口地址集中在 config.gd(API_BASE_URL = "http://localhost:8000")。dialogue_ui.gd 负责对话框的显示/隐藏、富文本对话渲染与发送逻辑,并在对话框打开时屏蔽 WASD/E/空格等游戏按键防止误操作。

main.gd 作为协调中枢,每NPC_STATUS_UPDATE_INTERVAL(30 秒)拉取一次/npcs/status,将各 NPC 的自主对话分发给对应节点更新气泡。

配置 AutoLoad 单例

Project -> Project Settings -> AutoLoad中注册config.gd(名称Config)与api_client.gd(名称APIClient),即可在任何脚本中通过Config.API_CHAT/root/APIClient访问。

常见问题排查

问题检查项
后端启动失败Python 版本是否 ≥3.10、虚拟环境是否激活、依赖是否安装完整、.env是否配置正确
Godot 无法打开项目Godot 版本是否 ≥4.2、project.godot是否存在、导入目录是否正确
游戏运行但无法对话后端服务是否运行、地址是否默认http://localhost:8000、查看 Godot 控制台报错
好感度没有变化对话是否过于中性、情感分析 Agent 是否判定无需改变、LLM 响应解析是否失败(可用更明确的情感表达重试)
好感度变化过快/过慢修改relationship_manager.py中变化量范围、调整情感分析提示词、用PUT接口手动设置初始值
NPC 记不住对话检查记忆系统初始化日志、memory_data目录是否存在、必要时调低importance_threshold

总结与扩展方向

赛博小镇完整演示了"HelloAgents 多智能体框架 + FastAPI 后端 + Godot 前端"的三层技术栈协作:SimpleAgent提供 NPC 智能,MemoryManager(SQLite + Qdrant)提供两级记忆,RelationshipManager提供基于 LLM 情感分析的好感度系统,NPCBatchGeneratorNPCStateManager提供低成本的自主行为,logger.py+view_logs.py提供可视化调试。对应教材章节 docs/chapter15/第十五章 构建赛博小镇.md(英文版见 Chapter15-Building-Cyber-Town.md)给出了完整的逐步实现思路。

项目本身具备清晰的可扩展空间:接入 WebSocket 实现多人在线、为 NPC 设计基于好感度门槛的任务系统、增加 NPC 之间的互动对话、引入情绪系统、设计团队会议等动态事件,或将世界从单一办公室扩展为多场景地图。本文所有源码均可在 code/chapter15/Helloagents-AI-Town 目录下直接查阅与运行,配套的四份指南(安装配置、对话日志、好感度系统、记忆系统)可帮助你按模块逐步深入。

【免费下载链接】hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程项目地址: https://gitcode.com/datawhalechina/hello-agents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询