From 56fc0cf374db8691e1b4c8f65709f083ba0fa2c8 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Thu, 31 Jul 2025 17:08:18 -0700 Subject: [PATCH] ui polish --- .../src/components/add_fallbacks.tsx | 216 +++++++++++++----- 1 file changed, 153 insertions(+), 63 deletions(-) diff --git a/ui/litellm-dashboard/src/components/add_fallbacks.tsx b/ui/litellm-dashboard/src/components/add_fallbacks.tsx index 4ac5beab60..3ab7bc7e8e 100644 --- a/ui/litellm-dashboard/src/components/add_fallbacks.tsx +++ b/ui/litellm-dashboard/src/components/add_fallbacks.tsx @@ -4,25 +4,16 @@ -import React, { useState, useEffect, useRef } from "react"; +import React, { useState, useEffect } from "react"; import { Button, TextInput, Grid, Col } from "@tremor/react"; -import { Select, SelectItem, MultiSelect, MultiSelectItem, Card, Metric, Text, Title, Subtitle, Accordion, AccordionHeader, AccordionBody, } from "@tremor/react"; -import { CopyToClipboard } from 'react-copy-to-clipboard'; +import { Select, SelectItem, MultiSelect, MultiSelectItem } from "@tremor/react"; import { setCallbacksCall } from "./networking"; import { - Button as Button2, Modal, Form, - Input, - InputNumber, - Select as Select2, message, } from "antd"; -import { keyCreateCall, slackBudgetAlertsHealthCheck, modelAvailableCall } from "./networking"; import { fetchAvailableModels, ModelGroup } from "./chat_ui/llm_calls/fetch_models"; -import { list } from "postcss"; - -const { Option } = Select2; interface AddFallbacksProps { models?: string[]; @@ -41,6 +32,7 @@ const AddFallbacks: React.FC = ({ const [isModalVisible, setIsModalVisible] = useState(false); const [selectedModel, setSelectedModel] = useState(""); const [modelInfo, setModelInfo] = useState([]); + const [selectedFallbacks, setSelectedFallbacks] = useState([]); useEffect(() => { const loadModels = async () => { @@ -57,11 +49,15 @@ const AddFallbacks: React.FC = ({ const handleOk = () => { setIsModalVisible(false); form.resetFields(); + setSelectedFallbacks([]); + setSelectedModel(""); }; const handleCancel = () => { setIsModalVisible(false); form.resetFields(); + setSelectedFallbacks([]); + setSelectedModel(""); }; const updateFallbacks = (formValues: Record) => { @@ -100,75 +96,169 @@ const AddFallbacks: React.FC = ({ message.success("router settings updated successfully"); - setIsModalVisible(false) + setIsModalVisible(false); form.resetFields(); + setSelectedFallbacks([]); + setSelectedModel(""); }; return (
- +

Add Fallbacks

+
+ } + open={isModalVisible} + width={900} footer={null} onOk={handleOk} onCancel={handleCancel} + className="top-8" + styles={{ + body: { padding: "24px" }, + header: { padding: "24px 24px 0 24px", border: "none" }, + }} > -
- <> - - { + setSelectedModel(value); + // Remove the selected model from fallbacks if it was selected + const updatedFallbacks = selectedFallbacks.filter(model => model !== value); + setSelectedFallbacks(updatedFallbacks); + form.setFieldValue('models', updatedFallbacks); + form.setFieldValue('model_name', value); + }} + > + {Array.from(new Set(modelInfo.map(option => option.model_group))).map((model: string, index: number) => ( + setSelectedModel(model)} - > + > {model} - - )) - } - - + + ))} + +

+ This is the primary model that users will request +

+ - - - {Array.from(new Set(modelInfo.map(option => option.model_group))) - .filter((data: string) => data != selectedModel) - .map((model: string) => ( - +
+ + + Fallback Models (select multiple) * + + } + name="models" + rules={[{ required: true, message: 'Please select at least one fallback model' }]} + className="!mb-0" + > +
+ {/* Show selected models in order */} + {selectedFallbacks.length > 0 && ( +
+

+ Fallback Order: +

+
+ {selectedFallbacks.map((model, index) => ( +
+ {index + 1}. + {model} + +
+ ))} +
+
+ )} + + {/* Model selector */} + +
+

+ Order matters: Models will be tried in the order shown above (1st, 2nd, 3rd, etc.) +

+
+ + +
+ + +
+ +