当前位置: 首页 > news >正文

字节二面:Agent 路由错了,最高分那个不是该选的应该怎么办?我说:用置信度第二高的。他摇了摇头:这是拍脑袋,生产环境得靠降级机制

前段时间有个粉丝去面字节的 Agent 方向,二面面试官问了一个他觉得不太会出问题的问题:“你的多 Agent 系统里,路由分类结果置信度很低的时候怎么办?”

他想了想,说选置信度最高的那个就行。面试官追问:"那如果最高分的也是错的呢?"他说那选第二高的呗,或者加个阈值,低于多少就拒答。面试官笑了笑,说:“你这个是拍脑袋,不是设计。生产环境里靠的不是’选哪个’,而是’选错了之后怎么兜住’。”

他当时觉得面试官说的有道理,但具体怎么兜,他没答上来。回来以后他把这个问题抛到群里讨论了一圈,发现大部分人给的答案也差不多——加阈值、选次优、人工兜底——都是"事后补救"的思路,没人从系统设计的角度去想过这件事。

说实话这个问题我自己第一次做的时候也没想清楚。路由系统看起来是多 Agent 架构里最简单的一层,但真上线以后最先出事的往往就是它。今天把 Agent 路由系统的设计原则、拓扑模式、常见坑和质量评估一起讲清楚,全文比较长,建议收藏慢慢看。

Agent 路由系统设计指南:从原理到避坑

Agent 路由系统呢,是多智能体架构里的一个核心部分。它决定了一个请求最终会被哪个能力单元去处理、以什么方式去处理、出错的时候又该如何去进行兜底。下面我从设计原则、拓扑模式、避坑清单、质量评估再到落地代码,一个一个给大家讲清楚。

✦ ✦ ✦

一、为什么路由系统会成为多智能体架构的瓶颈

单 Agent 系统其实不存在什么"路由"问题。毕竟所有请求都打到同一个模型、同一套工具上面去了。但是呢,当系统拆成多个专精 Agent 之后——比如代码、检索、数据分析、客服各司其职——路由层就变成了一个新的单点。

这里有几个问题需要大家去关注。

第一个问题,路由要是搞错了,再强的下游 Agent 也救不回来。因为它根本就没拿到该处理的任务嘛。

第二个问题,路由层的延迟会叠加到整条链路的首字节时间上面去。

第三个问题,路由的可解释性直接决定了系统出错以后能不能被 debug。

所以说路由系统不是"加一个 if-else 分发"那么简单的一件事。它需要被当作一个独立的、可评估的、可降级的、可观测的子系统来进行设计。

✦ ✦ ✦

二、核心设计原则

1. 分层职责要清晰

一个好的路由系统呢,至少要分三层。每一层都应该有明确的输入和输出契约,也就是所谓的 interface contract,而不是靠隐式约定来做事情。

先来说说 Orchestrator,也就是协调层。它做的事情是任务拆解和上下文管理。具体来讲呢,它负责把一个复合任务分解成子任务、识别子任务之间的依赖顺序——哪些能并行、哪些要串行——然后维护整个会话的状态,最后把结果聚合起来。有一点很重要,不要让它直接去调工具,那是 Agent 干的事。Orchestrator 的输出应该是一个任务图,也就是 DAG,而不是一段自然语言。

{ "session_id": "sess_8821", "tasks": [ {"id": "t1", "goal": "查询用户最近的订单", "depends_on": []}, {"id": "t2", "goal": "生成退款建议", "depends_on": ["t1"]} ]}

再来说说 Router,也就是路由层。它负责的是意图识别和分发决策。输入是一个子任务加上必要的上下文摘要,输出就是"交给哪个 Agent"。路由的一个关键点是置信度。不要只返回一个选择,而是要带着分数一起返回。比如像这样:{agent: "code", confidence: 0.91}。当置信度低于阈值的时候呢,就要走降级或者人工干预。Router 应该是无状态的。也就是说同一个输入,任何时候去调用都应该得到一致的结果,或者说能够解释为什么不一致。状态管理是 Orchestrator 的责任。

最后来说说 Agent,也就是执行层。各个 Agent 各司其职,只负责自己领域内的执行,不感知其他 Agent 的存在。它对外暴露的应该是一份"能力声明",也就是 capability schema,而不是一个黑盒:

{ "agent_id": "code_agent", "description": "处理代码生成、调试、代码审查、单元测试编写", "input_schema": {"task": "string", "context_files": "array<string>"}, "tools_allowlist": ["read_file", "write_file", "run_tests"], "cost_tier": "medium", "avg_latency_ms": 4200}

这份声明既是给 Router 做语义匹配用的,也是给安全边界用的。关于安全边界的问题,后面在"坑 10"那里会详细讲到。

2. 路由策略的几种主流模式

第一种是关键词加规则路由。这种模式速度最快,可以到微秒级。它的可解释性很强,而且零模型调用成本。适合意图边界清晰的场景,比如说客服系统里"退款"“发票”"物流"这类高频明确意图。实现上通常是一棵决策树或者一组正则和关键词表:

RULES = [ (r"退款|退货|发票", "billing_agent"), (r"SQL|查询.*数据|报表", "data_agent"), (r"bug|报错|代码|函数", "code_agent"),]def rule_route(text): for pattern, agent in RULES: if re.search(pattern, text): return {"agent": agent, "confidence": 1.0, "method": "rule"} return None

不过这种模式有一个缺点。维护成本会随着规则增长而指数上升。规则之间会互相冲突、覆盖不到长尾表达,而且没法处理那种"我想查一下上个月的退款金额趋势"这种横跨两个领域的复合意图。

第二种是 LLM 分类路由。让模型输出结构化 JSON 来判断意图。适合语义模糊、长尾表达多的输入。关键是 prompt 要给每个 Agent 写清楚"适合处理哪类任务、不适合处理哪类任务"的描述。负例和正例同样重要。而且要要求输出置信度和理由。建议用 few-shot 而不是纯零样本,边界 case 的示例比规则描述更能稳定模型行为。

第三种是 Embedding 相似度路由。把每个 Agent 的能力描述向量化存入向量库,输入 query 也向量化,做最近邻检索。

agent_vecs = {aid: embed(desc) for aid, desc in agent_descriptions.items()}def embedding_route(query, threshold=0.72): qv = embed(query) best_agent, best_score = max( ((aid, cosine_sim(qv, v)) for aid, v in agent_vecs.items()), key=lambda x: x[1] ) if best_score < threshold: return {"agent": "general_agent", "confidence": best_score, "method": "fallback"} return {"agent": best_agent, "confidence": best_score, "method": "embedding"}

这种模式冷启动很友好。新增 Agent 只需要写一段能力描述、生成向量插入索引就行了,不需要去改任何 prompt 或者规则表。不过缺点是对复合意图、否定语义不敏感。比如用户说"不要用 SQL,直接给我看图"这种情况处理不好。而且阈值需要持续去调优。

第四种是性能反馈路由,也叫 Bandit 路由。前面三种都是"内容匹配"。但在实际生产中呢,同一类任务可能有多个 Agent 都能处理,谁更擅长是要靠历史数据学出来的。可以用多臂老虎机,比如 Thompson Sampling 或者 UCB,根据各 Agent 历史成功率、用户满意度反馈来动态调整路由权重。在"探索新 Agent 能力"和"利用已知最优 Agent"之间做一个平衡。不过这种方式收敛比较慢,通常作为前几种方法之上的一层动态调权,而不是单独去使用。

第五种是混合路由,这也是生产环境推荐的做法。规则先过滤意图边界清晰的高频请求,命中率通常能覆盖 60% 到 70% 的流量,而且零延迟、零成本。不确定的走 LLM 分类或者 Embedding 检索。Bandit 权重在多个候选 Agent 之间做最终裁决。超低置信度的统一走人工兜底或者澄清话术。这也是目前业界对"路由"和"分发"模式的共同认识。确定性规则负责能预判的部分,模型判断负责处理边界模糊的长尾。

3. 路由拓扑:不止"选一个 Agent"这么简单

很多人把路由简化成"从 N 个 Agent 里选 1 个"。但在实际生产系统里呢,至少存在五种拓扑。如果搞混了它们,会直接导致延迟、成本、失败模式的误判。

拓扑模式说明典型场景
Pipeline(顺序链)固定顺序的 Agent 流水线,A 的输出是 B 的输入KYC 审核、文档三段式审批
Supervisor(层级监督)一个路由或监督 Agent 在顶层做分发、收敛、决定升级或重试客服 triage、最主流的生产默认模式
Handoff(移交)Agent 之间直接把控制权和上下文整体转交给下一个 Agent,转交后原 Agent 不再参与客服从通用坐席转接到专科坐席
Fan-out / Fan-in(并行分发加聚合)同一任务并行发给多个 Agent,结果汇总后再处理同时检索加查数据库加调用计算工具
Swarm / Debate(对等协作或多角度评议)多个 Agent 平级协作或互相评议、由裁判节点合并结论多视角内容审核、复杂决策的交叉验证

Supervisor 和 Handoff 的核心区别在于控制权是否收回。Supervisor 模式下呢,任务做完结果要"返回"给协调层。Handoff 模式下控制权是单向转移的,移交后原 Agent 彻底退出,新 Agent 独立负责到底,不再向前一个 Agent 汇报。选错拓扑的常见后果是什么呢?就是该用 Handoff 的场景用了 Supervisor,导致协调层在不必要的环节里反复中转上下文,白白增加了延迟。

✦ ✦ ✦

三、常见坑和避法

坑 1:路由层做了太多业务逻辑

Router 一旦开始判断"这个代码问题是 bug 修复还是新功能",就失控了。Router 的职责只是分发,业务细分是 Agent 自己的事。保持路由层的 prompt 简短一些。描述越长越容易漂移。经验值是什么呢?单个 Agent 的描述控制在 1 到 2 句话。超过这个长度的话,往往说明这个 Agent 的职责本身该去拆分了。

坑 2:Agent 之间直接调用形成隐式耦合

Agent A 内部 hardcode 调用 Agent B,一旦 B 改接口就全链路崩溃。而且这种耦合在测试环境里很难暴露出来,通常是上线以后才炸。正确做法是什么呢?所有跨 Agent 调用都走 Orchestrator 或者消息总线。Agent 只向上汇报结果,不横向去感知彼此。如果确实需要"A 完成后必须紧接着 B"这种强依赖,应该在 Orchestrator 的任务图里显式声明依赖边,而不是让 A 在代码里直接 import 或者 call B。

坑 3:没有置信度降级机制

这个问题就是面试官当时追问的那个核心点。路由分类的置信度低于阈值的时候——经验值常取 0.6 到 0.7,需要按场景去标定——系统应该触发澄清用户意图,或者路由到通用 Agent 兜底,或者发出人工干预信号。直接选最高分的 Agent 会在边界 case 静默出错。而且这种错误往往不会报异常、不会进日志告警,只会体现为"用户体验变差但你不知道为什么"。这是最难 debug 的一类问题。

面试官说的"降级机制"是什么呢?不是简单地"选第二高的"。而是一整套链路:LLM 分类超时退回规则路由、规则没命中路由到 general_agent、连续低置信度触发人工干预。每一层都有明确的出口,而不是靠"换一个候选"来碰运气。

坑 4:上下文在路由层丢失

多轮对话中,Router 如果每次只拿到当前这一句用户输入,会忘了上文。像"那这个呢"这种指代消解失败的请求大概率被错误分类。解决方案是什么呢?Orchestrator 维护 session 上下文,每次路由的时候把摘要一起打包给 Router。注意不是全量历史,避免 prompt 过长拖慢路由速度。Router 本身不应该自己去存状态。

坑 5:工具调用没有幂等保护

Agent 重试的时候会重复执行写操作,比如发邮件、下订单、扣款。所有工具调用需要带 request_id,工具层做幂等校验。同一个 request_id 的重复调用直接返回首次结果,不重新去执行。这不是路由层本身的问题,但路由层在设计重试策略的时候必须把这个约束考虑进去。比如低置信度重新路由、Agent 执行超时后换一个 Agent 重试这些场景。否则"路由重试"会变成"业务重复执行"。

坑 6:同步调用阻塞整条链

多个独立子任务串行执行会让延迟线性叠加。能并发执行的任务——比如同时搜索加查数据库——要在 Orchestrator 层用 Fan-out 拓扑并发发出,等 gather 结果再合并。不要因为实现省事就排队执行。一个实际的经验是:先画出任务依赖图,只有真正存在数据依赖的边才需要串行,没有依赖关系的任务默认应该并行。

坑 7:Agent 能力描述写得模糊,路由长期漂移

像"general_agent:处理其他任务"这种兜底描述写多了,Router 会逐渐倾向于把不确定的请求都丢给它。尤其是 LLM 分类路由更容易这样。结果就是专精 Agent 利用率走低、general_agent 越来越臃肿。能力描述应该既写清楚"擅长什么"也写清楚"不擅长什么、和谁的边界在哪"。而且要随着 Agent 实际能力变化去同步更新。能力声明是活文档,不是建系统时写一次就不动的静态配置。

坑 8:路由决策没有可观测性,出错了无法复盘

线上某个用户反馈"问题没得到正确处理",如果路由层没有记录每次决策的输入、候选 Agent 打分、最终选择和理由,是完全没法复盘的。最低限度应该给每次路由打日志。日志里要有 trace_id、原始输入摘要、各 Agent 候选分数、最终选择、路由方法、是否触发了降级。这套日志同时也是后面"路由质量评估"的原始数据来源。

坑 9:路由层本身是单点故障,没有降级链路

如果 Router 调用的分类模型超时或者限流了,整个系统的入口就瘫了。生产系统的路由层应该有显式的降级链路:LLM 分类超时就退回规则路由,规则也没命中就路由到 general_agent 而不是直接报错。路由层的可用性目标通常应该高于任何一个下游 Agent。因为它是所有流量的必经之路嘛。

坑 10:Agent 之间没有权限隔离,安全边界缺失

如果每个 Agent 都能调用全部工具——包括发邮件、改数据库、执行代码——一旦某个 Agent 被路由到了不该处理的任务、或者被 prompt injection 误导,影响面是整个系统级别的。每个 Agent 应该只被授权它能力声明里列出的工具白名单。这就是最小权限原则。路由层在分发任务的时候也应该去校验"这个任务所需的权限是否在目标 Agent 的授权范围内",而不是无条件信任分类结果。

✦ ✦ ✦

四、路由质量怎么评估

路由系统上线以后呢,不能只靠"感觉准不准",需要有量化指标。

第一个指标,按 Agent 维度的精确率和召回率。每个 Agent 类别单独算,不要只看整体准确率。整体 90% 准确率可能掩盖了某个低频但重要的 Agent 召回率只有 50%。

第二个指标,混淆矩阵。看看哪两个 Agent 之间最容易被混淆。这往往直接指向能力描述写得不够清晰、边界重叠的问题。

第三个指标,置信度校准曲线。模型给出 0.8 置信度的预测,实际准确率是不是也接近 80%?如果置信度系统性偏高或偏低,降级阈值就是错的,需要重新去标定。

第四个指标,离线评测集加人工标注闭环。定期从线上日志里抽样,人工标注"正确的 Agent 应该是谁",回灌成离线评测集。每次改动路由 prompt 或者规则之前先跑这个评测集做回归测试。这样可以避免"改好了 A 场景却悄悄改坏了 B 场景"。

第五个指标,延迟和成本分布。规则路由几乎零成本零延迟,LLM 分类路由每次都有 token 成本和网络延迟。混合路由系统要监控"走到了哪一层"的分布。如果发现大量请求都落到了最贵的 LLM 分类兜底层,说明规则层或者 Embedding 层的覆盖率需要去提升。

✦ ✦ ✦

五、一个更完整的路由 prompt 模板

相比只给 Agent 列表的简单模板呢,生产环境的路由 prompt 通常需要加入边界说明和 few-shot 示例来稳定边界 case 的判断:

你是一个意图路由器。根据用户输入,从以下 Agent 中选择最合适的一个。- code_agent:处理代码生成、调试、代码审查、单元测试。 不处理:纯数据查询、不涉及代码的报表需求(应路由到 data_agent)。- search_agent:处理联网查询、文档检索、事实核查。 不处理:需要执行计算或访问内部数据库的任务。- data_agent:处理数据分析、SQL 查询、图表生成。 不处理:代码层面的调试,即使涉及 SQL 代码本身的语法错误。- general_agent:处理闲聊、任务规划、以及不属于以上任何一类的请求。参考示例:输入:"帮我看看这段 Python 为什么报 KeyError" → code_agent(涉及代码调试)输入:"上个月各地区销售额对比一下,画个图" → data_agent(数据分析+可视化,非代码任务本身)输入:"这个 SQL 语句报语法错误,帮我改一下" → code_agent(虽然涉及 SQL,但本质是调试代码语法,不是数据分析需求)输出 JSON,不要输出任何额外文字:{"agent": "<agent_name>", "confidence": <0-1>, "reason": "<一句话,说明为什么不是其他候选>"}用户输入:{input}会话摘要(如有):{context_summary}

置信度低于 0.65 的时候呢,在 Orchestrator 里拦截,触发澄清流程。就是向用户追问一句,而不是直接选最高分硬路由。连续两次澄清仍然低置信度的话,就转人工或者转 general_agent,同时记录为待复盘 case。

✦ ✦ ✦

六、一个可运行的混合路由示例(伪代码)

把前面讲的规则、降级、日志串起来,大致是这样一个流程:

def route(query: str, session_ctx: dict) -> dict: trace_id = new_trace_id() # 1. 规则路由优先,零成本零延迟 result = rule_route(query) if result: log_routing_decision(trace_id, query, result) return result # 2. Embedding 路由,召回候选加打分 result = embedding_route(query, threshold=0.72) if result["confidence"] >= 0.85: log_routing_decision(trace_id, query, result) return result # 3. 候选不够确定,升级到 LLM 分类路由(带 few-shot prompt 加会话摘要) try: result = llm_classify_route(query, context_summary=session_ctx.get("summary")) except TimeoutError: # 9号坑:路由层自身的降级链路 result = {"agent": "general_agent", "confidence": 0.0, "method": "fallback_timeout"} # 4. 置信度阈值兜底 if result["confidence"] < 0.65: result = trigger_clarification_or_human_escalation(query, session_ctx) log_routing_decision(trace_id, query, result) return result

这个骨架的核心思路是什么呢?便宜的方法先尝试,贵的方法只在必要时去兜底。每一层都有明确的降级出口,而且每一次决策都落日志,供后续做质量评估和 A/B 测试。

✦ ✦ ✦

总结

一句话概括:路由层要薄,Orchestrator 要聪明,Agent 要专一,工具调用要防御性编程,每一次决策都要可观测、可降级、可复盘。

具体展开来讲:

三层职责——Orchestrator、Router、Agent——要靠清晰的接口契约分开,不要靠"大家心照不宣"。

路由策略按场景混用。规则兜底高频确定意图,LLM 和 Embedding 处理长尾模糊意图,Bandit 做动态调权。不要迷信单一方法。

拓扑模式——Pipeline、Supervisor、Handoff、Fan-out、Swarm——要按任务的依赖和控制权转移方式去选。选错会直接影响延迟和失败模式。

十个坑里,半数和"边界不清"有关——职责越界、能力描述模糊、权限未隔离。另一半和"缺乏防御性设计"有关——无降级、无幂等、无可观测性。

路由系统上线以后呢,要持续用量化指标做回归评估。这些指标包括精确率、召回率、置信度校准、延迟成本分布。不要只凭线上反馈"感觉"去调整。

哪一层越界做了不属于自己的事,或者哪一层缺了降级兜底,那里就会成为系统的脆弱点。

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

http://www.jsqmd.com/news/1078651/

相关文章:

  • 工业级许可证管理器设计:从安全校验到全生命周期管理
  • IwaraDownloadTool:3分钟快速上手,高效下载Iwara视频的终极解决方案
  • 这次终于选对了!2026年最值得用的专业降AI率网站
  • Video-Downloader:一个能下载各平台视频的桌面工具
  • VibeCoding 时代,程序员应该做什么产品?——副业、变现与成本深度分析
  • 3步搭建Sunshine游戏串流服务器:跨平台游戏共享终极指南
  • 专业钣金加工厂家推荐:深圳机汇五金一站式加工服务
  • 传统RAG已经落伍了?清华大神开源的这个 rag-skill,让知识库检索直接升维
  • Agent = LLM + Harness:用Python代码跑一遍就懂了
  • 企业数字化转型 AI 智能体解决方案哪家强? 2026全球主流Agent架构实测对比与落地指南
  • 2026年程序员学量化开发,先慢下来理清规则
  • aily blockly IDE尝鲜封神,实战硬伤尽显
  • Transformer组件级工程指南:从Attention实现到显存优化
  • 反序列化漏洞:从原理到防护的深度解析
  • 数据解封装:一条网络消息,怎样从网卡走到你的程序
  • 技术实现:如何利用Sherlock.js构建自然语言事件解析解决方案
  • RAG创新了,MCompassRAG装上了语义指南针
  • Faster-Whisper-GUI技术适配突破:日语语音识别6.3倍性能提升的实现路径
  • 如何免费制作专业PPT:PPTist在线演示文稿工具终极指南
  • 对话聊天(Chatbot)
  • LangGraph图编排底层原理:状态、节点与边的工程实践
  • 蓝速科技 10.1 寸会议预约门牌:小尺寸终端的大场景智慧落地方案
  • PVE Tools终极指南:让Proxmox VE管理变得简单高效的完整工具箱
  • LLM混合架构优化:量化、剪枝与蒸馏的工程化协同
  • 近期碎片0625
  • 一个传统企业老板的自白
  • TrollInstallerX:基于双漏洞利用机制的TrollStore部署方案
  • 从CWE到CVE:构建主动安全防御体系的核心逻辑与实践
  • RuntimeError: CUDA out of memory warming up sampler with 64 dummy requests——vLLM V1 引擎 OOM 排障指南
  • 被坑惨了!TypeScript 类型体操实战:我用 3 行代码干掉了 2000 行的 if-else