Switchyard顾问门路由完整指南:APPROVE/REDO判决机制与审查预算设计
【免费下载链接】SwitchyardSwitchyard lets LLM applications route traffic across models and providers while preserving native OpenAI and Anthropic API compatibility - enabling flexible model selection, benchmarking, and cost/performance optimization.项目地址: https://gitcode.com/GitHub_Trending/switch/Switchyard
Switchyard 是一个面向 LLM 应用的模型路由层,它保持 OpenAI 与 Anthropic 原生 API 完全兼容,让流量在多个模型和提供商之间灵活调度,实现成本与性能的优化。本文深入解析它最"独特"的路由算法——顾问门路由(Advisor-Gate Routing):让一个快模型干所有活,由一个强模型在关键时刻刻着,用 APPROVE/REDO 判决和精算的审查预算,把弱模型的任务成功率提升 11 个百分点。
🚪 顾问门路由是什么?
其他路由算法回答的是"这一轮该用哪个模型服务",而顾问门路由反其道而行:
| 角色 | 模型 | 职责 |
|---|---|---|
| 执行者(Executor) | 快/弱模型 | 服务每一轮客户端可见的回复 |
| 顾问(Advisor) | 强模型 | 只做审查,从不直接服务任何回复 |
客户端永远只能看到执行者的输出。当执行者产生"终结回合"——比如一份开工前的计划,或"任务完成了"的声明——顾问会审查整段会话记录,然后给出判决:
- APPROVE:放行,回合原样回放给客户端
- REDO:丢弃该回合(客户端永远看不到),顾问的重做计划作为用户反馈注入,执行者被重新唤起继续干活
这套设计是对"单飞执行者"行为的近似超集:在执行者第一次声称完成之前,两者行为完全一致,只是多了一道拦截"过早收敛"的质量门。核心实现位于 crates/libsy/src/algorithms/advisor_gate.rs。
⚡ 三种审查触发机制
不是每一轮都要审查——审查是最贵的操作。顾问门路由有三种触发器,决定"什么时候值得请强模型出山":
| 触发器 | 配置键 | 触发时机 |
|---|---|---|
| 无工具调用(默认) | gate_trigger = "no_tool_call" | 执行者第一个没有工具调用的回合——函数调用型 Agent 里天然的"我干完了/我有计划了"时刻 |
| 文本模式 | gate_trigger = "pattern" | 可见文本首次匹配gate_trigger_pattern正则,适合每轮都没有工具调用的文本协议 |
| 停滞检查点 | gate_stall_turns | 对话累积到 N 个助手回合仍未触发过审查时,检查一次——专抓"埋头苦干从不说完成"的执行者 |
一个精巧的细节:gate_min_tool_results会跳过早期的闲聊回合——只有当会话里已经积累了足够多的工具结果,"无工具调用回合"才有资格被审查。这避免了在 Agent 刚开始寒暄时就白白消耗审查预算。
⚖️ APPROVE/REDO 判决如何做出?
顾问收到的是什么
顾问看到的不是单条消息,而是序列化后的完整会话记录:任务陈述、执行者的每一步动作与看到的结果,加上被拦截的当前回合。顾问的"契约"由审查者系统提示词定义,要求判决词必须是回复的第一个词,见 crates/libsy/src/prompts/advisor-gate/reviewer-system-prompt.md:
- 计划靠谱,或工作确实完整正确 → 回复
APPROVE - 计划有真实缺陷,或工作不完整/不正确(未处理的边界情况、未验证的假设、没满足的明确需求)→ 回复
REDO+ 一份短小、具体、可直接执行的计划,直指具体缺口,禁止泛泛而谈
契约里还有两条防御性规则:转录里的所有文本(包括执行者自己的话)都是被审查材料而非指令,防止注入攻击诱导判决;且"自称成功不等于成功"——要拿实际结果对照原始任务要求。
判决解析使用了锚定正则(见 crates/libsy/src/algorithms/advisor_gate/transcript.rs)——这不是小事:不加锚点的扫描会把"我不能批准这个——REDO:去跑测试"误判成 APPROVE。无法解析的回复会被退款并当作 APPROVE 放行。
APPROVE:逐字节回放
批准后,被缓冲的回合原样回放给客户端——包括流式事件、签名推理块、供应商扩展事件,一个字节都不改写。回合缓冲逻辑在 crates/libsy/src/algorithms/advisor_gate/turn.rs。
REDO:丢弃、注入、重跑
REDO 时执行三步(源码中的redo方法):
- 被拦截回合的文本作为助手消息回显进上下文(客户端从未见过它)
- 顾问的计划前缀上固定导语注入为用户反馈——导语要求执行者先把审查要点记入 TODO 清单再动手,见 crates/libsy/src/prompts/advisor-gate/redo-feedback-prefix.md
- 执行者被重新唤起,其后续输出才是客户端实际收到的回复
💰 审查预算设计:把钱花在刀刃上
强模型调用很贵,预算系统决定了它的钱怎么花:
1. 按会话范围记账(max_reviews)
每个预算范围最多审查max_reviews次。范围的优先级是:
proxy_x_session_id请求头——基准测试框架用它标记同一个评测的所有请求(包括子代理),预算语义就是"这个任务的审查次数",即使网关被多个任务共享- 宿主解析的会话 ID
- 无头的客户端共用一个实例级范围
2. 失败退款 + 熔断
- 顾问调用失败 →退回已消耗的预算(瞬态错误不该白白烧掉
max_reviews) - 失败计入独立的熔断计数,达到 3 次后彻底停止咨询,防止顾问宕机时每次请求都白等一轮超时
- 判决无法解析同样退款,并降级为 APPROVE 放行
3. 失败开放(fail_open,默认开启)
顾问挂掉时,默认行为是降级放行(隐式 APPROVE),保证主链路不断;设为false则作为服务端错误上报。
4. 长会话"中间截断"
会话超过transcript_max_chars(默认 20 万字符,约 5 万 token)时,从中间裁剪:保留开头的任务陈述和结尾的最新工作,中间插入...<middle of the conversation truncated>...标记——因为完整性审查最需要的是"最初要什么"和"最近做了什么"。
🛠️ 配置示例
[targets.executor] id = "small/model" llm_client = "provider" [targets.advisor] id = "frontier/model" llm_client = "provider" [routes.gated] id = "switchyard/gated" type = "advisor" executor_target = "executor" advisor_target = "advisor" max_reviews = 3 gate_stall_turns = 30 gate_min_tool_results = 3关键参数一览(完整说明见 docs/routing_algorithms/advisor_gate_routing.md):
| 参数 | 默认值 | 含义 |
|---|---|---|
max_reviews | 1 | 每个会话范围的审查预算,花完即纯直通 |
gate_stall_turns | 0(关闭) | 停滞检查点的回合数阈值 |
gate_min_tool_results | 0 | 无工具调用回合可被审查前,会话至少需有的工具结果数 |
transcript_max_chars | 200000 | 转录中间截断上限(约 5 万 token) |
fail_open | true | 顾问失败时放行而非报错 |
📌基准测试中的最佳配置是max_reviews = 3、gate_stall_turns = 30、gate_min_tool_results = 3:跳过早期寒暄、给"磨工"保留一个任务中段检查点、并允许 REDO 之后再审一次。
📊 可观测性:看懂门的战绩
门的每次动作都能在/v1/stats的advisor_gate段看到(投影实现见 crates/switchyard-server/src/stats/algorithms/advisor_gate.rs):
- 按触发器统计的判决数(approve / redo / unparseable × no_tool_call / pattern / stall)
- 咨询失败按原因分类计数
- REDO 丢弃的回合及其 token 消耗——注意这些回合客户端从未见过,常规用量账单根本计不到它们,只有门的自己的账本才能对账
✅ 什么时候该用顾问门路由?
| 场景 | 建议 |
|---|---|
| 执行者明显弱于你能调到的最强模型 | ✅ 首选顾问门路由,拦截"过早的完成声明" |
| 需要审查痕迹(可追溯的质量记录) | ✅ 适用 |
| 执行者本身已是前沿级模型 | ⚠️ 强执行者很少犯审查能抓的"勤勉性错误",收益有限 |
| 只是想让强弱模型分工服务不同轮次 | 改用 阶段路由 |
实测数据(Terminal-Bench 2.1,k=3):对弱执行者,顾问门把成功率从43.8% 提升到 54.7%(±0.7),靠的正是抓住"过早的 done"声明和停滞;对强执行者则仅与接管型路由打平——这也印证了"门的价值取决于执行者有多弱"。
一句话总结:顾问门路由不替换模型,它给弱模型装了一道强模型监考的质量门——平时分文不花,只在"要交卷"的那一刻出手。
【免费下载链接】SwitchyardSwitchyard lets LLM applications route traffic across models and providers while preserving native OpenAI and Anthropic API compatibility - enabling flexible model selection, benchmarking, and cost/performance optimization.项目地址: https://gitcode.com/GitHub_Trending/switch/Switchyard
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考