diff --git a/config/config.example.json b/config/config.example.json index 95fe24e0b..bedd543d7 100644 --- a/config/config.example.json +++ b/config/config.example.json @@ -48,6 +48,11 @@ "model": "deepseek/deepseek-chat", "api_key": "sk-your-deepseek-key" }, + { + "model_name": "venice-uncensored", + "model": "venice/venice-uncensored", + "api_key": "your-venice-api-key" + }, { "model_name": "lmstudio-local", "model": "lmstudio/openai/gpt-oss-20b" diff --git a/docs/providers.md b/docs/providers.md index f45aa5f3b..b0dfa0bc8 100644 --- a/docs/providers.md +++ b/docs/providers.md @@ -16,6 +16,7 @@ | `openrouter` | LLM (recommended, access to all models) | [openrouter.ai](https://openrouter.ai) | | `anthropic` | LLM (Claude direct) | [console.anthropic.com](https://console.anthropic.com) | | `openai` | LLM (GPT direct) | [platform.openai.com](https://platform.openai.com) | +| `venice` | LLM (Venice AI direct) | [venice.ai](https://venice.ai) | | `deepseek` | LLM (DeepSeek direct) | [platform.deepseek.com](https://platform.deepseek.com) | | `qwen` | LLM (Qwen direct) | [dashscope.console.aliyun.com](https://dashscope.console.aliyun.com) | | `groq` | LLM + **Voice transcription** (Whisper) | [console.groq.com](https://console.groq.com) | @@ -46,6 +47,7 @@ This design also enables **multi-agent support** with flexible provider selectio | Vendor | `model` Prefix | Default API Base | Protocol | API Key | | ------------------- | ----------------- |-----------------------------------------------------| --------- | ---------------------------------------------------------------- | | **OpenAI** | `openai/` | `https://api.openai.com/v1` | OpenAI | [Get Key](https://platform.openai.com) | +| **Venice AI** | `venice/` | `https://api.venice.ai/api/v1` | OpenAI | [Get Key](https://venice.ai) | | **Anthropic** | `anthropic/` | `https://api.anthropic.com/v1` | Anthropic | [Get Key](https://console.anthropic.com) | | **智谱 AI (GLM)** | `zhipu/` | `https://open.bigmodel.cn/api/paas/v4` | OpenAI | [Get Key](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) | | **Z.AI Coding Plan** | `openai/` | `https://api.z.ai/api/coding/paas/v4` | OpenAI | [Get Key](https://z.ai/manage-apikey/apikey-list) | diff --git a/docs/zh/providers.md b/docs/zh/providers.md index 04b2f7a88..43c4f26db 100644 --- a/docs/zh/providers.md +++ b/docs/zh/providers.md @@ -15,6 +15,7 @@ | `openrouter` | LLM (推荐,可访问所有模型) | [openrouter.ai](https://openrouter.ai) | | `anthropic` | LLM (Claude 直连) | [console.anthropic.com](https://console.anthropic.com) | | `openai` | LLM (GPT 直连) | [platform.openai.com](https://platform.openai.com) | +| `venice` | LLM (Venice AI 直连) | [venice.ai](https://venice.ai) | | `deepseek` | LLM (DeepSeek 直连) | [platform.deepseek.com](https://platform.deepseek.com) | | `qwen` | LLM (通义千问) | [dashscope.console.aliyun.com](https://dashscope.console.aliyun.com) | | `groq` | LLM + **语音转录** (Whisper) | [console.groq.com](https://console.groq.com) | @@ -44,6 +45,7 @@ | 厂商 | `model` 前缀 | 默认 API Base | 协议 | 获取 API Key | | ------------------- | ----------------- | --------------------------------------------------- | --------- | ----------------------------------------------------------------- | | **OpenAI** | `openai/` | `https://api.openai.com/v1` | OpenAI | [获取密钥](https://platform.openai.com) | +| **Venice AI** | `venice/` | `https://api.venice.ai/api/v1` | OpenAI | [获取密钥](https://venice.ai) | | **Anthropic** | `anthropic/` | `https://api.anthropic.com/v1` | Anthropic | [获取密钥](https://console.anthropic.com) | | **智谱 AI (GLM)** | `zhipu/` | `https://open.bigmodel.cn/api/paas/v4` | OpenAI | [获取密钥](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) | | **DeepSeek** | `deepseek/` | `https://api.deepseek.com/v1` | OpenAI | [获取密钥](https://platform.deepseek.com) | diff --git a/pkg/config/defaults.go b/pkg/config/defaults.go index 6eac5d8b9..a9a107975 100644 --- a/pkg/config/defaults.go +++ b/pkg/config/defaults.go @@ -185,6 +185,13 @@ func DefaultConfig() *Config { APIBase: "https://api.deepseek.com/v1", }, + // Venice AI - https://venice.ai + { + ModelName: "venice-uncensored", + Model: "venice/venice-uncensored", + APIBase: "https://api.venice.ai/api/v1", + }, + // Google Gemini - https://ai.google.dev/ { ModelName: "gemini-2.0-flash", @@ -335,6 +342,13 @@ func DefaultConfig() *Config { APIBase: "http://localhost:8000/v1", }, + // LM Studio (local) - http://localhost:1234 + { + ModelName: "lmstudio-local", + Model: "lmstudio/openai/gpt-oss-20b", + APIBase: "http://localhost:1234/v1", + }, + // Azure OpenAI - https://portal.azure.com // model_name is a user-friendly alias; the model field's path after "azure/" is your deployment name { diff --git a/pkg/providers/factory_provider.go b/pkg/providers/factory_provider.go index 16b2ead10..fb5191bf8 100644 --- a/pkg/providers/factory_provider.go +++ b/pkg/providers/factory_provider.go @@ -24,6 +24,7 @@ type protocolMeta struct { var protocolMetaByName = map[string]protocolMeta{ "openai": {defaultAPIBase: "https://api.openai.com/v1"}, + "venice": {defaultAPIBase: "https://api.venice.ai/api/v1"}, "openrouter": {defaultAPIBase: "https://openrouter.ai/api/v1"}, "litellm": {defaultAPIBase: "http://localhost:4000/v1"}, "lmstudio": {defaultAPIBase: "http://localhost:1234/v1", emptyAPIKeyAllowed: true}, @@ -209,7 +210,7 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err } return provider, modelID, nil - case "litellm", "lmstudio", "openrouter", "groq", "zhipu", "gemini", "nvidia", + case "litellm", "lmstudio", "openrouter", "groq", "zhipu", "gemini", "nvidia", "venice", "ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras", "vivgrid", "volcengine", "vllm", "qwen", "qwen-intl", "qwen-international", "dashscope-intl", "qwen-us", "dashscope-us", "mistral", "avian", "longcat", "modelscope", "novita", diff --git a/pkg/providers/factory_provider_test.go b/pkg/providers/factory_provider_test.go index 588b81650..e2eafb934 100644 --- a/pkg/providers/factory_provider_test.go +++ b/pkg/providers/factory_provider_test.go @@ -112,6 +112,7 @@ func TestCreateProviderFromConfig_DefaultAPIBase(t *testing.T) { protocol string }{ {"openai", "openai"}, + {"venice", "venice"}, {"groq", "groq"}, {"novita", "novita"}, {"openrouter", "openrouter"}, @@ -160,6 +161,12 @@ func TestGetDefaultAPIBase_LMStudio(t *testing.T) { } } +func TestGetDefaultAPIBase_Venice(t *testing.T) { + if got := getDefaultAPIBase("venice"); got != "https://api.venice.ai/api/v1" { + t.Fatalf("getDefaultAPIBase(%q) = %q, want %q", "venice", got, "https://api.venice.ai/api/v1") + } +} + func TestCreateProviderFromConfig_LiteLLM(t *testing.T) { cfg := &config.ModelConfig{ ModelName: "test-litellm", @@ -362,6 +369,28 @@ func TestCreateProviderFromConfig_Mimo(t *testing.T) { } } +func TestCreateProviderFromConfig_Venice(t *testing.T) { + cfg := &config.ModelConfig{ + ModelName: "test-venice", + Model: "venice/venice-uncensored", + } + cfg.SetAPIKey("test-key") + + provider, modelID, err := CreateProviderFromConfig(cfg) + if err != nil { + t.Fatalf("CreateProviderFromConfig() error = %v", err) + } + if provider == nil { + t.Fatal("CreateProviderFromConfig() returned nil provider") + } + if modelID != "venice-uncensored" { + t.Errorf("modelID = %q, want %q", modelID, "venice-uncensored") + } + if _, ok := provider.(*HTTPProvider); !ok { + t.Fatalf("expected *HTTPProvider, got %T", provider) + } +} + func TestGetDefaultAPIBase_Mimo(t *testing.T) { if got := getDefaultAPIBase("mimo"); got != "https://api.xiaomimimo.com/v1" { t.Fatalf("getDefaultAPIBase(%q) = %q, want %q", "mimo", got, "https://api.xiaomimimo.com/v1") diff --git a/pkg/providers/openai_compat/provider.go b/pkg/providers/openai_compat/provider.go index aa9473731..4ff42506f 100644 --- a/pkg/providers/openai_compat/provider.go +++ b/pkg/providers/openai_compat/provider.go @@ -44,6 +44,7 @@ const defaultRequestTimeout = common.DefaultRequestTimeout var stripModelPrefixProviders = map[string]struct{}{ "litellm": {}, + "venice": {}, "moonshot": {}, "nvidia": {}, "groq": {}, diff --git a/pkg/providers/openai_compat/provider_test.go b/pkg/providers/openai_compat/provider_test.go index 823b0ff28..30aa76eb3 100644 --- a/pkg/providers/openai_compat/provider_test.go +++ b/pkg/providers/openai_compat/provider_test.go @@ -479,6 +479,11 @@ func TestProviderChat_StripsKnownProviderPrefixes(t *testing.T) { input: "lmstudio/openai/gpt-oss-20b", wantModel: "openai/gpt-oss-20b", }, + { + name: "strips venice prefix", + input: "venice/venice-uncensored", + wantModel: "venice-uncensored", + }, { name: "strips deepseek prefix", input: "deepseek/deepseek-chat", @@ -587,6 +592,9 @@ func TestNormalizeModel_UsesAPIBase(t *testing.T) { if got := normalizeModel("lmstudio/openai/gpt-oss-20b", "http://localhost:1234/v1"); got != "openai/gpt-oss-20b" { t.Fatalf("normalizeModel(lmstudio) = %q, want %q", got, "openai/gpt-oss-20b") } + if got := normalizeModel("venice/venice-uncensored", "https://api.venice.ai/api/v1"); got != "venice-uncensored" { + t.Fatalf("normalizeModel(venice) = %q, want %q", got, "venice-uncensored") + } if got := normalizeModel("openrouter/auto", "https://openrouter.ai/api/v1"); got != "openrouter/auto" { t.Fatalf("normalizeModel(openrouter) = %q, want %q", got, "openrouter/auto") }