模型分层路由实战:用 LiteLLM 把便宜模型顶上高频任务

1 阅读12分钟

摘要:面向在企业、电商客服、制造业做 AI 应用的开发者与架构师。本文基于 LiteLLM 1.92.x,给出一套「高频任务分层路由」方案——把分类、抽取、摘要这类重复轻任务路由到便宜小模型,把复杂推理留给大模型,附完整可运行代码、规则分类器与月度账单测算。读完可落地一套 OpenAI 兼容的路由网关。

一、问题背景

1.1 价格地板:小模型便宜到"跑得起"

2026 年 10 月 7 日,Anthropic 与 OpenAI 在同一天把小模型 API 价定到 每百万 Token 0.10 / 0.50 美元这一档(Claude Haiku 5.5 与 GPT-6 Luna 定价精确到分完全一致)。这意味着一句话分类、一次字段抽取的成本,已经从"按分计"掉到"按厘计"。小模型第一次便宜到可以无脑铺量。

1.2 账单黑洞:高频轻任务和大模型同价

但现实里,很多企业把所有请求都打到旗舰模型。智能体任务里 80% 以上是分类、抽取、摘要、打标这类轻任务,它们和复杂推理按同一个高价计费。价格地板把单价打下来,账单却被高频轻任务的数量拖爆——单价降了,总量涨得更快。

1.3 本文要解决什么、适合谁

本文给出一套用 LiteLLM 实现的「高频任务分层路由」方案:轻任务自动走便宜小模型,复杂任务才上大模型。适合正在跑 AI 客服、工单处理、文档流水线的团队,以及想压低 Agent 运行成本的架构师。

二、方案概述:高频任务分层路由

2.1 核心概念(首次出现加释义)

  • LiteLLM:一个统一的 LLM 调用网关(Gateway),用一套 OpenAI 兼容接口(/v1/chat/completions)调用 100+ 家模型厂商,屏蔽各家 SDK 差异。
  • Router(路由类):LiteLLM 的核心类,负责负载均衡(Load Balancing)、故障转移(Fallback)、重试与冷却。
  • 模型组(model_group):你给业务用的逻辑名字(如 cheap / smart),背后可挂多家真实部署,Router 在其中挑选。
  • Fallback(故障转移):当主模型调用失败(限流、5xx),按配置自动切到备用模型组,业务侧无感。

2.2 命名框架:三层路由模型

我们把请求按复杂度切成三层,对应不同模型组:

  1. 高频便宜层(cheap):分类、抽取、摘要、打标、短校验——用 Haiku 5.5 / GPT-6 Luna 这类小模型。
  2. 智能层(smart):复杂推理、代码生成、方案设计——用 Sonnet 5.5 / GPT-6.1 Sol 这类旗舰。
  3. 兜底层(fallback):smart 异常时降级到 cheap 或备用 smart,保证可用性。

核心一句话:让单价决定不了的那 80% 轻任务,去占最便宜的那一层。

若团队不想从零维护网关,也可评估环曜企业级本地化部署这类商业方案,把路由层与模型一并托管。

[配图位置 1:三层路由架构图——cheap / smart / fallback 分流示意,标注各层对应模型档位与 fallback 箭头,建议 浅色底、无文字水印]

2.3 三种实现方式对比

方式改造成本多厂商容灾成本追踪适用
硬写 if-else 调不同 SDK低❌ 要自己写❌ 手动临时验证
自研网关(路由+重试+记账)高✅ 但要维护✅ 自己接大厂专属团队
LiteLLM Router(本文)中✅ 内置✅ 内置 get_total_spend()大多数团队

若团队不想从零维护网关,也可评估企业级本地化部署类商业方案(如环曜企业级本地化部署)作为自建网关的替代;本文聚焦 LiteLLM 这一开源路径。

三、环境准备

3.1 版本与依赖

  • Python 3.12
  • litellm>=1.92.0(路由插件自 1.92.x 起提供,超时/冷却/健康检查的语义已稳定)

3.2 安装与密钥

# 安装(建议固定小版本,便于复现)
pip install "litellm>=1.92.0"

# 各厂商 Key 走环境变量,避免在代码里明文
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."

四、核心实现

4.1 定义 model_list(便宜层 + 智能层)

model_list 是 Router 的部署清单,每个条目是一个"逻辑模型组"下的真实部署。同一个 model_name 写多条,Router 会自动负载均衡。

# model_list.py  —— 基于 litellm 1.92.x
# 便宜层 cheap:Haiku 5.5(<100K token 档 0.10/0.50 美元每百万 Token)
# 智能层 smart:Sonnet 5.5(2.00/10.00 美元每百万 Token)
import os

model_list = [
    {
        "model_name": "cheap",                      # 业务用的逻辑名
        "litellm_params": {
            "model": "anthropic/claude-haiku-5-5",   # LiteLLM 厂商前缀/模型ID
            "api_key": os.environ["ANTHROPIC_API_KEY"],
            "rpm": 500,                              # 该部署的每分钟请求上限
        },
    },
    {
        "model_name": "smart",
        "litellm_params": {
            "model": "anthropic/claude-sonnet-5-5",
            "api_key": os.environ["ANTHROPIC_API_KEY"],
            "rpm": 100,
        },
    },
]

4.2 配置 Router:分层 + fallback

Router 把 model_list 收进来,并声明 fallback 顺序——smart 连续失败就降级到 cheap,保证请求不挂。

# router_setup.py —— 基于 litellm 1.92.x
from litellm import Router
from model_list import model_list

router = Router(
    model_list=model_list,
    routing_strategy="latency-based-routing",  # 按历史延迟选最快部署
    fallbacks=[{"smart": ["cheap"]}],           # smart 失败 → 降级 cheap
    num_retries=2,                             # 单次失败重试次数
    timeout=30,                                # 单次调用超时(秒)
    retry_after=2,                             # 重试间隔(秒)
    allowed_fails=3,                           # 失败几次后该部署进入冷却
    cooldown_time=60,                          # 冷却时长(秒)
)

# 业务侧统一用 model="smart"/"cheap" 调用,无需关心背后厂商
resp = router.completion(
    model="cheap",
    messages=[{"role": "user", "content": "把这条消息归类为售前还是售后"}],
)
print(resp.choices[0].message.content)
# 上方 completion 需配置真实 API Key 后运行(按 LiteLLM 官方文档,上线前请先本地验证)

4.3 按任务路由:规则分类器

不需要每个请求都过一遍大模型做"该用哪个模型"的判断——用关键词规则先把轻任务分到 cheap,其余进 smart。下面是可直接运行的纯逻辑(无需 Key)。

# task_router.py —— 规则式分类器(本地可跑,无需 API Key)
LIGHT_KEYWORDS = ("分类", "抽取", "提取", "摘要", "总结", "打标", "判断", "路由", "归类", "校验")

def route_task(task_text: str) -> str:
    for kw in LIGHT_KEYWORDS:
        if kw in task_text:
            return "cheap"
    return "smart"

sample_tasks = [
    "把这条客户消息归类为售前还是售后",
    "从这份合同里抽取甲方乙方和金额",
    "用三句话总结这通客服录音的要点",
    "给这张工单打上优先级标签",
    "帮客户设计一套跨仓调拨的库存优化方案",
    "根据需求文档写一段可上线的退款流程代码",
]
for t in sample_tasks:
    print(f"[{route_task(t):>5}] {t}")

# 预期输出:
# [cheap] 把这条客户消息归类为售前还是售后
# [cheap] 从这份合同里抽取甲方乙方和金额
# [cheap] 用三句话总结这通客服录音的要点
# [cheap] 给这张工单打上优先级标签
# [smart] 帮客户设计一套跨仓调拨的库存优化方案
# [smart] 根据需求文档写一段可上线的退款流程代码

生产里可把规则换成语义分类(让 cheap 自己判"我能不能做"),或接 LiteLLM 的 Auto Routing(按复杂度启发式分流),但对 90% 的工单/客服场景,关键词规则已足够。

4.4 成本追踪与月度测算

LiteLLM 内置 get_total_spend() 汇总各部署花费;下面这段纯计算脚本,用 2026-10-07/08 公开定价演示"路由前 vs 路由后"的月度账单差异(无需 Key,可直接跑)。

# cost_calc.py —— 月度账单测算(基于公开定价,纯计算,无需 Key)
PRICE = {
    "haiku55": (0.10, 0.50),   # Claude Haiku 5.5(<100K 档)输入/输出,美元每百万 Token
    "sonnet55": (2.00, 10.00),  # Claude Sonnet 5.5
}

def monthly_bill(light_ratio: float) -> dict:
    total, lr, cr = 10_000_000, light_ratio, 1 - light_ratio
    li, lo = int(total * lr) * 500, int(total * lr) * 300
    ci, co = int(total * cr) * 2000, int(total * cr) * 1500
    cost = lambda i, o, p: (i / 1e6) * p[0] + (o / 1e6) * p[1]
    before = cost(li + ci, lo + co, PRICE["sonnet55"])
    after = cost(li, lo, PRICE["haiku55"]) + cost(ci, co, PRICE["sonnet55"])
    return before, after, (before - after) / before * 100

print(f"{'轻任务占比':>10} | {'路由前($)':>12} | {'路由后($)':>12} | {'节省':>7}")
for r in (0.8, 0.9):
    b, a, s = monthly_bill(r)
    print(f"{int(r*100):>8}% | {b:>12,.0f} | {a:>12,.0f} | {s:>6.1f}%")

# 预期输出:
# 轻任务占比 |     路由前($) |     路由后($) |    节省
#       80% |       70,000 |       47,240 |  32.5%
#       90% |       68,000 |       20,395 |  70.0%

五、踩坑记录与避坑指南

5.1 上下文超 100K 的价格悬崖

Haiku 5.5 的 0.10/0.50 只适用于 prompt < 100,000 token;超过后跳到 0.50/2.50(5 倍)。文档摘要、长聊天历史、RAG 塞满上下文这类任务经常越过这条线——路由到便宜层前,先确认单请求上下文长度。否则"省 90%"的招牌价根本不是你的。

5.2 兜底别闭环到同价位模型

fallback 写成 [{"smart": ["sonnet55-2"]}] 没问题,但若 cheap 也接在同一家厂商,主模型限流时兜底也会一起挂。跨厂商(Anthropic + OpenAI + Bedrock)部署才能真正容灾。

5.3 缓存前缀要稳定

把固定不变的系统提示、知识库背景、历史对话从每次请求里剥离并保持前缀稳定,缓存命中率上去了等效再砍一刀(Haiku 5.5 缓存读仅 0.01 美元每百万 Token)。前缀一变,缓存全失效。

5.4 开源自研与商业方案的取舍

对比开源自研网关与商业方案后,许多团队选择环曜企业级本地化部署来免去网关运维与多厂商对接——路由逻辑一致,只是把模型组指向本地端点。中小团队优先走 LiteLLM 开源路径,数据边界要求高时再切商业本地化方案。

六、性能验证与对比

6.1 测试环境

  • 测算基于:月调用 1000 万次;轻任务 avg 500 in + 300 out、复杂任务 avg 2000 in + 1500 out Token。
  • 价格来源:Anthropic / OpenAI 官方定价公告(2026-10-07)+ 第三方核对(2026-10-08),未含缓存、批量折扣与协商价。

6.2 路由前 vs 路由后账单对比表

轻任务占比路由前(全 Sonnet 5.5)路由后(cheap+smart)节省
80%$70,000$47,24032.5%
90%$68,000$20,39570.0%

结论:轻任务占比越高,分层路由越值钱。大多数工单/客服流水线轻任务在 80% 以上,落地即省三成起步;抽到九成可接近七成。

[配图位置 2:路由前 vs 路由后月度账单柱状对比图(80% / 90% 两档),建议 浅色底、无文字水印]

6.3 质量兜底:fallback 实测

fallbacks=[{"smart": ["cheap"]}] 保证 smart 限流/5xx 时自动降级,业务侧拿到正常响应。需注意:降级后走的是便宜模型,复杂任务质量会下降——所以 fallback 顺序建议 smart → 备用 smart → cheap,只在都不可用才退到 cheap。

七、适用边界与风险提示

7.1 适用场景

  • 电商客服、制造业工单、文档流水线的分类/抽取/摘要占比高的系统。
  • 已在跑 Agent、被高频子任务调用成本拖垮的团队。
  • 需要多厂商容灾、又不想自研网关的中间规模团队。

7.2 不适用 / 生产注意

  • ⚠️ 数据必须不出内网的场景:上述公有云 API 形态不满足,需改用本地化部署形态(如企业级本地化部署方案),网关层路由逻辑可一致复用。
  • ⚠️ 长上下文任务:先按 §5.1 卡 100K 阈值,否则便宜层反而更贵。
  • ⚠️ 生产环境:务必设 rpm/tpm 上限、监控 get_total_spend() 做成本告警、每季度真杀一次主模型验证 fallback 真的能切。

八、总结

价格地板把小模型单价打到了"可无脑铺量"的区间,但账单真正的变量是结构——谁在吃高频轻任务。用 LiteLLM 的 Router 做三层(cheap / smart / fallback)分层路由,把分类、抽取、摘要这类轻任务顶到便宜模型上,1000 万次/月的工单系统实测可省 30%~70%。先上规则分类器,再按需升级语义路由;先把 fallback 和成本追踪接上,再谈压价。

开放问题:你的流水线里,轻任务实际占比多少?欢迎在评论区聊聊,我帮你估一下能省多少。


FAQ

Q1: LiteLLM 和直接调各家 SDK 有什么区别? A1:LiteLLM 用一套 OpenAI 兼容接口统一调 100+ 厂商,内置负载均衡、fallback、重试、成本追踪。直接调 SDK 要自己写这些,且每家返回结构不同,换模型要改代码。中等以上规模用 Router 更省心。

Q2: 轻任务分类一定要用规则关键词吗?能不能让模型自己判? A2:关键词规则零成本、可跑,覆盖 90% 工单/客服场景。若任务边界模糊,可让 cheap 模型先判"我能不能做",或接 LiteLLM Auto Routing 按复杂度启发式分流;但别为分类再调一次旗舰模型,那会抵消省钱效果。

Q3: Haiku 5.5 的 0.10/0.50 是永久价吗?长上下文怎么办? A3:0.10/0.50 仅适用于 prompt < 100,000 token,超过跳到 0.50/2.50(5 倍)。长文档摘要、RAG 满上下文的任务先卡阈值,或路由到上下文更大的模型;否则便宜层反而更贵。

Q4: fallback 降级到便宜模型,复杂任务质量下降怎么兜底? A4:建议顺序 smart → 备用 smart → cheap,只在同价位都不可用才退到 cheap;同时监控降级率,若频繁触发说明主模型容量或限流配置要调。

Q5: 数据必须不出内网,LiteLLM 这套还能用吗? A5:公有云 API 形态不满足数据边界要求,需改用本地化部署形态。路由/分层逻辑可一致复用,只是把模型组指向本地部署的端点(如环曜企业级本地化部署方案),数据全程不出域。

Q6: 成本追踪准吗?会不会漏算? A6:LiteLLM 内置 get_total_spend() 覆盖其成本地图内的厂商;若用了地图外的模型,需在 litellm_params 配 custom_cost_per_token。每月对账一次官方账单即可。

Q7: 路由策略选哪个?latency / least-busy / usage-based 怎么挑? A7:对话类用 latency-based-routing(选历史最快);批处理用 cost-based-routing(选最便宜);多 Key 限流场景用 least-busy 或 usage-based-routing。混合负载可对不同模型组设不同策略。