我们的业务场景不适合"每个Agent封装一个LLM调用"的常规模式,我们从消息总线、并发调度、职责划分三个维度,构建一套轻量级的多Agent协同系统。

一、问题定义:单Agent架构的三个局限性

TFT战术顾问的第一版采用单LLM调用模式:将阵容数据与用户问题拼接为prompt,直接请求大模型生成分析结果。该方案上线后,暴露出三个结构性问题:

第一,分析深度不足。 单个prompt需同时覆盖经济运营、阵容战力、站位布局三个维度,大模型倾向于对每个维度给出概括性描述,难以深入展开。该现象的本质是注意力分散——当prompt中同时存在多个异构任务时,模型对每个任务的token分配与推理深度呈反比。

第二,思维模式冲突。 三类分析对应三种不同的推理路径:经济运营是时序决策问题(何时升人口、何时D牌),战力分析是组合优化问题(羁绊激活层级、装备分配效率),站位分析是空间配置问题(前后排比例、主C保护)。将三种异质推理路径压缩到单一prompt中,导致模型在各模式间频繁切换上下文,输出的一致性和专业性均受影响。

第三,维度间存在信息依赖。 游戏阶段的判断(早期/中期/后期)直接影响装备建议的优先级阈值——早期仅对4费及以上缺装英雄预警,后期则需将阈值降至3费。类似地,战力分析的结论(哪些主C缺乏装备)应传递至站位分析模块,生成针对性的保护站位建议。单prompt方案无法在推理过程中显式建模此类跨维度依赖关系。

二、架构选择:非LLM驱动的Agent设计

当前主流多Agent框架(LangChain Agent、CrewAI、AutoGen等)普遍采用"Agent即LLM调用"的设计范式:每个Agent封装独立的prompt与工具集,Agent间通过自然语言文本传递信息。该范式在以下场景存在明确优势:任务需要语义理解、创造性推理或处理非结构化信息。但在TFT战术分析场景中,其面临三个适配性问题:

  1. 延迟叠加:串行LLM调用的网络往返时间线性累积,三个Agent三轮调用的总延迟远超用户可接受范围。
  2. 成本倍增:每个Agent独立调用LLM,token消耗随Agent数量线性增长。
  3. 信息密度低:Agent间通过自然语言传递结构化信号(如"当前处于游戏后期"),产生大量冗余token,属于典型的信道容量浪费。

基于上述分析,本项目采用了一种替代方案:将三个子Agent实现为纯Python规则引擎,唯一的LLM调用位于主协调器层面。该方案的核心假设是——TFT战术分析中的多数子任务属于确定性推理(规则计算、阈值判断、比例统计),无需LLM级别的语义理解能力。LLM的角色被重新定位为"表达层":将结构化的分析结论转化为面向用户的自然语言建议,结合RAG检索到的高端局参考数据,生成有上下文的战术指导。

架构示意如下:

该架构的设计原则可归纳为:将分析逻辑拆分为职责单一的微推理单元,以确定性代码实现各单元的核心逻辑,通过消息总线管理单元间的数据依赖,LLM仅负责最终的结论融合与自然语言生成。

三、AgentBus:消息总线的设计决策

Agent间通信存在多种可选方案:引入外部消息中间件(Redis Pub/Sub、RabbitMQ)、使用Python标准库的Queue模块、或自行实现轻量级总线。对于单进程桌面应用而言,外部中间件引入不必要的运维复杂度,而Queue模块的单一消费者模型与广播需求不兼容。最终实现了一个基于threading.Lock保护的发布-订阅总线,核心代码约45行。

3.1 推送与拉取的混合策略

publish()方法执行两个原子操作:将消息写入目标Agent的邮箱(拉取模式),同时同步触发所有匹配消息类型的已注册回调函数(推送模式)。两种模式的组合基于以下考虑:

三个Agent的run()方法在ThreadPoolExecutor中并发执行,消息发布的时序与Agent内部执行进度的相对顺序不确定。如果仅采用邮箱模式(拉取),存在以下情况:EconomyAgent完成分析并发布phase_result消息时,PowerAgent尚未执行到读取self._phase的代码段,消息在邮箱中处于未消费状态,PowerAgent可能基于默认值完成分析。回调机制消除了该时序依赖——无论Agent内部的执行进度如何,_on_phase回调在消息发布时立即更新PowerAgent的状态变量。

3.2 同步回调的取舍

回调函数在publish()的调用线程中同步执行,而非启动独立线程异步执行。该决策基于两点分析:

优势:在低延迟、单生产者场景中,同步回调保证了消息处理顺序与发布顺序严格一致。若采用异步回调,EconomyAgent连续发布两条消息时,回调的执行顺序可能因线程调度而乱序,导致后续Agent的状态更新出现不一致。

代价:若回调函数执行时间过长,会阻塞发布者线程。在本项目中,每个回调仅执行一次字典取值与属性赋值(self._phase = msg.payload.get("phase")),耗时在微秒量级,该代价可忽略。

3.3 订阅关系的静态设计原则

Agent间的订阅关系遵循两条约束:

  1. Agent间无直接引用——所有通信通过Bus中介,Agent仅持有Bus引用与自身名称。
  2. 订阅关系在构造阶段确定,运行期不变——避免了动态订阅引入的调试复杂度与潜在的内存泄漏风险。

实际的订阅拓扑为单向链式结构:

EconomyAgent ──[phase_result]──▶ PowerAgent._on_phase()
PowerAgent   ──[power_result]──▶ PositionAgent._on_power()

该拓扑的一个重要性质是单向依赖:EconomyAgent不感知PowerAgent的存在,PowerAgent不感知PositionAgent的存在。每个Agent仅负责"发布自身结论"与"订阅所需的前置信息"两个行为。该设计使得新增Agent的边际修改成本极低——例如,若要新增一个ItemAgent分析装备合成路径,只需让其订阅PowerAgent的相关消息,无需修改现有Agent的任何代码。

四、LLM的角色再定位

架构中最关键的设计决策是将LLM从"推理引擎"重新定位为"表达引擎"。三个子Agent均不调用LLM,它们的分析结论是结构化规则计算的确定性输出。唯一的LLM调用发生在TFTRagAgent.recommend()方法中,其输入由四部分组装:

  • system_prompt:格式化后的系统指令,含输出格式约束(四个强制章节)
  • team_summary:当前阵容的结构化描述
  • sub_agent_reports:三个子Agent的融合分析报告
  • rag_context:BM25检索返回的Top-6 KR服务器高端局参考数据

该设计的合理性基于以下论证:

第一,规则计算与LLM推理的能力边界分析。 "前排少于2个"、"平均星级低于1.5"、"羁绊距下一阶还差N个棋子"——这类判断属于确定性计算,规则引擎的执行结果零延迟、零token成本、100%准确。LLM在执行同类计算时不仅消耗token,还存在输出不稳定(同一输入多次调用可能产生不同表述)的问题。将确定性推理分配给规则引擎,是对各组件能力边界的合理划分。

第二,"最后一公里"问题的分解。 规则引擎可以输出"前排数量不足",但无法生成"建议将瑟提部署于第一排中央位置,搭配日炎斗篷承担主要伤害"这类结合游戏机制的上下文建议。这是LLM的核心价值所在——将离散的结构化结论转化为连贯的、可操作的战术指导。

第三,成本效率。 三个子Agent的分析过程token消耗为零。整个多Agent框架的额外边际成本为零,总的LLM调用次数与单Agent方案完全一致。该架构在不增加推理成本的前提下,通过结构化分解提升了分析的深度与专业性。

五、与主流框架的对比分析

维度 LangChain / CrewAI 范式 本项目方案
Agent定义方式 LLM + prompt + 工具集 Python规则引擎 + 总线接口
Agent间通信 自然语言文本 结构化数据报(AgentMessage dataclass)
调度拓扑 有向无环图(DAG) 线程池并行 + 回调驱动
LLM调用次数 N × M(N个Agent,M轮交互) 1次(仅融合阶段)
推理延迟 串行LLM调用的累加和 子Agent并发毫秒级 + LLM单次调用
输出可控性 依赖prompt质量,存在随机性 规则引擎输出100%确定
适用场景 需语义理解、创造性推理 可规则化的确定性分析
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐