# 虚拟模型

来源: https://platform.lyrouter.com/ai_gateway/docs/presets
更新日期: 2026-10-14

虚拟模型把主模型、备用模型、Channel 排序策略、推理参数和系统提示词打包成一个名称。客户端把请求的 `model` 写成 `@vmodel/<名称>`，网关先调用主模型，失败时按顺序改用备用模型，并把参数和系统提示词合并进发给上游的请求。之后更换模型或调整参数，只需修改虚拟模型，客户端代码不用改。

## 适用场景

- 多个应用共用同一套模型和参数，需要集中调整。
- 主模型不可用时自动改用其他模型，客户端不必自己换模型重试。
- 统一并锁定 `temperature`、`max_tokens`、输出格式等参数。
- 为没有自带系统提示词的请求补上统一的系统提示词。

如果只需要在同一模型的多个通道之间选路，直接调用模型 ID 即可，见[通道选择与路由策略](https://platform.lyrouter.com/ai_gateway/docs/routing)。

## 调用虚拟模型

把 `model` 写成 `@vmodel/<名称>`，其他写法与调用普通模型相同。下例调用名为 `support-bot` 的虚拟模型，环境变量的设置见[完成第一次模型调用](https://platform.lyrouter.com/ai_gateway/docs/quickstart)：

```bash
curl "$LYROUTER_BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $LYROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"@vmodel/support-bot","messages":[{"role":"user","content":"用一句话介绍你自己"}]}'
```

- **支持的接口**：`/v1/chat/completions`、`/v1/messages` 和 `/v1/responses`。图像、视频和语音接口不支持虚拟模型，会返回 403 `Model is not available in the model plaza`，请改用具体的模型 ID。
- **名称区分大小写**：名称只含小写字母、数字和连字符，`@vmodel/Support-Bot` 找不到 `support-bot`。旧前缀 `@preset/<名称>` 与 `@vmodel/<名称>` 等价。
- **按工作空间区分**：虚拟模型属于一个工作空间，该工作空间的任何有效 API Key 都可以调用它，没有单独的 Key 级授权。
- **查询可用名称**：`GET /v1/models` 会以 `@vmodel/<名称>` 列出工作空间中已启用的虚拟模型。看不到虚拟模型页面的成员可以从这里查到名称。
- **上游与计费**：上游收到的 `model` 是实际调用的模型 ID，费用也按实际模型计算。

## 创建虚拟模型

当前账号管理员在工作空间的 **虚拟模型** 页面点击 **创建虚拟模型**。普通成员看不到这个菜单，但可以调用已经启用的虚拟模型。表单分为「基础信息」「模型与路由」「推理参数」「系统提示词」四部分，只有「虚拟模型名称」和「默认模型」是必填项。

| 字段 | 说明 |
| --- | --- |
| 虚拟模型名称 | 调用名，即 `@vmodel/` 后面的部分。只能用小写字母、数字和连字符，以字母或数字开头，在工作空间内唯一 |
| 默认模型 | 优先使用的模型，列表中显示为「主模型」 |
| 备用模型 | 可选，可填多个，主模型不可用时按填写顺序尝试 |
| Channel 排序策略 | 同一模型有多个通道时的排序：按价格优先、按吞吐量优先、按延迟优先、负载均衡（默认） |
| 推理参数 | 七组共 17 个参数，每个参数可以单独锁定，见下文 |
| 系统提示词 | 客户端请求没有系统提示词时由网关补上，见下文 |

（截图：虚拟模型列表展示可复制的调用名称、主模型、锁定参数和启用状态。）

- 「默认模型」和「备用模型」可以从模型目录中选择，也可以直接输入模型 ID。保存时不检查这些模型在本工作空间是否可用，调用时会跳过不可用的模型。保存前请确认它们已在[模型广场](https://platform.lyrouter.com/ai_gateway/docs/choose)开通，或已配置可用的 [BYOK](https://platform.lyrouter.com/ai_gateway/docs/byok)。
- 保存后虚拟模型即为「已启用」，几秒内同步到网关，不需要更换 API Key。「保存并测试」按钮暂不可用，请直接发送一次调用验证。

（截图：虚拟模型配置中设置主模型、备用模型和推理参数；按实际名称调用。）

### 保存失败的常见提示

| 提示 | 原因 |
| --- | --- |
| 虚拟模型名称需匹配 ^[a-z0-9][a-z0-9-]*$ | 名称含大写字母、空格或中文，或以连字符开头 |
| 请选择默认模型 | 没有填写「默认模型」 |
| `slug already in use in this workspace` | 本工作空间已有同名虚拟模型 |
| JSON Schema 不是合法的 JSON，请检查语法。 | 「响应格式」的 JSON Schema 文本有语法错误 |
| `invalid preset params: response_format.json_schema.name is required ...` | JSON Schema 对象缺少非空的 `name`，见下文「推理参数」 |
| 请填写指定函数的名称 | 「工具选择」选了指定函数，但没有填写函数名 |

## 实际调用哪个模型

网关按以下顺序尝试，前一个模型的所有通道都失败后，才进入下一个模型：

1. 虚拟模型的「默认模型」（主模型）。
2. 「备用模型」，按填写顺序。网关不会因为某个备用模型更快或更便宜就把它提前。
3. 工作空间的默认模型，前提是已在[智能路由](https://platform.lyrouter.com/ai_gateway/docs/routing)中设置。

同一个模型由多个通道提供时，按虚拟模型的「Channel 排序策略」排序；在 BYOK 中设置的「优先使用此 Channel」「仅用此 BYOK」仍然优先。完整的回退规则和不会回退的情况见[失败重试与备用模型](https://platform.lyrouter.com/ai_gateway/docs/fallback)，其中两种最常见：

- 安全围栏的模型策略禁止了实际选中的模型时，请求立即返回 403 `Request blocked by guardrail policy`，不再尝试备用模型。围栏按实际模型 ID 检查，在模型策略里填写 `@vmodel/...` 不起作用。
- 当前模型不支持请求的输入或接口时（例如给只接受文本的模型发送图片），请求立即返回 400，不再尝试备用模型。因此备用模型应与主模型支持相同的输入类型和工具调用能力。

## 推理参数：默认值与锁定

每个参数在未锁定时是默认值，锁定后是强制值：

| 状态 | 客户端没传该参数 | 客户端传了该参数 |
| --- | --- | --- |
| 未锁定 | 使用虚拟模型的值 | 使用客户端的值 |
| 已锁定 | 使用虚拟模型的值 | 使用虚拟模型的值，覆盖客户端的值 |

| 分组 | 参数 | 取值 |
| --- | --- | --- |
| 采样 | `temperature`、`top_p`、`top_k`、`seed` | 0～2；0～1；≥0 的整数；整数 |
| 长度 | `max_tokens`、`stop` | ≥1 的整数；字符串或字符串数组 |
| 惩罚 | `frequency_penalty`、`presence_penalty`、`repetition_penalty` | -2～2；-2～2；大于 0 |
| 输出格式 | `response_format` | `text`、`json_object`、`json_schema` |
| 推理控制 | `reasoning_effort`、`enable_thinking`、`thinking_budget` | `minimal`/`low`/`medium`/`high`；是或否；≥0 的整数 |
| 工具 | `tool_choice`、`parallel_tool_calls` | `auto`、`none`、`required` 或指定函数；是或否 |
| 流式 | `stream`、`stream_options.include_usage` | 是或否；是或否 |

- 只有设置了值的参数才能锁定。`response_format`、`tool_choice` 这类对象参数整体替换，不逐字段合并。
- 未锁定的默认值不适用时会自动跳过：请求没有 `tools` 时不补 `tool_choice`；`response_format` 为 `json_object` 而对话中没有出现 "json" 字样时不补。锁定的参数总是写入。
- 参数按 Chat Completions 的字段名原样合并，`/v1/responses` 请求也是如此，例如 `max_tokens` 不会换成 `max_output_tokens`，上游可能因此返回 400。给 Responses 客户端使用的虚拟模型，建议只设置 `temperature`、`top_p` 这类两种协议通用的参数。
- `stream` 会改变响应形式：设为「是」并生效时，非流式请求也会收到 SSE 事件流。
- `reasoning_effort`、`enable_thinking`、`thinking_budget` 分属不同厂商，网关不会相互换算，请按主模型所属厂商支持的那一个填写。
- 「响应格式」选择 JSON Schema 时，要填 OpenAI `response_format.json_schema` 的完整对象，例如 `{"name": "answer", "schema": {"type": "object", "properties": {"text": {"type": "string"}}}}`。只粘贴 Schema 本身会保存失败。
- 控件变灰并提示「当前主模型不支持该参数」只是控制台提示，网关不会按模型能力删减参数。

## 系统提示词何时注入

| 接口 | 注入规则 |
| --- | --- |
| `/v1/chat/completions` | `messages` 中没有 `role` 为 `system` 的消息时，插到最前面；已有则不注入 |
| `/v1/messages` | 请求没有 `system` 时注入；已有则不注入 |
| `/v1/responses` | `instructions` 为空时直接填入；已有内容时空一行后追加 |

系统提示词不能锁定：Chat 和 Messages 请求自带系统提示词时，虚拟模型的提示词不生效。`developer` 角色的消息不算系统提示词。改用备用模型时会重新注入一次，不会重复叠加。

## 编辑、停用和删除

| 操作 | 对调用的影响 |
| --- | --- |
| 编辑 | 保存后新请求按新配置执行。修改名称等于修改调用名，旧名称立即失效 |
| 禁用 | 状态变为「已停用」，网关不再识别该名称，`GET /v1/models` 也不再列出 |
| 启用 | 原名称恢复可用 |
| 克隆 | 打开预填全部配置的创建表单，名称加 `-copy` 后缀，点击保存后才创建 |
| 删除 | 输入名称确认后永久删除，之后可以用同一名称重新创建 |

虚拟模型被禁用、删除或改名后，旧名称的请求不再匹配任何虚拟模型。工作空间设置了默认模型时，这类对话请求会改由默认模型回答；没有设置时返回 503 `all routed candidates exhausted`。

## 验证与常见问题

调用后在[请求日志](https://platform.lyrouter.com/ai_gateway/docs/logs)中打开这条记录，「路由追踪」的「虚拟模型」显示虚拟模型名称（不带 `@vmodel/` 前缀），「模型（实际）」显示实际回答的模型，详见[查看实际路由](https://platform.lyrouter.com/ai_gateway/docs/route-log)。

### 调用返回 503 `all routed candidates exhausted`，应该检查什么？

**答：** 先核对 `@vmodel/<名称>` 的拼写和大小写，再用 `GET /v1/models` 确认它在列表中，即处于已启用状态。名称无误时，请账号管理员确认「默认模型」和「备用模型」已在模型广场开通或配置了可用的 BYOK。

### 为什么回答来自虚拟模型之外的模型？

**答：** 主模型和备用模型都失败后，网关会使用工作空间的默认模型。名称写错或虚拟模型已停用时，对话请求也会直接由默认模型回答。在日志的「模型（实际）」中可以确认，不需要兜底时请账号管理员清空智能路由中的默认模型。

### 锁定参数后上游返回 400，怎么办？

**答：** 锁定的参数总是写入请求，上游不支持时会拒绝。打开日志的「原始报文」，对比「上游请求」与「上游响应」找到被拒绝的参数，再取消锁定或删除该参数。
