mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-09 01:08:05 +00:00
ui polish
This commit is contained in:
@@ -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<AddFallbacksProps> = ({
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [selectedModel, setSelectedModel] = useState("");
|
||||
const [modelInfo, setModelInfo] = useState<ModelGroup[]>([]);
|
||||
const [selectedFallbacks, setSelectedFallbacks] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadModels = async () => {
|
||||
@@ -57,11 +49,15 @@ const AddFallbacks: React.FC<AddFallbacksProps> = ({
|
||||
const handleOk = () => {
|
||||
setIsModalVisible(false);
|
||||
form.resetFields();
|
||||
setSelectedFallbacks([]);
|
||||
setSelectedModel("");
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setIsModalVisible(false);
|
||||
form.resetFields();
|
||||
setSelectedFallbacks([]);
|
||||
setSelectedModel("");
|
||||
};
|
||||
|
||||
const updateFallbacks = (formValues: Record<string, any>) => {
|
||||
@@ -100,75 +96,169 @@ const AddFallbacks: React.FC<AddFallbacksProps> = ({
|
||||
|
||||
message.success("router settings updated successfully");
|
||||
|
||||
setIsModalVisible(false)
|
||||
setIsModalVisible(false);
|
||||
form.resetFields();
|
||||
setSelectedFallbacks([]);
|
||||
setSelectedModel("");
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button className="mx-auto" onClick={() => setIsModalVisible(true)}>
|
||||
+ Add Fallbacks
|
||||
<Button
|
||||
className="mx-auto"
|
||||
onClick={() => setIsModalVisible(true)}
|
||||
icon={() => <span className="mr-1">+</span>}
|
||||
>
|
||||
Add Fallbacks
|
||||
</Button>
|
||||
<Modal
|
||||
title="Add Fallbacks"
|
||||
visible={isModalVisible}
|
||||
width={800}
|
||||
title={
|
||||
<div className="pb-4 border-b border-gray-100">
|
||||
<h2 className="text-xl font-semibold text-gray-900">Add Fallbacks</h2>
|
||||
</div>
|
||||
}
|
||||
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" },
|
||||
}}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={updateFallbacks}
|
||||
labelCol={{ span: 8 }}
|
||||
wrapperCol={{ span: 16 }}
|
||||
labelAlign="left"
|
||||
>
|
||||
<>
|
||||
<Form.Item
|
||||
label="Public Model Name"
|
||||
name="model_name"
|
||||
rules={[{ required: true, message: 'Set the model to fallback for' }]}
|
||||
help="required"
|
||||
>
|
||||
<Select defaultValue={selectedModel}>
|
||||
{Array.from(new Set(modelInfo.map(option => option.model_group))).map((model: string, index: number) => (
|
||||
<SelectItem
|
||||
<div className="mt-6">
|
||||
<div className="mb-6">
|
||||
<p className="text-gray-600">
|
||||
Configure fallback models to improve reliability. When the primary model fails or is unavailable,
|
||||
requests will automatically route to the specified fallback models in order.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={updateFallbacks}
|
||||
layout="vertical"
|
||||
className="space-y-6"
|
||||
>
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
<Form.Item
|
||||
label={
|
||||
<span className="text-sm font-medium text-gray-700">
|
||||
Primary Model <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="model_name"
|
||||
rules={[{ required: true, message: 'Please select the primary model that needs fallbacks' }]}
|
||||
className="!mb-0"
|
||||
>
|
||||
<Select
|
||||
placeholder="Select the model that needs fallback protection"
|
||||
value={selectedModel}
|
||||
onValueChange={(value: string) => {
|
||||
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) => (
|
||||
<SelectItem
|
||||
key={index}
|
||||
value={model}
|
||||
onClick={() => setSelectedModel(model)}
|
||||
>
|
||||
>
|
||||
{model}
|
||||
</SelectItem>
|
||||
))
|
||||
}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
This is the primary model that users will request
|
||||
</p>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Fallback Models"
|
||||
name="models"
|
||||
rules={[{ required: true, message: 'Please select a model' }]}
|
||||
help="required"
|
||||
>
|
||||
<MultiSelect>
|
||||
{Array.from(new Set(modelInfo.map(option => option.model_group)))
|
||||
.filter((data: string) => data != selectedModel)
|
||||
.map((model: string) => (
|
||||
<MultiSelectItem key={model} value={model}>
|
||||
<div className="border-t border-gray-200 my-6"></div>
|
||||
|
||||
<Form.Item
|
||||
label={
|
||||
<span className="text-sm font-medium text-gray-700">
|
||||
Fallback Models (select multiple) <span className="text-red-500">*</span>
|
||||
</span>
|
||||
}
|
||||
name="models"
|
||||
rules={[{ required: true, message: 'Please select at least one fallback model' }]}
|
||||
className="!mb-0"
|
||||
>
|
||||
<div className="space-y-3">
|
||||
{/* Show selected models in order */}
|
||||
{selectedFallbacks.length > 0 && (
|
||||
<div className="border border-gray-200 rounded-lg p-3 bg-gray-50">
|
||||
<p className="text-sm font-medium text-gray-700 mb-2">
|
||||
Fallback Order:
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{selectedFallbacks.map((model, index) => (
|
||||
<div key={model} className="flex items-center bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm">
|
||||
<span className="font-medium mr-2">{index + 1}.</span>
|
||||
<span>{model}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const newFallbacks = selectedFallbacks.filter(m => m !== model);
|
||||
setSelectedFallbacks(newFallbacks);
|
||||
form.setFieldValue('models', newFallbacks);
|
||||
}}
|
||||
className="ml-2 text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Model selector */}
|
||||
<Select
|
||||
placeholder="Add a fallback model"
|
||||
value=""
|
||||
onValueChange={(value: string) => {
|
||||
if (value && !selectedFallbacks.includes(value)) {
|
||||
const newFallbacks = [...selectedFallbacks, value];
|
||||
setSelectedFallbacks(newFallbacks);
|
||||
form.setFieldValue('models', newFallbacks);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{Array.from(new Set(modelInfo.map(option => option.model_group)))
|
||||
.filter((data: string) => data !== selectedModel && !selectedFallbacks.includes(data))
|
||||
.sort()
|
||||
.map((model: string) => (
|
||||
<SelectItem key={model} value={model}>
|
||||
{model}
|
||||
</MultiSelectItem>
|
||||
))}
|
||||
|
||||
</MultiSelect>
|
||||
</Form.Item>
|
||||
</>
|
||||
|
||||
<div style={{ textAlign: "right", marginTop: "10px" }}>
|
||||
<Button2 htmlType="submit">Add Fallbacks</Button2>
|
||||
</div>
|
||||
</Form>
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
<strong>Order matters:</strong> Models will be tried in the order shown above (1st, 2nd, 3rd, etc.)
|
||||
</p>
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end space-x-3 pt-6 border-t border-gray-100">
|
||||
<Button variant="secondary" onClick={handleCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="primary" type="submit">
|
||||
Add Fallbacks
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user