系列收官篇。前四篇拆了会话控制、上下文管理、记忆、工具执行。但还有一层没有显式画在架构图里,却横跨所有层——模型路由。用一个模型跑所有任务,要么太贵(全用旗舰),要么质量不够(全用便宜的)。这篇讲怎么在 Harness 里设计智能路由,让每个任务自动跑在最合适的模型上。

为什么需要模型路由

一个跑了一个月的 Agent,日均处理 180 条消息,任务类型分布大致是这样的:

任务类型 占比 需要的模型能力
简单问答(天气、翻译、算术) 35% 基础
文本处理(摘要、改写) 20% 中等
单步工具调用 18% 中等
多步工具链 12%
代码生成/审查 10%
复杂推理 5% 最高

如果全用旗舰模型(如 Opus 4.7,$5/$25 MTok):

月成本 ≈ 180条 × 30天 × ~3000 token/条 × $15/MTok输出 ≈ $243/月

如果 73% 的简单任务(问答+文本+单步工具)用便宜模型($0.27 MTok),复杂任务才用旗舰:

简单任务: 131条 × 30天 × ~2000 token × $0.41/MTok ≈ $3.2/月
复杂任务: 49条 × 30天 × ~4000 token × $25/MTok ≈ $147/月
混合月成本 ≈ $150/月(省了 38%)

同样的消息量,路由后省 38% 成本,而且简单任务的响应速度反而更快(小模型推理更快)。

路由架构的 3 种设计模式

模式 1:基于规则的静态路由

最简单的方案。根据预设规则把任务分流到不同模型。

def route_by_rules(message: str, tools_needed: int) -> str:
    """基于规则的静态路由"""
    
    # 规则1:多步工具调用 → 旗舰模型
    if tools_needed >= 3:
        return "anthropic/claude-opus-4-7"
    
    # 规则2:代码相关 → 中高端模型
    code_signals = ["代码", "函数", "bug", "报错", "review", "重构", "测试"]
    if any(s in message for s in code_signals):
        return "anthropic/claude-sonnet-4-6"
    
    # 规则3:需要推理 → 中高端模型
    reasoning_signals = ["分析", "为什么", "比较", "优缺点", "方案", "设计", "架构"]
    if any(s in message for s in reasoning_signals):
        return "anthropic/claude-sonnet-4-6"
    
    # 规则4:其他 → 便宜模型
    return "deepseek/deepseek-v3"
优点 缺点
零延迟(纯字符串匹配) 关键词匹配不够精准
实现简单 边界 case 处理不了
行为可预测 规则维护成本随模型增多线性增长

适用场景:任务类型明确可分(比如"代码类"和"非代码类"),模型选择不超过 3 个。

模式 2:基于 LLM 的动态路由

用一个轻量模型先判断任务复杂度,再路由到对应模型。

ROUTER_PROMPT = """你是一个任务分类器。根据用户消息判断任务复杂度,返回 JSON。

分类标准:
- simple: 简单问答、翻译、格式转换、单步查询
- medium: 多步操作、文本分析、单文件代码修改
- complex: 架构设计、多文件重构、复杂推理、长链工具调用

只返回 JSON: {"complexity": "simple|medium|complex"}"""

async def route_by_llm(message: str) -> str:
    """用轻量模型做路由决策"""
    response = await client.chat.completions.create(
        model="qwen/qwen3.5-9b",  # 用最便宜的模型做路由
        messages=[
            {"role": "system", "content": ROUTER_PROMPT},
            {"role": "user", "content": message}
        ],
        max_tokens=50,
        response_format={"type": "json_object"}
    )
    
    result = json.loads(response.choices[0].message.content)
    
    model_map = {
        "simple": "deepseek/deepseek-v3",         # $0.27/MTok
        "medium": "anthropic/claude-sonnet-4-6",   # $3/MTok
        "complex": "anthropic/claude-opus-4-7",    # $5/MTok
    }
    
    return model_map.get(result["complexity"], "anthropic/claude-sonnet-4-6")
优点 缺点
语义理解,比关键词精准 多一次模型调用(+200-500ms 延迟)
不需要维护规则 路由模型本身也会犯错
能处理模糊任务 路由调用也有成本(虽然很低)

路由调用的成本:用 Qwen 3.5 9B 做路由,每次调用约 100 token 输入 + 20 token 输出 ≈ $0.000016。每天 180 条消息的路由成本约 $0.003——可以忽略。

适用场景:任务类型多样、边界模糊,静态规则覆盖不了。

模式 3:级联路由(Cascade)

先用便宜模型跑,如果结果质量不够再升级到更强的模型。

async def route_cascade(message: str, tools: list) -> tuple:
    """级联路由:先便宜后贵"""
    
    models = [
        ("deepseek/deepseek-v3", 0.85),       # 便宜,置信度阈值 0.85
        ("anthropic/claude-sonnet-4-6", 0.70), # 中等,置信度阈值 0.70
        ("anthropic/claude-opus-4-7", 0.0),    # 最贵,兜底
    ]
    
    for model, threshold in models:
        response = await client.chat.completions.create(
            model=model,
            messages=[{"role": "user", "content": message}],
            tools=tools,
        )
        
        result = response.choices[0]
        
        # 简单的质量判断(生产中可以更复杂)
        confidence = estimate_confidence(result)
        
        if confidence >= threshold:
            return result, model  # 质量够了,不升级
    
    return result, models[-1][0]  # 兜底

def estimate_confidence(result) -> float:
    """估算回答质量(简化版)"""
    content = result.message.content or ""
    
    # 低置信度信号
    if "我不确定" in content or "可能" in content:
        return 0.5
    if len(content) < 20:  # 回答太短
        return 0.6
    if result.finish_reason == "length":  # 被截断
        return 0.4
    
    return 0.9  # 默认高置信度
优点 缺点
简单任务真的只花便宜模型的钱 失败时延迟翻倍(要跑两次)
自动适配任务难度 质量判断逻辑需要调优
不需要预分类 实现最复杂

适用场景:成本敏感、能容忍偶尔的额外延迟。适合异步/后台 Agent(不需要实时响应)。

3 种模式的决策矩阵

维度 静态规则 LLM 动态 级联
路由延迟 0ms 200-500ms 0ms(成功)/翻倍(升级)
路由精度 60-70% 85-90% 80-85%
实现复杂度 ⭐⭐ ⭐⭐⭐⭐
成本节省 20-30% 30-45% 35-50%
适合场景 任务类型清晰 通用 后台/异步

我的推荐:从静态规则开始,不够了升 LLM 动态路由。 级联路由只在特定场景值得(后台批量任务、成本极度敏感)。

降级链设计:路由之外的可靠性保障

路由解决"选哪个模型"。降级链解决"选好的模型挂了怎么办"。

class ModelRouter:
    def __init__(self):
        self.breakers = {}  # 每个模型一个熔断器
    
    async def call(self, message: str, tools: list) -> tuple:
        """路由 + 降级"""
        primary = self.route(message, tools)
        fallback_chain = self.get_fallback_chain(primary)
        
        for model in fallback_chain:
            breaker = self.breakers.setdefault(model, CircuitBreaker())
            
            try:
                result = await breaker.call(
                    lambda: client.chat.completions.create(
                        model=model, messages=[...], tools=tools
                    )
                )
                return result, model
            except Exception as e:
                print(f"{model} 失败: {e}")
                continue
        
        raise Exception("所有模型不可用")
    
    def get_fallback_chain(self, primary: str) -> list:
        """降级链:跨厂商降级比同厂商更可靠"""
        chains = {
            "anthropic/claude-opus-4-7": [
                "anthropic/claude-opus-4-7",
                "deepseek/deepseek-v3",     # 跨厂商
                "qwen/qwen3.5-plus",        # 再跨一个
            ],
            "anthropic/claude-sonnet-4-6": [
                "anthropic/claude-sonnet-4-6",
                "deepseek/deepseek-v3",
                "qwen/qwen3.5-plus",
            ],
            "deepseek/deepseek-v3": [
                "deepseek/deepseek-v3",
                "qwen/qwen3.5-plus",
                "anthropic/claude-sonnet-4-6",
            ],
        }
        return chains.get(primary, [primary, "deepseek/deepseek-v3"])

关键设计:降级链要跨厂商。 同一厂商的多个模型可能共享基础设施——一个挂了另一个大概率也在抖。跨厂商降级的可靠性高得多。

配合熔断器使用(系列第一篇提过):连续失败 3 次自动跳过,60 秒冷却后试探性重试。

路由在 Harness 架构里的位置

回到系列第一篇的 5 层架构图,模型路由不是独立的第 6 层——它横跨在所有层和模型之间

┌─ 第5层:输出通道 ─────────────────────┐
├─ 第4层:工具执行 ─────────────────────┤
├─ 第3层:记忆 ─────────────────────────┤
├─ 第2层:上下文管理 ──────────────────┤
├─ 第1层:会话控制 ─────────────────────┤
└───────────────────────────────────────┘
          ↕
    ┌── 模型路由层 ──┐
    │ 规则/LLM/级联  │
    │ 降级链+熔断器  │
    └────────────────┘
          ↕
    ┌── 模型 API ───┐
    │ Claude / GPT  │
    │ DeepSeek/Qwen │
    └────────────────┘

各层和路由的交互:

提供给路由的信号 路由的决策依据
会话控制 触发类型(消息/cron/事件) cron 任务默认用便宜模型
上下文管理 当前上下文 token 数 上下文太大时选窗口更大的模型
记忆 任务历史模式 同类任务之前用哪个模型效果好
工具执行 需要调用的工具数量 多工具时选 Tool Use 强的模型

上下文感知路由的例子:如果上下文已经膨胀到 80K token,自动切到上下文窗口更大的模型(比如从 128K 的切到 200K 的),而不是让它截断。

路由策略的实际效果

根据公开的成本分析和架构报告,智能路由能带来的收益范围:

路由方式 成本节省 质量影响 延迟影响
全用旗舰(无路由) 基线 最高 最慢
静态规则路由 省 20-30% 降 1-2pp 简单任务更快
LLM 动态路由 省 30-45% 降 1-3pp 多 200ms 路由延迟
网关层路由 省 30-45% 降 0-1pp 多 10-50ms

网关层路由的特殊优势:路由逻辑在网关层实现,不在应用代码里。这意味着:

  1. 改路由规则不用改代码、不用重新部署
  2. 路由逻辑可以跨多个 Agent 共享
  3. 网关自带降级、熔断、限流、监控

我自己用的 TheRouter 就是这种方案——路由规则在网关后台配,代码里只写一个 model 参数,网关根据规则决定实际路由到哪个厂商的哪个模型。

系列总结

5 篇文章覆盖了 Agent Harness 的完整架构:

主题 核心问题
5 层总览 什么是 Harness,每层做什么
上下文管理 4 种策略:全量/窗口/摘要/RAG
记忆 3 种架构:KV/日志+摘要/向量
工具执行 数量控制、安全防护、动态加载
模型路由 3 种模式:规则/LLM/级联 + 降级链

一句话总结整个系列:模型决定了 Agent 的能力上限,Harness 决定了这个上限能发挥多少。投资 Harness 的 ROI 比升级模型高——因为模型在进步,但 Harness 的坑每个新模型都得填。

常见问题

Q: 路由模型本身也要钱,不是多了一层成本吗?
A: 路由调用用最便宜的模型($0.10/MTok),每次约 120 token,成本约 $0.000012。每天 180 次路由的总成本 $0.002——相比路由节省的 30-45% 费用,可以忽略。

Q: 模型越来越便宜,以后还需要路由吗?
A: 价格下降但差异比不会消失。旗舰模型永远比中端贵 10 倍以上。而且路由不只省钱——它还提升速度(简单任务用小模型响应更快)和可靠性(跨厂商降级)。

Q: 能不能让模型自己选用哪个模型?
A: 理论上可以(“你觉得这个任务需要多强的模型?”),但不推荐。模型倾向于高估任务难度(选更强的模型),因为它没有成本概念。路由决策应该由 Harness 做,不是模型。

更多推荐