mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-08 17:10:14 +00:00
EditAutoRouterTabProps
This commit is contained in:
@@ -0,0 +1,293 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Card, Form, Button, Tooltip, Typography, Select as AntdSelect, message } from "antd";
|
||||
import type { FormInstance } from "antd";
|
||||
import { Text, TextInput } from "@tremor/react";
|
||||
import { modelAvailableCall } from "../networking";
|
||||
import { all_admin_roles } from "@/utils/roles";
|
||||
import { fetchAvailableModels, ModelGroup } from "../chat_ui/llm_calls/fetch_models";
|
||||
import RouterConfigBuilder from "../add_model/router_config_builder";
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
interface EditAutoRouterTabProps {
|
||||
form: FormInstance;
|
||||
localModelData: any;
|
||||
accessToken: string;
|
||||
userRole: string;
|
||||
isEditing: boolean;
|
||||
setIsDirty: (dirty: boolean) => void;
|
||||
}
|
||||
|
||||
const EditAutoRouterTab: React.FC<EditAutoRouterTabProps> = ({
|
||||
form,
|
||||
localModelData,
|
||||
accessToken,
|
||||
userRole,
|
||||
isEditing,
|
||||
setIsDirty,
|
||||
}) => {
|
||||
const [modelAccessGroups, setModelAccessGroups] = useState<string[]>([]);
|
||||
const [modelInfo, setModelInfo] = useState<ModelGroup[]>([]);
|
||||
const [showCustomDefaultModel, setShowCustomDefaultModel] = useState<boolean>(false);
|
||||
const [showCustomEmbeddingModel, setShowCustomEmbeddingModel] = useState<boolean>(false);
|
||||
const [routerConfig, setRouterConfig] = useState<any>(null);
|
||||
|
||||
const isAdmin = all_admin_roles.includes(userRole);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchModelAccessGroups = async () => {
|
||||
const response = await modelAvailableCall(accessToken, "", "", false, null, true, true);
|
||||
setModelAccessGroups(response["data"].map((model: any) => model["id"]));
|
||||
};
|
||||
fetchModelAccessGroups();
|
||||
}, [accessToken]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadModels = async () => {
|
||||
try {
|
||||
const uniqueModels = await fetchAvailableModels(accessToken);
|
||||
console.log("Fetched models for auto router edit:", uniqueModels);
|
||||
setModelInfo(uniqueModels);
|
||||
} catch (error) {
|
||||
console.error("Error fetching model info for auto router edit:", error);
|
||||
}
|
||||
};
|
||||
loadModels();
|
||||
}, [accessToken]);
|
||||
|
||||
// Initialize form values and router config when localModelData changes
|
||||
useEffect(() => {
|
||||
if (localModelData) {
|
||||
const autoRouterConfig = localModelData.litellm_params?.auto_router_config;
|
||||
let parsedConfig = null;
|
||||
|
||||
if (autoRouterConfig) {
|
||||
try {
|
||||
// Parse the JSON string to object
|
||||
parsedConfig = typeof autoRouterConfig === 'string'
|
||||
? JSON.parse(autoRouterConfig)
|
||||
: autoRouterConfig;
|
||||
setRouterConfig(parsedConfig);
|
||||
} catch (error) {
|
||||
console.error("Error parsing auto router config:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if using custom models
|
||||
const defaultModel = localModelData.litellm_params?.auto_router_default_model;
|
||||
const embeddingModel = localModelData.litellm_params?.auto_router_embedding_model;
|
||||
|
||||
setShowCustomDefaultModel(defaultModel && !modelInfo.some(m => m.model_group === defaultModel));
|
||||
setShowCustomEmbeddingModel(embeddingModel && !modelInfo.some(m => m.model_group === embeddingModel));
|
||||
}
|
||||
}, [localModelData, modelInfo]);
|
||||
|
||||
const handleRouterConfigChange = (config: any) => {
|
||||
setRouterConfig(config);
|
||||
form.setFieldValue('auto_router_config', config);
|
||||
setIsDirty(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<Title level={3}>Auto Router Configuration</Title>
|
||||
<Text className="text-gray-600">
|
||||
Configure the auto routing logic that automatically selects the best model based on user input patterns and semantic matching.
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
{/* Auto Router Name */}
|
||||
<div>
|
||||
<Text className="font-medium">Auto Router Name</Text>
|
||||
{isEditing ? (
|
||||
<Form.Item name="auto_router_name" className="mb-0">
|
||||
<TextInput
|
||||
placeholder="e.g., auto_router_1, smart_routing"
|
||||
onChange={() => setIsDirty(true)}
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<div className="mt-1 p-2 bg-gray-50 rounded">
|
||||
{localModelData.model_name || "Not Set"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Router Configuration Builder */}
|
||||
{isEditing ? (
|
||||
<div className="w-full">
|
||||
<RouterConfigBuilder
|
||||
modelInfo={modelInfo}
|
||||
value={routerConfig}
|
||||
onChange={handleRouterConfigChange}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Text className="font-medium">Router Configuration</Text>
|
||||
<div className="mt-1 p-2 bg-gray-50 rounded">
|
||||
{routerConfig ? (
|
||||
<div className="space-y-2">
|
||||
<Text className="text-sm font-medium">Routes: {routerConfig.routes?.length || 0}</Text>
|
||||
{routerConfig.routes?.map((route: any, index: number) => (
|
||||
<div key={index} className="text-sm bg-white p-2 rounded border">
|
||||
<div><strong>Model:</strong> {route.name}</div>
|
||||
<div><strong>Description:</strong> {route.description}</div>
|
||||
<div><strong>Utterances:</strong> {route.utterances?.length || 0} examples</div>
|
||||
<div><strong>Score Threshold:</strong> {route.score_threshold}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
"No router configuration"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Default Model */}
|
||||
<div>
|
||||
<Text className="font-medium">Default Model</Text>
|
||||
{isEditing ? (
|
||||
<>
|
||||
<Form.Item name="auto_router_default_model" className="mb-0">
|
||||
<AntdSelect
|
||||
placeholder="Select a default model"
|
||||
onChange={(value) => {
|
||||
setShowCustomDefaultModel(value === 'custom');
|
||||
setIsDirty(true);
|
||||
}}
|
||||
options={[
|
||||
...Array.from(new Set(modelInfo.map(option => option.model_group)))
|
||||
.map((model_group) => ({
|
||||
value: model_group,
|
||||
label: model_group,
|
||||
})),
|
||||
{ value: 'custom', label: 'Enter custom model name' }
|
||||
]}
|
||||
style={{ width: "100%" }}
|
||||
showSearch={true}
|
||||
/>
|
||||
</Form.Item>
|
||||
{showCustomDefaultModel && (
|
||||
<Form.Item name="custom_default_model" className="mb-0 mt-2">
|
||||
<TextInput
|
||||
placeholder="Enter custom model name"
|
||||
onChange={(e) => {
|
||||
form.setFieldValue('auto_router_default_model', e.target.value);
|
||||
setIsDirty(true);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className="mt-1 p-2 bg-gray-50 rounded">
|
||||
{localModelData.litellm_params?.auto_router_default_model || "Not Set"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Embedding Model */}
|
||||
<div>
|
||||
<Text className="font-medium">Embedding Model</Text>
|
||||
{isEditing ? (
|
||||
<>
|
||||
<Form.Item name="auto_router_embedding_model" className="mb-0">
|
||||
<AntdSelect
|
||||
placeholder="Select an embedding model (optional)"
|
||||
onChange={(value) => {
|
||||
setShowCustomEmbeddingModel(value === 'custom');
|
||||
setIsDirty(true);
|
||||
}}
|
||||
options={[
|
||||
...Array.from(new Set(modelInfo.map(option => option.model_group)))
|
||||
.map((model_group) => ({
|
||||
value: model_group,
|
||||
label: model_group,
|
||||
})),
|
||||
{ value: 'custom', label: 'Enter custom model name' }
|
||||
]}
|
||||
style={{ width: "100%" }}
|
||||
showSearch={true}
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
{showCustomEmbeddingModel && (
|
||||
<Form.Item name="custom_embedding_model" className="mb-0 mt-2">
|
||||
<TextInput
|
||||
placeholder="Enter custom embedding model name"
|
||||
onChange={(e) => {
|
||||
form.setFieldValue('auto_router_embedding_model', e.target.value);
|
||||
setIsDirty(true);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className="mt-1 p-2 bg-gray-50 rounded">
|
||||
{localModelData.litellm_params?.auto_router_embedding_model || "Not Set"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Model Access Groups - Admin only */}
|
||||
{isAdmin && (
|
||||
<div>
|
||||
<Text className="font-medium">Model Access Groups</Text>
|
||||
{isEditing ? (
|
||||
<Form.Item name="model_access_group" className="mb-0">
|
||||
<AntdSelect
|
||||
mode="tags"
|
||||
showSearch
|
||||
placeholder="Select existing groups or type to create new ones"
|
||||
optionFilterProp="children"
|
||||
tokenSeparators={[',']}
|
||||
options={modelAccessGroups.map((group) => ({
|
||||
value: group,
|
||||
label: group
|
||||
}))}
|
||||
maxTagCount="responsive"
|
||||
allowClear
|
||||
onChange={() => setIsDirty(true)}
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<div className="mt-1 p-2 bg-gray-50 rounded">
|
||||
{localModelData.model_info?.access_groups ? (
|
||||
Array.isArray(localModelData.model_info.access_groups) ? (
|
||||
localModelData.model_info.access_groups.length > 0 ? (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{localModelData.model_info.access_groups.map(
|
||||
(group: string, index: number) => (
|
||||
<span
|
||||
key={index}
|
||||
className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800"
|
||||
>
|
||||
{group}
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
"No groups assigned"
|
||||
)
|
||||
) : (
|
||||
localModelData.model_info.access_groups
|
||||
)
|
||||
) : (
|
||||
"Not Set"
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditAutoRouterTab;
|
||||
Reference in New Issue
Block a user