AI模型路由实战:智能分发的LLM成本优化方案
2026/9/22 10:01:49 网站建设 项目流程

实际 LLM 应用中,很多团队会遇到一个共同问题:所有请求都调用同一个最强模型,效果虽然稳定,成本却随着调用量上升迅速失控。AI model router 就是用来解决这类问题的一种中间层,它根据请求类型、模型能力、价格和当前负载,把请求分发到合适的 LLM,用较低成本满足大部分需求。这篇文章以一次成本优化项目为背景,完整梳理模型路由器的设计思路、最小实现、成本验证和生产落地要点。

需要先说明一点:标题里的 94% 成本下降来自特定业务场景,不一定能在所有系统上复现。文章给出的代码和配置是用于讲解实现思路,落地时要以实际模型 API、定价策略和业务数据为准。

1. 先理解 AI 模型路由器的价值边界

1.1 模型路由要解决什么问题

模型路由器的核心问题只有一个:当前这个请求,真的需要最强的模型吗?

在自然语言处理项目中,并不是所有请求都要求高推理能力。用户问“今天天气怎么样”“这个接口返回的字段是什么意思”,和用户提交一份包含数学推理、代码调试、多步规划的复杂问题,对模型能力的需求完全不同。如果统一调用大参数、高价格模型,简单请求会支付超额成本;如果统一调用小模型,复杂请求会频繁失败或质量下降。

AI model router 就是在用户请求和底层 LLM 之间增加一层决策逻辑。它把请求分类,估算需要的输出长度,读取每个模型的能力和价格,然后决定把请求交给哪个模型。本质上是在“效果、延迟、成本”三者之间做权衡。

1.2 为什么路由会带来成本下降

LLM 的成本结构通常由输入 token 数、输出 token 数和不同模型单价决定。大部分业务场景里,高频请求其实是短文本问答、摘要、格式转换、意图识别这类任务,它们不需要顶级模型的全部能力。

一个典型例子:

  • 1000 次请求全部走大模型,每次输入约 500 token,输出约 200 token,成本按大模型单价计算。
  • 其中 800 次请求实际是小模型就能完成的,只有 200 次真正需要大模型。

如果路由逻辑能把 800 次简单请求切到小模型,成本变化会非常明显。这不是通过压缩模型参数量实现的,而是通过减少高单价模型调用次数实现的。94% 这个数字虽然来自特定案例,但背后的逻辑是一致的:大部分成本浪费来自“模型能力和请求需求不匹配”。

1.3 路由器与 API 网关的差异

有人会把模型路由器当成 API 网关,两者职责并不一样。

API 网关关心的是路由转发、鉴权、限流、协议转换、负载均衡,它不关心模型能力是否匹配。模型路由器关心的是业务语义和模型能力:任务属于哪个类别、输出质量要求多高、延迟预算多少、当前模型能不能处理。

实际项目中,两者可以配合:API 网关负责把外部请求接入系统,模型路由器位于网关之后,在内部完成模型选择。不要把模型路由逻辑直接写进网关,否则后续调整模型策略会受制于网关发布和团队职责边界。

2. 从案例出发确定路由目标和判断维度

2.1 一次成本优化项目的背景

以一次成本优化项目为例。团队运营一个企业内部知识库助手,主要包含三类请求:

  • 文档内容问答:用户针对某段文档提问,问题通常短、答案可以从上下文里提取。
  • 代码与命令生成:用户要求生成脚本、调试命令,对步骤准确性要求高。
  • 综合总结与规划:用户提交多段材料,要求生成结构化报告或方案。

项目启动前,所有请求都调用同一个高价模型。监控显示,每月 token 消耗中约 20% 的请求属于代码和复杂规划类,剩下 80% 是文档问答和短文本处理。把 80% 的简单请求拆到低成本模型,是成本优化的主要切入点。

目标并不是让所有请求都用最便宜的模型,而是保证每个请求都使用“够用且不浪费”的模型。还需要约束延迟和错误率,否则成本降下来但用户体验变差,优化没有意义。

2.2 决策维度一览

模型路由决策不是一个单一的 if else,而是多维度打分的组合。常用维度如下:

维度说明影响
任务类型问答、摘要、代码、数学、推理、生成等决定是否需要强模型
输入长度段落长度、上下文大小影响输入成本和延迟
预期输出长度回复长度估算影响输出成本和模型输出上限
质量要求是否存在标准答案、是否会被人工审查低质量场景可接受较小模型
延迟预算用户能接受的等待时间大模型延迟高,小模型延迟低
成本上限单次请求允许的最大成本超预算请求必须切模型或拒绝

在最小实现里,任务类型往往是最强信号。代码、数学、复杂推理优先分给强模型;文档问答、简单摘要、意图识别分给小模型。但要避免只按任务类型判断,因为同一个任务类型内部复杂度也可能差别很大。

2.3 示例价格模型

为了演示成本计算,需要先定义模型和价格。以下价格不是任何平台的实时报价,仅作为示例:

模型标识输入价格(美元/1K token)输出价格(美元/1K token)能力倾向
llm-large0.0150.075高推理、代码、长文生成
llm-small0.00150.006短问答、摘要、格式转换
llm-medium0.0030.015中等复杂度解释、分类

把这组价格写进配置,路由服务才能按实际 token 用量计算成本。注意,采购或接入新模型时,价格要单独确认并测试 tokenizer 的切分规则,不同模型对同一段文本的 token 计费可能不同。

3. 最小可运行的模型路由服务

3.1 项目结构与数据模型

下面用一个最小示例说明模型路由器的实现思路。项目结构如下:

llm-router/ ├── config/ │ └── routing.yaml ├── core/ │ ├── scheme.py │ ├── estimator.py │ ├── router.py │ └── client.py ├── logs/ │ └── router.log └── main.py

首先定义模型配置。用ModelConfig保存模型名称、价格、上下文窗口和是否支持复杂推理:

# core/scheme.py from dataclasses import dataclass from typing import Optional @dataclass class ModelConfig: name: str input_price: float output_price: float context_window: int = 8192 max_output_tokens: int = 4096 supports_reasoning: bool = False @dataclass class RouteRequest: task_type: str prompt: str expected_output_tokens: int = 512 max_cost_usd: Optional[float] = None max_latency_seconds: Optional[float] = None

RouteRequest是路由器的统一入参。在线服务中,它通常由上游服务组装:从请求体里读取用户输入,用分类模型或规则识别任务类型,再传给路由器。

3.2 统一请求响应结构

路由器返回时不能只告诉上层“选择了哪个模型”,还要返回内容、token 用量和成本。这样才能在后面做成本统计和质量回归。

@dataclass class RouteResponse: model: str content: str input_tokens: int output_tokens: int cost_usd: float

统一响应结构有两个作用:

  • 上层业务代码不关心底层模型差异,只需要处理一个响应对象。
  • 成本统计模块可以从响应对象中提取 token 和费用,不需要额外去查调用链。

3.3 基于规则的路由实现

先实现一个 token 估算器。真实项目应该使用各模型对应的 tokenizer,但最小示例可以用字符数近似:

# core/estimator.py def estimate_tokens(text: str, bytes_per_token: float = 4.0) -> int: if not text: return 0 return max(1, int(len(text.encode("utf-8")) / bytes_per_token))

这个函数的价值是:在真正调用模型前,先得到输入 token 数量,用于成本估算和模型选择。生产环境里,建议在每个 provider adapter 中调用官方 tokenizer,避免估算偏差影响路由判断。

接下来实现规则路由器:

# core/router.py from core.scheme import ModelConfig, RouteRequest from core.estimator import estimate_tokens class RuleRouter: def __init__(self, models: dict[str, ModelConfig]): self.models = models def route(self, req: RouteRequest) -> str: input_tokens = estimate_tokens(req.prompt) if input_tokens > self.models["llm-large"].context_window * 0.8: return "llm-large" if req.task_type in {"code", "math", "reasoning", "multi-step-plan"}: return "llm-large" if req.task_type in {"qa-extractive", "summarize-short", "intent"}: return "llm-small" return "llm-medium"

这个路由规则包含三层判断:

  • 超长输入优先走大模型,因为小模型上下文窗口不足。
  • 高推理任务直接走大模型,避免小模型反复生成错误内容。
  • 简单任务走小模型,其余走中等模型。

这里要强调:规则路由器适合快速验证思路,但不适合长期维护。规则会随着任务类型增加而膨胀,最终出现“优先级冲突”和“难以解释”的问题。更可靠的方式是引入打分函数。

3.4 本地验证与预期输出

main.py里模拟一次调用:

from core.scheme import ModelConfig, RouteRequest from core.router import RuleRouter models = { "llm-large": ModelConfig( name="llm-large", input_price=0.015, output_price=0.075, context_window=128000, supports_reasoning=True, ), "llm-medium": ModelConfig( name="llm-medium", input_price=0.003, output_price=0.015, context_window=32000, ), "llm-small": ModelConfig( name="llm-small", input_price=0.0015, output_price=0.006, context_window=16000, ), } router = RuleRouter(models) req = RouteRequest(task_type="qa-extractive", prompt="后端返回的 error_code 是什么意思?") print(router.route(req))

预期输出是llm-small。用同样的方法构造一个task_type="code"的请求,预期输出是llm-large。这就是最小闭环:输入请求,输出模型选择结果。之后再把模型选择结果接入真实客户端,替换返回的content字段。

4. 让路由决策更可靠

4.1 从规则路由升级为打分路由

规则路由的缺点是“一刀切”。同样是代码任务,修改一行配置和编写一个完整微服务,复杂度完全不同。打分路由的思路是:为每个候选模型计算综合分数,选择分数最高的模型。

打分函数可以包含三个子分数:成本分、延迟分、质量分。

def score_model( model: ModelConfig, input_tokens: int, expected_output_tokens: int, task_quality_need: float, latency_budget: float, ) -> float: cost = input_tokens / 1000 * model.input_price + expected_output_tokens / 1000 * model.output_price cost_score = 1.0 / (1.0 + cost * 100) quality_score = model.supports_reasoning * task_quality_need + (1.0 - model.supports_reasoning) * (1.0 - task_quality_need) latency_score = max(0.0, 1.0 - latency_budget / 10.0) return cost_score * 0.5 + quality_score * 0.4 + latency_score * 0.1

这里的参数不能直接复制到生产环境。它只是说明打分路由的构造方式:每一项都应该是可量化的,并且权重需要根据业务反馈调整。真实项目中,成本分应该使用真实单价,质量分应该来自离线评测或线上效果指标,而不是简单用supports_reasoning代替。

4.2 回退机制设计

路由器需要处理小模型失败的情况。常见失败包括:内容被过滤、输出格式不符合要求、捕获到异常、质量分过低。

回退机制可以这样实现:

def route_with_fallback(req: RouteRequest, client, router) -> str: selected = router.route(req) response = client.complete(model=selected, prompt=req.prompt) if not response.is_valid: return client.complete(model="llm-large", prompt=req.prompt) return response

回退机制的关键是:不要无限制重试。第一跳失败后切到更大模型,最多重试两次;如果仍然失败,直接进入错误处理流程。否则,成本没有降下来,延迟反而翻倍。

4.3 动态调节路由策略

路由器的配置不应该写死在代码里。推荐把模型价格、任务类型映射、权重参数放到配置中心或独立配置文件,运行时可以动态更新。

# config/routing.yaml default_model: llm-medium rules: - task_type: qa-extractive model: llm-small - task_type: code model: llm-large - task_type: reasoning model: llm-large fallback: enabled: true max_retry: 2 fallback_model: llm-large

更新配置后,要记录版本号和生效时间。模型价格调整或新模型接入时,先在小流量环境验证,再全量发布。不要直接修改生产配置后不做任何验证,否则可能出现“所有请求都路由到同一个模型”的问题。

5. 成本统计与收益验证

5.1 按模型聚合成本

成本优化是否有效,不能只看总账单。要建立按模型、按任务类型、按天聚合的成本视图。

可以写一个简单的统计函数:

def aggregate_cost(responses: list[RouteResponse]) -> dict[str, float]: result = {} for resp in responses: key = resp.model result[key] = result.get(key, 0.0) + resp.cost_usd return result

更完整的方案是把每次调用的RouteResponse写入日志表,字段包括请求 ID、模型、输入 token、输出 token、任务类型、耗时、成本。后续做分析时,只需要按模型聚合,就能看到成本分布。

5.2 验证收益时要排除缓存干扰

很多 LLM 产品提供 prompt 缓存。如果缓存命中,token 成本可能大幅下降。但这部分收益来自缓存,不是完全来自模型路由。

验证路由器收益时,建议先关闭缓存,或者分别统计“缓存命中”和“未命中缓存”的两组数据。否则,两种优化混在一起,无法判断路由策略是否真的合适。

另一个容易忽略的问题是 token 估算误差。假如estimate_tokens低估了实际 token 数,成本统计就会偏乐观。生产环境里,成本统计必须以实际扣费回执为准,不要用估算值做对账。

5.3 在测试环境做质量回归

路由优化不能只看钱,还要看效果。建议建立一个小规模测试集,里面包含三类请求:

  • 小模型应该能处理的简单请求。
  • 必须由大模型处理的高难度请求。
  • 边界请求,比如超长输入、低质量 prompt、多语言混合内容。

每次调整路由策略后,跑一遍测试集,记录模型选择结果和质量评分。如果小模型在简单请求上出现明显下降,需要调整路由规则或质量评分权重。

6. 常见问题与排查路径

6.1 路由结果不稳定

现象:同一个请求在不同时间被路由到不同模型。

排查路径:

  1. 确认请求参数是否一致,特别是task_type是否由上游传递。
  2. 检查输入长度是否接近阈值,estimate_tokens可能因为字符集不同产生偏差。
  3. 检查配置是否被动态更新,规则表是否被中途修改。

解决方案是把路由决策结果连同输入摘要写入日志。出现问题时,可以回放当时的请求和配置版本。

6.2 成本没有下降反而上升

现象:接入路由器后总成本更高。

常见原因:

  • 小模型需要多次重试才能达到效果,重试导致 token 消耗增加。
  • 回退机制过于宽松,大量请求第一次失败后都走了大模型。
  • 上游请求经过路由后,输出长度估算不准,大模型输出了更多 token。
  • 缓存策略变化,原本命中的缓存失效。

排查时先看“模型调用次数”和“平均输出 token 数”两个指标。如果小模型调用次数高,但失败后重试次数也高,说明小模型选择边界可能太激进。

6.3 小模型抢占高价值请求

现象:代码生成或复杂推理请求被路由到小模型,用户反馈答案质量差。

原因通常是任务类型识别不准。比如用户用“帮我看看这个命令有没有问题”表达代码调试需求,但上游把这句话分类成了普通问答。

解决方式:

  • 提升任务分类准确率。
  • 在路由规则中设置关键词扩展。
  • 引入质量反馈机制,用户“不满意”或“重新生成”的请求下次直接走大模型。

6.4 日志和监控维度缺失

现象:优化上线后,只能看到总账单,无法定位是哪类请求贡献了大部分成本。

这是最需要提前预防的问题。从第一天起就记录路由决策、token 用量、模型名称、任务类型、耗时和错误状态。没有这些数据,任何成本异常都无法快速定位。

7. 生产环境落地的关键点

7.1 配置外置与动态更新

模型路由的配置变化非常频繁。新模型发布、价格调整、业务任务类型变化,都会影响路由策略。配置应该放在独立配置中心,而不是编译进代码。

生产环境至少需要:

  • 配置版本管理。
  • 灰度发布能力。
  • 配置变更后自动加载。
  • 变更审计日志。

7.2 超时、重试与熔断

每个模型调用的超时时间不同。小模型响应快,大模型在长上下文下可能很慢。路由器需要为不同模型设置不同的超时时间,不能共用同一个值。

重试需要考虑两个层面:

  • 网络或服务端错误,例如 429、5xx,可以重试。
  • 模型输出质量不合格,只能走回退逻辑。

如果某个模型连续失败,比如连续 5 次超时或 5 次返回空内容,应该触发熔断,暂时把请求切到其他模型,并发送告警。

7.3 安全、权限与合规

模型路由器会暴露模型调用能力,需要严格控制访问权限。

  • 内部服务通过 API Key 或服务账号访问路由器。
  • 外部用户请求不能直接指定模型名称。
  • 需要记录输入内容,区分哪些字段可以进入模型、哪些字段必须脱敏。
  • 对于涉及个人信息的请求,路由日志不能完整保存原文。

模型路由虽然能降低成本,但不应成为数据合规的例外点。日志中保存最小必要字段,并在保存前进行敏感信息过滤。

7.4 生产部署前检查清单

上线前可以按下面这个清单逐项确认:

检查项确认内容
模型可用性候选模型 API 是否可用,是否有配额限制
单价确认输入输出单价是否与合同或控制台一致
Tokenizer 验证估算 token 与实际 tokenizer 的误差是否在可接受范围
超时配置每个模型是否设置了独立超时时间
回退策略回退重试次数是否限制,是否会触发告警
日志字段是否记录了请求 ID、模型、token、成本、错误信息
质量测试集简单请求和高难度请求是否都覆盖
灰度计划能否先切 10% 流量,观察后再放量
回滚方案配置是否可以快速一键回滚
成本监控是否按模型和任务类型设置成本告警

这张清单同样适用于学习环境之外的所有阶段。不要在没有质量测试集和日志指标的情况下直接全量发布。

8. 从路由器到更细粒度的成本治理

模型路由器不是成本优化的终点。它是一套机制的入口:请求分类、能力评估、成本计算、质量反馈、灰度实验、指标监控,这些能力组合起来,才构成完整的成本治理体系。

对新手来说,最有价值的练习不是直接搭一个生产级路由器,而是先用最小规则路由跑通流程,记录 1000 条真实请求,统计其中高频任务类型和成本分布。有了真实数据,再逐步把规则改成打分路由,把小模型的选择边界调整到合理范围。

这篇文章主要聚焦在模型选择层。后续可以继续深入三个方向:一是基于 embedding 的语义路由,把请求向量化和历史效果做匹配;二是基于强化学习的路由策略,让模型选择随质量反馈自动优化;三是把路由器接入 MCP 或 Agent 工具链,在多个工具和模型之间统一调度。每个方向都需要稳定的日志和评估体系支撑,否则再复杂的路由算法也缺少判断依据。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询