Add ovms support

This commit is contained in:
John Feng 2026-04-10 23:37:51 +08:00
parent db1bc6a1f8
commit 903e90afcf
10 changed files with 40 additions and 9 deletions

View file

@ -25,10 +25,11 @@ Examples:
picoclaw model # Show current default model
picoclaw model gpt-5.2 # Set gpt-5.2 as default
picoclaw model claude-sonnet-4.6 # Set claude-sonnet-4.6 as default
picoclaw model local-model # Set local VLLM server as default
picoclaw model local-model # Set local VLLM/OVMS server as default
Note: 'local-model' is a special value for using a local VLLM server
(running at localhost:8000 by default) which does not require an API key.`,
(running at localhost:8000 by default) which does not require an API key.
You can also use OVMS (OpenVINO Model Server) or other OpenAI-compatible servers.`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
configPath := internal.GetConfigPath()

View file

@ -26,7 +26,7 @@ func supportsAudioTranscription(modelCfg *config.ModelConfig) bool {
case "openai", "azure", "azure-openai",
"litellm", "openrouter", "groq", "zhipu", "gemini", "nvidia",
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
"vivgrid", "volcengine", "vllm", "qwen", "qwen-portal", "qwen-intl", "qwen-international", "dashscope-intl",
"vivgrid", "volcengine", "vllm", "ovms", "qwen", "qwen-portal", "qwen-intl", "qwen-international", "dashscope-intl",
"qwen-us", "dashscope-us", "mistral", "avian", "minimax", "longcat", "modelscope", "novita",
"coding-plan", "alibaba-coding", "qwen-coding", "zai":
// These protocols all go through the OpenAI-compatible or Azure provider path in
@ -47,7 +47,11 @@ func supportsWhisperTranscription(modelCfg *config.ModelConfig) bool {
switch protocol {
case "openai", "litellm", "openrouter", "groq", "zhipu", "gemini", "nvidia",
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
<<<<<<< HEAD
"vivgrid", "volcengine", "vllm", "qwen", "qwen-portal", "qwen-intl", "qwen-international", "dashscope-intl",
=======
"vivgrid", "volcengine", "vllm", "ovms", "qwen", "qwen-intl", "qwen-international", "dashscope-intl",
>>>>>>> 793357c6 (Add ovms support)
"qwen-us", "dashscope-us", "mistral", "avian", "minimax", "longcat", "modelscope", "novita",
"coding-plan", "alibaba-coding", "qwen-coding", "zai", "mimo":
return true

View file

@ -271,6 +271,13 @@ func DefaultConfig() *Config {
APIBase: "http://localhost:8000/v1",
},
// OVMS (local) - http://localhost:8000
{
ModelName: "local-ovms",
Model: "ovms/custom-model",
APIBase: "http://localhost:8000/v3",
},
// LM Studio (local) - http://localhost:1234
{
ModelName: "lmstudio-local",

View file

@ -54,6 +54,7 @@ var protocolMetaByName = map[string]protocolMeta{
"alibaba-coding-anthropic": {defaultAPIBase: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic"},
"zai": {defaultAPIBase: "https://api.z.ai/api/coding/paas/v4"},
"vllm": {defaultAPIBase: "http://localhost:8000/v1", emptyAPIKeyAllowed: true},
"ovms": {defaultAPIBase: "http://localhost:8000/v3", emptyAPIKeyAllowed: true},
"mistral": {defaultAPIBase: "https://api.mistral.ai/v1"},
"avian": {defaultAPIBase: "https://api.avian.io/v1"},
"minimax": {defaultAPIBase: "https://api.minimaxi.com/v1"},
@ -248,7 +249,7 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
case "litellm", "lmstudio", "openrouter", "groq", "zhipu", "nvidia", "venice",
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
"vivgrid", "volcengine", "vllm", "qwen", "qwen-portal", "qwen-intl", "qwen-international", "dashscope-intl",
"vivgrid", "volcengine", "vllm", "ovms", "qwen", "qwen-portal", "qwen-intl", "qwen-international", "dashscope-intl",
"qwen-us", "dashscope-us", "mistral", "avian", "longcat", "modelscope", "novita",
"coding-plan", "alibaba-coding", "qwen-coding", "zai", "mimo":
// All other OpenAI-compatible HTTP providers

View file

@ -199,6 +199,7 @@ func TestCreateProviderFromConfig_DefaultAPIBase(t *testing.T) {
{"vivgrid", "vivgrid"},
{"qwen", "qwen"},
{"vllm", "vllm"},
{"ovms", "ovms"},
{"deepseek", "deepseek"},
{"ollama", "ollama"},
{"lmstudio", "lmstudio"},
@ -316,6 +317,20 @@ func TestCreateProviderFromConfig_LocalProviders(t *testing.T) {
apiKey: "",
wantModelID: "Qwen/Qwen3-8B",
},
{
name: "OVMS with API key",
modelName: "test-ovms",
model: "ovms/llama3",
apiKey: "test-key",
wantModelID: "llama3",
},
{
name: "OVMS without API key",
modelName: "test-ovms",
model: "ovms/llama3",
apiKey: "",
wantModelID: "llama3",
},
}
for _, tt := range tests {

View file

@ -341,7 +341,7 @@ Check these in the dashboard:
- a default model is selected
- the model has credentials or OAuth state
- local models such as Ollama or vLLM are reachable
- local models such as Ollama, vLLM, or OVMS are reachable
### The launcher cannot find `picoclaw`

View file

@ -176,7 +176,7 @@ func runLocalModelProbe(m *config.ModelConfig) bool {
switch protocol {
case "ollama":
return probeOllamaModelFunc(apiBase, modelID)
case "vllm", "lmstudio":
case "vllm", "ovms", "lmstudio":
return probeOpenAICompatibleModelFunc(apiBase, modelID, m.APIKey())
case "github-copilot", "copilot":
return probeTCPServiceFunc(apiBase)

View file

@ -42,9 +42,10 @@ const PROVIDER_PRIORITY: Record<string, number> = {
azure: 23,
ollama: 24,
vllm: 25,
lmstudio: 26,
zai: 27,
mimo: 28,
ovms: 26,
lmstudio: 27,
zai: 28,
mimo: 29,
}
interface ProviderGroup {

View file

@ -41,6 +41,7 @@ const PROVIDER_DOMAINS: Record<string, string> = {
mistral: "mistral.ai",
avian: "avian.io",
vllm: "vllm.ai",
ovms: "docs.openvino.ai",
zhipu: "zhipuai.cn",
zai: "z.ai",
mimo: "xiaomi.com",

View file

@ -20,6 +20,7 @@ const PROVIDER_LABELS: Record<string, string> = {
mistral: "Mistral AI",
avian: "Avian",
vllm: "VLLM (local)",
ovms: "OVMS (local)",
zhipu: "Zhipu AI (智谱)",
zai: "Z.ai",
mimo: "Xiaomi MiMo",