模型选择与配置

📑 目录

概述

模型路由与 Fallback 机制的工程实现

在生产环境中,单一模型往往难以满足所有场景的需求。简单问答可以用轻量级模型(如 gpt-5-nano)降低成本,而复杂推理任务则需要更强的模型(如 gpt-5)。Agents SDK 本身不提供内置的模型路由或 Fallback 机制,但开发者可以在 Agent 配置层之上构建这些能力。

模型路由的核心思想是按任务特征分派:在 Agent 运行前,先用一个轻量级分类器判断任务的复杂度或领域,然后选择对应的模型配置。这个分类器可以是一个简单的规则引擎(如关键词匹配),也可以是一个小型的 LLM 调用。

Fallback 机制则关注可靠性:当主模型因 rate limit、服务宕机或内容审核而失败时,系统自动降级到备用模型。实现 Fallback 时需要注意:

  1. 异常分类:区分可重试错误(如 429 rate limit)和不可重试错误(如 401 认证失败)。
  2. 状态一致性:Fallback 到不同模型时,应确保上下文格式兼容(虽然 OpenAI 的模型家族基本兼容,但温度、top_p 等行为差异可能导致输出风格突变)。
  3. 熔断保护:如果备用模型也连续失败,应触发熔断,避免级联故障拖垮整个系统。

从成本角度分析,模型路由通常能在不明显降低质量的情况下节省 30%-50% 的 token 费用。而 Fallback 虽然不直接降低成本,但能显著提升系统的可用性 SLA。

ModelSettings 详解:temperature、top_p、tool_choice,以及多模型提供商适配。

正文

相关阅读

参考文档

完整实战示例:智能模型路由与 Fallback 系统

以下示例展示了如何在 Agents SDK 之上实现一个支持路由和 Fallback 的模型管理层:

import asyncio
import random
from dataclasses import dataclass
from agents import Agent, Runner, ModelSettings


@dataclass
class ModelConfig:
    model_id: str
    settings: ModelSettings
    cost_per_1k_tokens: float
    timeout: float


class ModelRouter:
    """智能模型路由器,支持按任务复杂度分派和失败降级。"""

    MODELS = {
        "nano": ModelConfig("gpt-5-nano", ModelSettings(temperature=0.1), 0.05, 10.0),
        "standard": ModelConfig("gpt-5", ModelSettings(temperature=0.2), 0.50, 15.0),
        "pro": ModelConfig("gpt-5.4", ModelSettings(temperature=0.3), 3.00, 20.0),
    }

    def __init__(self):
        self.failure_counts = {k: 0 for k in self.MODELS}
        self.circuit_threshold = 3  # 连续失败3次触发熔断

    def classify_complexity(self, user_input: str) -> str:
        """简易任务复杂度分类器,生产环境可替换为 LLM 分类。"""
        complex_keywords = ["analyze", "compare", "debug", "refactor", "architecture"]
        simple_keywords = ["hello", "hi", "what is", "how to", "yes", "no"]
        lowered = user_input.lower()
        if any(k in lowered for k in complex_keywords):
            return "pro"
        if any(k in lowered for k in simple_keywords):
            return "nano"
        return "standard"

    def select_model(self, user_input: str) -> list[str]:
        """返回按优先级排序的模型列表(主模型 + fallback 链)。"""
        primary = self.classify_complexity(user_input)
        order = [primary]
        if primary == "pro":
            order += ["standard", "nano"]
        elif primary == "standard":
            order += ["nano", "pro"]
        else:
            order += ["standard", "pro"]
        # 过滤掉已熔断的模型
        return [m for m in order if self.failure_counts[m] < self.circuit_threshold]

    async def run_with_fallback(self, agent_builder, user_input: str):
        """尝试主模型,失败时依次降级。"""
        models = self.select_model(user_input)
        last_error = None
        for model_key in models:
            cfg = self.MODELS[model_key]
            try:
                agent = agent_builder(model=cfg.model_id, settings=cfg.settings)
                result = await asyncio.wait_for(
                    Runner.run(agent, user_input),
                    timeout=cfg.timeout
                )
                return result
            except Exception as e:
                self.failure_counts[model_key] += 1
                last_error = e
        if last_error:
            raise last_error
        raise RuntimeError("All models failed")

模型选择决策树

以下决策树帮助你在不同场景下快速选择最适合的模型:
mermaid
flowchart TD
A[开始选择模型] --> B{延迟要求 < 500ms?}
B -->|是| C[选择 gpt-5-nano]
B -->|否| D{任务复杂度?}
D -->|简单问答| E[gpt-5-mini]
D -->|推理+工具| F[gpt-5]
D -->|多模态| G[gpt-5 或 gpt-5o]
C --> H{输出质量达标?}
E --> H
F --> I[直接采用]
G --> I
H -->|是| I
H -->|否| J[升级模型]
J --> D
style C fill:#c5e0b4,stroke:#5a4a3a
style F fill:#e8d5b5,stroke:#5a4a3a
style G fill:#e8d5b5,stroke:#5a4a3a


模型选择的核心权衡是质量、速度和成本三者的平衡。没有最好的模型,只有最适合当前场景的模型。

## 多模型协作:专家混合架构

单一模型难以在所有任务上达到最优。实践中,可以采用专家混合(Mixture of Experts)思路,让不同模型各司其职:

**路由层设计**:使用一个小型快速模型(如 gpt-5-nano)作为路由分类器,判断请求应该由哪个专家模型处理。分类器的训练数据来自历史请求的手动标注,准确率通常可以达到 90% 以上。

```python
from agents import Agent, Runner

router = Agent(
    name="Router",
    instructions="将用户请求分类为: coding, writing, analysis, chat",
    model="gpt-5-nano"
)

coding_expert = Agent(name="Coder", instructions="编程专家", model="gpt-5")
writing_expert = Agent(name="Writer", instructions="写作专家", model="gpt-5")

async def multi_model_chat(message: str):
    route = await Runner.run(router, message)
    category = route.final_output.strip().lower()
    experts = {
        "coding": coding_expert,
        "writing": writing_expert,
    }
    expert = experts.get(category, chat_expert)
    return await Runner.run(expert, message)

这种架构的优势在于成本可控:80% 的简单请求由廉价模型处理,只有 20% 的复杂请求需要调用昂贵的强模型。长期来看,这可以将 API 费用降低 40-60%。

需要注意的是,路由错误会导致用户体验下降。为此,应设置置信度阈值:当路由分类器的置信度低于 0.8 时,直接降级到最强的通用模型,宁可多花钱也不要给错答案。

模型选择不应一成不变。随着业务场景演变,原先适用的模型可能不再是最优解。建议每季度回顾模型性能数据,根据实际效果调整默认模型配置。成本监控同样重要,不同模型的 Token 单价差异巨大,建议在追踪系统中记录每次调用的模型名称和 Token 消耗,定期分析成本分布,优化模型选择策略。

常见问题与调试

问题一:不同模型的输出格式不兼容

当 Fallback 从 gpt-5.4 降级到 gpt-5-nano 时,输出质量可能显著下降,导致下游解析失败(如 JSON 解析错误)。解决方案:

  1. 在 instructions 中强制要求统一的输出格式(如 "Always respond in valid JSON")。
  2. 在后置 Guardrails 中校验输出格式,如果不符合则重试或返回友好的错误信息。
  3. 为轻量级模型提供更详细的格式示例(few-shot)。

问题二:Rate limit 导致频繁降级

如果主模型的 rate limit 过低,系统会频繁触发 Fallback,不仅增加延迟,还可能因备用模型费用更高而反而增加成本。建议:

  1. 在应用层实现令牌桶限流器,主动控制请求速率。
  2. 对非实时请求使用队列缓冲,平滑流量峰值。
  3. 监控各模型的调用比例,及时调整路由策略。

问题三:温度参数对输出一致性的影响

不同任务对创造性的需求不同。客服场景需要低温度(0.0-0.2)以保证回答一致性,而内容创作场景需要高温度(0.7-0.9)以增加多样性。建议在配置中心按 Agent 类型预设温度模板,而不是在每个 Agent 中硬编码。

与其他方案对比

维度Agents SDK + 自建路由LiteLLM ProxyLangChain Model Router
路由粒度任意逻辑(代码级)基于模型可用性基于 Runnable 配置
Fallback 支持需自行实现原生支持需通过 try/catch 实现
成本监控需自建内置 dashboard依赖 LangSmith
部署复杂度低(库内实现)中(独立服务)低(框架内实现)

LiteLLM Proxy 是目前业界最成熟的统一模型接入层,支持 100+ 种模型提供商的原生 Fallback、负载均衡和成本追踪。如果你的系统需要对接多个模型提供商(如 OpenAI + Anthropic + 本地模型),LiteLLM 是更专业的选择。Agents SDK 自建路由的优势在于与业务逻辑的深度整合,例如可以根据用户等级、任务类型甚至时间窗口进行高度定制化的路由决策。

自适应模型路由决策流

---
title: 智能模型路由与Fallback决策流程
---
flowchart TD
    A[用户输入] --> B[任务复杂度分类器]
    B -->|简单查询| C[gpt-5-nano]
    B -->|中等任务| D[gpt-5]
    B -->|复杂推理| E[gpt-5.4]
    C --> F{调用结果}
    D --> F
    E --> F
    F -->|成功| G[返回输出]
    F -->|Rate Limit| H[降级到备用模型]
    F -->|超时| H
    F -->|内容审核失败| I[返回错误信息]
    H --> J{备用模型可用}
    J -->|是| K[重试调用]
    J -->|否| L[触发熔断保护]
    K --> G
    L --> I

自适应模型调参与成本预算控制

模型参数(temperature、top_p、max_tokens)的最优值并非一成不变。同一模型在不同任务类型、不同输入长度下,其最佳配置可能存在显著差异。更进一步,当系统接入了成本预算限制时,传统的静态配置无法满足在预算内最大化效果的需求。温度参数尤其值得关注:客服场景需要低温度以保证回答一致性,而创意写作场景需要高温度以增加多样性,错误地混用这两类配置会导致用户体验严重下降。top_p参数则与temperature形成互补:temperature控制整体随机性,top_p控制词汇截断范围,两者通常只需调整其一即可。

以下是一个自适应参数调优器的实现,它根据任务特征和剩余预算动态调整模型配置:

from dataclasses import dataclass
from typing import Optional
from agents import ModelSettings


@dataclass
class BudgetState:
    daily_limit_usd: float
    consumed_usd: float
    request_count: int


class AdaptiveModelTuner:
    """根据任务复杂度和预算状态自适应调整模型参数。"""
    
    COST_RATES = {
        "gpt-5-nano": 0.05,
        "gpt-5": 0.50,
        "gpt-5.4": 3.00,
    }
    
    def __init__(self, budget: BudgetState):
        self.budget = budget
    
    @property
    def remaining_budget(self) -> float:
        return self.budget.daily_limit_usd - self.budget.consumed_usd
    
    @property
    def budget_pressure(self) -> float:
        if self.budget.daily_limit_usd <= 0:
            return 0.0
        return self.budget.consumed_usd / self.budget.daily_limit_usd
    
    def select_model_and_settings(
        self,
        task_complexity: float,
        expected_output_tokens: int = 500
    ) -> tuple[str, ModelSettings]:
        pressure = self.budget_pressure
        
        if pressure > 0.9:
            model = "gpt-5-nano"
            settings = ModelSettings(temperature=0.1, top_p=0.9, max_tokens=256)
        elif pressure > 0.7:
            model = "gpt-5" if task_complexity > 0.5 else "gpt-5-nano"
            settings = ModelSettings(temperature=0.15, top_p=0.95, max_tokens=512)
        else:
            if task_complexity > 0.8:
                model = "gpt-5.4"
                settings = ModelSettings(temperature=0.3, top_p=1.0,
                                         max_tokens=2048)
            elif task_complexity > 0.4:
                model = "gpt-5"
                settings = ModelSettings(temperature=0.2, top_p=1.0,
                                         max_tokens=1024)
            else:
                model = "gpt-5-nano"
                settings = ModelSettings(temperature=0.1, top_p=0.9,
                                         max_tokens=512)
        
        est_input_tokens = 1000
        total_tokens = est_input_tokens + expected_output_tokens
        cost = (total_tokens / 1000) * self.COST_RATES[model]
        self.budget.consumed_usd += cost
        self.budget.request_count += 1
        
        return model, settings

模型调用延迟分析与语义缓存策略

不同模型的响应延迟差异巨大,轻量级模型可能在数百毫秒内完成,而顶级推理模型可能需要数秒。对于高频重复性问题(如FAQ),在路由层前加入语义缓存可以显著降低成本和延迟。实现语义缓存的关键是计算用户查询与历史查询的向量相似度,当相似度超过阈值时直接返回缓存结果。缓存策略需要权衡命中率与准确率:阈值过高导致命中率低,阈值过低则容易返回不相关答案。生产环境中建议对缓存命中结果进行二次校验,确保语义一致性。

以下是一个基于向量相似度的语义缓存装饰器:

import numpy as np
from typing import Callable
from functools import wraps


class SemanticCache:
    """基于向量相似度的语义缓存,用于拦截高频重复查询。"""
    
    def __init__(self, embedding_fn: Callable[[str], list[float]],
                 similarity_threshold: float = 0.92):
        self.embedding_fn = embedding_fn
        self.threshold = similarity_threshold
        self._cache: list[tuple[list[float], str]] = []
    
    def _cosine_similarity(self, a: list[float], b: list[float]) -> float:
        va, vb = np.array(a), np.array(b)
        return float(np.dot(va, vb) /
                    (np.linalg.norm(va) * np.linalg.norm(vb)))
    
    def get(self, query: str) -> str:
        query_vec = self.embedding_fn(query)
        for cached_vec, cached_result in self._cache:
            sim = self._cosine_similarity(query_vec, cached_vec)
            if sim >= self.threshold:
                return cached_result
        raise KeyError("Cache miss")
    
    def put(self, query: str, result: str):
        query_vec = self.embedding_fn(query)
        self._cache.append((query_vec, result))

要点总结

  1. 预算压力系数是动态降级的核心触发条件,建议设置多级阈值(70%、90%),并在接近上限时提前告警。
  2. 任务复杂度评估可通过轻量级分类器或历史数据聚合得到;预算估算应包含输入和输出token,输出长度可通过max_tokens进行上限控制。
  3. 温度参数的选择应匹配业务场景:低温度适合确定性任务,高温度适合创意任务;不建议在配置中硬编码,而应按任务类型动态派发。
  4. 语义缓存适用于高频重复查询场景,阈值设置需权衡命中率与准确率;缓存容量应设上限避免内存溢出,缓存键应做隐私脱敏处理。
  5. 建议在每日零点重置预算状态,并通过持久化存储避免进程重启导致数据丢失;语义缓存应定期清理过期条目。

生产环境部署与性能优化

模型路由策略的实践要点

将本章节的技术应用到生产环境时,首要考虑的是稳定性与可观测性。建议采用渐进式 rollout 策略:先在开发环境验证核心逻辑,再迁移到预发布环境进行压力测试,最后才全量上线。部署过程中应配置完善的日志收集和指标监控,确保任何问题都能被快速发现和定位。

具体来说,需要在基础设施层面做好以下准备:容器资源限制(CPU/内存)、网络策略配置(防火墙规则、服务网格)、持久化存储选型(SSD vs 标准盘)以及备份恢复方案。对于高可用要求严格的场景,建议部署多实例并配置负载均衡,避免单点故障导致服务中断。

模型性能监控的关键指标

监控是生产系统的生命线。针对本章节涉及的功能,建议重点跟踪以下指标:请求延迟(P50/P95/P99)、错误率(4xx/5xx/超时)、吞吐量(QPS/TPS)以及资源利用率(CPU/内存/磁盘/网络)。这些指标应接入统一的监控大盘,并设置合理的告警阈值。

除了基础指标,还应关注业务层面的指标。例如功能成功率、用户满意度、成本消耗趋势等。通过将技术指标与业务指标关联分析,可以更准确地评估系统改进的实际价值,避免陷入"为了优化而优化"的陷阱。

多模型负载均衡的架构考量

随着业务规模增长,单实例部署很快会成为瓶颈。扩展性设计应在项目初期就纳入考量,而非事后补救。水平扩展通常比垂直扩展更具成本效益,但也引入了分布式系统的复杂性(数据一致性、服务发现、负载均衡等)。

在扩展过程中,建议遵循"无状态优先"原则:将状态外置到独立的存储层(如 Redis、PostgreSQL),使计算层可以随时水平扩容。对于无法避免的状态(如会话、缓存),采用分布式一致性协议或最终一致性模型来管理。定期进行容量规划和压力测试,确保系统在流量峰值时仍能稳定运行。

运维团队的协作建议

技术方案的落地离不开高效的团队协作。建议建立清晰的运维手册(Runbook),涵盖常见故障的诊断步骤、应急处理流程和升级路径。同时,通过定期的复盘会议,将线上事故转化为团队的学习素材,持续完善系统的健壮性。

在工具链方面,推荐将本章节的配置和脚本纳入版本控制(Git),并使用 Infrastructure as Code(IaC)工具(如 Terraform、Ansible)管理基础设施变更。这不仅能提高部署效率,还能确保环境一致性,减少"在我机器上能跑"的问题。

模型选择的决策应基于数据而非直觉。建议搭建模型效果评估平台,对同一批测试用例在不同模型上运行,自动化对比准确率、延迟和成本,形成量化的选型报告。

成本控制是模型选型的核心维度之一。建议每月审查各模型的调用量和费用占比,识别是否存在大材小用的情况。将简单查询迁移到轻量级模型,往往能带来显著的成本优化。
模型选择不应一成不变。随着业务场景演变,原先适用的模型可能不再是最优解。建议每季度回顾模型性能数据,根据实际效果调整默认模型配置。