公司动态
Hermes Agent多智能体编排实战:主控调度+Qwen通义千问集成
这次我们来看一个多智能体编排项目Hermes Agent。它的核心思路很直接——用 1 个主控调度 Agent 统一接收用户需求再分发给 3 个不同的子 Agent 去执行底层模型接入的是阿里云通义千问 Qwen 系列。也就是说你不再需要手动切换不同的 AI 工具只需要把任务丢给主控由它决定“这个问题该交给谁处理”。这种架构在真实项目里非常常见一个编排中心负责任务拆解和路由多个专业 Agent 分别负责代码生成、知识库问答、文档写作等具体工作。这篇文章会从零开始搭建一套可运行的 Hermes Agent 教学实现包含 1 个主控调度 Agent、3 个 Worker Agent代码 Agent、知识库 Agent、写作 Agent并演示如何接入 Qwen 通义千问 API、如何启动本地服务、如何通过接口调用整个多智能体系统。如果你关心多智能体调度、Agent 编排、Qwen 模型接入或者想在本地快速验证一套可扩展的 Agent 框架这篇文章可以直接收藏。下面按“规格速览 - 环境准备 - 安装部署 - 功能测试 - 接口调用 - 性能观察 - 问题排查”的顺序展开。1. Hermes Agent 多智能体核心能力速览能力项说明项目类型多智能体编排系统教学用轻量实现核心能力1 个主控调度 Agent 3 个子 Agent 协同工作模型接入通义千问 Qwen 系列通过 OpenAI 兼容接口调用子 Agent 类型代码 Agent、知识库 Agent、写作 Agent启动方式命令行交互启动 / FastAPI 服务启动是否支持 API支持提供 REST 接口是否支持批量任务支持可通过接口循环提交推荐硬件纯 API 调用普通 CPU 即可本地部署 Qwen 模型则需要相应 GPU 资源支持平台macOS / Linux / Windows建议使用 Python 3.10适合场景任务路由、代码生成、知识库问答、文档写作、Agent 框架学习需要说明的是这套系统的调度逻辑是我按教学目标从零实现的没有依赖重型框架。生产环境里完全可以用同样的思路替换成 LangChain、CrewAI 或自研调度中心。具体模型名、API Key 配置、依赖版本以你本机实际环境为准。2. 适用场景与使用边界2.1 这套系统适合谁如果你手头有多个 AI 任务要处理比如写代码、查资料、写文档又不想每次手动切换工具Hermes Agent 这种主控调度模式就很合适。它适合以下场景学习多智能体编排原理想快速验证“主控路由 子 Agent 执行”的完整链路。做一个私人的 AI 助手把代码问答、知识库查询、文案生成统一到一个入口。给团队搭建一个内部 Agent 服务通过 HTTP 接口接入内部工具或自动化流程。作为课程设计或技术分享的演示项目。2.2 使用边界与合规提醒这类系统本质上是把用户的输入转发给大模型再把模型输出返回。使用时有几个边界需要明确子 Agent 的输出必须经过人工复核尤其是代码和知识库问答结果不能直接用于生产环境。如果知识库中包含内部资料、用户隐私或受版权保护的内容需要确认数据来源和授权范围。不要用多智能体系统去做自动化内容灌水、批量生成违规信息或绕过平台规则的操作。敏感数据不建议直接传入云端模型 API必要时使用本地部署模型或脱敏后再处理。3. 本地部署环境准备在开始之前先检查本机环境。这套教学实现比较轻不涉及本地大模型推理所以对显卡没有硬性要求。3.1 基础环境清单依赖项要求说明操作系统macOS 12 / Ubuntu 20.04 / Windows 10命令略有差异下文会分别给Python3.10 或 3.11推荐使用 venv 虚拟环境Git可选如果从 Git 仓库拉代码需要pip最新版用于安装 Python 依赖网络可以访问阿里云百炼服务需要调用 Qwen APIAPI Key阿里云百炼 DashScope API Key需在控制台创建3.2 获取 Qwen API KeyQwen 通义千问的接口服务由阿里云百炼平台提供。大致流程是注册并登录阿里云百炼控制台。在“API-KEY 管理”页面创建一个 API Key。确认账号已开通需要使用的模型服务比如 qwen-plus、qwen-turbo、qwen-max。保存 API Key后续填入配置文件或环境变量。注意不同模型的可选范围和计费方式不同具体以百炼控制台页面展示为准。建议第一次先用 qwen-turbo 或 qwen-plus成本低、响应快适合验证调度流程。3.3 检查端口占用后文会启动 FastAPI 服务默认端口可以设为 8000。启动前先确认端口没有被占用。# Linux / macOS lsof -i :8000 # Windows PowerShell netstat -ano | findstr :8000如果端口被占用可以换一个比如 8001。4. Hermes Agent 安装部署与启动这一节我们从零创建项目骨架实现主控调度和 3 个子 Agent。所有代码都以教学示例为准你可以在此基础上继续扩展。4.1 创建项目目录mkdir hermes-agent cd hermes-agent建议创建一个 Python 虚拟环境避免污染全局环境# macOS / Linux python3 -m venv venv source venv/bin/activate # Windows PowerShell python -m venv venv venv\Scripts\activate4.2 安装依赖创建 requirements.txtopenai1.35.0 PyYAML6.0 fastapi0.111.0 uvicorn0.30.0然后安装pip install -r requirements.txt这里使用 openai 库的 OpenAI 兼容模式来调用 Qwen 接口这样代码结构清晰未来切换其他兼容服务也很方便。4.3 创建配置文件 config.yaml在项目根目录创建 config.yamlllm: api_key: ${DASHSCOPE_API_KEY} base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 model: qwen-plus temperature: 0.7 timeout: 60 orchestrator: name: 主控调度 system_prompt: | 你是多智能体系统的主控调度器。你的任务是根据用户请求 判断应该交给哪个子 Agent 处理。 可选 Agentcoder代码、knowledge知识库、writer写作。 返回结果时直接给出子 Agent 的名称和处理结果。 agents: coder: name: 代码 Agent system_prompt: | 你是资深软件工程师负责回答编程问题、生成代码、 解释技术概念、排查代码错误。 knowledge: name: 知识库 Agent system_prompt: | 你是知识库问答助手。你的职责是根据提供的参考资料 准确回答问题。如果资料中找不到答案明确说明未知 不要编造内容。 writer: name: 写作 Agent system_prompt: | 你是专业写作助手擅长撰写技术博客、工作汇报、 产品文案和总结摘要。语言简洁、结构清晰。实际运行时建议用环境变量传入 API Key避免把密钥写死在仓库里。可以执行# macOS / Linux export DASHSCOPE_API_KEY你的API Key # Windows PowerShell $env:DASHSCOPE_API_KEY你的API Key4.4 实现 Agent 基类创建 agents 目录mkdir agents创建 agents/base.py定义统一的 Agent 调用逻辑import os from openai import OpenAI class BaseAgent: 所有子 Agent 的基类封装 Qwen 接口调用。 def __init__(self, name: str, system_prompt: str, config: dict): self.name name self.system_prompt system_prompt self.model config[model] self.temperature config.get(temperature, 0.7) self.timeout config.get(timeout, 60) self.client OpenAI( api_keyconfig[api_key], base_urlconfig[base_url], timeoutself.timeout, ) def run(self, user_message: str, history: list | None None) - str: messages [ {role: system, content: self.system_prompt}, ] if history: messages.extend(history) messages.append({role: user, content: user_message}) try: resp self.client.chat.completions.create( modelself.model, messagesmessages, temperatureself.temperature, ) return resp.choices[0].message.content.strip() except Exception as exc: return f[{self.name} 调用失败] {exc}这个基类做了三件事加载配置、构造 OpenAI 兼容客户端、执行对话补全。所有子 Agent 只需要继承它并传入不同的 system prompt 即可。4.5 实现主控调度与 3 个子 Agent创建 agents/orchestrator.pyfrom .base import BaseAgent class Orchestrator(BaseAgent): 主控调度 Agent负责判断任务应该交给哪个子 Agent。 def __init__(self, config: dict, agents: dict): super().__init__( name主控调度, system_promptconfig[system_prompt], configconfig[llm], ) self.agents agents def route(self, user_message: str) - str: 简单的关键词路由生产环境可以换成更智能的分类策略。 msg user_message.lower() if any(k in msg for k in [代码, python, java, sql, debug, 报错, 函数]): return coder if any(k in msg for k in [知识库, 资料, 文档问答, 根据资料, 查询]): return knowledge return writer def dispatch(self, user_message: str, history: list | None None) - tuple[str, str]: 调度入口选择子 Agent执行并返回结果。 agent_key self.route(user_message) agent self.agents.get(agent_key) if agent is None: return unknown, 没有找到可用的子 Agent result agent.run(user_message, history) return agent_key, result创建 agents/coder.pyfrom .base import BaseAgent class CoderAgent(BaseAgent): 代码 Agent负责编程类任务。 def __init__(self, config: dict): super().__init__( name代码 Agent, system_promptconfig[agents][coder][system_prompt], configconfig[llm], )创建 agents/knowledge.pyfrom .base import BaseAgent class KnowledgeAgent(BaseAgent): 知识库 Agent负责知识库问答。 def __init__(self, config: dict): super().__init__( name知识库 Agent, system_promptconfig[agents][knowledge][system_prompt], configconfig[llm], )创建 agents/writer.pyfrom .base import BaseAgent class WriterAgent(BaseAgent): 写作 Agent负责文案和总结。 def __init__(self, config: dict): super().__init__( name写作 Agent, system_promptconfig[agents][writer][system_prompt], configconfig[llm], )注意这里为了保持示例简洁三个子 Agent 的代码结构几乎一样真正的差异在 system prompt。实际落地时知识库 Agent 内部可以加入向量检索代码 Agent 可以挂上代码执行器或静态检查工具。4.6 创建启动入口 main.py先做一个命令行交互版本方便快速验证整个链路。创建 main.pyimport os import yaml from agents.coder import CoderAgent from agents.knowledge import KnowledgeAgent from agents.orchestrator import Orchestrator from agents.writer import WriterAgent def load_config() - dict: with open(config.yaml, r, encodingutf-8) as f: config yaml.safe_load(f) api_key os.getenv(DASHSCOPE_API_KEY) if api_key: config[llm][api_key] api_key if not config[llm].get(api_key) or sk- not in config[llm][api_key]: raise ValueError(请先设置 DASHSCOPE_API_KEY 环境变量) return config def main(): config load_config() agents { coder: CoderAgent(config), knowledge: KnowledgeAgent(config), writer: WriterAgent(config), } orchestrator Orchestrator(config[orchestrator], agents) print(Hermes Agent 已启动输入任务后按回车。输入 exit 退出。) while True: task input(\n任务: ).strip() if task.lower() in {exit, quit}: break agent_key, result orchestrator.dispatch(task) print(f\n[路由到 {agent_key}]) print(result) if __name__ __main__: main()启动python main.py输入任务后主控会根据关键词把任务路由到对应子 Agent。例如输入“用 Python 写一个快速排序”系统会路由到 coder Agent返回 Qwen 生成的代码。4.7 启动 API 服务命令行模式适合验证但实际接入外部系统时需要 HTTP 接口。创建 api_server.pyimport os import uvicorn import yaml from fastapi import FastAPI, HTTPException from pydantic import BaseModel from agents.coder import CoderAgent from agents.knowledge import KnowledgeAgent from agents.orchestrator import Orchestrator from agents.writer import WriterAgent app FastAPI(titleHermes Agent API) config None orchestrator None class TaskRequest(BaseModel): task: str history: list | None None app.on_event(startup) def startup(): global config, orchestrator with open(config.yaml, r, encodingutf-8) as f: config yaml.safe_load(f) api_key os.getenv(DASHSCOPE_API_KEY) if api_key: config[llm][api_key] api_key agents { coder: CoderAgent(config), knowledge: KnowledgeAgent(config), writer: WriterAgent(config), } orchestrator Orchestrator(config[orchestrator], agents) app.post(/api/chat) def chat(req: TaskRequest): if orchestrator is None: raise HTTPException(status_code500, detail服务未初始化) agent_key, result orchestrator.dispatch(req.task, req.history) return { agent: agent_key, result: result, } app.get(/health) def health(): return {status: ok} if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8000)启动python api_server.py启动成功后浏览器访问 http://127.0.0.1:8000/health 会返回{status:ok}。5. 功能测试与效果验证部署完成后建议按以下顺序逐项测试。每项测试都给出输入示例、预期结果和判断标准。5.1 基础任务路由测试启动命令行模式后输入帮我写一段 Python 代码读取 CSV 文件并打印前 10 行预期结果系统打印[路由到 coder]然后输出 Qwen 生成的 Python 代码。判断标准路由结果是否为 coder。代码是否包含 pandas 或 csv 模块的合理用法。代码是否可以直接复制运行。5.2 知识库问答测试输入根据知识库资料说明多智能体系统里主控调度的作用是什么这里有一个需要注意的问题当前教学实现中的 knowledge Agent 内部没有实际检索逻辑它只会根据 system prompt 回答。如果要真正实现“外挂知识库”需要引入向量检索模块比如 Qwen Embedding Milvus LangChain4j 的调用链。从热词来看这也是很多人在研究的方向。5.3 写作 Agent 测试输入帮我写一段 200 字的项目周报主要内容是本周围绕多智能体调度完成了架构设计和接口联调。预期结果路由到 writer输出一篇结构清晰的周报。判断标准文本是否包含项目背景、本周进展、下一步计划等基础信息。5.4 多轮对话测试输入带历史的上文观察 Agent 是否能结合历史回答。注意当前示意代码中多轮 history 会直接透传给子 Agent但如果路由到不同子 Agent不同 Agent 之间不会共享上下文。这是多智能体系统常见的“记忆隔离”问题。实际项目里如果要让主控 Agent 记住所有子 Agent 的对话历史需要把历史统一存储在主控层每次路由时把相关历史传给目标子 Agent。5.5 批量任务测试用 API 模式跑一个批量任务循环。创建一个 batch_test.pyimport requests url http://127.0.0.1:8000/api/chat tasks [ 用 Python 写一个二分查找, 写一段商品介绍文案50 字左右, 解释一下什么是多智能体系统, ] for task in tasks: resp requests.post(url, json{task: task}, timeout120) data resp.json() print(data[agent], data[result][:100])运行python batch_test.py判断标准每个任务都返回了对应的 agent 路由标识且内容非空。如果某个任务超时需要检查模型响应时间和网络状况。6. 接口 API 与批量任务接入API 服务启动后任何支持 HTTP 请求的工具都可以接入。这里给出 curl、Python requests 和外部系统接入的示例。6.1 curl 请求示例curl -X POST http://127.0.0.1:8000/api/chat \ -H Content-Type: application/json \ -d {task: 用 Python 统计一个列表中出现次数最多的元素}返回示例{ agent: coder, result: 可以使用 collections.Counter 来实现... }需要注意实际返回内容由 Qwen 模型生成不同模型和参数下内容会不同。6.2 Python 接口调用示例import requests url http://127.0.0.1:8000/api/chat payload { task: 写一篇 200 字的技术博客开头主题是 Agent 编排, history: [] } response requests.post(url, jsonpayload, timeout120) print(response.json())6.3 批量任务队列设计在真实项目中批量任务不能简单用一个 for 循环去请求接口建议增加消息队列和任务状态管理。一个常见的方案是{ task_id: 20250201-001, agent: auto, input: 任务内容, status: pending, retry_count: 0 }由调度中心从队列取任务调用 Hermes Agent API把结果写回数据库支持失败重试和超时报警。这里的重点是任务要可追踪失败要可重试结果要可回放。7. 资源占用与性能观察7.1 API 模式资源占用纯 API 调用模式下Hermes Agent 本身只消耗少量 CPU 和内存。因为没有本地模型推理对显存基本没有要求。你可以用topLinux / macOS或任务管理器Windows观察资源占用。从实践来看真正影响体验的是网络延迟请求 Qwen API 的往返时间。模型响应速度不同模型处理长文本的速度差异明显。请求并发数同时发起多个请求时服务端和 API 端会有排队。超时设置如果任务内容很长默认 60 秒超时可能不够。7.2 本地模型模式如果要把 Qwen 模型部署到本地那就是另一套资源要求了。以 qwen-7b 或 qwen-14b 这类模型为例4-bit 量化通常需要 6GB 到 12GB 显存具体要看模型版本和推理框架。这个数字只是通用经验实际占用需要以你本机部署后的显存监控为准。本地模型的好处是数据不出内网适合敏感场景。缺点是部署和调优成本更高响应速度通常不如云端 API。7.3 如何降低延迟使用 qwen-turbo 作为默认模型处理简单路由和短文本任务。把 system prompt 精简减少无用背景信息。关闭流式输出不需要的历史记录。对知识库检索等耗时操作做缓存。批量任务并发数控制在 3 到 5 个避免瞬时打满 API 配额。8. 常见问题与排查方法问题现象可能原因排查方式解决方案启动后页面打不开服务未启动或端口被占用查看终端日志检查端口更换端口或重启服务调用 Agent 超时网络延迟、模型响应慢、超时配置过短查看日志确认请求耗时调大 timeout或换 qwen-turbo返回内容为空API Key 无效或模型未开通检查环境变量访问控制台确认模型权限重新生成 API Key开通模型服务agent execution provider did not respond in timeAgent 执行器响应超时可能是网络或模型阻塞查看调用链日志确认是哪个子 Agent 超时增加超时时间拆分更长任务安装依赖失败网络源不可用或 Python 版本过低更换 pip 源确认 Python 版本使用清华源升级 Python 到 3.10想修改 API Key 不生效配置文件被缓存或环境变量优先级不对检查 config.yaml 和 env修改后重启服务优先使用环境变量CLI 无法返回主界面程序在子菜单或交互状态输入 exit / quit 或按快捷键查看 CLI 帮助命令知识库 Agent 答非所问没有实际检索能力只靠大模型编造检查 system prompt 和资料入库逻辑接入向量检索输出参考资料引用端口冲突8000 端口被其他进程占用lsof / netstat 查看占用进程更换监听端口这里特别说一个现象agent execution provider did not respond in time。这个问题往往不是 Hermes Agent 本身的逻辑错误而是后端模型调用超时。检查顺序是网络连通性 - API Key 是否有效 - 模型是否开通 - 请求体是否过大 - 超时时间是否太短。大多数情况下调大 timeout 就能解决。9. 最佳实践与使用建议9.1 配置和密钥分离密钥不要写死在代码或配置文件里。推荐使用环境变量或密钥管理服务。上面示例中已经用了DASHSCOPE_API_KEY这个习惯建议保持到生产环境。9.2 每个 Agent 的 system prompt 单独维护随着 Agent 数量增加system prompt 会变成维护重点。建议把每个 Agent 的 prompt 放到单独的文件或配置节里方便调试和版本管理。9.3 日志比界面更重要多智能体系统调试起来比单个模型调用复杂因为一次请求可能要经过主控、路由、子 Agent 多个环节。建议每个环节都打印结构化日志{ ts: 2025-01-01T10:00:00Z, task_id: 20250101-001, route: coder, agent: 代码 Agent, prompt_len: 128, response_len: 512, cost_ms: 1200 }这样出现问题可以快速定位到具体环节。9.4 批量任务必须考虑失败重试模型接口不是百分百稳定批量任务必须有重试机制。建议规则连接超时重试 2 次。响应结果为空的请求重试 1 次。连续失败超过 3 次标记任务失败并进人工队列。每次重试间隔递增避免把接口打满。9.5 安全边界如果服务绑定在0.0.0.0意味着局域网内其他机器也能访问。在没有加鉴权之前建议只绑定127.0.0.1或者增加 Token 校验。涉及人脸、声音、版权素材、内部文档时务必确认授权范围后再进入 Agent 流程。9.6 知识库外挂的扩展方向这套教学实现里的 knowledge Agent 还比较“裸”只是让模型凭自身知识回答。真正的知识库外挂需要加一层检索把文档切片、向量化存入 Milvus 或类似的向量数据库查询时先检索相关片段再交给 Qwen 生成回答。如果你用的是 Java 技术栈可以关注 LangChain4j 结合 Qwen Embedding、Milvus 的调用方式如果是 Python 技术栈考虑引入向量检索库或 LangChain 的 RetrievalQA 链路。10. 总结与下一步这套从零实现的 Hermes Agent 多智能体系统核心价值不在于代码量而在于把“主控调度 多个子 Agent Qwen 模型接入”的完整链路跑通了。先启动 API 服务再通过接口提交任务观察主控如何路由再逐步扩展成适合自己业务场景的 Agent 平台。建议你按这个顺序继续深入先跑通命令行模式体验主控调度和 3 个子 Agent 的协作。再启动 API 服务用 curl 或 Python 脚本验证接口。接着给 knowledge Agent 加上向量检索让知识库问答真正基于资料回答。最后加入任务队列、日志和重试机制把系统工程化。最容易踩的坑有两个一个是超时设置任务一长就容易把 Agent 调用拖垮另一个是知识库 Agent 的“伪检索”没有接入真实资料库时大模型会一本正经地编造答案。建议先做好单个 Agent 的稳定性再扩展多智能体编排能力。