working add alias flow

This commit is contained in:
Ishaan Jaff 2025-05-19 16:56:00 -07:00
parent b69a44f083
commit 3b5aa43ba1
3 changed files with 310 additions and 2 deletions

View file

@ -62,6 +62,8 @@ import {
adminGlobalActivityExceptions,
adminGlobalActivityExceptionsPerDeployment,
allEndUsersCall,
getRouterSettings,
updateRouterSettings,
} from "./networking";
import { BarChart, AreaChart } from "@tremor/react";
import {
@ -114,6 +116,7 @@ import { ModelDataTable } from "./model_dashboard/table";
import { columns } from "./model_dashboard/columns";
import { all_admin_roles } from "@/utils/roles";
import { Table as TableInstance } from '@tanstack/react-table';
import ModelAliasManagement from "./model_dashboard/model_alias_management";
interface ModelDashboardProps {
accessToken: string | null;
@ -670,6 +673,8 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
handleRefreshClick();
}, [accessToken, token, userRole, userID, modelMap, lastRefreshed, selectedTeam]);
if (!modelData) {
return <div>Loading...</div>;
}
@ -1067,13 +1072,13 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
</Tab>}
{all_admin_roles.includes(userRole) && <Tab>Model Analytics</Tab>}
{all_admin_roles.includes(userRole) && <Tab>Model Retry Settings</Tab>}
{all_admin_roles.includes(userRole) && <Tab>Model Group Aliases</Tab>}
</div>
<div className="flex items-center space-x-2">
{lastRefreshed && <Text>Last Refreshed: {lastRefreshed}</Text>}
<Icon
icon={RefreshIcon} // Modify as necessary for correct icon name
icon={RefreshIcon}
variant="shadow"
size="xs"
className="self-center"
@ -1602,6 +1607,15 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
Save
</Button>
</TabPanel>
<TabPanel>
{accessToken && (
<ModelAliasManagement
accessToken={accessToken}
availableModels={availableModelGroups}
onRefresh={handleRefreshClick}
/>
)}
</TabPanel>
</TabPanels>
</TabGroup>

View file

@ -0,0 +1,239 @@
import React, { useState, useEffect } from "react";
import {
Card,
Title,
Text,
Table,
TableHead,
TableRow,
TableHeaderCell,
TableCell,
TableBody,
Button
} from "@tremor/react";
import {
Input,
Select,
message,
Button as AntdButton,
} from "antd";
import {
PencilIcon,
TrashIcon,
} from "@heroicons/react/outline";
import { getRouterSettings, updateRouterSettings } from "../networking";
interface ModelAliasManagementProps {
accessToken: string;
availableModels: string[];
onRefresh: () => void;
}
const ModelAliasManagement: React.FC<ModelAliasManagementProps> = ({
accessToken,
availableModels,
onRefresh,
}) => {
const [modelGroupAliases, setModelGroupAliases] = useState<Record<string, string>>({});
const [newAliasName, setNewAliasName] = useState<string>("");
const [selectedModelForAlias, setSelectedModelForAlias] = useState<string>("");
const [editingAlias, setEditingAlias] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(false);
// Fetch router settings
useEffect(() => {
fetchRouterSettings();
}, [accessToken]);
const fetchRouterSettings = async () => {
if (!accessToken) return;
setIsLoading(true);
try {
const settings = await getRouterSettings(accessToken);
if (settings?.router_settings?.model_group_alias) {
setModelGroupAliases(settings.router_settings.model_group_alias);
} else {
setModelGroupAliases({});
}
} catch (error) {
console.error("Failed to fetch router settings:", error);
message.error("Failed to load model aliases");
} finally {
setIsLoading(false);
}
};
// Handle adding or updating a model group alias
const handleSaveModelGroupAlias = async () => {
if (!accessToken || !newAliasName || !selectedModelForAlias) {
message.error("Alias name and model selection are required");
return;
}
setIsLoading(true);
try {
const updatedAliases = { ...modelGroupAliases };
// If editing, remove the old alias first
if (editingAlias && editingAlias !== newAliasName) {
delete updatedAliases[editingAlias];
}
updatedAliases[newAliasName] = selectedModelForAlias;
await updateRouterSettings(accessToken, {
model_group_alias: updatedAliases
});
setModelGroupAliases(updatedAliases);
setNewAliasName("");
setSelectedModelForAlias("");
setEditingAlias(null);
message.success(`Model group alias ${editingAlias ? 'updated' : 'created'} successfully`);
onRefresh();
} catch (error) {
console.error("Failed to save model group alias:", error);
message.error(`Failed to ${editingAlias ? 'update' : 'create'} model group alias`);
} finally {
setIsLoading(false);
}
};
// Handle deleting a model group alias
const handleDeleteModelGroupAlias = async (aliasName: string) => {
setIsLoading(true);
try {
const updatedAliases = { ...modelGroupAliases };
delete updatedAliases[aliasName];
await updateRouterSettings(accessToken, {
model_group_alias: updatedAliases
});
setModelGroupAliases(updatedAliases);
message.success(`Model group alias deleted successfully`);
onRefresh();
} catch (error) {
console.error("Failed to delete model group alias:", error);
message.error("Failed to delete model group alias");
} finally {
setIsLoading(false);
}
};
// Handle editing a model group alias
const handleEditModelGroupAlias = (aliasName: string) => {
setEditingAlias(aliasName);
setNewAliasName(aliasName);
setSelectedModelForAlias(modelGroupAliases[aliasName] || "");
};
return (
<Card>
<Title>Model Group Aliases</Title>
<Text className="mb-6">
Map model alias names to actual model names. Aliases can be used interchangeably with the original model names in API calls.
</Text>
<div className="mb-8">
<form className="flex flex-col space-y-4">
<div className="flex space-x-4 items-end">
<div className="flex-1">
<Text>Alias Name</Text>
<Input
placeholder="Enter alias name"
value={newAliasName}
onChange={(e) => setNewAliasName(e.target.value)}
/>
</div>
<div className="flex-1">
<Text>Target Model</Text>
<Select
placeholder="Select model"
value={selectedModelForAlias}
onChange={(value: string) => setSelectedModelForAlias(value)}
style={{ width: '100%' }}
>
{availableModels.map((model, idx) => (
<Select.Option key={idx} value={model}>
{model}
</Select.Option>
))}
</Select>
</div>
<AntdButton
onClick={handleSaveModelGroupAlias}
disabled={!newAliasName || !selectedModelForAlias || isLoading}
type="primary"
loading={isLoading}
>
{editingAlias ? "Update" : "Add"} Alias
</AntdButton>
{editingAlias && (
<AntdButton
onClick={() => {
setEditingAlias(null);
setNewAliasName("");
setSelectedModelForAlias("");
}}
disabled={isLoading}
>
Cancel
</AntdButton>
)}
</div>
</form>
</div>
<Table>
<TableHead>
<TableRow>
<TableHeaderCell>Alias Name</TableHeaderCell>
<TableHeaderCell>Target Model</TableHeaderCell>
<TableHeaderCell>Actions</TableHeaderCell>
</TableRow>
</TableHead>
<TableBody>
{Object.entries(modelGroupAliases).map(([alias, model], idx) => (
<TableRow key={idx}>
<TableCell>{alias}</TableCell>
<TableCell>{model}</TableCell>
<TableCell>
<div className="flex space-x-2">
<Button
size="xs"
variant="secondary"
icon={PencilIcon}
onClick={() => handleEditModelGroupAlias(alias)}
disabled={isLoading}
/>
<Button
size="xs"
variant="secondary"
icon={TrashIcon}
onClick={() => handleDeleteModelGroupAlias(alias)}
disabled={isLoading}
/>
</div>
</TableCell>
</TableRow>
))}
{Object.keys(modelGroupAliases).length === 0 && (
<TableRow>
<TableCell colSpan={3} className="text-center">
No model group aliases defined
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</Card>
);
};
export default ModelAliasManagement;

View file

@ -5187,3 +5187,58 @@ export const updateGuardrailCall = async (
throw error;
}
};
export const getRouterSettings = async (accessToken: string) => {
try {
const url = proxyBaseUrl ? `${proxyBaseUrl}/router_settings` : `/router_settings`;
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(
errorData.detail?.error || "Failed to fetch router settings"
);
}
return await response.json();
} catch (error) {
handleError(`Error fetching router settings: ${error}`);
throw error;
}
};
export const updateRouterSettings = async (
accessToken: string,
settings: Record<string, any>
) => {
const url = proxyBaseUrl ? `${proxyBaseUrl}/router_settings` : `/router_settings`;
try {
const response = await fetch(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify(settings),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(
errorData.detail?.error || "Failed to update router settings"
);
}
return await response.json();
} catch (error) {
handleError(`Error updating router settings: ${error}`);
throw error;
}
};