From 95521038f25634ea697b121e48694a275d99f2a2 Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Mon, 2 Mar 2026 10:52:45 -0800 Subject: [PATCH] Add openai/ prefix for OpenAI-Compatible provider in Add Model UI Refactor Azure-specific model name prefixing into a generic prefixWithProvider helper that uses provider_map for lookups. This fixes OpenAI-Compatible models not getting the required openai/ routing prefix (e.g. BAAI/bge-m3-gaudi -> openai/BAAI/bge-m3-gaudi), and also fixes the free-text input for OpenAI-Compatible and Ollama providers not creating model mappings at all. --- .../conditional_public_model_name.tsx | 31 ++---------- .../add_model/litellm_model_name.tsx | 47 +++++-------------- .../components/provider_info_helpers.test.tsx | 7 --- .../src/components/provider_info_helpers.tsx | 10 +++- 4 files changed, 25 insertions(+), 70 deletions(-) diff --git a/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx b/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx index 0a77c252133..825bab7acfe 100644 --- a/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx +++ b/ui/litellm-dashboard/src/components/add_model/conditional_public_model_name.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import { Form, Table } from "antd"; import { TextInput } from "@tremor/react"; import { Tooltip } from "../atoms/index"; -import { Providers } from "../provider_info_helpers"; +import { Providers, prefixWithProvider } from "../provider_info_helpers"; const ConditionalPublicModelName: React.FC = () => { const form = Form.useFormInstance(); @@ -20,15 +20,9 @@ const ConditionalPublicModelName: React.FC = () => { const currentMappings = form.getFieldValue("model_mappings") || []; const updatedMappings = currentMappings.map((mapping: any) => { if (mapping.public_name === "custom" || mapping.litellm_model === "custom") { - if (selectedProvider === Providers.Azure) { - return { - public_name: customModelName, - litellm_model: `azure/${customModelName}`, - }; - } return { public_name: customModelName, - litellm_model: customModelName, + litellm_model: prefixWithProvider(selectedProvider, customModelName), }; } return mapping; @@ -52,36 +46,21 @@ const ConditionalPublicModelName: React.FC = () => { if (model === "custom") { return mapping.litellm_model === "custom" || mapping.litellm_model === customModelName; } - if (selectedProvider === Providers.Azure) { - return mapping.litellm_model === `azure/${model}`; - } - return mapping.litellm_model === model; + return mapping.litellm_model === prefixWithProvider(selectedProvider, model); }), ); if (shouldUpdateMappings) { const mappings = selectedModels.map((model: string) => { if (model === "custom" && customModelName) { - if (selectedProvider === Providers.Azure) { - return { - public_name: customModelName, - litellm_model: `azure/${customModelName}`, - }; - } return { public_name: customModelName, - litellm_model: customModelName, - }; - } - if (selectedProvider === Providers.Azure) { - return { - public_name: model, - litellm_model: `azure/${model}`, + litellm_model: prefixWithProvider(selectedProvider, customModelName), }; } return { public_name: model, - litellm_model: model, + litellm_model: prefixWithProvider(selectedProvider, model), }; }); diff --git a/ui/litellm-dashboard/src/components/add_model/litellm_model_name.tsx b/ui/litellm-dashboard/src/components/add_model/litellm_model_name.tsx index 521fed7f7b5..c9c0cb83607 100644 --- a/ui/litellm-dashboard/src/components/add_model/litellm_model_name.tsx +++ b/ui/litellm-dashboard/src/components/add_model/litellm_model_name.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Form, Select as AntSelect } from "antd"; import { TextInput, Text } from "@tremor/react"; import { Row, Col } from "antd"; -import { Providers } from "../provider_info_helpers"; +import { Providers, prefixWithProvider } from "../provider_info_helpers"; interface LiteLLMModelNameFieldProps { selectedProvider: Providers; @@ -31,18 +31,10 @@ const LiteLLMModelNameField: React.FC = ({ // Only update if the value has actually changed if (JSON.stringify(currentModel) !== JSON.stringify(values)) { // Create mappings first - const mappings = values.map((model) => { - if (selectedProvider === Providers.Azure) { - return { - public_name: model, - litellm_model: `azure/${model}`, - }; - } - return { - public_name: model, - litellm_model: model, - }; - }); + const mappings = values.map((model) => ({ + public_name: model, + litellm_model: prefixWithProvider(selectedProvider, model), + })); // Update both fields in one call to reduce re-renders form.setFieldsValue({ @@ -53,43 +45,28 @@ const LiteLLMModelNameField: React.FC = ({ } }; - const handleAzureDeploymentNameChange = (e: React.ChangeEvent) => { - const deploymentName = e.target.value; + const handleFreeTextModelChange = (e: React.ChangeEvent) => { + const modelName = e.target.value; - // Create mapping with Azure-specific format - const mappings = deploymentName - ? [ - { - public_name: deploymentName, - litellm_model: `azure/${deploymentName}`, - }, - ] + const mappings = modelName + ? [{ public_name: modelName, litellm_model: prefixWithProvider(selectedProvider, modelName) }] : []; - // Update both fields form.setFieldsValue({ - model: deploymentName, + model: modelName, model_mappings: mappings, }); }; - // Handle custom model name changes const handleCustomModelNameChange = (e: React.ChangeEvent) => { const customName = e.target.value; - // Immediately update the model mappings const currentMappings = form.getFieldValue("model_mappings") || []; const updatedMappings = currentMappings.map((mapping: any) => { if (mapping.public_name === "custom" || mapping.litellm_model === "custom") { - if (selectedProvider === Providers.Azure) { - return { - public_name: customName, - litellm_model: `azure/${customName}`, - }; - } return { public_name: customName, - litellm_model: customName, + litellm_model: prefixWithProvider(selectedProvider, customName), }; } return mapping; @@ -121,7 +98,7 @@ const LiteLLMModelNameField: React.FC = ({ <> ) : providerModels.length > 0 ? ( diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx index a8021f94d84..0e51d6b8175 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx @@ -267,13 +267,6 @@ describe("provider_info_helpers", () => { expect(result).toEqual(["valid-model"]); }); - it("should log provider key and mapped provider when called", () => { - const modelMap = { "gpt-3.5-turbo": { litellm_provider: "openai" } }; - getProviderModels(Providers.OpenAI, modelMap); - expect(consoleSpy).toHaveBeenCalledWith(`Provider key: ${Providers.OpenAI}`); - expect(consoleSpy).toHaveBeenCalledWith(`Provider mapped to: ${provider_map[Providers.OpenAI]}`); - }); - it("should return empty array for provider with no matching models", () => { const modelMap = { "gpt-3.5-turbo": { litellm_provider: "openai" }, diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx index bf9e9449d8e..29d51fcb9e5 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx @@ -368,11 +368,17 @@ export const getPlaceholder = (selectedProvider: string): string => { } }; +const providersRequiringPrefix = new Set(["Azure", "OpenAI_Compatible"]); + +export const prefixWithProvider = (provider: string, modelName: string): string => { + if (!providersRequiringPrefix.has(provider)) return modelName; + const prefix = provider_map[provider]; + return prefix ? `${prefix}/${modelName}` : modelName; +}; + export const getProviderModels = (provider: Providers, modelMap: any): Array => { let providerKey = provider; - console.log(`Provider key: ${providerKey}`); let custom_llm_provider = provider_map[providerKey]; - console.log(`Provider mapped to: ${custom_llm_provider}`); let providerModels: Array = [];