forked from phoenix/litellm-mirror
Merge pull request #3441 from BerriAI/ui_select_start_end_time
UI select start end time
This commit is contained in:
commit
8e9ba0f27f
3 changed files with 93 additions and 63 deletions
|
@ -7552,7 +7552,7 @@ async def model_metrics(
|
||||||
FROM
|
FROM
|
||||||
"LiteLLM_SpendLogs"
|
"LiteLLM_SpendLogs"
|
||||||
WHERE
|
WHERE
|
||||||
"startTime" >= NOW() - INTERVAL '30 days'
|
"startTime" BETWEEN $2::timestamp AND $3::timestamp
|
||||||
AND "model" = $1 AND "cache_hit" != 'True'
|
AND "model" = $1 AND "cache_hit" != 'True'
|
||||||
GROUP BY
|
GROUP BY
|
||||||
api_base,
|
api_base,
|
||||||
|
@ -7653,6 +7653,8 @@ FROM
|
||||||
WHERE
|
WHERE
|
||||||
"model" = $2
|
"model" = $2
|
||||||
AND "cache_hit" != 'True'
|
AND "cache_hit" != 'True'
|
||||||
|
AND "startTime" >= $3::timestamp
|
||||||
|
AND "startTime" <= $4::timestamp
|
||||||
GROUP BY
|
GROUP BY
|
||||||
api_base
|
api_base
|
||||||
ORDER BY
|
ORDER BY
|
||||||
|
@ -7660,7 +7662,7 @@ ORDER BY
|
||||||
"""
|
"""
|
||||||
|
|
||||||
db_response = await prisma_client.db.query_raw(
|
db_response = await prisma_client.db.query_raw(
|
||||||
sql_query, alerting_threshold, _selected_model_group
|
sql_query, alerting_threshold, _selected_model_group, startTime, endTime
|
||||||
)
|
)
|
||||||
|
|
||||||
if db_response is not None:
|
if db_response is not None:
|
||||||
|
|
|
@ -16,8 +16,8 @@ import {
|
||||||
AccordionHeader,
|
AccordionHeader,
|
||||||
AccordionBody,
|
AccordionBody,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
import { TabPanel, TabPanels, TabGroup, TabList, Tab, TextInput, Icon } from "@tremor/react";
|
import { TabPanel, TabPanels, TabGroup, TabList, Tab, TextInput, Icon, DateRangePicker } from "@tremor/react";
|
||||||
import { Select, SelectItem, MultiSelect, MultiSelectItem } from "@tremor/react";
|
import { Select, SelectItem, MultiSelect, MultiSelectItem, DateRangePickerValue } from "@tremor/react";
|
||||||
import { modelInfoCall, userGetRequesedtModelsCall, modelCreateCall, Model, modelCostMap, modelDeleteCall, healthCheckCall, modelUpdateCall, modelMetricsCall, modelExceptionsCall, modelMetricsSlowResponsesCall } from "./networking";
|
import { modelInfoCall, userGetRequesedtModelsCall, modelCreateCall, Model, modelCostMap, modelDeleteCall, healthCheckCall, modelUpdateCall, modelMetricsCall, modelExceptionsCall, modelMetricsSlowResponsesCall } from "./networking";
|
||||||
import { BarChart, AreaChart } from "@tremor/react";
|
import { BarChart, AreaChart } from "@tremor/react";
|
||||||
import {
|
import {
|
||||||
|
@ -206,6 +206,10 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
const [allExceptions, setAllExceptions] = useState<any[]>([]);
|
const [allExceptions, setAllExceptions] = useState<any[]>([]);
|
||||||
const [failureTableData, setFailureTableData] = useState<any[]>([]);
|
const [failureTableData, setFailureTableData] = useState<any[]>([]);
|
||||||
const [slowResponsesData, setSlowResponsesData] = 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 EditModelModal: React.FC<EditModelModalProps> = ({ visible, onCancel, model, onSubmit }) => {
|
const EditModelModal: React.FC<EditModelModalProps> = ({ visible, onCancel, model, onSubmit }) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
@ -454,11 +458,25 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
|
|
||||||
setAvailableModelGroups(_array_model_groups);
|
setAvailableModelGroups(_array_model_groups);
|
||||||
|
|
||||||
|
console.log("array_model_groups:", _array_model_groups)
|
||||||
|
let _initial_model_group = "all"
|
||||||
|
if (_array_model_groups.length > 0) {
|
||||||
|
// set selectedModelGroup to the last model group
|
||||||
|
_initial_model_group = _array_model_groups[_array_model_groups.length - 1];
|
||||||
|
console.log("_initial_model_group:", _initial_model_group)
|
||||||
|
setSelectedModelGroup(_initial_model_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("selectedModelGroup:", selectedModelGroup)
|
||||||
|
|
||||||
|
|
||||||
const modelMetricsResponse = await modelMetricsCall(
|
const modelMetricsResponse = await modelMetricsCall(
|
||||||
accessToken,
|
accessToken,
|
||||||
userID,
|
userID,
|
||||||
userRole,
|
userRole,
|
||||||
null
|
_initial_model_group,
|
||||||
|
dateValue.from?.toISOString(),
|
||||||
|
dateValue.to?.toISOString()
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("Model metrics response:", modelMetricsResponse);
|
console.log("Model metrics response:", modelMetricsResponse);
|
||||||
|
@ -473,7 +491,9 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
accessToken,
|
accessToken,
|
||||||
userID,
|
userID,
|
||||||
userRole,
|
userRole,
|
||||||
null
|
_initial_model_group,
|
||||||
|
dateValue.from?.toISOString(),
|
||||||
|
dateValue.to?.toISOString()
|
||||||
)
|
)
|
||||||
console.log("Model exceptions response:", modelExceptionsResponse);
|
console.log("Model exceptions response:", modelExceptionsResponse);
|
||||||
setModelExceptions(modelExceptionsResponse.data);
|
setModelExceptions(modelExceptionsResponse.data);
|
||||||
|
@ -484,7 +504,9 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
accessToken,
|
accessToken,
|
||||||
userID,
|
userID,
|
||||||
userRole,
|
userRole,
|
||||||
null
|
_initial_model_group,
|
||||||
|
dateValue.from?.toISOString(),
|
||||||
|
dateValue.to?.toISOString()
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log("slowResponses:", slowResponses)
|
console.log("slowResponses:", slowResponses)
|
||||||
|
@ -492,40 +514,6 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
setSlowResponsesData(slowResponses);
|
setSlowResponsesData(slowResponses);
|
||||||
|
|
||||||
|
|
||||||
// let modelMetricsData = modelMetricsResponse.data;
|
|
||||||
// let successdeploymentToSuccess: Record<string, number> = {};
|
|
||||||
// for (let i = 0; i < modelMetricsData.length; i++) {
|
|
||||||
// let element = modelMetricsData[i];
|
|
||||||
// let _model_name = element.model;
|
|
||||||
// let _num_requests = element.num_requests;
|
|
||||||
// successdeploymentToSuccess[_model_name] = _num_requests
|
|
||||||
// }
|
|
||||||
// console.log("successdeploymentToSuccess:", successdeploymentToSuccess)
|
|
||||||
|
|
||||||
// let failureTableData = [];
|
|
||||||
// let _failureData = modelExceptionsResponse.data;
|
|
||||||
// for (let i = 0; i < _failureData.length; i++) {
|
|
||||||
// const model = _failureData[i];
|
|
||||||
// let _model_name = model.model;
|
|
||||||
// let total_exceptions = model.total_exceptions;
|
|
||||||
// let total_Requests = successdeploymentToSuccess[_model_name];
|
|
||||||
// if (total_Requests == null) {
|
|
||||||
// total_Requests = 0
|
|
||||||
// }
|
|
||||||
// let _data = {
|
|
||||||
// model: _model_name,
|
|
||||||
// total_exceptions: total_exceptions,
|
|
||||||
// total_Requests: total_Requests,
|
|
||||||
// failure_rate: total_Requests / total_exceptions
|
|
||||||
// }
|
|
||||||
// failureTableData.push(_data);
|
|
||||||
// // sort failureTableData by failure_rate
|
|
||||||
// failureTableData.sort((a, b) => b.failure_rate - a.failure_rate);
|
|
||||||
|
|
||||||
// setFailureTableData(failureTableData);
|
|
||||||
// console.log("failureTableData:", failureTableData);
|
|
||||||
// }
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("There was an error fetching the model data", error);
|
console.error("There was an error fetching the model data", error);
|
||||||
}
|
}
|
||||||
|
@ -678,16 +666,17 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const updateModelMetrics = async (modelGroup: string | null) => {
|
const updateModelMetrics = async (modelGroup: string | null, startTime: Date | undefined, endTime: Date | undefined) => {
|
||||||
console.log("Updating model metrics for group:", modelGroup);
|
console.log("Updating model metrics for group:", modelGroup);
|
||||||
if (!accessToken || !userID || !userRole) {
|
if (!accessToken || !userID || !userRole || !startTime || !endTime) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
console.log("inside updateModelMetrics - startTime:", startTime, "endTime:", endTime)
|
||||||
setSelectedModelGroup(modelGroup); // If you want to store the selected model group in state
|
setSelectedModelGroup(modelGroup); // If you want to store the selected model group in state
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const modelMetricsResponse = await modelMetricsCall(accessToken, userID, userRole, modelGroup);
|
const modelMetricsResponse = await modelMetricsCall(accessToken, userID, userRole, modelGroup, startTime.toISOString(), endTime.toISOString());
|
||||||
console.log("Model metrics response:", modelMetricsResponse);
|
console.log("Model metrics response:", modelMetricsResponse);
|
||||||
|
|
||||||
// Assuming modelMetricsResponse now contains the metric data for the specified model group
|
// Assuming modelMetricsResponse now contains the metric data for the specified model group
|
||||||
|
@ -698,7 +687,9 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
accessToken,
|
accessToken,
|
||||||
userID,
|
userID,
|
||||||
userRole,
|
userRole,
|
||||||
modelGroup
|
modelGroup,
|
||||||
|
startTime.toISOString(),
|
||||||
|
endTime.toISOString()
|
||||||
)
|
)
|
||||||
console.log("Model exceptions response:", modelExceptionsResponse);
|
console.log("Model exceptions response:", modelExceptionsResponse);
|
||||||
setModelExceptions(modelExceptionsResponse.data);
|
setModelExceptions(modelExceptionsResponse.data);
|
||||||
|
@ -709,7 +700,9 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
accessToken,
|
accessToken,
|
||||||
userID,
|
userID,
|
||||||
userRole,
|
userRole,
|
||||||
modelGroup
|
modelGroup,
|
||||||
|
startTime.toISOString(),
|
||||||
|
endTime.toISOString()
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log("slowResponses:", slowResponses)
|
console.log("slowResponses:", slowResponses)
|
||||||
|
@ -1118,20 +1111,47 @@ const handleEditSubmit = async (formValues: Record<string, any>) => {
|
||||||
</Card>
|
</Card>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<p style={{fontSize: '0.85rem', color: '#808080'}}>View how requests were load balanced within a model group</p>
|
{/* <p style={{fontSize: '0.85rem', color: '#808080'}}>View how requests were load balanced within a model group</p> */}
|
||||||
<Select
|
|
||||||
className="mb-4 mt-2"
|
<Grid numItems={2} className="mt-2">
|
||||||
>
|
<Col>
|
||||||
{availableModelGroups.map((group, idx) => (
|
<Text>Select Time Range</Text>
|
||||||
<SelectItem
|
<DateRangePicker
|
||||||
key={idx}
|
enableSelect={true}
|
||||||
value={group}
|
value={dateValue}
|
||||||
onClick={() => updateModelMetrics(group)}
|
onValueChange={(value) => {
|
||||||
>
|
setDateValue(value);
|
||||||
{group}
|
updateModelMetrics(selectedModelGroup, value.from, value.to); // Call updateModelMetrics with the new date range
|
||||||
</SelectItem>
|
}}
|
||||||
))}
|
/>
|
||||||
</Select>
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Text>Select Model Group</Text>
|
||||||
|
<Select
|
||||||
|
className="mb-4 mt-2"
|
||||||
|
defaultValue={selectedModelGroup? selectedModelGroup : availableModelGroups[0]}
|
||||||
|
value={selectedModelGroup ? selectedModelGroup : availableModelGroups[0]}
|
||||||
|
>
|
||||||
|
{availableModelGroups.map((group, idx) => (
|
||||||
|
<SelectItem
|
||||||
|
key={idx}
|
||||||
|
value={group}
|
||||||
|
onClick={() => updateModelMetrics(group, dateValue.from, dateValue.to)}
|
||||||
|
>
|
||||||
|
{group}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Grid numItems={2}>
|
<Grid numItems={2}>
|
||||||
<Col>
|
<Col>
|
||||||
|
|
|
@ -441,6 +441,8 @@ export const modelMetricsCall = async (
|
||||||
userID: String,
|
userID: String,
|
||||||
userRole: String,
|
userRole: String,
|
||||||
modelGroup: String | null,
|
modelGroup: String | null,
|
||||||
|
startTime: String | undefined,
|
||||||
|
endTime: String | undefined
|
||||||
) => {
|
) => {
|
||||||
/**
|
/**
|
||||||
* Get all models on proxy
|
* Get all models on proxy
|
||||||
|
@ -448,7 +450,7 @@ export const modelMetricsCall = async (
|
||||||
try {
|
try {
|
||||||
let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics` : `/model/metrics`;
|
let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics` : `/model/metrics`;
|
||||||
if (modelGroup) {
|
if (modelGroup) {
|
||||||
url = `${url}?_selected_model_group=${modelGroup}`
|
url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}`
|
||||||
}
|
}
|
||||||
// message.info("Requesting model data");
|
// message.info("Requesting model data");
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
|
@ -481,6 +483,8 @@ export const modelMetricsSlowResponsesCall = async (
|
||||||
userID: String,
|
userID: String,
|
||||||
userRole: String,
|
userRole: String,
|
||||||
modelGroup: String | null,
|
modelGroup: String | null,
|
||||||
|
startTime: String | undefined,
|
||||||
|
endTime: String | undefined
|
||||||
) => {
|
) => {
|
||||||
/**
|
/**
|
||||||
* Get all models on proxy
|
* Get all models on proxy
|
||||||
|
@ -488,8 +492,9 @@ export const modelMetricsSlowResponsesCall = async (
|
||||||
try {
|
try {
|
||||||
let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics/slow_responses` : `/model/metrics/slow_responses`;
|
let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics/slow_responses` : `/model/metrics/slow_responses`;
|
||||||
if (modelGroup) {
|
if (modelGroup) {
|
||||||
url = `${url}?_selected_model_group=${modelGroup}`
|
url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// message.info("Requesting model data");
|
// message.info("Requesting model data");
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
@ -520,14 +525,17 @@ export const modelExceptionsCall = async (
|
||||||
userID: String,
|
userID: String,
|
||||||
userRole: String,
|
userRole: String,
|
||||||
modelGroup: String | null,
|
modelGroup: String | null,
|
||||||
|
startTime: String | undefined,
|
||||||
|
endTime: String | undefined
|
||||||
) => {
|
) => {
|
||||||
/**
|
/**
|
||||||
* Get all models on proxy
|
* Get all models on proxy
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics/exceptions` : `/model/metrics/exceptions`;
|
let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics/exceptions` : `/model/metrics/exceptions`;
|
||||||
|
|
||||||
if (modelGroup) {
|
if (modelGroup) {
|
||||||
url = `${url}?_selected_model_group=${modelGroup}`
|
url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}`
|
||||||
}
|
}
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue