Merge pull request #18552 from BerriAI/litellm_ui_model_loading

[Refactor] UI - Remove Model Analytics From Model Page
This commit is contained in:
yuneng-jiang
2025-12-31 15:02:01 -08:00
committed by GitHub
11 changed files with 230 additions and 335 deletions
@@ -0,0 +1,155 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { renderHook, waitFor } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import React, { ReactNode } from "react";
import { useModelCostMap } from "./useModelCostMap";
import { modelCostMap } from "@/components/networking";
// Mock the networking function
vi.mock("@/components/networking", () => ({
modelCostMap: vi.fn(),
}));
// Mock the queryKeysFactory - we'll mock the specific return value
vi.mock("../common/queryKeysFactory", () => ({
createQueryKeys: vi.fn((resource: string) => ({
all: [resource],
lists: () => [resource, "list"],
list: (params?: any) => [resource, "list", { params }],
details: () => [resource, "detail"],
detail: (uid: string) => [resource, "detail", uid],
})),
}));
// Mock data
const mockModelCostData: Record<string, any> = {
"gpt-3.5-turbo": {
litellm_provider: "openai",
input_cost_per_token: 0.0015,
output_cost_per_token: 0.002,
},
"claude-3-sonnet-20240229": {
litellm_provider: "anthropic",
input_cost_per_token: 0.003,
output_cost_per_token: 0.015,
},
};
describe("useModelCostMap", () => {
let queryClient: QueryClient;
beforeEach(() => {
queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
// Reset all mocks
vi.clearAllMocks();
});
const wrapper = ({ children }: { children: ReactNode }) =>
React.createElement(QueryClientProvider, { client: queryClient }, children);
it("should return model cost map data when query is successful", async () => {
// Mock successful API call
(modelCostMap as any).mockResolvedValue(mockModelCostData);
const { result } = renderHook(() => useModelCostMap(), { wrapper });
// Initially loading
expect(result.current.isLoading).toBe(true);
expect(result.current.data).toBeUndefined();
// Wait for success
await waitFor(() => {
expect(result.current.isLoading).toBe(false);
expect(result.current.isSuccess).toBe(true);
});
expect(result.current.data).toEqual(mockModelCostData);
expect(result.current.error).toBeNull();
expect(modelCostMap).toHaveBeenCalledTimes(1);
});
it("should handle error when modelCostMap fails", async () => {
const errorMessage = "Failed to fetch model cost map";
const testError = new Error(errorMessage);
// Mock failed API call
(modelCostMap as any).mockRejectedValue(testError);
const { result } = renderHook(() => useModelCostMap(), { wrapper });
// Initially loading
expect(result.current.isLoading).toBe(true);
// Wait for error
await waitFor(() => {
expect(result.current.isLoading).toBe(false);
expect(result.current.isError).toBe(true);
});
expect(result.current.error).toEqual(testError);
expect(result.current.data).toBeUndefined();
expect(modelCostMap).toHaveBeenCalledTimes(1);
});
it("should return empty object when API returns empty data", async () => {
// Mock API returning empty object
(modelCostMap as any).mockResolvedValue({});
const { result } = renderHook(() => useModelCostMap(), { wrapper });
// Wait for success
await waitFor(() => {
expect(result.current.isLoading).toBe(false);
expect(result.current.isSuccess).toBe(true);
});
expect(result.current.data).toEqual({});
expect(modelCostMap).toHaveBeenCalledTimes(1);
});
it("should handle network timeout error", async () => {
const timeoutError = new Error("Network timeout");
// Mock network timeout
(modelCostMap as any).mockRejectedValue(timeoutError);
const { result } = renderHook(() => useModelCostMap(), { wrapper });
// Wait for error
await waitFor(() => {
expect(result.current.isError).toBe(true);
});
expect(result.current.error).toEqual(timeoutError);
expect(result.current.data).toBeUndefined();
});
it("should have correct query configuration", async () => {
// Mock successful API call
(modelCostMap as any).mockResolvedValue(mockModelCostData);
const { result } = renderHook(() => useModelCostMap(), { wrapper });
// Wait for query to complete
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
});
// Verify the query was called
expect(modelCostMap).toHaveBeenCalledTimes(1);
// The hook should have the expected properties from useQuery
expect(result.current).toHaveProperty("data");
expect(result.current).toHaveProperty("isLoading");
expect(result.current).toHaveProperty("isError");
expect(result.current).toHaveProperty("isSuccess");
expect(result.current).toHaveProperty("error");
});
});
@@ -0,0 +1,14 @@
import { modelCostMap } from "@/components/networking";
import { useQuery } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
const modelCostMapKeys = createQueryKeys("modelCostMap");
export const useModelCostMap = () => {
return useQuery<Record<string, any>>({
queryKey: modelCostMapKeys.list({}),
queryFn: async () => await modelCostMap(),
staleTime: 60 * 1000, // 1 minute
gcTime: 60 * 1000, // 1 minute
});
};
@@ -9,34 +9,24 @@ vi.mock("@/components/networking", () => ({
credentialListCall: vi.fn().mockResolvedValue({ credentials: [] }),
modelInfoCall: vi.fn().mockResolvedValue({ data: [] }),
modelCostMap: vi.fn().mockResolvedValue({}),
modelMetricsCall: vi.fn().mockResolvedValue({ data: [], all_api_bases: [] }),
streamingModelMetricsCall: vi.fn().mockResolvedValue({ data: [], all_api_bases: [] }),
modelExceptionsCall: vi.fn().mockResolvedValue({ data: [], exception_types: [] }),
modelMetricsSlowResponsesCall: vi.fn().mockResolvedValue([]),
getPassThroughEndpointsCall: vi.fn().mockResolvedValue({ endpoints: {} }),
getCallbacksCall: vi.fn().mockResolvedValue({ router_settings: {} }),
setCallbacksCall: vi.fn().mockResolvedValue(undefined),
modelSettingsCall: vi.fn().mockResolvedValue([]),
adminGlobalActivityExceptions: vi.fn().mockResolvedValue({ sum_num_rate_limit_exceptions: 0, daily_data: [] }),
adminGlobalActivityExceptionsPerDeployment: vi.fn().mockResolvedValue([]),
allEndUsersCall: vi.fn().mockResolvedValue([]),
latestHealthChecksCall: vi.fn().mockResolvedValue({ latest_health_checks: {} }),
getPassThroughEndpointsCall: vi.fn().mockResolvedValue({ endpoints: {} }),
getGuardrailsList: vi.fn().mockResolvedValue([]),
tagListCall: vi.fn().mockResolvedValue([]),
modelAvailableCall: vi.fn().mockResolvedValue({ data: [] }),
modelHubCall: vi.fn().mockResolvedValue({ data: [] }),
getModelCostMapReloadStatus: vi.fn().mockResolvedValue({
scheduled: false,
interval_hours: null,
last_run: null,
next_run: null,
}),
getUiSettings: vi.fn().mockResolvedValue({ values: {} }),
}));
vi.mock("@/app/(dashboard)/models-and-endpoints/components/ModelAnalyticsTab/ModelAnalyticsTab", () => ({
default: () => null,
}));
vi.mock("@/components/add_model/add_auto_router_tab", () => ({
default: () => null,
}));
vi.mock("@/components/add_model/AddModelForm", () => ({
default: () => null,
}));
vi.mock("@/app/(dashboard)/hooks/useTeams", () => ({
default: () => ({
teams: [],
@@ -54,6 +44,16 @@ vi.mock("@/app/(dashboard)/hooks/uiSettings/useUISettings", () => ({
useUISettings: () => mockUseUISettings(),
}));
const mockUseModelCostMap = vi.fn();
vi.mock("@/app/(dashboard)/hooks/models/useModelCostMap", () => ({
useModelCostMap: () => mockUseModelCostMap(),
}));
const mockUseAuthorized = vi.fn();
vi.mock("@/app/(dashboard)/hooks/useAuthorized", () => ({
default: () => mockUseAuthorized(),
}));
const createQueryClient = () =>
new QueryClient({
defaultOptions: { queries: { retry: false, gcTime: 0 } },
@@ -69,6 +69,17 @@ describe("ModelsAndEndpointsView", () => {
mockUseUISettings.mockReturnValue({
data: { values: {} },
});
mockUseModelCostMap.mockReturnValue({
data: {},
isLoading: false,
error: null,
});
mockUseAuthorized.mockReturnValue({
accessToken: "123",
token: "123",
userRole: "Admin",
userId: "123",
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(global as any).ResizeObserver = class {
observe() {}
@@ -82,10 +93,7 @@ describe("ModelsAndEndpointsView", () => {
const { findByText } = render(
<QueryClientProvider client={queryClient}>
<ModelsAndEndpointsView
accessToken="123"
token="123"
userRole="123"
userID="123"
modelData={{ data: [] }}
keys={[]}
setModelData={() => {}}
@@ -1,52 +1,34 @@
import { useQueryClient } from "@tanstack/react-query";
import { Col, Grid, Text } from "@tremor/react";
import React, { useEffect, useRef, useState } from "react";
import { handleAddModelSubmit } from "@/components/add_model/handle_add_model_submit";
import { useCredentials } from "@/app/(dashboard)/hooks/credentials/useCredentials";
import { useModelCostMap } from "@/app/(dashboard)/hooks/models/useModelCostMap";
import { useModelsInfo } from "@/app/(dashboard)/hooks/models/useModels";
import { Team } from "@/components/key_team_helpers/key_list";
import CredentialsPanel from "@/components/model_add/credentials";
import {
adminGlobalActivityExceptions,
adminGlobalActivityExceptionsPerDeployment,
allEndUsersCall,
getCallbacksCall,
modelCostMap,
modelExceptionsCall,
modelMetricsCall,
modelMetricsSlowResponsesCall,
modelSettingsCall,
setCallbacksCall,
streamingModelMetricsCall,
} from "@/components/networking";
import { Providers, getPlaceholder, getProviderModels } from "@/components/provider_info_helpers";
import { getDisplayModelName } from "@/components/view_model/model_name_display";
import { RefreshIcon } from "@heroicons/react/outline";
import { DateRangePickerValue, Icon, Tab, TabGroup, TabList, TabPanel, TabPanels } from "@tremor/react";
import type { UploadProps } from "antd";
import { Form, Typography } from "antd";
import AddModelTab from "../../../components/add_model/add_model_tab";
import ModelInfoView from "../../../components/model_info_view";
import TeamInfoView from "../../../components/team/team_info";
import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings";
import AllModelsTab from "@/app/(dashboard)/models-and-endpoints/components/AllModelsTab";
import ModelAnalyticsTab from "@/app/(dashboard)/models-and-endpoints/components/ModelAnalyticsTab/ModelAnalyticsTab";
import ModelRetrySettingsTab from "@/app/(dashboard)/models-and-endpoints/components/ModelRetrySettingsTab";
import PriceDataManagementTab from "@/app/(dashboard)/models-and-endpoints/components/PriceDataManagementTab";
import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings";
import { handleAddModelSubmit } from "@/components/add_model/handle_add_model_submit";
import { Team } from "@/components/key_team_helpers/key_list";
import CredentialsPanel from "@/components/model_add/credentials";
import { getCallbacksCall, setCallbacksCall } from "@/components/networking";
import { Providers, getPlaceholder, getProviderModels } from "@/components/provider_info_helpers";
import { getDisplayModelName } from "@/components/view_model/model_name_display";
import { all_admin_roles, internalUserRoles, isProxyAdminRole, isUserTeamAdminForAnyTeam } from "@/utils/roles";
import { RefreshIcon } from "@heroicons/react/outline";
import { useQueryClient } from "@tanstack/react-query";
import { Col, Grid, Icon, Tab, TabGroup, TabList, TabPanel, TabPanels, Text } from "@tremor/react";
import type { UploadProps } from "antd";
import { Form, Typography } from "antd";
import React, { useEffect, useState } from "react";
import AddModelTab from "../../../components/add_model/add_model_tab";
import HealthCheckComponent from "../../../components/model_dashboard/HealthCheckComponent";
import ModelGroupAliasSettings from "../../../components/model_group_alias_settings";
import ModelInfoView from "../../../components/model_info_view";
import NotificationsManager from "../../../components/molecules/notifications_manager";
import PassThroughSettings from "../../../components/pass_through_settings";
import TeamInfoView from "../../../components/team/team_info";
import useAuthorized from "../hooks/useAuthorized";
interface ModelDashboardProps {
accessToken: string | null;
token: string | null;
userRole: string | null;
userID: string | null;
modelData: any;
keys: any[] | null;
setModelData: any;
@@ -82,77 +64,33 @@ interface ProviderSettings {
}
const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
accessToken,
token,
userRole,
userID,
modelData = { data: [] },
keys,
setModelData,
premiumUser,
teams,
}) => {
const { accessToken, token, userRole, userId: userID } = useAuthorized();
const [addModelForm] = Form.useForm();
const [modelMap, setModelMap] = useState<any>(null);
const [lastRefreshed, setLastRefreshed] = useState("");
const [providerModels, setProviderModels] = useState<Array<string>>([]); // Explicitly typing providerModels as a string array
const [providerSettings, setProviderSettings] = useState<ProviderSettings[]>([]);
const [selectedProvider, setSelectedProvider] = useState<Providers>(Providers.Anthropic);
const [editModalVisible, setEditModalVisible] = useState<boolean>(false);
const [selectedModel, setSelectedModel] = useState<any>(null);
const [availableModelGroups, setAvailableModelGroups] = useState<Array<string>>([]);
const [availableModelAccessGroups, setAvailableModelAccessGroups] = useState<Array<string>>([]);
const [selectedModelGroup, setSelectedModelGroup] = useState<string | null>(null);
const [modelMetrics, setModelMetrics] = useState<any[]>([]);
const [modelMetricsCategories, setModelMetricsCategories] = useState<any[]>([]);
const [streamingModelMetrics, setStreamingModelMetrics] = useState<any[]>([]);
const [streamingModelMetricsCategories, setStreamingModelMetricsCategories] = useState<any[]>([]);
const [modelExceptions, setModelExceptions] = useState<any[]>([]);
const [allExceptions, setAllExceptions] = useState<any[]>([]);
const [slowResponsesData, setSlowResponsesData] = useState<any[]>([]);
const [dateValue, setDateValue] = useState<DateRangePickerValue>({
from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
to: new Date(),
});
const [modelGroupRetryPolicy, setModelGroupRetryPolicy] = useState<RetryPolicyObject | null>(null);
const [globalRetryPolicy, setGlobalRetryPolicy] = useState<GlobalRetryPolicyObject | null>(null);
const [defaultRetry, setDefaultRetry] = useState<number>(0);
const [globalExceptionData, setGlobalExceptionData] = useState<GlobalExceptionActivityData>(
{} as GlobalExceptionActivityData,
);
const [globalExceptionPerDeployment, setGlobalExceptionPerDeployment] = useState<any[]>([]);
const [showAdvancedFilters, setShowAdvancedFilters] = useState<boolean>(false);
const [selectedAPIKey, setSelectedAPIKey] = useState<any | null>(null);
const [selectedCustomer, setSelectedCustomer] = useState<any | null>(null);
const [allEndUsers, setAllEndUsers] = useState<any[]>([]);
// Model Group Alias state
const [modelGroupAlias, setModelGroupAlias] = useState<{ [key: string]: string }>({});
// Add state for advanced settings visibility
const [showAdvancedSettings, setShowAdvancedSettings] = useState<boolean>(false);
// Add these state variables
const [selectedModelId, setSelectedModelId] = useState<string | null>(null);
const [editModel, setEditModel] = useState<boolean>(false);
const [selectedTeamId, setSelectedTeamId] = useState<string | null>(null);
const [selectedTeam, setSelectedTeam] = useState<string | null>(null);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
const queryClient = useQueryClient();
const { data: modelDataResponse, isLoading: isLoadingModels, refetch: refetchModels } = useModelsInfo();
const { data: modelCostMapData } = useModelCostMap();
const { data: credentialsResponse } = useCredentials();
const credentialsList = credentialsResponse?.credentials || [];
const { data: uiSettings } = useUISettings(accessToken || "");
@@ -166,21 +104,10 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
const shouldHideAddModelTab = !isProxyAdmin && (addModelDisabledForInternalUsers || !isUserTeamAdmin);
const setProviderModelsFn = (provider: Providers) => {
const _providerModels = getProviderModels(provider, modelMap);
const _providerModels = getProviderModels(provider, modelCostMapData);
setProviderModels(_providerModels);
};
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsDropdownOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
const uploadProps: UploadProps = {
name: "file",
accept: ".json",
@@ -196,7 +123,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
};
reader.readAsText(file);
}
// Prevent upload
return false;
},
onChange(info) {
@@ -209,10 +135,8 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
};
const handleRefreshClick = () => {
// Update the 'lastRefreshed' state to the current date and time
const currentDate = new Date();
setLastRefreshed(currentDate.toLocaleString());
// Invalidate and refetch models data using React Query
queryClient.invalidateQueries({ queryKey: ["models", "list"] });
refetchModels();
};
@@ -228,7 +152,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
};
if (selectedModelGroup === "global") {
// Only update global retry policy
if (globalRetryPolicy) {
payload.router_settings.retry_policy = globalRetryPolicy;
}
@@ -253,19 +176,12 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
const fetchData = async () => {
try {
setModelData(modelDataResponse);
const _providerSettings = await modelSettingsCall(accessToken);
if (_providerSettings) {
setProviderSettings(_providerSettings);
}
// loop through modelDataResponse and get all`model_name` values
let all_model_groups: Set<string> = new Set();
for (let i = 0; i < modelDataResponse.data.length; i++) {
const model = modelDataResponse.data[i];
all_model_groups.add(model.model_name);
}
let _array_model_groups = Array.from(all_model_groups);
// sort _array_model_groups alphabetically
_array_model_groups = _array_model_groups.sort();
setAvailableModelGroups(_array_model_groups);
@@ -286,80 +202,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
setAvailableModelAccessGroups(Array.from(all_model_access_groups));
let _initial_model_group = "all";
if (_array_model_groups.length > 0) {
_initial_model_group = _array_model_groups[_array_model_groups.length - 1];
}
const modelMetricsResponse = await modelMetricsCall(
accessToken,
userID,
userRole,
_initial_model_group,
dateValue.from?.toISOString(),
dateValue.to?.toISOString(),
selectedAPIKey?.token,
selectedCustomer,
);
setModelMetrics(modelMetricsResponse.data);
setModelMetricsCategories(modelMetricsResponse.all_api_bases);
const streamingModelMetricsResponse = await streamingModelMetricsCall(
accessToken,
_initial_model_group,
dateValue.from?.toISOString(),
dateValue.to?.toISOString(),
);
// Assuming modelMetricsResponse now contains the metric data for the specified model group
setStreamingModelMetrics(streamingModelMetricsResponse.data);
setStreamingModelMetricsCategories(streamingModelMetricsResponse.all_api_bases);
const modelExceptionsResponse = await modelExceptionsCall(
accessToken,
userID,
userRole,
_initial_model_group,
dateValue.from?.toISOString(),
dateValue.to?.toISOString(),
selectedAPIKey?.token,
selectedCustomer,
);
setModelExceptions(modelExceptionsResponse.data);
setAllExceptions(modelExceptionsResponse.exception_types);
const slowResponses = await modelMetricsSlowResponsesCall(
accessToken,
userID,
userRole,
_initial_model_group,
dateValue.from?.toISOString(),
dateValue.to?.toISOString(),
selectedAPIKey?.token,
selectedCustomer,
);
const dailyExceptions = await adminGlobalActivityExceptions(
accessToken,
dateValue.from?.toISOString().split("T")[0],
dateValue.to?.toISOString().split("T")[0],
_initial_model_group,
);
setGlobalExceptionData(dailyExceptions);
const dailyExceptionsPerDeplyment = await adminGlobalActivityExceptionsPerDeployment(
accessToken,
dateValue.from?.toISOString().split("T")[0],
dateValue.to?.toISOString().split("T")[0],
_initial_model_group,
);
setGlobalExceptionPerDeployment(dailyExceptionsPerDeplyment);
setSlowResponsesData(slowResponses);
let all_end_users_data = await allEndUsersCall(accessToken);
setAllEndUsers(all_end_users_data?.map((u: any) => u.user_id));
const routerSettingsInfo = await getCallbacksCall(accessToken, userID, userRole);
let router_settings = routerSettingsInfo.router_settings;
@@ -370,7 +212,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
setGlobalRetryPolicy(router_settings.retry_policy);
setDefaultRetry(default_retries);
// Set model group alias
const model_group_alias = router_settings.model_group_alias || {};
setModelGroupAlias(model_group_alias);
} catch (error) {
@@ -381,24 +222,12 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
if (accessToken && token && userRole && userID && modelDataResponse) {
fetchData();
}
const fetchModelMap = async () => {
const data = await modelCostMap();
console.log(`received model cost map data: ${Object.keys(data)}`);
setModelMap(data);
};
if (modelMap == null) {
fetchModelMap();
}
}, [accessToken, token, userRole, userID, modelDataResponse]);
if (!modelData || isLoadingModels) {
return <div>Loading...</div>;
}
if (!accessToken || !token || !userRole || !userID) {
return <div>Loading...</div>;
}
let all_models_on_proxy: any[] = [];
let all_providers: string[] = [];
@@ -409,7 +238,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
let custom_llm_provider = curr_model?.litellm_params?.custom_llm_provider;
let model_info = curr_model?.model_info;
let defaultProvider = "openai";
let provider = "";
let input_cost = "Undefined";
let output_cost = "Undefined";
@@ -423,9 +251,9 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
* - check if model in model map
* - return it's litellm_provider, if so
*/
if (modelMap !== null && modelMap !== undefined) {
if (typeof modelMap == "object" && model in modelMap) {
return modelMap[model]["litellm_provider"];
if (modelCostMapData !== null && modelCostMapData !== undefined) {
if (typeof modelCostMapData == "object" && model in modelCostMapData) {
return modelCostMapData[model]["litellm_provider"];
}
}
return "openai";
@@ -495,46 +323,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
</div>
);
}
const customTooltip = (props: any) => {
const { payload, active } = props;
if (!active || !payload) return null;
// Extract the date from the first item in the payload array
const date = payload[0]?.payload?.date;
// Sort the payload array by category.value in descending order
let sortedPayload = payload.sort((a: any, b: any) => b.value - a.value);
// Only show the top 5, the 6th one should be called "X other categories" depending on how many categories were not shown
if (sortedPayload.length > 5) {
let remainingItems = sortedPayload.length - 5;
sortedPayload = sortedPayload.slice(0, 5);
sortedPayload.push({
dataKey: `${remainingItems} other deployments`,
value: payload.slice(5).reduce((acc: number, curr: any) => acc + curr.value, 0),
color: "gray",
});
}
return (
<div className="w-150 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown">
{date && <p className="text-tremor-content-emphasis mb-2">Date: {date}</p>}
{sortedPayload.map((category: any, idx: number) => {
const roundedValue = parseFloat(category.value.toFixed(5));
const displayValue = roundedValue === 0 && category.value > 0 ? "<0.00001" : roundedValue.toFixed(5);
return (
<div key={idx} className="flex justify-between">
<div className="flex items-center space-x-2">
<div className={`w-2 h-2 mt-1 rounded-full bg-${category.color}-500`} />
<p className="text-tremor-content">{category.dataKey}</p>
</div>
<p className="font-medium text-tremor-content-emphasis text-righ ml-2">{displayValue}</p>
</div>
);
})}
</div>
);
};
const handleOk = async () => {
try {
@@ -589,17 +377,13 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
{selectedModelId ? (
<ModelInfoView
modelId={selectedModelId}
editModel={true}
onClose={() => {
setSelectedModelId(null);
setEditModel(false);
}}
modelData={modelData.data.find((model: any) => model.model_info.id === selectedModelId)}
accessToken={accessToken}
userID={userID}
userRole={userRole}
setEditModalVisible={setEditModalVisible}
setSelectedModel={setSelectedModel}
onModelUpdate={(updatedModel) => {
// Handle model deletion
if (updatedModel.deleted) {
@@ -633,7 +417,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
{all_admin_roles.includes(userRole) && <Tab>LLM Credentials</Tab>}
{all_admin_roles.includes(userRole) && <Tab>Pass-Through Endpoints</Tab>}
{all_admin_roles.includes(userRole) && <Tab>Health Status</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 Alias</Tab>}
{all_admin_roles.includes(userRole) && <Tab>Price Data Reload</Tab>}
@@ -658,7 +441,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
availableModelAccessGroups={availableModelAccessGroups}
setSelectedModelId={setSelectedModelId}
setSelectedTeamId={setSelectedTeamId}
setEditModel={setEditModel}
/>
{!shouldHideAddModelTab && (
<TabPanel className="h-full">
@@ -701,41 +483,6 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
setSelectedModelId={setSelectedModelId}
/>
</TabPanel>
<ModelAnalyticsTab
dateValue={dateValue}
setDateValue={setDateValue}
selectedModelGroup={selectedModelGroup}
availableModelGroups={availableModelGroups}
setShowAdvancedFilters={setShowAdvancedFilters}
modelMetrics={modelMetrics}
modelMetricsCategories={modelMetricsCategories}
streamingModelMetrics={streamingModelMetrics}
streamingModelMetricsCategories={streamingModelMetricsCategories}
customTooltip={customTooltip}
slowResponsesData={slowResponsesData}
modelExceptions={modelExceptions}
globalExceptionData={globalExceptionData}
allExceptions={allExceptions}
globalExceptionPerDeployment={globalExceptionPerDeployment}
allEndUsers={allEndUsers}
keys={keys}
setSelectedAPIKey={setSelectedAPIKey}
setSelectedCustomer={setSelectedCustomer}
teams={teams}
selectedAPIKey={selectedAPIKey}
selectedCustomer={selectedCustomer}
selectedTeam={selectedTeam}
setAllExceptions={setAllExceptions}
setGlobalExceptionData={setGlobalExceptionData}
setGlobalExceptionPerDeployment={setGlobalExceptionPerDeployment}
setModelExceptions={setModelExceptions}
setModelMetrics={setModelMetrics}
setModelMetricsCategories={setModelMetricsCategories}
setSelectedModelGroup={setSelectedModelGroup}
setSlowResponsesData={setSlowResponsesData}
setStreamingModelMetrics={setStreamingModelMetrics}
setStreamingModelMetricsCategories={setStreamingModelMetricsCategories}
/>
<ModelRetrySettingsTab
selectedModelGroup={selectedModelGroup}
setSelectedModelGroup={setSelectedModelGroup}
@@ -754,7 +501,7 @@ const ModelsAndEndpointsView: React.FC<ModelDashboardProps> = ({
onAliasUpdate={setModelGroupAlias}
/>
</TabPanel>
<PriceDataManagementTab setModelMap={setModelMap} />
<PriceDataManagementTab />
</TabPanels>
</TabGroup>
)}
@@ -19,7 +19,6 @@ interface AllModelsTabProps {
availableModelAccessGroups: string[];
setSelectedModelId: (id: string) => void;
setSelectedTeamId: (id: string) => void;
setEditModel: (edit: boolean) => void;
}
const AllModelsTab = ({
@@ -29,7 +28,6 @@ const AllModelsTab = ({
availableModelAccessGroups,
setSelectedModelId,
setSelectedTeamId,
setEditModel,
}: AllModelsTabProps) => {
const { data: modelData } = useModelsInfo();
const { userId, userRole, premiumUser } = useAuthorized();
@@ -359,7 +357,6 @@ const AllModelsTab = ({
getDisplayModelName,
() => {},
() => {},
setEditModel,
expandedRows,
setExpandedRows,
)}
@@ -1,15 +1,12 @@
import { TabPanel, Text, Title } from "@tremor/react";
import PriceDataReload from "@/components/price_data_reload";
import { modelCostMap } from "@/components/networking";
import React from "react";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { useModelCostMap } from "../../hooks/models/useModelCostMap";
interface PriceDataManagementPanelProps {
setModelMap: (data: any) => void;
}
const PriceDataManagementTab = ({ setModelMap }: PriceDataManagementPanelProps) => {
const PriceDataManagementTab = () => {
const { accessToken } = useAuthorized();
const { refetch: refetchModelCostMap } = useModelCostMap();
return (
<TabPanel>
@@ -23,12 +20,7 @@ const PriceDataManagementTab = ({ setModelMap }: PriceDataManagementPanelProps)
<PriceDataReload
accessToken={accessToken}
onReloadSuccess={() => {
// Refresh the model map after successful reload
const fetchModelMap = async () => {
const data = await modelCostMap();
setModelMap(data);
};
fetchModelMap();
refetchModelCostMap();
}}
buttonText="Reload Price Data"
size="middle"
@@ -6,17 +6,14 @@ import { useState } from "react";
import ModelsAndEndpointsView from "@/app/(dashboard)/models-and-endpoints/ModelsAndEndpointsView";
const ModelsAndEndpointsPage = () => {
const { token, accessToken, userRole, userId, premiumUser } = useAuthorized();
const { token, premiumUser } = useAuthorized();
const [keys, setKeys] = useState<null | any[]>([]);
const { teams } = useTeams();
return (
<ModelsAndEndpointsView
accessToken={accessToken}
token={token}
userRole={userRole}
userID={userId}
modelData={{ data: [] }}
keys={keys}
setModelData={() => {}}
-3
View File
@@ -323,11 +323,8 @@ export default function CreateKeyPage() {
/>
) : page == "models" ? (
<OldModelDashboard
userID={userID}
userRole={userRole}
token={token}
keys={keys}
accessToken={accessToken}
modelData={modelData}
setModelData={setModelData}
premiumUser={premiumUser}
@@ -47,9 +47,6 @@ interface ModelInfoViewProps {
accessToken: string | null;
userID: string | null;
userRole: string | null;
editModel: boolean;
setEditModalVisible: (visible: boolean) => void;
setSelectedModel: (model: any) => void;
onModelUpdate?: (updatedModel: any) => void;
modelAccessGroups: string[] | null;
}
@@ -61,9 +58,6 @@ export default function ModelInfoView({
accessToken,
userID,
userRole,
editModel,
setEditModalVisible,
setSelectedModel,
onModelUpdate,
modelAccessGroups,
}: ModelInfoViewProps) {
@@ -14,7 +14,6 @@ export const columns = (
getDisplayModelName: (model: any) => string,
handleEditClick: (model: any) => void,
handleRefreshClick: () => void,
setEditModel: (edit: boolean) => void,
expandedRows: Set<string>,
setExpandedRows: (expandedRows: Set<string>) => void,
): ColumnDef<ModelData>[] => [
@@ -301,7 +300,6 @@ export const columns = (
onClick={() => {
if (canEditModel) {
setSelectedModelId(model.model_info.id);
setEditModel(false);
}
}}
className={!canEditModel ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:text-red-600"}
@@ -1021,7 +1021,6 @@ const OldModelDashboard: React.FC<ModelDashboardProps> = ({
{selectedModelId ? (
<ModelInfoView
modelId={selectedModelId}
editModel={true}
onClose={() => {
setSelectedModelId(null);
setEditModel(false);
@@ -1030,8 +1029,6 @@ const OldModelDashboard: React.FC<ModelDashboardProps> = ({
accessToken={accessToken}
userID={userID}
userRole={userRole}
setEditModalVisible={setEditModalVisible}
setSelectedModel={setSelectedModel}
onModelUpdate={(updatedModel) => {
// Update the model in the modelData.data array
const updatedModelData = {
@@ -1327,7 +1324,6 @@ const OldModelDashboard: React.FC<ModelDashboardProps> = ({
getDisplayModelName,
handleEditClick,
handleRefreshClick,
setEditModel,
expandedRows,
setExpandedRows,
)}