- 人工智能
- AI 应用
- AI Agent
- 交互助手
- 工具调用
- MCP Clients
- Agent 记忆
【免费下载链接】picoclaw
Tiny, Fast, and Deployable anywhere — automate the mundane, unleash your creativity
本指南针对 PicoClaw 启动或调用模型时最常见的两类报错 ——Error creating provider: model "openrouter/free" not found in model_list与 OpenRouter 返回的"free is not a valid model ID"—— 从症状、根因到配置修复给出完整排查路径,并深入到model_list的 provider/model 两步解析原理与底层源码实现。读完本文,你将能够正确配置agents.defaults.model_name与model_list条目,彻底避开 OpenRouter 免费层路由的经典配置陷阱,并掌握排查同类 "模型未找到" 错误的方法。
症状:你会看到以下错误之一
在 PicoClaw 中配置 OpenRouter 免费模型时,通常会在启动 Agent 或发送首条消息时遇到以下两类报错:
Error creating provider: model "openrouter/free" not found in model_list- OpenRouter 返回 HTTP 400:
"free is not a valid model ID"
第一类错误来自 PicoClaw 本地解析阶段,第二类错误来自 OpenRouter 服务端的拒绝响应。两者往往是同一个配置问题在不同阶段的表现形式:model_list中的model字段被直接当作请求参数发送给上游 API,而它并不是一个 OpenRouter 认可的有效模型路由 ID。
根因:PicoClaw 的 provider/model 两步解析规则
要理解这个报错,必须先理解 PicoClaw 解析 provider 与 model 的两步规则(该规则同样记录在 provider 解析文档 中):
- 如果配置中显式设置了
provider字段,则model字段会被原样发送给该 provider,不做任何改写。 - 如果省略了
provider字段,PicoClaw 会把model中第一个/之前的内容当作 provider,把第一个/之后的内容当作最终发送给上游的运行时模型 ID。
针对 OpenRouter 免费层路由,官方文档(见 troubleshooting.md 与 SKILL.md 中的 "OpenRouterfree is not a valid model ID" 一节)给出的结论非常明确:推荐显式设置provider。逐条对比:
| 配置写法 | 解析结果 | 结论 |
|---|---|---|
"model": "free" | 未选中任何 provider,free被当作裸模型名 | 错误:free不是可直接路由的 OpenRouter 模型配置,且默认会被归到openai协议下 |
"provider": "openrouter", "model": "free" | provider 为openrouter,OpenRouter 收到free | 正确:显式指定 provider,free触发 OpenRouter 自动免费层路由 |
"model": "openrouter/free" | provider 解析为openrouter,运行时模型 ID 解析为free | 也兼容:利用斜杠前缀的隐式解析 |
注意:仓库中另一份多语言版本的文档(如 troubleshooting.pt-br.md)在示例中使用了"model": "openrouter/free"这种隐式写法,而最新版英文文档 troubleshooting.md 则推荐显式"provider": "openrouter", "model": "free"。两者都能工作,但显式provider是更稳妥、可读性更高的推荐写法——它不依赖斜杠切分逻辑,也避免误判含多个斜杠的模型 ID。
修复步骤:正确配置 model_list
在~/.picoclaw/config.json(或你通过配置路径参数指定的其他配置文件)中,按以下两步修改:
agents.defaults.model_name必须匹配model_list中某个条目的model_name。例如默认模型名设为"openrouter-free",就必须能在model_list中找到一个model_name同为"openrouter-free"的条目,否则启动时会直接报model "xxx" not found in model_list or providers(参见 GetModelConfig 的错误分支)。- 该条目的
model字段必须是 OpenRouter 认可的有效模型 ID。推荐同时显式设置provider为openrouter。可选的有效模型 ID 示例:"free"—— OpenRouter 自动免费层路由"google/gemini-2.0-flash-exp:free""meta-llama/llama-3.1-8b-instruct:free"
以最新版推荐写法(显式 provider)为例,一个最小可用的配置片段如下:
{ "agents": { "defaults": { "model_name": "openrouter-free" } }, "model_list": [ { "model_name": "openrouter-free", "provider": "openrouter", "model": "free", "api_keys": ["sk-or-v1-YOUR_OPENROUTER_KEY"], "api_base": "https://openrouter.ai/api/v1" } ] }如果你的配置沿用了隐式写法,也可以写成"model": "openrouter/free"(并在model_list中保留同样的model_name别名),效果等价:
{ "model_name": "openrouter-free", "model": "openrouter/free", "api_keys": ["sk-or-v1-YOUR_OPENROUTER_KEY"], "api_base": "https://openrouter.ai/api/v1" }两种写法共同的关键点在于:agents.defaults.model_name引用的是model_list条目的别名(model_name字段),而model字段才是真正发送给上游 API 的模型标识。OpenRouter 的 API Key 需要在 OpenRouter Keys 中的配置示例。
源码级原理:provider/model 是如何被解析的
ExtractProtocol:两步解析的核心实现
PicoClaw 在创建 provider 时,会调用ExtractProtocol来解出"协议(provider)"与"运行时模型 ID"两个值。该函数的完整注释与实现位于 pkg/providers/factory_provider.go:
func ExtractProtocol(cfg *config.ModelConfig) (protocol, modelID string) { if cfg == nil { return "", "" } model := strings.TrimSpace(cfg.Model) if provider := strings.TrimSpace(cfg.Provider); provider != "" { return NormalizeProvider(provider), model } return SplitModelProviderAndID(model, "openai") }其行为与文档描述的规则完全一致:Provider字段优先;当Provider为空时,回退到从Model推断,且裸模型名(不含/)默认归入openai协议。这也解释了为什么只写"model": "free"时free会被当作普通 OpenAI 兼容模型的 ID 发送——它根本不会命中 OpenRouter 的任何免费路由。函数注释中还给出了几个典型解析示例:
Model "openai/gpt-4o"→("openai", "gpt-4o")Model "nvidia/z-ai/glm-5.1"→("nvidia", "z-ai/glm-5.1")(只有第一个/之前是 provider,其余保留)Provider "nvidia", Model "z-ai/glm-5.1"→("nvidia", "z-ai/glm-5.1")Model "gpt-4o"→("openai", "gpt-4o")
SplitModelProviderAndID:斜杠切分与未知前缀兜底
当provider缺省时,实际执行切分的是 pkg/providers/provider_catalog.go 中的SplitModelProviderAndID。它的一个关键细节是:只有第一个/段落在受支持的 provider 名单(IsSupportedModelProvider)中时,才被当作 provider 剥离;否则整个字符串都视为模型 ID,并回退到默认 provider。这意味着像"openrouter/free"这样以已知协议名开头的写法可以正确解析,而一个既无显式 provider 又不以受支持协议名开头的裸 ID 则会落入默认的openai协议——这正是"model": "free"场景的失败路径。
GetModelConfig:model_name 别名查找与轮询
解析的入口是 pkg/config/config.go 中的GetModelConfig:它以agents.defaults.model_name传入的别名在model_list中查找匹配项,找不到时返回model "xxx" not found in model_list or providers;如果存在多个同名条目,还会通过rrCounter做轮询以实现负载均衡。完整的模型条目字段定义(model_name、provider、model、api_keys、api_base等)见 ModelConfig 结构体,其中model_name被明确注释为 "User-facing alias for the model"(面向用户的别名),而model是 "optionally provider-prefixed"(可选带 provider 前缀)的模型标识。
排查同类错误的扩展清单
除了 OpenRouter 免费层问题,model ... not found in model_list还可能有其他成因,仓库的 SKILL.md 与 model-list 迁移文档 给出了通用排查清单:
- 别名是否匹配:
agents.defaults.model_name与model_list条目的model_name是否完全一致(区分大小写)。 - 条目是否启用:
model_list中目标条目的enabled是否为true。若省略该字段,加载时会按规则推断——具有 API key 或使用保留名"local-model"的条目会被自动启用(见 ModelConfig 注释)。 - provider/model 写法是否符合规则:优先使用显式
provider加原生模型 ID 的写法;使用provider/model兼容写法时,/前的段落必须是受支持的 provider 名。 - 迁移兼容性:如果是从旧版
providers配置迁移而来,旧配置会自动迁移到model_list,同时api_key与api_keys会被合并;若出现unknown provider "xxx" in model "xxx/model-name"报错,说明协议名不受支持,应改用受支持的provider值。
总结
"free is not a valid model ID"与"model ... not found in model_list"本质上是同一个配置误区:把 OpenRouter 的免费层快捷路由free当成了普通模型名直接写在model字段里,却没有正确声明 provider。修复的关键只有两点——在model_list条目中显式设置provider: "openrouter",并确保agents.defaults.model_name与条目的model_name别名一一对应。理解了ExtractProtocol的两步解析逻辑后,这类模型路由问题基本可以做到一次定位、立即修复。
如需进一步了解 PicoClaw 的完整调试流程,可参阅 debug 指南;若要理解其他模型路由与回退机制,可阅读 providers 参考文档。
- 人工智能
- AI 应用
- AI Agent
- 交互助手
- 工具调用
- MCP Clients
- Agent 记忆
【免费下载链接】picoclaw
Tiny, Fast, and Deployable anywhere — automate the mundane, unleash your creativity
相关推荐
PicoClaw 排障指南:修复 "model not found in model_list" 与 OpenRouter "free is not a valid model ID"
PicoClaw 排障指南:修复 "model not found in model_list" 与 OpenRouter "free is not a val
人工智能AI 应用AI Agent交互助手工具调用MCP ClientsAgent 记忆Flipper Zero 车库门 Sub-GHz 破解完整教程:从信号捕获到 12 位暴力破解
Flipper Zero 车库门 Sub GHz 破解完整教程:从信号捕获到 12 位暴力破解 这个 Flipper Zero 资源仓库收录了大量 Sub GH
人工智能AI 应用AI Agent交互助手工具调用MCP ClientsAgent 记忆Paperless-ngx 在 Kubernetes 上 granian 报 is not a valid port number 怎么修复
Paperless ngx 在 Kubernetes 上 granian 报 is not a valid port number 怎么修复 在 Kuberne
后端前端全文检索OCR知识管理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考