mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
fix(ui): register tencent in the Add Model provider dropdown (#40924)
* fix(ui): register tencent in the Add Model provider dropdown The Add Model provider dropdown is driven by the proxy's /public/providers/fields endpoint, which serves provider_create_fields.json. Tencent was frozen in the test's ADD_MODEL_UNLISTED_PROVIDERS set, so it never appeared in the dropdown. Add a Tencent entry (optional api_base + required api_key, matching TENCENT_API_BASE/TENCENT_API_KEY) and unfreeze it in the backend test. Register Tencent in the UI Providers enum, provider_map, and placeholder map so the dropdown resolves the display name and model placeholder. * fix(tencent): drop test docstring to satisfy comment policy * fix(ui): bundle the Tencent Cloud logo for the provider dropdown
This commit is contained in:
parent
ebfec956d2
commit
19da81579b
5 changed files with 73 additions and 1 deletions
|
|
@ -3161,6 +3161,34 @@
|
|||
],
|
||||
"default_model_placeholder": "soniox/stt-async-v5"
|
||||
},
|
||||
{
|
||||
"provider": "Tencent",
|
||||
"provider_display_name": "Tencent",
|
||||
"litellm_provider": "tencent",
|
||||
"credential_fields": [
|
||||
{
|
||||
"key": "api_base",
|
||||
"label": "API Base",
|
||||
"placeholder": "https://tokenhub-intl.tencentcloudmaas.com/v1",
|
||||
"tooltip": null,
|
||||
"required": false,
|
||||
"field_type": "text",
|
||||
"options": null,
|
||||
"default_value": null
|
||||
},
|
||||
{
|
||||
"key": "api_key",
|
||||
"label": "API Key",
|
||||
"placeholder": null,
|
||||
"tooltip": null,
|
||||
"required": true,
|
||||
"field_type": "password",
|
||||
"options": null,
|
||||
"default_value": null
|
||||
}
|
||||
],
|
||||
"default_model_placeholder": "tencent/deepseek-v4-pro"
|
||||
},
|
||||
{
|
||||
"provider": "TEXT_COMPLETION_CODESTRAL",
|
||||
"provider_display_name": "Text-Completion-Codestral",
|
||||
|
|
|
|||
|
|
@ -377,6 +377,31 @@ def test_chatgpt_provider_fields():
|
|||
assert chatgpt["credential_fields"] == []
|
||||
|
||||
|
||||
def test_tencent_provider_fields():
|
||||
app_instance = FastAPI()
|
||||
app_instance.include_router(router)
|
||||
test_client = TestClient(app_instance)
|
||||
|
||||
response = test_client.get("/public/providers/fields")
|
||||
assert response.status_code == 200
|
||||
providers = response.json()
|
||||
|
||||
tencent = next((p for p in providers if p["provider"] == "Tencent"), None)
|
||||
assert tencent is not None, "Tencent provider entry not found"
|
||||
|
||||
assert tencent["provider_display_name"] == "Tencent"
|
||||
assert tencent["litellm_provider"] == LlmProviders.TENCENT.value
|
||||
assert tencent["default_model_placeholder"].startswith("tencent/")
|
||||
|
||||
fields_by_key = {f["key"]: f for f in tencent["credential_fields"]}
|
||||
|
||||
assert fields_by_key["api_key"]["required"] is True
|
||||
assert fields_by_key["api_key"]["field_type"] == "password"
|
||||
|
||||
assert fields_by_key["api_base"]["field_type"] == "text"
|
||||
assert fields_by_key["api_base"]["required"] is False
|
||||
|
||||
|
||||
ADD_MODEL_UNLISTED_PROVIDERS: Final = frozenset(
|
||||
{
|
||||
"a2a",
|
||||
|
|
@ -412,7 +437,6 @@ ADD_MODEL_UNLISTED_PROVIDERS: Final = frozenset(
|
|||
"scaleway",
|
||||
"stability",
|
||||
"synthetic",
|
||||
"tencent",
|
||||
"tensormesh",
|
||||
"text-completion-inception",
|
||||
"transcribe",
|
||||
|
|
|
|||
6
ui/litellm-dashboard/public/assets/logos/tencent.svg
Normal file
6
ui/litellm-dashboard/public/assets/logos/tencent.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<svg viewBox="255 77 555 393" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
|
||||
<title>Tencent Cloud</title>
|
||||
<path fill="#00A3FF" d="M724.4,396.5c-8.7,8.7-26.1,21.7-56.5,21.7h-187c56.5-54.1,104.4-99.6,108.8-104c8.3-8.4,17-16.3,26.1-23.8 c21.8-19.5,39.1-21.7,54.4-21.7c21.7,0,39.1,8.7,54.4,21.6C754.9,318.5,754.9,368.4,724.4,396.5z M761.4,255.6 c-23-24.8-55.3-39-89.2-39c-30.4,0-56.5,10.9-80.5,28.2c-8.8,8.7-21.8,17.3-32.7,30.3c-8.7,8.7-195.7,190.7-195.7,190.7 c10.9,2.2,23.9,2.2,34.8,2.2h237.1c17.4,0,30.5,0,43.5-2.2c30-2.2,58.3-14.4,80.5-34.7C809.2,383.5,809.2,303.4,761.4,255.6 L761.4,255.6z"/>
|
||||
<path fill="#00C8DC" d="M456.9,242.6c-23.9-17.3-47.9-26-76.1-26c-33.9,0-66.2,14.2-89.2,39c-48.4,49.7-47.4,129.2,2.2,177.7 c21.7,19.5,43.5,30.3,69.6,32.5l50-47.7h-28.3c-28.3-2.1-45.7-10.8-56.5-21.6c-30-29.6-30.9-77.6-2.2-108.3 c15.2-15.2,32.6-21.7,54.4-21.7c13.1,0,32.6,2.1,52.2,21.6c8.7,8.7,32.6,26,41.3,34.7h2.1l32.6-32.5v-2.2 C493.9,273,470,253.5,456.9,242.6"/>
|
||||
<path fill="#006EFF" d="M685.3,188.5c-24.7-66.3-88-110.4-158.8-110.5c-84.8,0-152.2,62.8-165.3,140.8c6.5,0,13.1-2.1,21.8-2.1 c8.7,0,19.6,2.1,28.3,2.1c10.9-54.2,58.7-93.2,115.3-93.2c47.8,0,89.2,28.2,108.7,69.3c0,0,2.2,2.2,2.2,0 C652.6,192.8,670,188.5,685.3,188.5L685.3,188.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -209,6 +209,11 @@ describe("provider_info_helpers", () => {
|
|||
const { logo } = getProviderLogoAndName("openai");
|
||||
expect(logo).toContain("openai_small");
|
||||
});
|
||||
|
||||
it("should resolve the Tencent provider to its bundled logo", () => {
|
||||
const { logo } = getProviderLogoAndName("tencent");
|
||||
expect(logo).toContain("tencent");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getPlaceholder", () => {
|
||||
|
|
@ -309,6 +314,10 @@ describe("provider_info_helpers", () => {
|
|||
expect(getPlaceholder("CHATGPT")).toBe("chatgpt/gpt-5.4");
|
||||
});
|
||||
|
||||
it("should return a tencent/ placeholder for the Tencent provider", () => {
|
||||
expect(getPlaceholder(Providers.Tencent)).toBe("tencent/deepseek-v4-pro");
|
||||
});
|
||||
|
||||
it("should return default gpt-3.5-turbo placeholder for unknown provider", () => {
|
||||
expect(getPlaceholder("UnknownProvider" as any)).toBe("gpt-3.5-turbo");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import sapLogo from "../../public/assets/logos/sap.png";
|
|||
import scxAiLogo from "../../public/assets/logos/scx_ai.svg";
|
||||
import snowflakeLogo from "../../public/assets/logos/snowflake.svg";
|
||||
import sonioxLogo from "../../public/assets/logos/soniox.svg";
|
||||
import tencentLogo from "../../public/assets/logos/tencent.svg";
|
||||
import togetheraiLogo from "../../public/assets/logos/togetherai.svg";
|
||||
import topazLogo from "../../public/assets/logos/topaz.svg";
|
||||
import v0Logo from "../../public/assets/logos/v0.svg";
|
||||
|
|
@ -167,6 +168,7 @@ export enum Providers {
|
|||
Snowflake = "Snowflake",
|
||||
Soniox = "Soniox",
|
||||
TEXT_COMPLETION_CODESTRAL = "Text-Completion-Codestral",
|
||||
Tencent = "Tencent",
|
||||
TogetherAI = "TogetherAI",
|
||||
TOPAZ = "Topaz",
|
||||
Triton = "Triton",
|
||||
|
|
@ -286,6 +288,7 @@ export const provider_map: Record<string, string> = {
|
|||
Snowflake: "snowflake",
|
||||
Soniox: "soniox",
|
||||
TEXT_COMPLETION_CODESTRAL: "text-completion-codestral",
|
||||
Tencent: "tencent",
|
||||
TogetherAI: "together_ai",
|
||||
TOPAZ: "topaz",
|
||||
Triton: "triton",
|
||||
|
|
@ -384,6 +387,7 @@ export const providerLogoMap: Partial<Record<Providers, string>> = {
|
|||
[Providers.SCX_AI]: scxAiLogo.src,
|
||||
[Providers.Snowflake]: snowflakeLogo.src,
|
||||
[Providers.Soniox]: sonioxLogo.src,
|
||||
[Providers.Tencent]: tencentLogo.src,
|
||||
[Providers.TEXT_COMPLETION_CODESTRAL]: mistralLogo.src,
|
||||
[Providers.TogetherAI]: togetheraiLogo.src,
|
||||
[Providers.TOPAZ]: topazLogo.src,
|
||||
|
|
@ -453,6 +457,7 @@ const providerPlaceholderMap: Partial<Record<Providers, string>> = {
|
|||
[Providers.Sail]: "sail/openai/gpt-oss-120b",
|
||||
[Providers.SCX_AI]: "scx-ai/GLM-5.2",
|
||||
[Providers.Snowflake]: "snowflake/mistral-7b",
|
||||
[Providers.Tencent]: "tencent/deepseek-v4-pro",
|
||||
[Providers.Vertex_AI]: "gemini-pro",
|
||||
[Providers.VolcEngine]: "volcengine/<any-model-on-volcengine>",
|
||||
[Providers.Voyage]: "voyage/",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue