ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零构建多智能体协作系统:基于AI Town项目的实践指南

从零构建多智能体协作系统:基于AI Town项目的实践指南 在实际 AI 应用开发中我们常常面临一个核心矛盾如何让 AI 模型不仅理解指令还能在特定场景下进行持续、自主的交互与协作甚至像人类一样拥有“记忆”和“目标”传统的单次问答模型如基础的聊天机器人难以胜任需要长期状态维护和多步骤决策的任务。这正是AI Agent智能体概念兴起的原因。它不是一个具体的模型而是一种架构范式旨在赋予 AI 系统感知、规划、决策和行动的能力使其能在复杂环境中完成目标。本文将围绕一个名为“AI Town”的开源项目深入探讨如何从零开始构建一个可运行的、支持多智能体协作的模拟环境。这个项目提供了一个绝佳的实践样本让我们能直观理解智能体的核心组件——如记忆、对话、行动规划是如何通过代码实现的以及如何利用现有的大模型如 OpenAI GPT、本地模型作为智能体的“大脑”。通过复现和剖析这个项目开发者可以掌握 AI Agent 开发的关键技术栈、常见设计模式并理解如何将 Spring AI、本地模型集成等热门技术应用于实际场景中。1. 理解 AI Agent 的核心架构与“AI Town”项目在深入代码之前必须厘清 AI Agent 的基本构成。一个典型的智能体通常包含以下几个核心模块感知模块接收来自环境用户输入、系统事件、其他智能体消息的信息。记忆模块存储智能体的历史交互、知识、目标和状态。这是实现持续对话和长期规划的基础。决策/规划模块基于当前感知和记忆决定下一步要执行的动作或要输出的内容。这通常由一个大语言模型驱动。行动模块执行决策例如调用一个工具函数、生成一段回复、修改环境状态等。学习模块可选根据行动的结果反馈更新记忆或策略。“AI Town”项目正是上述架构的一个生动实现。它是一个虚拟小镇的模拟镇上的居民智能体拥有自己的身份、记忆和目标他们可以彼此交谈、形成关系、执行日常活动。项目的核心价值在于它提供了一个完整的、可扩展的框架而非一个封闭的演示。通过研究其代码我们可以学习到智能体状态管理如何用数据结构如AgentState来封装记忆、当前对话、目标等信息。动作系统如何定义智能体可执行的动作如SayMove并设计路由逻辑让 LLM 选择合适的动作。记忆与检索如何存储大量的交互历史并在决策时快速检索出相关记忆。环境模拟如何设计一个“世界”状态GameState并驱动所有智能体并行或顺序运行。与 LLM 集成如何将 OpenAI API 或本地模型封装成统一的接口供智能体的决策模块调用。理解这些概念后我们就能带着明确的目标去配置和运行项目而不是盲目地执行命令。2. 环境准备与项目初始化“AI Town”是一个基于 TypeScript/JavaScript 的全栈项目前端使用 React后端使用 Convex一个集成了数据库、函数和实时功能的 BaaS 平台。为了顺利运行我们需要准备以下环境。2.1 系统与工具要求请确保你的开发环境满足以下最低要求组件要求检查命令备注Node.jsLTS 版本 (如 18.x, 20.x)node --version运行 JavaScript/TypeScript 的基石。npm通常随 Node.js 安装npm --version用于管理项目依赖。Git最新稳定版git --version用于克隆项目代码。Convex 账户免费注册-项目后端依赖 Convex 云服务。OpenAI API Key或本地模型配置-为智能体提供“大脑”。免费账户有额度限制。注意如果你打算完全使用本地模型如通过 Ollama 运行 Llama 2则需要额外配置本地模型服务并修改项目的 LLM 调用代码。本文主要基于 OpenAI API 进行说明因为这是项目默认且最易上手的配置。2.2 获取项目代码并安装依赖首先从 GitHub 克隆项目到本地。# 克隆项目仓库 git clone https://github.com/mewamew/my_ai_town.git # 进入项目目录 cd my_ai_town项目根目录下通常包含client/前端、convex/后端函数和数据库模式、scripts/工具脚本等文件夹。接下来安装所有必要的依赖。# 安装项目根目录及子目录所需的依赖 npm install这个过程可能会花费几分钟取决于网络速度。安装完成后你的项目结构应大致如下my_ai_town/ ├── client/ # React 前端应用 ├── convex/ # Convex 后端函数、数据库 schema、动作定义 ├── scripts/ # 辅助脚本如初始化智能体 ├── package.json ├── .env.local # 环境变量配置文件需要手动创建 └── README.md2.3 配置环境变量与 Convex项目运行依赖于两个关键配置OpenAI API Key 和 Convex 部署环境。创建环境变量文件在项目根目录下创建.env.local文件。这个文件用于存储敏感信息不应提交到 Git。# 在项目根目录执行 touch .env.local配置 OpenAI API Key打开.env.local文件添加你的 OpenAI API Key。# .env.local OPENAI_API_KEYsk-your-actual-openai-api-key-here重要将sk-your-actual-openai-api-key-here替换为你从 OpenAI 平台获取的真实密钥。密钥前缀为sk-。初始化并部署 Convex访问 Convex 官网 注册并登录。在 Dashboard 中创建一个新项目Project例如命名为ai-town。按照 Convex 的指引在本地项目目录下运行其 CLI 命令进行链接和部署。# 安装 Convex CLI如果尚未安装 npm install -g convex # 登录 Convex convex login # 将本地项目链接到云端项目会提示你选择刚创建的项目 convex dev运行convex dev命令后CLI 会自动检测项目引导你完成链接并开始一个本地开发环境。它还会在.env.local中自动添加CONVEX_DEPLOYMENT变量。首次部署可能需要一些时间。3. 核心代码解析智能体如何运作配置好环境后我们来深入代码看看“AI Town”的智能体是如何被构造和驱动的。理解这部分是自定义和扩展项目的关键。3.1 智能体状态定义 (AgentState)在convex/schema.ts或类似的文件中定义了智能体的核心数据结构。这相当于智能体的“记忆体”。// 示例代码基于项目思想简化 interface AgentState { id: Idagents; // 智能体唯一ID name: string; // 名字如“咖啡师Alice” identity: string; // 背景描述用于塑造性格 plan: string; // 当前目标如“为顾客做一杯拿铁” memory: string; // 浓缩的记忆摘要记录重要经历 // 可能还包括位置、与其他智能体的关系等字段 }这个AgentState对象会被持久化在 Convex 的数据库中。每当智能体执行一个动作或进行一场对话后这个状态就会被更新。记忆memory字段是精髓它不是一个完整的聊天记录而是经过提炼的、对智能体认知最重要的信息摘要这解决了直接存储全部历史带来的 token 长度和相关性检索问题。3.2 动作系统与决策循环智能体的“思考-行动”循环在convex/agent/目录下的文件中实现。核心流程如下感知系统一个定时任务或世界模拟器从数据库中获取一个智能体的当前AgentState和周围环境信息如附近的其他智能体、地点对象。生成提示词系统根据状态和环境构造一个详细的提示词Prompt发送给 LLM。这个提示词通常包含identity: 你是谁。memory: 你记得什么。plan: 你当前要做什么。recent events: 刚刚发生了什么。available actions: 你现在可以做什么如说话、移动、使用物品。LLM 决策LLM 根据提示词生成一个结构化的响应。这个响应被解析为一个具体的动作Action例如{ action: “say”, content: “你好今天天气真不错” }。执行动作后端接收到这个动作描述执行相应的函数。如果是say就将对话内容写入数据库如果是move就更新智能体的位置。更新状态动作执行后会产生新的结果和观察。系统再次调用 LLM让它根据新的观察来更新memory和plan字段然后将新的AgentState写回数据库完成一个循环。// 伪代码展示决策循环 async function runAgentStep(agentId: Id“agents”) { // 1. 读取状态和环境 const state await db.get(agentId); const surroundings await getSurroundings(state.location); // 2. 构造决策提示词 const decisionPrompt buildDecisionPrompt(state, surroundings); // 3. 调用 LLM 获取动作 const actionResponse await callLlm(decisionPrompt); // 例如: “{“action”: “say“, “args”: {“content”: “Hello”}}” const action parseAction(actionResponse); // 4. 执行动作 const actionResult await executeAction(action, agentId); // 5. 构造状态更新提示词 const updatePrompt buildMemoryUpdatePrompt(state, action, actionResult); // 6. 调用 LLM 更新记忆和计划 const newMemoryAndPlan await callLlm(updatePrompt); // 7. 保存新状态 await db.update(agentId, { memory: newMemoryAndPlan.memory, plan: newMemoryAndPlan.plan, // ... 其他字段 }); }3.3 与 LLM 的集成项目通过抽象层来调用 LLM。在convex/lib/llm.ts或类似文件中你会看到一个统一的callLlm函数它内部根据配置决定是调用 OpenAI 的接口还是本地的模型服务。// 简化示例 import { OpenAI } from “openai”; const openai new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); export async function callLlm(messages: Array{role: string, content: string}, model: string “gpt-4”): Promisestring { const completion await openai.chat.completions.create({ model: model, messages: messages, temperature: 0.7, // 控制创造性 }); return completion.choices[0].message.content; }如果你想切换为本地模型例如使用 Ollama只需修改这个函数将其指向本地服务的端点。// 切换到本地 Ollama 服务的示例 export async function callLlm(messages: Array{role: string, content: string}, model: string “llama2”): Promisestring { const response await fetch(“http://localhost:11434/api/chat”, { method: “POST”, headers: { “Content-Type”: “application/json” }, body: JSON.stringify({ model: model, messages: messages, stream: false, }), }); const data await response.json(); return data.message.content; }4. 运行与验证项目当环境和代码理解到位后就可以启动项目并观察智能体的行为了。4.1 启动开发服务器在项目根目录下运行以下命令来同时启动前端开发服务器和后端 Convex 开发环境。npm run dev这个命令通常会做两件事启动 Convex 的本地开发服务器和同步进程。启动 React 前端开发服务器通常运行在http://localhost:3000。控制台会输出相关的访问地址和日志信息。确保没有报错特别是关于OPENAI_API_KEY缺失或 Convex 认证失败的提示。4.2 初始化世界与智能体首次访问前端页面 (http://localhost:3000) 时小镇可能是空的。你需要运行项目提供的初始化脚本来创建初始的智能体和世界状态。# 通常项目会提供一个种子脚本 npm run seed # 或者通过 Convex Dashboard 运行一个初始化 mutation 函数执行成功后刷新前端页面你应该能看到一个带有几个智能体居民的小镇地图。每个智能体旁边可能会显示其名字和当前状态如“正在公园散步”。4.3 观察与交互在前端界面你可以观察智能体会自动根据其目标和记忆开始行动和对话。你可以看到对话气泡在地图上出现。查看日志打开浏览器的开发者工具F12中的“网络”或“控制台”标签页可以看到前端与 Convex 后端之间的实时数据流其中包含了智能体动作和状态更新的信息。数据库洞察登录 Convex Dashboard进入你项目的数据库页面可以实时查看agents表等数据的变化直观看到memory、plan字段是如何被更新的。一个成功的运行标志是智能体们在没有用户干预的情况下能够持续地进行符合其身份的、有逻辑的对话和活动并且他们的memory字段会随着时间推移而演进。5. 常见问题排查与调试在运行“AI Town”这类复杂 AI 应用时你可能会遇到以下典型问题。这里提供系统的排查路径。5.1 智能体不行动或“发呆”现象可能原因检查与解决步骤前端地图上的智能体静止不动无对话气泡。1. 后端模拟引擎未启动。2. LLM 调用失败。3. 数据库初始状态错误。1.检查后端日志在运行npm run dev的终端或 Convex Dashboard 的日志中查看是否有定时任务如runAgentStep在执行以及是否有报错。2.检查 LLM 连接查看日志中是否有 OpenAI API 调用超时、认证失败错误码 401或额度不足错误码 429的报错。确认.env.local中的OPENAI_API_KEY正确无误。3.检查数据库在 Convex Dashboard 中查看agents表确认是否有数据且plan字段非空。运行npm run seed重新初始化。5.2 对话内容无意义或循环重复现象可能原因检查与解决步骤智能体对话脱离设定身份或反复说同样的话。1. 提示词Prompt设计不佳。2. LLM 温度temperature参数过低。3. 记忆更新机制失效。1.审查提示词模板查看convex/agent/prompts.ts等文件中的提示词。确保identity、plan的描述足够清晰有力能引导 LLM 扮演角色。2.调整 LLM 参数尝试在callLlm函数中提高temperature如从 0.7 调到 0.9以增加随机性或降低temperature如调到 0.3以增加确定性。3.检查记忆流在数据库中跟踪一个智能体的memory字段变化。如果它从不更新问题可能出在“更新记忆”的 LLM 调用步骤或提示词上。5.3 性能问题与 API 费用消耗过快现象可能原因检查与解决步骤应用运行缓慢或 OpenAI API 费用激增。1. 智能体数量太多循环频率太高。2. 提示词过长导致每次调用 token 数巨大。3. 使用了更昂贵的模型如 GPT-4。1.控制模拟规模减少初始智能体数量修改种子脚本或降低模拟步进的频率调整定时任务间隔。2.优化提示词精简提示词移除不必要的描述。确保memory字段是摘要而非全文历史。3.降级模型或使用本地模型在开发阶段将callLlm的默认模型改为gpt-3.5-turbo。对于长期运行考虑集成本地大模型如通过 Ollama 运行 Mistral、Llama 2这能彻底消除 API 费用。5.4 前端无法连接后端Convex现象可能原因检查与解决步骤前端页面白屏或报错 “Failed to fetch”。1. Convex 项目未正确链接或部署。2. 环境变量CONVEX_DEPLOYMENT缺失或错误。3. 网络问题。1.确认 Convex 状态运行convex status查看当前链接的项目和部署状态。运行convex deploy确保最新代码已部署。2.检查环境变量确认.env.local文件存在且其中包含由convex dev自动生成的正确CONVEX_DEPLOYMENT值。重启开发服务器。3.检查 Convex Dashboard登录 Dashboard确认项目处于 “Active” 状态且没有报错。6. 扩展方向与最佳实践“AI Town”项目是一个强大的起点你可以基于它进行深度定制和扩展以构建更复杂的 AI Agent 应用。6.1 扩展智能体能力增加新动作在convex/actions/目录下创建新的动作函数如trade.ts交易、craft.ts制作并在智能体的可用动作列表中注册。同时需要更新决策提示词告诉 LLM 有这个新选项。丰富环境交互在数据库 schema 中增加objects物品表让智能体可以感知并操作环境中的物品如“拿起一本书”、“打开电脑”。实现更复杂的记忆当前项目使用了简单的文本摘要记忆。可以引入向量数据库如 Pinecone、Chroma将记忆片段向量化存储实现更精准、更长期的相关性检索。6.2 集成本地大模型对于需要控制成本、保障数据隐私或进行深度定制的场景集成本地模型是必经之路。搭建本地模型服务使用 Ollama 或 LocalAI 在本地运行一个开源大模型如 Llama 2、Mistral、Qwen。修改 LLM 调用层如前文代码示例所示将callLlm函数中的请求目标从api.openai.com改为本地服务的端点如http://localhost:11434。调整提示词不同模型对提示词的格式和风格响应不同。可能需要为本地模型微调提示词模板以达到与 GPT-3.5/4 类似的效果。6.3 应用于实际场景的思考将“AI Town”的架构模式迁移到实际项目例如客服助手、游戏 NPC、自动化工作流引擎时需注意状态设计仔细设计你的AgentState它应包含业务所需的所有关键上下文。避免将临时信息与长期记忆混在一起。动作边界清晰定义智能体能做什么动作不能做什么。动作的执行函数必须健壮做好错误处理避免因单个动作失败导致整个智能体崩溃。提示词工程这是智能体表现好坏的关键。投入时间精心设计系统提示词System Prompt明确角色、规则、输出格式。使用少样本Few-shot示例来引导模型输出更稳定的结构化数据。成本与延迟监控在生产环境中务必记录每次 LLM 调用的 token 消耗和耗时。设置告警防止因意外循环或提示词膨胀导致成本失控。评估与测试建立一套评估体系测试智能体在关键场景下的表现。这可以是人工检查也可以是自动化的单元测试如给定固定输入检查输出是否包含特定关键词或符合某种格式。通过“AI Town”这个项目我们不仅看到了多智能体协作的生动演示更获得了一个可拆解、可学习、可扩展的工程范本。从配置环境、理解数据流到调试问题、规划扩展每一步都对应着 AI Agent 开发中的真实挑战。下一步你可以尝试修改一个智能体的身份和目标观察其行为变化或者尝试集成一个本地模型感受不同“大脑”带来的差异。这些实践远比阅读理论更能加深对 AI Agent 架构的理解。
返回列表