[控场AI]
· 6 分钟阅读· 3,469 字

LangGraph Supervisor为何这么烧Token?逐跳拆解成本真相

LangGraph Supervisor为何这么烧Token?逐跳拆解成本真相

LangGraph 多智能体架构中 Supervisor 因逐跳重读上下文导致 Token 成本反超全部 worker,需从源码级优化并逐跳度量。

文章以一个 Reddit 案例切入:某团队用 LangGraph 搭建多智能体系统,Supervisor 单节点的月度 Token 消耗竟与其旗下 8 个专家 Agent 的总和相当。根源在于 create_supervisor 的默认行为——Supervisor 会在每个 worker 完成后被重新调用一次,每次都要重读不断膨胀的共享消息列表(用户输入、路由历史、transfer messages、worker 输出)和路由提示词。由于仓库已归档且 LangChain 推荐多数场景直接用 tools 实现 supervisor pattern,文章给出五个源码级优化方向:直达当前 Agent、精简路由输入、关闭 handoff messages、保住 prefix cache、确定性意图短路,并强调应按跳度量 Token 用量而非只看月度总量。

LangGraph supervisor token cost discussion

一个 LangGraph 多智能体系统的月度 Token 账单里,Supervisor 一个节点的消耗,居然相当于它旗下全部 8 个专家 Agent 加起来的总和。这个来自 Reddit 的案例之所以值得细看,不是因为数字夸张,而是因为它戳中了多智能体架构里一个被长期忽视的成本结构问题。

多智能体架构的隐藏账单:Supervisor 为何吃掉了一半 Token

这个团队用的是 Qwen3-14B 跑在 vLLM 上,对简单场景做了确定性短路(deterministic shortcuts),路由提示词却在不断膨胀——用他们自己的话说,"我们积累了大量规则和示例来防止错误路由"。最终结果是一个相当讽刺的局面:负责"指挥"的 Supervisor,成本反超了真正干活的专家们。

问题不在模型选型,也不在 Prompt 写得好不好,而在于 create_supervisor 的默认行为决定了 Supervisor 会在每个 worker 完成后被重新调用一次。也就是说,如果 Supervisor 先派给 Agent A,再派给 Agent B,它会运行三次:第一次是初始路由,之后每完成一个 worker 就再跑一次。

create_supervisor 是 langgraph-supervisor 库提供的工厂函数,用一行代码就能把一个或多个 worker Agent 挂到一个中心 Supervisor 之下,自动生成路由逻辑、handoff 状态机和消息传递管线。它的默认参数(如 output_mode="last_message"、add_handoff_messages=True)都是为「通用可用」而非「成本最优」设计的,所以在生产环境里往往需要显式覆盖。理解默认值背后的假设——即 Supervisor 是轻量调度器、worker 是重负载执行者——是识别成本倒挂问题的前提:当路由提示词膨胀到与任务提示词同量级时,这个假设就失效了。

Token 到底耗在了哪里:逐跳拆解 Supervisor 的上下文

每次 Supervisor 被唤醒,它都要重新读一遍共享的消息列表。这个列表里堆着:

  • 用户的每轮输入
  • Supervisor 自己之前的每一次路由调用
  • 每一次交接(handoff)和返回(return)产生的一对 transfer message
  • 每个 worker 的最后一条消息,或者它停在工具调用上时的最后一次工具调用和结果(output_mode="last_message" 是默认值)

这个机制的关键在于:Supervisor 在每一跳都会运行,而它携带的历史每次都在变长。 你写进 Supervisor Prompt 的任何内容——还是那个团队的案例里,包括每个 Agent 的描述加上大量 few-shot——都会在每一次调用中完整地跟着传一遍。

Worker 在交接时同样会拿到完整历史。这才是 Token 消耗呈非线性增长的根源:不是单次调用贵,而是调用次数乘以不断膨胀的上下文。

Prefix cache(前缀缓存) 是大模型推理服务中一项关键的成本优化机制。当多次请求的 prompt 前缀完全相同时,vLLM 等引擎可以复用这部分 KV cache,跳过重算,从而大幅降低首 token 延迟和计算成本。但它的前提是前缀逐字节一致:任何插入、改动或时间戳差异都会让缓存从该点起全部失效。在多智能体场景中,Supervisor 的路由提示词通常固定放在 prompt 开头,worker 输出追加在后面,这种结构天然适合 prefix cache。反之,若在提示词顶部放一个变化的 timestamp 或动态 few-shot 示例,则每次调用都会击穿缓存,使路由成本成倍增加。

官方态度:仓库已归档,推荐直接用 tool 模式

值得关注的是,langgraph-supervisor 仓库目前已经归档。README 里明确写着,LangChain 推荐"在大多数情况下直接通过 tools 实现 supervisor pattern"。LangChain 的多智能体文档也点出了这个模式的成本:subagents 会额外增加"一次调用,因为结果要流经主 Agent 返回"。

这不是在否定 Supervisor 模式的价值,而是在提醒:当你需要一个中心调度者时,要清醒地知道它的成本结构和适用边界。 简单的任务分发用工具调用就够了,只有真正需要多轮协商、动态规划的场景才值得上完整 Supervisor。

成本优化:五个源码级可验证的修复方向

好消息是,大部分修复都很小,而且都能在源码里找到依据:

1. 让后续提问直达当前 Agent。 检测话题是否切换(用一个廉价的判断即可),没变就直接发给正在处理对话的那个 Agent,不必再绕回 Supervisor。

2. 精简路由器的输入。 给路由器只传最新用户消息加一段简短摘要,而不是整段历史。pre_model_hook 加在 Supervisor 上就能裁剪它看到的内容。

3. 关掉 transfer message 的堆积。 create_supervisor 的 add_handoff_messages=False 和 add_handoff_back_messages=False 可以把这些成对的交接消息从历史里去掉。

4. 保住 prefix cache。 确保路由 Prompt 的开头在多次调用之间保持一致。一个放在顶部的 timestamp 会破坏其后所有内容的 prefix cache。在 vLLM 上,还要确认路由器的 enable_prefix_caching 是打开的。

5. 把确定性意图拦在 LLM 之前。 那些 unambiguous intents 直接用代码处理,正如那个团队已经在做的那样。

度量比优化更重要:按跳拆解 Token 用量

看月度总量无法告诉你哪一跳最贵。LangSmith 的 trace tree 能把 Token 用量按 run 拆开;而开源项目 traceAI-langchain 是一个 OpenTelemetry instrumentor,能给每个 LangGraph 节点分配独立的 span,并在其下的 LLM 调用上记录 Token 数(前提是模型返回 usage),这样 Supervisor 的份额就能逐跳显现出来。

省 Token 之前,先搞清楚 Token 花在了哪一跳上。

LangSmith trace tree 是 LangChain 官方可观测性平台的核心视图,它把一次完整请求展开为树状结构:根节点是顶层 Agent 调用,子节点是每一次 LLM 调用、工具调用和节点跳转,每个节点都附带 Token 用量、延迟和输入输出。对于 Supervisor 架构,这意味着你可以直接看到「初始路由」和「worker 完成后回看」各自消耗了多少 Token,而不是被月度总计掩盖。traceAI-langchain 则是开源替代方案,通过 OpenTelemetry 的 instrumentor 机制,为每个 LangGraph 节点生成独立 span,并在其下的 LLM 调用上记录 usage 字段(需要模型侧返回该字段)。两者都能把 Token 消耗从「总量黑盒」变成「逐跳明细」。

一个留给生产环境的问题

原文最后抛出了两个问题,值得每个跑 Supervisor 的人自问:

你的 Supervisor 真的需要在每个 worker 完成后再看一眼吗?还是可以把最终答案直接送到 END?

以及:裁剪 few-shot 之后,你的路由准确率有没有掉?

这两个问题没有标准答案,取决于你的任务复杂度。但如果你的 Supervisor 成本已经超过所有专家之和,那大概率是时候重新审视这个架构选择了。

#LangGraph Supervisor#多智能体架构#Token成本优化#langgraph-supervisor#LLM路由#vLLM prefix caching#OpenTelemetry
分享:

相关推荐