Skip to content

模型与路由:不要把「换模型」当成搜索替换

问题场景

Agent 应用不是只选一个最强模型就结束。真实项目里,模型选择会同时受到任务类型、成本、延迟、上下文长度、工具调用能力、结构化输出能力和供应商稳定性的影响。

对 vibe coding 开发者来说,最常见的风险是让 AI 把模型名写死在多个文件里。这样做短期能跑,后续切换供应商、做 A/B 测试或接本地模型时会很难维护。

Mastra 的模型接口

Mastra 官方 Models 文档说明,模型可以用统一的 provider/model 字符串表示。例如:

ts
const studyAgent = new Agent({
  id: 'study-agent',
  name: 'Study Agent',
  instructions: '基于课程资料回答学习问题。',
  model: 'openai/gpt-5.5',
})

同一个 Agent 可以切到其他供应商,不需要改 Agent 的主体结构:

ts
const studyAgent = new Agent({
  id: 'study-agent',
  name: 'Study Agent',
  instructions: '基于课程资料回答学习问题。',
  model: 'anthropic/claude-sonnet-4-6',
})

官方文档还说明,Mastra 会根据模型供应商读取对应环境变量。缺少 API Key 时,应把它视为运行时配置错误,而不是把密钥写进代码。

不要把密钥交给 AI

.env 只放在本机或部署环境中。给 AI 编程工具的上下文里只需要变量名,例如 OPENAI_API_KEYANTHROPIC_API_KEY,不要粘贴真实值。

模型策略不是一个字段

模型策略至少要回答四个问题:

问题设计选项验证方式
哪个任务用哪个模型计划生成用便宜模型,复杂推理用强模型固定样例对比质量和耗时
失败时怎么办设置 fallback 模型模拟主模型不可用
用户能不能选模型RequestContext 动态选择两组上下文返回不同模型
本地模型能不能接入使用 OpenAI-compatible endpoint本地服务断开时有清楚错误
mermaid
flowchart LR
  A["用户请求"] --> B["RequestContext"]
  B --> C{"任务类型"}
  C -- "检索摘要" --> D["低成本模型"]
  C -- "复杂规划" --> E["强推理模型"]
  C -- "主模型失败" --> F["fallback 模型"]
  D --> G["Agent / Tool / Workflow"]
  E --> G
  F --> G

动态模型选择

新版官方文档把请求级变量称为 RequestContext。模型字段可以写成函数,根据请求级变量决定使用哪个模型:

ts
import { RequestContext } from '@mastra/core/request-context'

type StudyRequestContext = {
  'model-tier': 'fast' | 'reasoning'
}

const context = new RequestContext<StudyRequestContext>()
context.set('model-tier', 'reasoning')

const studyAgent = new Agent({
  id: 'study-agent',
  name: 'Study Agent',
  instructions: '基于课程资料回答学习问题。',
  model: ({ requestContext }) => {
    const tier = requestContext.get('model-tier')
    return tier === 'reasoning' ? 'openai/gpt-5.5' : 'openai/gpt-5-mini'
  },
})

await studyAgent.generate('制定 3 天学习计划', {
  requestContext: context,
})

这类逻辑适合放在服务端。前端最多传入「快 / 准 / 省」这类业务选项,不应该直接让未受信任用户提交任意模型 ID。

Fallback 不是质量提升器

Mastra 支持模型 fallback:主模型遇到 500、限流或超时时,自动尝试下一个模型。

ts
const resilientAgent = new Agent({
  id: 'resilient-study-agent',
  name: 'Resilient Study Agent',
  instructions: '基于课程资料回答学习问题。',
  model: [
    { model: 'openai/gpt-5.5', maxRetries: 2 },
    { model: 'anthropic/claude-sonnet-4-6', maxRetries: 1 },
    { model: 'google/gemini-2.5-pro', maxRetries: 1 },
  ],
})

Fallback 只解决可用性问题,不保证答案更好。不同模型的工具调用、结构化输出、长上下文表现可能不同,所以必须配合固定评估样例。

Embedding 模型也要纳入策略

RAG 和 semantic recall 会用 embedding 模型。官方 Embedding models 文档说明,embedding 也可以使用 provider/model 形式,并要关注向量维度。

ts
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'

const embedder = new ModelRouterEmbeddingModel('openai/text-embedding-3-small')

设计 RAG 时要把「生成模型」和「embedding 模型」分开记录:

模型负责内容常见失败
生成模型读上下文并回答幻觉、工具调用不稳定、格式错误
embedding 模型把文本转成向量维度不匹配、语义召回差
rerank 模型重排候选片段成本上升、延迟增加

给 AI 编程工具的提示词

text
请为这个 Mastra Study Agent 设计模型策略。
要求:
- 不要把模型名散落在多个文件。
- 默认模型从环境变量 MASTRA_MODEL 读取,缺省值写在一个地方。
- 用 RequestContext 支持 fast / reasoning 两种模式。
- 设计 fallback,但说明 fallback 只处理可用性,不代表质量更高。
- 列出需要新增或读取的环境变量名,不要要求我提供真实密钥。
- 给出 5 条验证样例,比较输出质量、延迟、工具调用和结构化输出。

验证清单

验证项方法
模型配置集中搜索 model:,确认没有无意义重复
API Key 不进代码搜索 sk-api_key=、真实供应商密钥格式
动态模型生效用两组 RequestContext 调用同一输入
fallback 可观测记录最终使用的模型和失败原因
RAG 维度匹配embedding 模型维度与向量库 index 一致
质量可比较同一 eval cases 下比较不同模型分数

常见错误

错误后果修复
直接让前端传模型 ID用户可能选择未授权模型或高成本模型前端传模式,服务端映射模型
只测试最终文本看不出工具调用能力差异同时检查 tool-calltool-result 和结构化输出
fallback 模型能力不一致主模型失败后输出格式变了只选择能力相近的 fallback
embedding 模型随意替换向量库旧数据不可用或召回变差记录模型和维度,必要时重建索引

小练习

为 Study Agent 设计一张模型矩阵:fastbalancedreasoning 三种模式分别使用什么生成模型、embedding 模型、RAG topK 和最大工具调用步数。再写出两条必须人工验收的评估样例。