config.yaml 成为可选项。
对于常规部署、CI、容器以及 Secret(密钥)注入,建议优先使用环境变量。
当您需要环境变量难以清晰表达的结构时,再使用 config.yaml,尤其是:
- 按提供商覆盖弹性与容错设置
- 自定义提供商实例名称,且无法套用环境变量自动生成的
<provider-type>-<suffix>命名 - 更丰富、便于审阅的提供商模型列表,尤其是在使用 allowlist 模式时
- 按
user_path设置、便于审阅的预算限额 - 较大的嵌套配置,放在一个文件中更便于审阅
<PROVIDER>_<SUFFIX>_API_KEY、<PROVIDER>_<SUFFIX>_BASE_URL 和
<PROVIDER>_<SUFFIX>_MODELS。后缀会转换为以连字符连接的提供商名称:
OPENAI_EAST_API_KEY 注册 openai-east,
OLLAMA_A_BASE_URL 注册 ollama-a。Azure 还支持
<PROVIDER>_<SUFFIX>_API_VERSION。
Google Vertex AI 遵循相同的后缀命名规则(VERTEX_US_PROJECT
注册 vertex-us)。每个实例的 Vertex 项目、区域及其他 Vertex 设置都必须使用相同的后缀:
例如,应将 VERTEX_US_PROJECT 与 VERTEX_US_LOCATION 搭配使用,而不是通用的
VERTEX_PROJECT 或 VERTEX_LOCATION。VERTEX_AUTH_TYPE 默认为
gcp_adc。
已配置的提供商模型列表可以通过 <PROVIDER>_MODELS 保留在环境变量中,例如
OPENROUTER_MODELS、ORACLE_MODELS、AZURE_MODELS、SGLANG_MODELS、
VLLM_MODELS 或 LLMD_MODELS。llm-d 实例还接受带后缀的
LLMD_<SUFFIX>_INFERENCE_OBJECTIVE 和
LLMD_<SUFFIX>_FAIRNESS_FROM_USER_PATH 控制项。
设置 CONFIGURED_PROVIDER_MODELS_MODE=fallback(默认)时,仅在上游 /models 失败或返回为空时使用这些列表;设置为
allowlist 时,对定义了列表的提供商只暴露已配置的模型,并跳过其上游
/models 调用;设置为 merge 时,会在发现的模型清单之上追加已配置的模型——适用于提供商实际提供、却未列在其
/models 列表中的模型。
过滤提供商的模型
model_filter 会将提供商的模型清单收窄到您真正希望可路由的模型。当提供商的模型目录远大于您想暴露的范围时可以使用它——例如使用 OpenRouter 的免费套餐做实验,而由另一个提供商承载生产环境流量。
模式为 glob,与提供商的原始模型 ID 进行不区分大小写的匹配。
* 匹配任意长度的字符序列,包括 /,因此 *:free 可匹配
deepseek/deepseek-r1:free;? 恰好匹配一个字符。
设置了 max_price_per_mtok 时,定价未知的模型会被丢弃:放行未知价格模型的价格上限算不上上限。价格来自模型注册表以及提供商自身的报告——OpenRouter 会公布自己的费率,因此其模型目录(包括 :free 变体)无需额外配置即可获得定价。本地提供商通常完全不报告定价,因此应按模式而不是按价格过滤它们。
max_price_per_mtok 必须是大于或等于 0 的有限数。负数、NaN 或无穷大的上限会导致启动失败,而不是静默拒绝所有模型或禁用上限;环境变量值根本不是数字时同样如此——运维人员以为已生效的成本控制,绝不能悄无声息地缺失。
过滤作用于最终的模型清单,即在
configured_provider_models_mode 解析完成之后,因此它也会收窄通过
models 添加的模型。被过滤的模型会完全离开可路由目录:它们不再出现在
GET /v1/models 中,对它们的请求会返回 “model not found”。
过滤只是提供商所提供模型的一个视图,而不是删除。网关会在内存和模型缓存中保留未过滤的清单,因此放宽过滤条件——或者某个模型降价到可以通过价格上限——会在下一次元数据刷新时恢复该模型,无需等待上游 /models 调用成功。
同样的过滤器也可以通过环境变量按提供商配置:
OPENROUTER_EU_MODEL_FILTER_INCLUDE 配置的是
openrouter-eu。
优先级顺序
实际生效的优先级为:- 环境变量
- 可选的
config/config.yaml或config.yaml - 代码中的内置默认值
.env 并不是单独的优先级层。它只是在启动前加载环境变量的一种便捷方式。
每一层都叠加在前一层之上,因此在 config.yaml 中声明、再由环境变量覆盖的提供商,仍被视为来自配置文件。
启动校验
声明式配置采用严格解析:未知键会导致启动错误,而不是被静默忽略。这可以捕获拼写错误(如把port: 写成 prot:),更重要的是能捕获缩进错误的配置段——参见下文的注意事项。
这同时适用于 config.yaml 以及以 JSON 声明相同结构的环境变量:VIRTUAL_MODELS、SET_RATE_LIMIT_* 和 SET_BUDGET_*。
由于环境变量条目会覆盖 YAML 条目,否则其中的拼写错误会悄无声息地压过正确的 YAML 条目。
默认采用严格模式,是因为 providers、rate_limits、budgets
或 guardrails 条目一旦被丢弃,就会静默改变路由、成本或安全行为——一个从未生效的成本上限,看起来和一个正在生效的成本上限毫无二致。
设置 CONFIG_STRICT=false 可将未知键降级为警告,并在忽略这些键的情况下启动。此选项用于在较新的配置文件下回滚二进制文件,不适合日常使用:
CONFIG_STRICT 放宽的是接受哪些键,从不放宽值是否合理的检查。格式错误的值(port: [9999, 8080])在两种模式下都会中止启动。
实体级校验同样仍然适用:如果某个虚拟模型的目标指向一个不存在的提供商,即使本应声明该提供商的键已被作为警告忽略,启动也会失败。
为确认提供商来自哪一层,GoModel 会在启动时输出一行日志:
from_config_file: 0,表示该文件未提供任何提供商。GoModel 还会输出包含解析后路径的 config file loaded,或包含已搜索路径的
no config file found。
当前 Schema
当前的权威来源位于主代码库中: 如果部署挂载在域名根路径之下,请设置server.base_path 或
BASE_PATH。例如,BASE_PATH=/g 会在 /g/v1/...、
/g/admin/... 和 /g/health 下提供网关服务。
如需更改入站用户路径请求头,请设置 server.user_path_header 或
USER_PATH_HEADER。默认值仍为 X-GoModel-User-Path。
对此文件的修改可通过 gomodel --reload 应用到正在运行的网关,
该命令会重新读取文件和环境变量,并原地重建网关——
参见 CLI 操作。如果新文件加载失败,则不会发生任何变化。server.port 和 server.pid_file 是例外:
两者在进程生命周期内固定不变,因此重载时会输出警告,并保留当前运行值,直到网关重启。
Docker
GoModel 会先读取config/config.yaml,然后读取 config.yaml。
使用 docker run 时,您可以在主机上保留名为 config.yml 的文件,并将其挂载到 GoModel 期望的容器内路径:
注意事项
未解析的 ${VAR} 占位符会导致提供商被丢弃
如果 YAML 中出现了 ${OPENAI_API_KEY},但该环境变量实际并未设置,字面字符串 ${OPENAI_API_KEY} 就会成为 API 密钥的值。凭据过滤器检测到 ${ 子串后,会将该提供商整个移除。如果 ${VAR} 出现在值的中间(例如
prefix-${OPENAI_API_KEY}),同样如此。启动进程前请务必确认环境变量已导出,或者提供默认值:${OPENAI_API_KEY:-}。如果希望改为中止启动,请使用严格的
Secret 引用 ${env:OPENAI_API_KEY}。
缩进错误的 providers: 配置段会被拒绝
YAML 会将下面的内容解析为一个空的 providers: 配置段加上两个无关的顶层键,而不是两个提供商:
providers: 下缩进两个空格。在引入严格解析之前,这种配置会以零个 YAML 提供商启动,且不报任何错误。使用 CONFIG_STRICT=false 时,它会以零个 YAML 提供商启动,并为每个未缩进的键输出一条警告。
按提供商的弹性与容错设置只能来自 YAML
环境变量覆盖遍历会跳过map 字段。RETRY_MAX_RETRIES 会更改所有提供商的全局默认值,但无法针对单个提供商。
按提供商调整需要在 config.yaml 中使用 providers.<name>.resilience: 块。
部分 YAML 会让其余字段保持默认值
YAML 会被反序列化到一个已填充内置默认值的结构体上。只有文件中出现的字段才会被写入。在resilience.retry 中省略
max_backoff 时,它会保持内置默认值;对满意的默认值,您无需重复声明。