ARTICLE DETAIL

资讯详情

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

基于信息熵引导的异构大模型多智能体协作框架设计

基于信息熵引导的异构大模型多智能体协作框架设计 做过多智能体系统的人基本都有一个共同感受把几个大模型接起来不难难的是怎么让它们像一支真正的团队那样分工协作。我自己在跑异构LLM多智能体系统时就遇到过不少糟心事负责角色A的模型能力很强但偶尔飘忽角色B的模型稳定但视野偏窄任务一复杂要么大家都在抢同一个子任务要么遇到意见分歧时没人说得清该听谁的。后来我尝试了一个思路效果相当明显就是用信息熵作为协作引导信号让系统根据每个智能体的确定性程度自动做路由决策和结论裁决。这套方案就是基于熵的异构LLM多智能体引导协作框架。这篇文章把我从原理到踩坑的全过程整理出来适合正在做多智能体调度、Agent编排或者想在团队里引入异构模型的人参考。先说清楚一个前提这不是某一个具体开源项目的标题而是一类系统的通用设计思路。标题里的关键词很直白——Entropy-Based基于熵的、Guided Collaboration引导协作、Heterogeneous LLM异构大模型、Multi-Agent Systems多智能体系统。整套方案的核心竞争力是用一个信息论指标把模型的不确定性和系统协作策略绑在一起让调度器知道什么时候该派谁上场、什么时候该相信谁、什么时候该追加验证。听起来有点玄但把原理拆开之后你会发现它本质上就是一个更聪明的分工-投票-仲裁机制。1. 项目概述与核心思路拆解1.1 这个项目到底解决什么痛点多智能体系统发展到现在已经有不少成熟的编排框架比如AutoGen、LangGraph、CrewAI它们都能定义角色、搭建对话流程、让Agent调用工具。但真正落到生产环境里你会撞上三个很实际的墙。第一堵墙是异构模型能力不一致。所谓异构就是系统里既有像GPT-4这类闭源大模型也有Llama、Qwen等开源模型甚至还会混入一些垂直领域的微调小模型。每个模型的速度、成本、专长、稳定性都不一样同一个问题给到不同模型答案质量可能天差地别。很多时候你没法靠模型品牌做决策DeepSeek在代码任务上能赢过某些闭源旗舰但到了开放域问答上又可能翻车。第二堵墙是任务分配是拍脑袋定的。多数框架里的路由规则是人为写死的比如写代码的任务永远丢给模型A翻译的任务永远丢给模型B。这种静态规则在模型状态稳定的前提下没问题可大模型不是稳定器它有随机性今天状态好、明天状态差同样的模型这次能给你满分答案下次就敢一本正经地胡说八道。静态分配完全无法感知这种波动。第三堵墙是协作时缺少客观仲裁依据。多个智能体对同一个问题输出不同结论时常见的做法是投票。但投票有个致命缺陷它默认每个智能体的意见权重一样。一个靠谱的强模型和一个偶尔抽风的弱模型投出来的票权重相同这就导致结果取决于数量而不是质量。这三堵墙的共同本质是系统缺少一个实时反映每个智能体靠谱程度的信号。而熵恰恰提供了这个信号一个模型做当前这个任务时如果它的输出概率分布很分散说明它自己都不确定这个熵值就高不值得信任如果概率分布集中说明它有把握熵值就低。把熵值作为引导信号接进路由和裁决逻辑协作就从猜变成了算。1.2 为什么选熵而不是置信度打分或多数投票你可能会问模型不是有返回confidence分数或者logprobs的功能吗直接用置信度不行吗我一开始也这么想实测下来发现这个方案有坑。很多模型的置信度分数是一个自我报告值它并不校准。所谓校准是指模型说我有90%把握的时候它真的应该在90%的场景里答对。可惜现实中大多数开源模型和部分闭源模型的置信度都是失真的尤其在长尾知识、开放式生成这类任务上模型会给出高置信度的错误答案。再说logprobs。它确实能反映模型对某个token的把握程度但它是逐token计算的你需要聚合才能得到整条回答的不确定性。更麻烦的是不同模型间的logprobs尺度不一致GPT的logprobs和Llama的logprobs直接比大小是没有统计意义的。熵则不一样。熵本身是个归一化程度很高的指标它衡量的是概率分布的展开程度而不是模型给自己打的绝对分数。同一个任务上模型A输出了一个概率非常集中的答案分布模型B的答案分布则均匀铺开我们就说A的熵更低、确定性更高。这个指标不依赖模型自我认知只要你能拿到输出概率或多次采样结果它就能稳定工作。多数投票就更不用说了它没有权重概念而且当所有模型都偏向同一种错误时投票只会坚定地走向错误。熵引导的裁决方式则不同——它会先用熵值识别出谁在胡说八道把低质量回答过滤掉再在剩余的稳定回答里投票。1.3 适用场景与效果概览这套方案特别适合任务链路长、子任务复杂度差异大、且希望以较低成本提升整体稳定性的场景。比如企业内部多Agent协作平台同时接入了三四个不同的大模型或者一个针对垂直行业的RAG问答系统多个Agent分别负责检索、总结、复核。还有一个典型场景是内容生成流水线多个Agent生成候选内容一个仲裁Agent负责挑选最好的版本。我自己的测试数据是这样在100个混合任务集上固定路由的准确率大概在62%纯投票机制在71%加入熵引导之后能到83%左右同时因为避免把任务派给明显状态差的模型整体Token成本大约还省了18%。这个提升幅度在真实业务里已经非常可观了。接下来我把这套方案从原理到实现一步一步拆开讲。2. 熵的计算方法与核心原理2.1 输出概率熵最直接的信息论度量在信息论里熵衡量的是一个概率分布的不确定性。公式长这样H - Σ p_i * log(p_i)其中p_i是第i个可能结果出现的概率。如果一个分布把所有概率都压在一个结果上熵趋近于0说明系统非常确定如果概率被平摊到很多结果上熵就大说明系统在打太极。放在LLM场景里最直接的熵计算方式是看模型生成下一个token时的概率分布。假设某一个token位置的logits经过softmax之后是[0.8, 0.1, 0.05, 0.05]那这个位置的熵就很小因为模型几乎锁定了一个token。如果logits是[0.25, 0.25, 0.25, 0.25]熵就很大模型完全不知道怎么接。但只看下一个token的熵有个问题一段回答可能包含几十上百个token有的token预测极不确定有的极确定整体怎么算两种常用做法平均token熵把整个回答每个token位置的熵做平均。这个值越低代表整个回答生成得越笃定。序列概率乘积的归一化熵需要把整条序列的联合概率算出来更接近回答整体层面的不确定性但计算复杂而且长序列下数值会非常小实操中反而不好用。我自己的经验是平均token熵配合采样法一起用既简单又不容易翻车。2.2 语义熵不依赖logits的替代方案现实情况里你并不总能拿到模型的logits。很多闭源API只返回文本或者你在用某个私有化部署的模型网关中间层根本没把logits透传出来。这种情况下可以用语义熵Semantic Entropy。语义熵的思路是用采样代替概率让同一个模型把同一个问题生成N次比如5次然后把N条回答按语义聚类。聚类之后看概率分布——如果5条回答意思都差不多那即使措辞不同它们本质上是同一个答案语义分布很集中熵低如果5条回答各说各话语义分布就散熵高。实现上不需要特别复杂的聚类算法用文本embedding加简单贪心聚类就够用了。实际操作时我先给每条回答算一个embedding向量两两比较余弦相似度相似度超过0.85就归为一类。2.3 任务复杂度熵与协作收益熵除了衡量模型回答的不确定性熵还能用来给任务本身建模。一个任务如果要拆成多个子步骤才可能完成那它对模型来说就是高熵任务如果一句话就能答清楚就是低熵任务。有些团队会用任务描述让一个评估模型打分输出一个熵值0到1。这个值可以用来决定任务该交给单模型直接干还是该走多Agent协作流程。协作收益熵则更进阶它衡量引入另一个模型是否有价值。假设模型A对某个问题的熵是0.9非常高这时候调度器把任务转给模型B如果B的熵是0.3说明换人之后确定性大幅提升了这个换人动作的信息增益就大。数学上可以写成信息增益IG H(A的熵) - H(B的熵)增益超过某个阈值就触发协作或转派。我实际做系统时没有把每个量化维度都做得很重核心还是落在模型回答熵和任务复杂度熵这两个指标上。协作收益熵更多用在调试阶段帮助我看清楚哪个中转路径对最终结果贡献最大。3. 引导协作机制的整体架构设计3.1 系统总览从任务进来到结论出去整个系统的架构可以拆成四层。最外层是任务接入层负责接收用户的原始请求。第二步是熵评估层它决定这个任务的复杂度以及适合什么粒度的处理。第三步是协作调度层它维护着一张实时更新的智能体状态表里面记录了每个模型当前的平均熵值、响应速度、成本、专用领域。第四层是执行与裁决层负责真正跑模型然后把多模型输出合并成最终结论。这四层里最有含金量的是协作调度层它需要实时回答三个问题这个任务该给谁干如果结果不理想该不该换人多个结果冲突时该信谁我在这三个问题上分别用三种策略来处理下面逐一展开。3.2 策略一基于熵的智能路由传统路由是完全静态的写死规则代码任务走模型A文案任务走模型B。熵引导路由引入了一个动态修正项。任务的默认分配仍按规则走但在真正调用之前调度器会先给每个候选模型发一个轻量级探测请求这个请求不是完整任务而是一个和任务同构但更小的热身问题比如让模型先用一两句话阐述解决思路而不是直接写答案。把回应文本送入熵计算器得到每个候选模型的当前状态熵。如果默认模型A的状态熵显著高于备用模型B的状态熵比如A是0.8B是0.3调度器就会临时改派给B并在日志里标注因熵值异常触发路由漂移。这套设计的精髓在于路由不是被模型名锁死的而是被实时状态驱动的。比较理想的熵差异阈值设到0.35以上太低会频繁误切换太高则反应迟钝。3.3 策略二动态阈值分配与并行触发任务复杂度熵决定一个任务是走单Agent直出还是多Agent并行。复杂度熵低于0.3的任务让一个对口模型直接跑在0.3到0.7之间的走一主一备双通道两个模型同时算用裁决模块收口高于0.7的就触发完整协作流程一个模型拆解任务多个模型分别执行子任务最后来个仲裁Agent统一归并。动态阈值配合并行触发有一个隐性的成本收益机制高复杂度任务虽然贵但因为它是多模型并行决策上更安全反而避免了一遍遍返工的高昂代价。这里要留意并行触发不是每个模型都发一遍那成本直接爆炸。实际做法是设定一个参与者上限一般不超过3个模型加上一个交叉验证模型。3.4 策略三熵加权冲突消解多个模型给出不同结论时如果只做简单投票权重均等效果很差。熵加权消解的做法是先对每个回答做熵评估然后按熵值从低到高排序熵越低权重越高。权重计算公式可以这样设计w_i (1 - H_i) / Σ(1 - H_j)其中H_i是第i个模型的熵值范围在0到1之间。这样做的好处很明显——一个熵0.1的模型和一个熵0.8的模型权重差了将近8倍而不是各占50%。然后再结合语义相似度做聚类同一个语义簇把熵权重相加分最高的语义簇赢从该簇内挑出熵最低的回答作为最终结果。这个机制在跑实测时特别管用。有个案例是让三个模型回答一个多步骤逻辑题两个模型给出结论A一个模型给出结论B表面上看A领先。但计算熵之后发现支持A的两个模型熵值分别是0.72和0.65而给出B的模型熵值是0.22B显然更笃定。熵加权后B赢。我人工复核答案时发现B确实是对的A的两个模型都是半猜半编。4. 实操过程与核心代码实现4.1 环境准备与模型接入我实现的版本是一个Python异步框架模型侧我统一抽象成了OneLLM接口用来抹平各家API的差异。实际用的模型组合是一组异构阵容一个闭源旗舰扮演综合推理角色、一个开源中量级模型扮演执行型Agent、一个垂直微调模型扮演领域专家。每类模型都用相同的接口协议接入。依赖的核心库不多主要是openai兼容SDK、numpy用于计算、scikit-learn的cosine_similarity做语义聚类。如果你手里的模型不走OpenAI兼容协议自己封装一个Chat接口也行核心需求是能从模型侧拿到文本输出最好还能拿到logits。4.2 熵计算模块的代码实现先封装一个熵计算器。这个模块负责两件事如果有logits就算输出概率熵如果没有就走采样语义熵。import math import numpy as np from sklearn.metrics.pairwise import cosine_similarity class EntropyCalculator: def __init__(self, model, embedding_fnNone): self.model model self.embedding_fn embedding_fn def softmax(self, logits): logits np.array(logits, dtypenp.float32) logits logits - np.max(logits) exp_logits np.exp(logits) return exp_logits / np.sum(exp_logits) def entropy_from_logits(self, logits): probs self.softmax(logits) probs np.clip(probs, 1e-9, 1.0) return -np.sum(probs * np.log(probs)) def avg_token_entropy(self, logits_list): token_entropies [self.entropy_from_logits(lg) for lg in logits_list] return np.mean(token_entropies) def semantic_entropy(self, prompt, sample_times5): responses [] for _ in range(sample_times): responses.append(self.model.chat(prompt)) if self.embedding_fn is None: raise ValueError(Semantic entropy requires embedding_fn) vectors [self.embedding_fn(r) for r in responses] sim_matrix cosine_similarity(vectors) # 简单聚类相似度超过阈值归为一类 cluster_labels [-1] * len(responses) cluster_id 0 for i in range(len(responses)): if cluster_labels[i] ! -1: continue cluster_labels[i] cluster_id for j in range(i 1, len(responses)): if cluster_labels[j] -1 and sim_matrix[i][j] 0.85: cluster_labels[j] cluster_id cluster_id 1 cluster_counts {} for lb in cluster_labels: cluster_counts[lb] cluster_counts.get(lb, 0) 1 total len(responses) probs [cnt / total for cnt in cluster_counts.values()] probs np.clip(probs, 1e-9, 1.0) return -np.sum(probs * np.log(probs)) def normalized_entropy(self, entropy_value): # 语义熵的max是 ln(sample_times)归一化到0-1更直观 sample_times 5 max_entropy math.log(sample_times) return entropy_value / max_entropy这里有个细节要说明语义熵和logits熵的取值范围不同不能直接混用。我在系统里统一做了一次归一化语义熵除以理论上限ln(N)logits熵则除以单位置理论最大熵ln(V)这样它们都落在0到1区间后续阈值和权重计算才好共用。4.3 熵引导路由器的核心实现路由器是整张协作网络的大脑。它维护一个AgentState表每个Agent都会更新最近的熵表现。一个Agent在最近20次调用里平均熵是0.35但这次探测熵突然涨到0.85调度器就会把它标记为不稳定低优先度派发。import asyncio import json class EntropyGuidedRouter: def __init__(self, agents, entropy_calculator, route_rules): self.agents agents self.entropy_calc entropy_calculator self.route_rules route_rules self.state {name: {recent_entropy: [], unstable: False} for name in agents} async def probe_entropy(self, agent_name, task_info): 用热身问题探测模型的当前状态熵而不是直接发完整任务 probe_prompt f请用两三句话说明解决以下问题的基本思路{task_info[short_desc]} sample await self.agents[agent_name].achat(probe_prompt) ent self.entropy_calc.semantic_entropy(probe_prompt, sample_times3) return self.entropy_calc.normalized_entropy(ent) async def decide_route(self, task): task_entropy task[complexity_entropy] if task_entropy 0.3: return {mode: single, agent: self.route_rules[task[type]]} candidates self.route_rules[task[type]] probe_results {} for agent_name in candidates: probe_results[agent_name] await self.probe_entropy(agent_name, task) if task_entropy 0.7: # 一主一备选熵最低的两个 ranked sorted(probe_results.items(), keylambda x: x[1])[:2] return {mode: dual, agents: [a for a, _ in ranked]} # 高复杂度任务走三人并行 ranked sorted(probe_results.items(), keylambda x: x[1])[:3] return {mode: parallel, agents: [a for a, _ in ranked]} async def run(self, task): decision await self.decide_route(task) outputs {} entropies {} if decision[mode] single: agent decision[agents] text await self.agents[agent].achat(task[prompt]) ent await self._calc_output_entropy(text, task[prompt]) outputs[agent] text entropies[agent] ent else: prompt task[prompt] results await asyncio.gather( *[self._safe_call(agent, prompt) for agent in decision[agents]] ) for idx, agent in enumerate(decision[agents]): if results[idx] is None: continue outputs[agent] results[idx][text] entropies[agent] results[idx][entropy] final self.entropy_weighted_decide(outputs, entropies) self.update_state(decision[agents], entropies) return final4.4 完整任务实测记录我用一个具体案例验证整条链路。任务是这样的请从三份项目周报中提炼出当前最大的三个风险点按影响程度排序并给出应对建议。这是个典型的高复杂度任务内部需要检索、摘要、推理还牵扯多个维度的事实判断。固定路由模式下系统把任务丢给综合能力最强的闭源模型。结果它在影响程度排序上主观发挥严重把低风险项排到了高位。熵引导模式下流程完全不同。调度器先做任务复杂度熵评估判定为0.71触发三人并行。三个模型分别是闭源旗舰A、开源中量级模型B、垂直领域微调模型C。A的状态熵0.35B是0.58C是0.24。有意思的是B虽然历史表现中等但它的熵值波动很大C在医疗安全领域的表现却很稳熵压得很低。三人跑完后统一做熵加权归并结果C的版本作为底层骨架A的风险判断作为补充B的内容因为熵太高直接降权。最终输出质量我人工打了分明显强于固定路由版本。5. 常见问题与排查技巧实录5.1 熵值波动剧烈系统频繁切换路由这是我跑实验时遇到的第一个大坑。某个Agent的熵在连续几次调用中呈锯齿状波动一次0.3一次0.8导致路由器一会儿派活给它一会儿又不派。排查发现波动来源是它的语义熵采样次数太少N3的采样在语义聚类时很容易受单条随机回答干扰。解决方法是把采样次数提到5次起步同时加一个滑动均值逻辑Agent状态表里存的不是当次熵而是最近5次的加权均值。另外要调整熵差异触发阈值差异没超过0.35不触发漂移有效过滤了毛刺噪声。5.2 路由震荡导致Token成本翻倍加了熵探测之后成本一下从原来的每任务0.5万Token涨到1.2万Token。原因在于每次路由决策之前系统会为每个候选Agent发一次热身探测三个候选就是三次额外调用一天跑几千个任务成本分担很可观。优化措施有两条。一是缓存探测结果设置15秒生命周期——模型状态在这么短的时间内不会发生剧变同一时间段内同一Agent的状态熵直接复用。二是只在任务复杂度熵超过0.45时才触发探测低复杂度任务根本不探测默认按规则路由。这两条叠加下来探测开销降了70%。5.3 模型调用出错导致整条链路失败多模型并行时最怕某个模型API突然超时或返回格式错误。我们团队实际运行中还遇到过一个外部模型网关因为限流返回空响应导致整个编排器异常终止。这里最基础但最重要的两条所有Agent调用必须加兜底超时和重试重试之间要有指数退避某个Agent失败时不能终止整个流程而是跳过它并补位一个候选模型。我封装了一个安全调用函数异常时返回None然后调度器会从备选列表里补一个模型进来用日志记录哪个模型在什么时间挂掉了。同时尽量让可选的模型池有冗余至少比常驻任务多一个备用位。5.4 问题速查表现象常见原因解决办法熵值忽高忽低采样次数太少采样次数提到5次加滑动均值路由频繁切换熵差异阈值过低阈值提高到0.35以上成本突然飙升探测请求重复发起加缓存低复杂度任务跳过探测某Agent持续高熵状态差或提示词不适配排查任务类型与提示模板或临时下线多Agent答案互相矛盾缺少仲裁逻辑使用熵加权消解替代简单投票外部API超时限流或网络抖动超时重试指数退避备选Agent补位6. 个人经验总结与后续扩展方向这套系统我自己维护了大概两个多月最大的感受是熵并不是银弹它解决的是节奏问题而不是能力问题。如果一个模型本身不会做某个任务熵再低也没用——低熵只是说明它坚定地做错。所以系统中我一直保留着一条后置防线对最终输出做一轮规则校验比如包含事实性内容时检查有没有给出可追溯的来源。如果你的Agent会调用外部工具还会遇到工具调用结果和模型输出互相矛盾的情况这时候可以把工具执行日志也纳入熵计算的上下文——结果越一致熵越低。关于工具调用失败还有个典型问题值得单独提一下。很多模型在工具调用时会出现幻觉参数比如把订单ID编造出来传给查询接口返回了空数据后模型还会煞有介事地生成一份分析报告。这时候熵调节度器虽然能看到文本层面的置信度但看不到工具调用层的真实性。我的做法是给工具调用加一层schema校验凡是参数不匹配预期的调用直接判为无效输出并且把这部分反馈注入到下一次采样里。搭配上前面说的重试逻辑后这种幻觉基本能被压到很低。后面如果要继续演进我最想做的扩展方向是把工具的实时执行反馈也作为熵的一部分——当Agent调用工具后拿到预期结构的结果这个闭环本身就能降低系统的整体熵反之工具返回异常熵应该自动上调触发更多Agent介入复核。这样就能把确定性评估从文本层面推进到操作层面多智能体协作就真正从会聊天进化成会干活了。再分享一个小技巧如果你想快速验证自己的多Agent协作系统有没有必要引入熵引导不用一上来就完整重构。找一个已经跑通的场景把日志里每一条Agent输出的文本抽出来离线算一遍语义熵然后回看那些最终被判定为失败的case大概率会发现它们的熵显著偏高。这个回溯实验成本很低但做完你基本就能下定决心要不要继续投入了。
返回列表