OpenCode 模型与 Provider:多模型自由切换
Posted on Sat 03 October 2026 in AI 编程 • Sucre Liu
模型引用长什么样
OpenCode 里模型的标准引用是:
provider/model
openai/gpt-5.2
openai/gpt-5.2#high
openrouter/anthropic/claude-sonnet-4.5#high
规则要记清,否则会配出莫名其妙的值:
| 部分 | 规则 |
|---|---|
| provider | 到第一个 / 为止,不能含 / 或 # |
| model | 可以再含 /,不能含 # |
| variant | 跟在 # 后面 |
| 大小写 | provider 和 model ID 区分大小写 |
用目录里的 ID,不要用 provider 的展示名。会话里用 /models 选,会把它列出来:
/models
选择只作用于当前会话,不会改配置文件。这一点和很多工具不同,意味着你随手试一个贵模型,不会不小心把它变成默认。
连接与默认值
大多数 provider 先连账号:
/connect
/models
设默认模型写在项目或全局配置里:
{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-5"
}
几个行为要知道:
- 配置的默认模型只在"已启用且 provider 可用"时生效,否则回退到最新的可用模型;
- 会话里已经选过的模型优先于配置默认;
- 切换会话模型不会回写配置文件;
- 根级
model只保留 provider 和 model,不保留 variant。
最后一条是个坑:你写 "model": "openai/gpt-5.2#high" 到根级,variant 可能不生效。要变体,就在会话、run、agent、command 上指定。
变体:控成本最直接的杠杆
变体(variant)是同一个模型上的命名选项,通常对应推理强度或 token 预算:
opencode run --model openai/gpt-5.2#high "Review this migration plan"
变体名来自模型当前目录的元数据。low、high、max 这类名字不是每个模型都有,写了不存在的变体会直接报模型解析错误。
你也可以自己定义或覆盖同 ID 的变体:
{
"providers": {
"openai": {
"models": {
"gpt-5.2": {
"variants": [
{ "id": "fast", "settings": { "reasoningEffort": "low" } },
{ "id": "deep", "settings": { "reasoningEffort": "high", "reasoningSummary": "auto" } }
]
}
}
}
}
}
实践里,把"日常改动用低推理、复杂决策用高推理"固化成两个变体,比每次手动切模型更省事,也更省钱。
请求覆盖:settings / headers / body
provider、model、variant 三层都可以加请求设置,应用顺序是 provider → model → variant:
{
"providers": {
"openai": {
"settings": { "baseURL": "https://api.example.com/v1" },
"headers": { "X-Team": "platform" },
"models": {
"gpt-5.2": {
"settings": { "reasoningEffort": "high" },
"body": { "store": false }
}
}
}
}
}
settings:provider 包选项,如baseURL、reasoningEffort;headers:附加 HTTP 头(大小写不敏感);body:合并进请求体的字段。
嵌套对象合并,数组和标量后者覆盖前者。选项是 provider 特定的,换一个 provider 包可能被忽略或拒绝。
modelID 和 model:别搞反
这里有个命名陷阱,值得单独拎出来:
- 在选择器里(会话、agent、command 的
model)用model; - 在 provider 的
models映射里,键是 OpenCode 用的 ID,modelID才是发给 provider 的真实 ID。
{
"model": "openai/coding-default",
"providers": {
"openai": {
"models": {
"coding-default": {
"modelID": "gpt-5.2",
"name": "Coding default"
}
}
}
}
}
这里 openai/coding-default 是你选的,gpt-5.2 是发给 provider 的。报错 Model unavailable 时,先核对映射的键,而不是 modelID。
本地模型:开箱发现
Ollama、LM Studio、vLLM 在默认地址上会被自动发现,不需要连接账号:
{
"model": "ollama/gemma3:4b"
}
各自默认端点和注意点:
| 运行时 | 默认地址 | 注意 |
|---|---|---|
| Ollama | http://127.0.0.1:11434 |
只收录带 completion 能力的模型,嵌入模型不出现 |
| LM Studio | http://127.0.0.1:1234 |
排除嵌入模型 |
| vLLM | http://127.0.0.1:8000 |
先查 /health;工具调用能力无法探测,默认关闭 |
vLLM 那条尤其重要:工具调用要靠服务端开关(如 --enable-auto-tool-choice 和对应的 parser),而发现过程拿不到这些信息,所以发现出来的模型 tools 是关的。需要就手动在配置里声明能力。
换地址就设 settings.baseURL,并且带上 /v1(否则发现路径会对不上)。要关掉某个自动发现:
{ "plugins": ["-opencode.provider.ollama"] }
自定义 OpenAI 兼容端点
不在目录里的服务,手写一个 provider。至少给包、端点和一个模型:
{
"model": "local/coder",
"providers": {
"local": {
"name": "Local server",
"package": "@opencode/ai/providers/openai-compatible",
"settings": { "baseURL": "http://127.0.0.1:1234/v1" },
"models": {
"coder": {
"modelID": "model-name-on-server",
"capabilities": { "tools": true, "input": ["text"], "output": ["text"] },
"limit": { "context": 32768, "output": 8192 }
}
}
}
}
}
能力与上限要你手填准确值。 OpenCode 对目录外的模型有一组兜底假设(如 200k 上下文、32k 输出、支持工具),那只是假设,不是探测结果。填错会导致截断或工具调用失败。
网关与几家特殊 provider
- OpenRouter 用原生运行时和目录,模型引用带完整 OpenRouter ID;走兼容网关时保留原生包,才能保住它的请求与推理行为。
- Azure 需要
settings.resourceName(或环境变量),且不会查询管理 API 或自动发现部署;部署名和目录名不一致时用modelID映射。 - Bedrock 走 AWS 默认凭据链,profile 或凭据是必需项,只设区域不会激活。
- Vertex 用 ADC,且必须有可解析的 project,光有 ADC 不会激活。
这些"看起来配了却没出现"的情况,多半就卡在上面这几条。
WebSocket:长会话的省流
OpenAI、xAI 和部分 Azure Responses 模型可以每个会话保持一条 WebSocket,连续步骤只发增量:
{ "providers": { "openai": { "settings": { "transport": "websocket" } } } }
找不到通道会降级回 HTTP;连接断开下一步重连。装了 http.request/http.response 钩子的 provider 插件会留在 HTTP,保证每个请求可观测。
配错时先看这张表
| 现象 | 先查 |
|---|---|
No model is available for session |
当前没有可选模型,先完成连接再选 |
Model unavailable: provider/model |
provider 未激活、ID 不存在/被禁用,或发现不再返回;自定义别名核对映射键 |
Cannot initialize ... NAME is required |
baseURL 里还有未替换的 ${NAME} 占位 |
| Azure 报资源名缺失 | 配 resourceName 或对应环境变量 |
| Vertex 不出现 | 缺 project(ADC 不够) |
| Bedrock 不出现 | 缺 profile 或凭据(区域不够) |
| Ollama 无模型 | 检查 /api/tags、/api/show 与 completion 能力 |
小结
- 引用格式
provider/model#variant,provider 到第一个/为止,大小写敏感。 - 根级
model不保留变体;变体在会话/run/agent/command 上指定。 modelID是"发给 provider 的 ID",别和选择器的model搞混。- 本地模型自动发现,但 vLLM 的工具能力探测不到,要手配。
- 目录外模型的能力/上限要手填准确,别信兜底假设。
下一篇讲怎么把这套能力组织成你自己的工具:自定义 agent、技能与命令。