LobeHub CLI 深度指南:`lh model` 与 `lh provider` 模型与供应商管理命令
本篇围绕 LobeHub CLI 中 lh model 与 lh provider 两组命令展开:覆盖完整的子命令清单、选项参数、默认值与典型用法,并深入 CLI 实现源码(apps/cli/src/commands/model.ts、apps/cli/src/commands/provider.ts)、服务端 tRPC 路由(apps/server/src/routers/lambda/aiModel.ts、apps/server/src/routers/lambda/aiProvider.ts)与数据仓库层(packages/database/src/repositories/aiInfra/index.ts),说明每条命令背后的真实调用链、权限约束与数据合并逻辑,帮助你用命令行完成模型/供应商的全生命周期管理并理解其底层实现。
一、命令体系总览:CLI 如何操作模型与供应商
LobeHub CLI(npm 包名 @lobehub/cli,见 apps/cli/package.json)提供 lh(以及别名 lobe、lobehub)两个入口,基于 commander 构建命令树。模型与供应商管理由两个注册函数提供:
registerModelCommand:apps/cli/src/commands/model.tsregisterProviderCommand:apps/cli/src/commands/provider.ts
从源码结构看,CLI 本身不直接访问数据库,而是通过 getTrpcClient()(apps/cli/src/api/client.ts)建立 tRPC 客户端,所有写操作最终落到服务端路由:
| CLI 命令 | tRPC 过程(mutation/query) | 服务端路由文件 |
|---|---|---|
lh model list |
aiModel.getAiProviderModelList(query) |
aiModel.ts |
lh model create |
aiModel.createAiModel |
同上 |
lh model edit |
aiModel.updateAiModel |
同上 |
lh model toggle |
aiModel.toggleModelEnabled |
同上 |
lh model batch-toggle |
aiModel.batchToggleAiModels |
同上 |
lh model batch-update |
aiModel.batchUpdateAiModels |
同上 |
lh model sort |
aiModel.updateAiModelOrder |
同上 |
lh model delete |
aiModel.removeAiModel |
同上 |
lh model clear |
aiModel.clearModelsByProvider / clearRemoteModels |
同上 |
lh provider list / view |
aiProvider.getAiProviderList / getAiProviderById(query) |
aiProvider.ts |
lh provider create |
aiProvider.createAiProvider |
同上 |
lh provider edit |
aiProvider.updateAiProvider |
同上 |
lh provider config |
aiProvider.updateAiProviderConfig |
同上 |
lh provider test |
aiProvider.checkProviderConnectivity |
同上 |
lh provider toggle |
aiProvider.toggleProviderEnabled |
同上 |
lh provider delete |
aiProvider.removeAiProvider |
同上 |
一个重要的版本细节:模型类型 stt 已在 schema 中重命名为标准写法 asr。CLI 在 model.ts#L10-L13 中保留了对旧别名的兼容——normalizeModelType 把传入的 stt 归一化为 asr 后再转发与比较,因此老脚本和习惯用法(如 --type stt)仍然可用;服务端仓库层也通过 normalizeAiModelType(packages/model-bank/src/types/aiModel.ts)做读取时的映射。官方命令描述中的类型枚举为:
chat | embedding | tts | asr | image | video | text2music | realtime
二、模型管理:lh model 全子命令详解
2.1 lh model list <providerId>:列出供应商下的模型
列出某个供应商下的模型,支持类型过滤、启用状态过滤、条数限制与 JSON 输出:
lh model list openai
lh model list openai --type image --enabled
lh model list lobehub --type video --json
| 选项 | 说明 | 默认值 |
|---|---|---|
-L, --limit <n> |
最大返回条数 | 50 |
--enabled |
只显示已启用的模型 | false |
--type <type> |
按类型过滤(chat|embedding|tts|asr|image|video|text2music|realtime,兼容旧别名 stt) |
- |
--json [fields] |
输出 JSON,可附带字段名(逗号分隔)做字段投影 | - |
表格输出列为 ID、NAME、ENABLED、TYPE(见 model.ts#L64-L71),启用状态以绿色 ✓ 显示,禁用为暗淡 ✗;NAME 列超过 40 字符会被 truncate 截断。
参数取值范围:limit 的服务端 zod 校验为 z.number().int().min(1).max(200)(aiModel.ts#L169-L177),即单次最多取 200 条,超出会被服务端拒绝。
底层数据合并逻辑。list 调用的 AiInfraRepos.getAiProviderModelList(packages/database/src/repositories/aiInfra/index.ts#L351-L417)并非简单读库,而是一条合并流水线:
- 分别取出数据库中用户侧模型行(
getModelListByProviderId)与内置模型卡片(model-bank 配置,自定义供应商回退为空数组); - 用
mergeArrayById按 ID 合并,用户行覆盖内置卡片的同名字段; - 类型以内置配置为准:从供应商 API 远程拉取的模型(如 OpenAI
/v1/models)不返回type字段,若直接用会错误落库为chat(例如 sora-2 本是视频模型),因此内置列表中存在同 ID 模型时强制回填其type,并对遗留值做stt → asr归一化; - 过滤"仅剩推理偏好"的幽灵行(preference-only shell)与不可见模型(
visible === false的行在 CLI 侧的isVisibleModel也会被剔除); - 依次应用
enabled、type过滤,最后做offset/limit切片。
仓库内还配有专门的测试用例 getAiProviderModelList.test.ts 覆盖该合并行为。
2.2 lh model view <id>:查看模型详情
lh model view gpt-4o
lh model view gpt-4o --json
lh model view gpt-4o --json id,displayName,type,enabled
调用 aiModel.getAiModelById(query,仅按模型 ID 查询)。非 JSON 模式下显示显示名,以及 Provider、Type、Enabled/Disabled 元信息行;模型不存在时打印错误并以退出码 1 结束(model.ts#L77-L104)。--json 可附加逗号分隔字段名做投影,方便在脚本中取值。
2.3 lh model create:创建自定义模型
lh model create --id my-model --provider openai --type chat
lh model create --id my-model --provider openai --display-name "My Model" --type image
| 选项 | 说明 | 默认值 |
|---|---|---|
--id <id> |
模型 ID | 必填 |
--provider <providerId> |
所属供应商 ID | 必填 |
--display-name <name> |
显示名称 | - |
--type <type> |
模型类型 | chat |
服务端 createAiModel 有值得注意的去重语义(aiModel.ts#L117-L150):若同 (id, providerId) 已存在真实模型行,返回 CONFLICT: Model "..." already exists(对 Postgres 唯一约束 23505 做了一层友好转译);若已存在行只是"偏好壳"(例如清空远程模型后残留的推理参数行),则不会报错,而是将该行升级为 source: 'custom'、enabled: true 的正式自定义模型,并浅合并保留已有 chatConfig。
2.4 lh model edit <id>:更新模型信息
lh model edit my-model --provider openai --display-name "New Name"
lh model edit my-model --provider openai --type asr
--provider 必填;--display-name 与 --type 至少提供一个,否则 CLI 直接报错退出(model.ts#L137-L163)。变更通过 updateAiModel mutation 以 {id, providerId, value} 结构提交,value 仅包含本次显式修改的字段。
2.5 lh model toggle <id>:启用 / 禁用单个模型
lh model toggle gpt-4o --provider openai --enable
lh model toggle gpt-4o --provider openai --disable
| 选项 | 说明 | 要求 |
|---|---|---|
--provider <providerId> |
供应商 ID | 必填 |
--enable |
启用该模型 | 二选一 |
--disable |
禁用该模型 | 二选一 |
--enable 与 --disable 必须且只能提供一个,缺失时打印 Specify --enable or --disable. 并退出。
2.6 lh model batch-toggle <ids...>:批量启用 / 禁用
lh model batch-toggle model1 model2 model3 --provider openai --enable
lh model batch-toggle gpt-4o gpt-4o-mini --provider openai --disable
与单条 toggle 相同的选项约束(--provider 必填、--enable/--disable 二选一)。从源码结构看,服务端 batchToggleAiModels 的入参 id 字段即供应商 ID、models 为模型 ID 数组(aiModel.ts#L74-L85),一次 mutation 完成批量翻转。
2.7 源码中额外提供的 batch-update 与 sort
除参考文档列出的子命令外,model.ts 中还实现了两条面向批量运维的命令:
# 批量更新模型对象(--models 传 JSON 数组)
lh model batch-update openai --models '[{"id":"m1","sort":1},{"id":"m2","sort":2}]'
# 更新模型排序(--sort-map 传 {id, sort, type?} JSON 数组)
lh model sort openai --sort-map '[{"id":"m1","sort":1},{"id":"m2","sort":2,"type":"chat"}]'
两条命令都会先做 JSON.parse 与数组校验,失败时打印明确的错误信息并退出;sort 对应服务端 updateAiModelOrder,其 zod schema 对 sortMap 元素要求 id: string、sort: number、type 可选且必须是合法的 AiModelTypeSchema 枚举值。
2.8 lh model delete <id>:删除模型
lh model delete my-model --provider openai
lh model delete my-model --provider openai --yes
不带 --yes 时会弹出交互式确认(Are you sure you want to delete this model?),输入取消则打印 Cancelled. 并中止。注意权限约束:服务端 removeAiModel 挂了 ai_model:delete 权限门与 requireWorkspaceRoleWhenScoped('admin')(aiModel.ts#L191-L197),即在 workspace 模式下删除是面向全工作区的工作(无用户维度收窄),需要 Admin 及以上角色;而 toggle/update/order 等按调用者 upsert 的操作保持成员可访问。
2.9 lh model clear:清空供应商的模型
# 清空该供应商的全部模型
lh model clear --provider openai --yes
# 只清空远程/拉取来源的模型,保留自定义模型
lh model clear --provider openai --remote
| 选项 | 说明 |
|---|---|
--provider <providerId> |
供应商 ID(必填) |
--remote |
仅清空远程/拉取的模型 |
--yes |
跳过确认提示 |
CLI 根据 --remote 分别调用 clearRemoteModels 或 clearModelsByProvider(model.ts#L302-L327),确认文案也会相应区分 remote models 与 all models。与 delete 相同,两者在服务端都要求 ai_model:delete 权限且 workspace 模式下需要 admin 角色。
三、供应商管理:lh provider 全子命令详解
3.1 lh provider list / lh provider view <id>
lh provider list
lh provider list --json
lh provider view openai
lh provider view openai --json id,name,source,enabled
list 调用 aiProvider.getAiProviderList,表格列为 ID、NAME、ENABLED、SOURCE(NAME 超过 30 字符截断)。从仓库实现看,服务端列表是把内置供应商(DEFAULT_MODEL_PROVIDER_LIST,source 标记为 builtin)与用户侧覆盖行按 ID 合并,再按内置清单顺序排序,未知供应商排在末尾(aiInfra/index.ts#L97-L121)。view 调用 getAiProviderById,显示名称、Enabled/Disabled、Source 等元信息。
3.2 lh provider create:创建供应商
lh provider create --id openrouter -n "OpenRouter" -s custom \
-d "OpenRouter 聚合网关" --logo https://example.com/logo.png --sdk-type openai
| 选项 | 说明 | 默认值 |
|---|---|---|
--id <id> |
供应商 ID | 必填 |
-n, --name <name> |
供应商名称 | 必填 |
-s, --source <source> |
来源类型(builtin 或 custom) |
custom |
-d, --description <desc> |
描述 | - |
--logo <logo> |
Logo URL | - |
--sdk-type <sdkType> |
SDK 类型(openai、anthropic、azure、bedrock 等) |
- |
服务端对 ID 冲突做了友好处理:捕获 Postgres 唯一约束错误码 23505 后抛 CONFLICT: Provider "..." already exists(aiProvider.ts#L132-L149)。sdkType 决定运行时以哪套 SDK 适配层发起请求,接入 OpenAI 兼容网关时通常传 openai。
3.3 lh provider edit <id>:更新供应商信息
lh provider edit openrouter -n "New Name"
lh provider edit openrouter --sdk-type anthropic
支持 -n, --name、-d, --description、--logo、--sdk-type 四个变更项,至少提供一个,否则报错 No changes specified. Use --name, --description, --logo, or --sdk-type.(provider.ts#L112-L140)。变更经 updateAiProvider 提交,仅携带本次显式修改的字段。
3.4 lh provider config <id>:配置 API Key、Base URL 等运行参数
这是把供应商"接通"的核心命令:
lh provider config openai --api-key sk-xxx
lh provider config openai --base-url https://custom-endpoint.com
lh provider config openai --show
lh provider config openai --show --json
| 选项 | 说明 |
|---|---|
--api-key <key> |
设置 API Key |
--base-url <url> |
设置 Base URL |
--check-model <model> |
设置连通性检测用模型 |
--enable-response-api |
开启 Response API 模式(OpenAI) |
--disable-response-api |
关闭 Response API 模式 |
--fetch-on-client |
开启客户端侧拉取模型列表 |
--no-fetch-on-client |
关闭客户端侧拉取模型列表 |
--show |
查看当前配置 |
--json [fields] |
以 JSON 输出(需配合 --show) |
三条值得注意的实现细节:
- 凭据加密落库。
--api-key/--base-url写入keyVaults结构,经KeyVaultsGateKeeper加密器(ctx.gateKeeper.encrypt)加密后存储(aiProvider.ts#L286-L302);--show打印 API Key 时也只回显前 8 位加省略号,避免终端日志泄露完整密钥(provider.ts#L199-L206)。受限作用域的 API Key 在查询时甚至会被服务端直接剔除keyVaults字段,防止凭据外泄(aiProvider.ts#L151-L166)。 - 平台托管保护。
lobehub供应商由 LobeHub 平台托管,CLI 在发起请求前就拦截:对其执行--api-key或--base-url会直接报错退出——Provider "lobehub" is managed by the LobeHub platform. You cannot set --api-key or --base-url for it.(provider.ts#L170-L176)。 - 至少要给一个配置项。若不指定
--show且未携带任何配置 flag,CLI 报错并列出可选项。
3.5 lh provider test <id>:连通性测试
lh provider test openai
lh provider test openai -m gpt-4o --json
| 选项 | 说明 |
|---|---|
-m, --model <model> |
指定测试模型(默认使用该供应商配置的 checkModel) |
--json |
以 JSON 输出结果 |
从源码结构看,checkProviderConnectivity 并非简单的 HTTP ping:它会从数据库初始化该供应商的模型运行时(initModelRuntimeFromDB),向指定模型发起一次真实的非流式 chat 请求(messages: [{role:'user', content:'Hi'}]、temperature: 0、stream: false),收到无错误的响应即判定连通(aiProvider.ts#L74-L130)。测试模型取值顺序为:命令行 -m 优先,其次供应商的 checkModel 配置;两者都缺省时返回 {ok: false, error: 'No check model configured. Use --model to specify one.'}。CLI 侧成功时打印 Provider <id> is reachable (model: ...),失败时打印具体 model 与 error 并以退出码 1 结束,便于在脚本中做断言。
3.6 lh provider toggle <id> / lh provider delete <id>
lh provider toggle my-provider --enable
lh provider toggle my-provider --disable
lh provider delete my-provider
lh provider delete my-provider --yes
toggle 与模型版相同,--enable/--disable 二选一。注意服务端有一层保护:官方供应商(isOfficialProvider)被尝试禁用时会抛 BAD_REQUEST(OFFICIAL_PROVIDER_DISABLE_ERROR),即内置官方供应商不允许被用户侧关闭(aiProvider.ts#L254-L271)。delete 默认交互式确认,--yes 跳过;workspace 模式下同样需要 admin 角色(供应商行携带工作区共享凭据,删除是工作区级操作)。
四、一个完整的实战工作流:接入自定义 OpenAI 兼容网关
把前述命令串起来,是典型的自定义供应商接入流程(以仓库中的命令语义为准,实际执行需要已登录的 CLI 会话与可达的服务端):
# 1. 创建供应商,声明 SDK 适配层
lh provider create --id my-gateway -n "My Gateway" -s custom \
-d "自建的 OpenAI 兼容网关" --sdk-type openai
# 2. 配置凭据与基础地址,并指定连通性检测模型
lh provider config my-gateway --api-key sk-xxx \
--base-url https://my-gateway.example.com/v1 \
--check-model gpt-4o
# 3. 验证连通性
lh provider test my-gateway --json
# 4. 注册网关上实际可用的模型
lh model create --id gpt-4o --provider my-gateway --display-name "GPT-4o"
lh model create --id my-embed --provider my-gateway --type embedding
# 5. 检查与过滤
lh model list my-gateway --enabled
lh model list my-gateway --type embedding --json id,type,enabled
# 6. 需要下线模型时批量禁用(而非删除)
lh model batch-toggle gpt-4o --provider my-gateway --disable
脚本化场景下,--json 输出天然适配 jq 之类的工具;破坏性命令(delete、clear)在 CI 中应显式加 --yes 跳过交互确认。
五、小结
lh model提供list / view / create / edit / toggle / batch-toggle / batch-update / sort / delete / clear一整套模型生命周期操作;列表数据是"内置模型卡片 + 用户覆盖行"的合并结果,类型字段始终以内置配置为准,并做了stt → asr的兼容归一。lh provider提供供应商的 CRUD、config(API Key/Base URL/检测模型/Response API 开关等)、test(真实 chat 请求探测连通性)、toggle与delete;凭据经 KeyVaults 加密落库并在展示时脱敏。- 权限边界清晰:创建/更新/开关模型面向成员(对应
ai_model:*、ai_provider:*权限),而删除模型、清空模型、删除/编辑供应商等在 workspace 模式下收敛到 Admin 角色;lobehub供应商与官方供应商分别受到"平台托管"和"禁止禁用"的额外保护。 - 参考文档中
--type的stt枚举可视为旧别名:当前 CLI 描述使用asr,两者在 apps/cli/src/commands/model.ts 中归一化处理,均可用于list/create/edit的--type参数。
如需进一步阅读,可对照 apps/cli/src/commands/model.ts 与 apps/cli/src/commands/provider.ts 的完整实现,以及 packages/database/src/repositories/aiInfra/index.ts 中的模型合并与运行时状态组装逻辑。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00