feat(models): custom model explanation standardization

This commit is contained in:
zhayujie
2026-06-19 21:06:56 +08:00
parent 03ffa2db7d
commit 6996215d3b
5 changed files with 17 additions and 17 deletions

View File

@@ -2949,10 +2949,10 @@ class ModelsHandler:
{ {
"action": "set_custom_provider", "action": "set_custom_provider",
"id": "3f2a9c1b", # required for edit; omit for create "id": "3f2a9c1b", # required for edit; omit for create
"name": "siliconflow", # required, display label "name": "my-provider", # required, display label
"api_base": "https://...", # required when creating "api_base": "https://...", # required when creating
"api_key": "sk-...", # optional on edit (keep existing) "api_key": "sk-...", # optional on edit (keep existing)
"model": "deepseek-ai/...", # optional default model "model": "model-name", # optional default model
"make_active": true # optional, also activate it "make_active": true # optional, also activate it
} }
""" """

View File

@@ -27,7 +27,7 @@ available_setting = {
"custom_api_key": "", # custom OpenAI-compatible provider api key (used when bot_type is "custom"); legacy single-provider field "custom_api_key": "", # custom OpenAI-compatible provider api key (used when bot_type is "custom"); legacy single-provider field
"custom_api_base": "", # custom OpenAI-compatible provider api base (used when bot_type is "custom"); legacy single-provider field "custom_api_base": "", # custom OpenAI-compatible provider api base (used when bot_type is "custom"); legacy single-provider field
# Multiple custom (OpenAI-compatible) providers. Activated via bot_type: "custom:<id>". # Multiple custom (OpenAI-compatible) providers. Activated via bot_type: "custom:<id>".
# Each item: {"id": "3f2a9c1b", "name": "siliconflow", "api_key": "sk-...", "api_base": "https://api.siliconflow.cn/v1", "model": "deepseek-ai/DeepSeek-V3"} # Each item: {"id": "3f2a9c1b", "name": "my-provider", "api_key": "sk-...", "api_base": "https://api.example.com/v1", "model": "model-name"}
"custom_providers": [], "custom_providers": [],
"proxy": "", # proxy used by openai "proxy": "", # proxy used by openai
# chatgpt model; when use_azure_chatgpt is true, this is the Azure model deployment name # chatgpt model; when use_azure_chatgpt is true, this is the Azure model deployment name

View File

@@ -14,10 +14,10 @@ Config model
{ {
"id": "3f2a9c1b", # server-generated short uuid (primary key) "id": "3f2a9c1b", # server-generated short uuid (primary key)
"name": "siliconflow", # user-facing display label (not a key) "name": "my-provider", # user-facing display label (not a key)
"api_key": "sk-...", # required "api_key": "sk-...", # required
"api_base": "https://...", # required, must be OpenAI-compatible "api_base": "https://...", # required, must be OpenAI-compatible
"model": "deepseek-ai/DeepSeek-V3" # optional default model "model": "model-name" # optional default model
} }
Routing Routing

View File

@@ -88,15 +88,15 @@ class TestResolveCustomCredentials(unittest.TestCase):
set_conf({ set_conf({
"bot_type": "custom:abc12345", "bot_type": "custom:abc12345",
"custom_providers": [ "custom_providers": [
{"id": "sf001", "name": "siliconflow", "api_key": "sf-key", {"id": "sf001", "name": "provider-a", "api_key": "key-a",
"api_base": "https://api.siliconflow.cn/v1", "model": "deepseek-ai/DeepSeek-V3"}, "api_base": "https://api.example.com/v1", "model": "model-a"},
{"id": "abc12345", "name": "qiniu", "api_key": "qn-key", {"id": "abc12345", "name": "provider-b", "api_key": "key-b",
"api_base": "https://api.qnaigc.com/v1", "model": "deepseek-v3"}, "api_base": "https://api.example.org/v1", "model": "model-b"},
], ],
}) })
self.assertEqual( self.assertEqual(
self.resolve(), self.resolve(),
("qn-key", "https://api.qnaigc.com/v1", "deepseek-v3"), ("key-b", "https://api.example.org/v1", "model-b"),
) )
def test_id_not_found_falls_back_to_legacy(self): def test_id_not_found_falls_back_to_legacy(self):
@@ -105,8 +105,8 @@ class TestResolveCustomCredentials(unittest.TestCase):
"custom_api_key": "legacy-key", "custom_api_key": "legacy-key",
"custom_api_base": "https://legacy.example.com/v1", "custom_api_base": "https://legacy.example.com/v1",
"custom_providers": [ "custom_providers": [
{"id": "sf001", "name": "siliconflow", "api_key": "sf-key", {"id": "sf001", "name": "provider-a", "api_key": "key-a",
"api_base": "https://api.siliconflow.cn/v1"}, "api_base": "https://api.example.com/v1"},
], ],
}) })
self.assertEqual( self.assertEqual(

View File

@@ -74,8 +74,8 @@ class TestSetCustomProvider(unittest.TestCase):
def test_create_provider_does_not_hijack_bot_type(self): def test_create_provider_does_not_hijack_bot_type(self):
"""Creating a provider without make_active must not change bot_type.""" """Creating a provider without make_active must not change bot_type."""
res = self.h.call(action="set_custom_provider", name="siliconflow", res = self.h.call(action="set_custom_provider", name="my-provider",
api_base="https://api.siliconflow.cn/v1", api_key="sf-key") api_base="https://api.example.com/v1", api_key="key-a")
self.assertEqual(res["status"], "success") self.assertEqual(res["status"], "success")
self.assertTrue(res["created"]) self.assertTrue(res["created"])
self.assertIn("id", res) self.assertIn("id", res)
@@ -85,13 +85,13 @@ class TestSetCustomProvider(unittest.TestCase):
providers = config_module.conf().get("custom_providers") providers = config_module.conf().get("custom_providers")
self.assertEqual(len(providers), 1) self.assertEqual(len(providers), 1)
self.assertEqual(providers[0]["id"], res["id"]) self.assertEqual(providers[0]["id"], res["id"])
self.assertEqual(providers[0]["name"], "siliconflow") self.assertEqual(providers[0]["name"], "my-provider")
self.assertEqual(self.h.bridge_resets, 1) self.assertEqual(self.h.bridge_resets, 1)
def test_create_with_make_active_switches_bot_type(self): def test_create_with_make_active_switches_bot_type(self):
"""Creating a provider with make_active=true must switch bot_type.""" """Creating a provider with make_active=true must switch bot_type."""
res = self.h.call(action="set_custom_provider", name="siliconflow", res = self.h.call(action="set_custom_provider", name="my-provider",
api_base="https://api.siliconflow.cn/v1", api_key="sf-key", api_base="https://api.example.com/v1", api_key="key-a",
make_active=True) make_active=True)
self.assertEqual(res["status"], "success") self.assertEqual(res["status"], "success")
bot_type = config_module.conf().get("bot_type") bot_type = config_module.conf().get("bot_type")