diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 74d84a456a..9f81806410 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -8001,10 +8001,12 @@ async def update_config(config_info: ConfigYAML): _updated_environment_variables[k] = base64.b64encode( encrypted_value ).decode("utf-8") - config["environment_variables"] = { - **_updated_environment_variables, - **config["environment_variables"], - } + + _existing_env_variables = config["environment_variables"] + + for k, v in _updated_environment_variables.items(): + # overwrite existing env variables with updated values + _existing_env_variables[k] = _updated_environment_variables[k] # update the litellm settings if config_info.litellm_settings is not None: diff --git a/ui/litellm-dashboard/src/components/leftnav.tsx b/ui/litellm-dashboard/src/components/leftnav.tsx index 121f1cbb61..99da050025 100644 --- a/ui/litellm-dashboard/src/components/leftnav.tsx +++ b/ui/litellm-dashboard/src/components/leftnav.tsx @@ -46,8 +46,8 @@ const Sidebar: React.FC = ({ ); } return ( - - + + = ({ ) : null} setPage("settings")}> - Settings + Integrations {userRole == "Admin" ? ( diff --git a/ui/litellm-dashboard/src/components/model_dashboard.tsx b/ui/litellm-dashboard/src/components/model_dashboard.tsx index 9a2ee3c42b..c9c67c6109 100644 --- a/ui/litellm-dashboard/src/components/model_dashboard.tsx +++ b/ui/litellm-dashboard/src/components/model_dashboard.tsx @@ -176,58 +176,67 @@ const ModelDashboard: React.FC = ({ } const handleSubmit = async (formValues: Record) => { - const litellmParamsObj: Record = {}; - const modelInfoObj: Record = {}; - let modelName: string = ""; - // Iterate through the key-value pairs in formValues - for (const [key, value] of Object.entries(formValues)) { - if (key == "model_name") { - modelName = value - } - - // Check if key is any of the specified API related keys - if (key === "api_key" || key === "model" || key === "api_base" || key === "api_version" || key.startsWith("aws_")) { - // Add key-value pair to litellm_params dictionary - litellmParamsObj[key] = value; - } - - // Check if key is "base_model" - if (key === "base_model") { - // Add key-value pair to model_info dictionary - modelInfoObj[key] = value; - } + try { - if (key == "litellm_extra_params") { - console.log("litellm_extra_params:", value); - let litellmExtraParams = {}; - try { - litellmExtraParams = JSON.parse(value); + const litellmParamsObj: Record = {}; + const modelInfoObj: Record = {}; + let modelName: string = ""; + // Iterate through the key-value pairs in formValues + for (const [key, value] of Object.entries(formValues)) { + if (key == "model_name") { + modelName = value } - catch (error) { - message.error("Failed to parse LiteLLM Extra Paras: " + error); - throw new Error("Failed to parse litellm_extra_params: " + error); - } - for (const [key, value] of Object.entries(litellmExtraParams)) { + + // Check if key is any of the specified API related keys + if (key === "api_key" || key === "model" || key === "api_base" || key === "api_version" || key.startsWith("aws_")) { + // Add key-value pair to litellm_params dictionary litellmParamsObj[key] = value; } + + // Check if key is "base_model" + if (key === "base_model") { + // Add key-value pair to model_info dictionary + modelInfoObj[key] = value; + } + + + if (key == "litellm_extra_params") { + console.log("litellm_extra_params:", value); + let litellmExtraParams = {}; + if (value && value != undefined) { + try { + litellmExtraParams = JSON.parse(value); + } + catch (error) { + message.error("Failed to parse LiteLLM Extra Params: " + error); + throw new Error("Failed to parse litellm_extra_params: " + error); + } + for (const [key, value] of Object.entries(litellmExtraParams)) { + litellmParamsObj[key] = value; + } + } + } } - } - const new_model: Model = { - "model_name": modelName, - "litellm_params": litellmParamsObj, - "model_info": modelInfoObj - } + const new_model: Model = { + "model_name": modelName, + "litellm_params": litellmParamsObj, + "model_info": modelInfoObj + } - + - const response: any = await modelCreateCall( - accessToken, - new_model - ); + const response: any = await modelCreateCall( + accessToken, + new_model + ); + form.resetFields(); - console.log(`response for model create call: ${response["data"]}`); + console.log(`response for model create call: ${response["data"]}`); + } catch (error) { + message.error("Failed to create model: " + error); + } } const handleOk = () => { @@ -235,7 +244,7 @@ const ModelDashboard: React.FC = ({ .validateFields() .then((values) => { handleSubmit(values); - form.resetFields(); + // form.resetFields(); }) .catch((error) => { console.error("Validation failed:", error); diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 5a096031a8..f702e407e4 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -38,7 +38,7 @@ export const modelCreateCall = async ( const data = await response.json(); console.log("API Response:", data); - message.success("Model created successfully. Wait 60s and refresh.") + message.success("Model created successfully. Wait 60s and refresh on 'All Models' page"); return data; } catch (error) { console.error("Failed to create key:", error); diff --git a/ui/litellm-dashboard/src/components/settings.tsx b/ui/litellm-dashboard/src/components/settings.tsx index 31e17b6f1a..fc9f48d35e 100644 --- a/ui/litellm-dashboard/src/components/settings.tsx +++ b/ui/litellm-dashboard/src/components/settings.tsx @@ -34,6 +34,7 @@ const Settings: React.FC = ({ const [callbacks, setCallbacks] = useState([]); const [isModalVisible, setIsModalVisible] = useState(false); const [form] = Form.useForm(); + const [selectedCallback, setSelectedCallback] = useState(null); useEffect(() => { if (!accessToken || !userRole || !userID) { @@ -55,6 +56,7 @@ const Settings: React.FC = ({ const handleCancel = () => { setIsModalVisible(false); form.resetFields(); + setSelectedCallback(null); }; const handleOk = () => { @@ -64,8 +66,8 @@ const Settings: React.FC = ({ // Handle form submission form.validateFields().then((values) => { // Call API to add the callback + console.log("Form values:", values); let payload; - console.log("Callback values:", values); if (values.callback === 'langfuse') { payload = { environment_variables: { @@ -80,8 +82,19 @@ const Settings: React.FC = ({ // add langfuse to callbacks setCallbacks(callbacks ? [...callbacks, values.callback] : [values.callback]); + } else if (values.callback === 'slack') { + payload = { + litellm_settings: { + success_callback: [values.callback] + }, + environment_variables: { + SLACK_WEBHOOK_URL: values.slackWebhookUrl + } + }; + setCallbacksCall(accessToken, payload); - + // add slack to callbacks + setCallbacks(callbacks ? [...callbacks, values.callback] : [values.callback]); } else { payload = { error: 'Invalid callback value' @@ -89,9 +102,14 @@ const Settings: React.FC = ({ } setIsModalVisible(false); form.resetFields(); + setSelectedCallback(null); }); }; + const handleCallbackChange = (value: string) => { + setSelectedCallback(value); + }; + return (
@@ -138,33 +156,48 @@ const Settings: React.FC = ({ name="callback" rules={[{ required: true, message: "Please select a callback" }]} > - langfuse - slack + slack alerting - - - + {selectedCallback === 'langfuse' && ( + <> + + + - - - + + + + + )} + + {selectedCallback === 'slack' && ( + + + + )} -
Save