forked from phoenix/litellm-mirror
ui - add callbacks through admin ui
This commit is contained in:
parent
b8c9326df4
commit
82a3b3e615
1 changed files with 157 additions and 10 deletions
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
Title,
|
|
||||||
Subtitle,
|
Subtitle,
|
||||||
Table,
|
Table,
|
||||||
TableHead,
|
TableHead,
|
||||||
|
@ -23,15 +23,20 @@ import {
|
||||||
TabList,
|
TabList,
|
||||||
Tab,
|
Tab,
|
||||||
Callout,
|
Callout,
|
||||||
|
SelectItem,
|
||||||
} from "@tremor/react";
|
} from "@tremor/react";
|
||||||
|
|
||||||
|
import { Modal, Typography, Form, Input, Select, Button as Button2, message } from "antd";
|
||||||
|
|
||||||
|
const { Title, Paragraph } = Typography;
|
||||||
import {
|
import {
|
||||||
getCallbacksCall,
|
getCallbacksCall,
|
||||||
setCallbacksCall,
|
setCallbacksCall,
|
||||||
serviceHealthCheck,
|
serviceHealthCheck,
|
||||||
} from "./networking";
|
} from "./networking";
|
||||||
import { Modal, Form, Input, Select, Button as Button2, message } from "antd";
|
|
||||||
import StaticGenerationSearchParamsBailoutProvider from "next/dist/client/components/static-generation-searchparams-bailout-provider";
|
import StaticGenerationSearchParamsBailoutProvider from "next/dist/client/components/static-generation-searchparams-bailout-provider";
|
||||||
import AlertingSettings from "./alerting/alerting_settings";
|
import AlertingSettings from "./alerting/alerting_settings";
|
||||||
|
import FormItem from "antd/es/form/FormItem";
|
||||||
interface SettingsPageProps {
|
interface SettingsPageProps {
|
||||||
accessToken: string | null;
|
accessToken: string | null;
|
||||||
userRole: string | null;
|
userRole: string | null;
|
||||||
|
@ -39,6 +44,15 @@ interface SettingsPageProps {
|
||||||
premiumUser: boolean;
|
premiumUser: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface genericCallbackParams {
|
||||||
|
|
||||||
|
litellm_callback_name: string // what to send in request
|
||||||
|
ui_callback_name: string // what to show on UI
|
||||||
|
litellm_callback_params: string[] | null // known required params for this callback
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
interface AlertingVariables {
|
interface AlertingVariables {
|
||||||
SLACK_WEBHOOK_URL: string | null;
|
SLACK_WEBHOOK_URL: string | null;
|
||||||
LANGFUSE_PUBLIC_KEY: string | null;
|
LANGFUSE_PUBLIC_KEY: string | null;
|
||||||
|
@ -92,7 +106,7 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
premiumUser,
|
premiumUser,
|
||||||
}) => {
|
}) => {
|
||||||
const [callbacks, setCallbacks] =
|
const [callbacks, setCallbacks] =
|
||||||
useState<AlertingObject[]>(defaultLoggingObject);
|
useState<AlertingObject[]>([]);
|
||||||
const [alerts, setAlerts] = useState<any[]>([]);
|
const [alerts, setAlerts] = useState<any[]>([]);
|
||||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
@ -104,6 +118,12 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
>({});
|
>({});
|
||||||
const [activeAlerts, setActiveAlerts] = useState<string[]>([]);
|
const [activeAlerts, setActiveAlerts] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const [showAddCallbacksModal, setShowAddCallbacksModal] = useState(false);
|
||||||
|
const [allCallbacks, setAllCallbacks] = useState<genericCallbackParams[]>([]);
|
||||||
|
|
||||||
|
const [selectedCallbacktoAdd, setSelectedCallbacktoAdd] = useState<string | null>(null);
|
||||||
|
const [selectedCallbackParams, setSelectedCallbackParams] = useState<string[]>([]);
|
||||||
|
|
||||||
const handleSwitchChange = (alertName: string) => {
|
const handleSwitchChange = (alertName: string) => {
|
||||||
if (activeAlerts.includes(alertName)) {
|
if (activeAlerts.includes(alertName)) {
|
||||||
setActiveAlerts(activeAlerts.filter((alert) => alert !== alertName));
|
setActiveAlerts(activeAlerts.filter((alert) => alert !== alertName));
|
||||||
|
@ -128,8 +148,7 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
}
|
}
|
||||||
getCallbacksCall(accessToken, userID, userRole).then((data) => {
|
getCallbacksCall(accessToken, userID, userRole).then((data) => {
|
||||||
console.log("callbacks", data);
|
console.log("callbacks", data);
|
||||||
let updatedCallbacks: any[] = defaultLoggingObject;
|
let updatedCallbacks: any[] = [];
|
||||||
|
|
||||||
updatedCallbacks = updatedCallbacks.map((item: any) => {
|
updatedCallbacks = updatedCallbacks.map((item: any) => {
|
||||||
const callback = data.callbacks.find(
|
const callback = data.callbacks.find(
|
||||||
(cb: any) => cb.name === item.name
|
(cb: any) => cb.name === item.name
|
||||||
|
@ -145,6 +164,8 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
setCallbacks(updatedCallbacks);
|
setCallbacks(updatedCallbacks);
|
||||||
|
|
||||||
|
setAllCallbacks(data.available_callbacks);
|
||||||
// setCallbacks(callbacks_data);
|
// setCallbacks(callbacks_data);
|
||||||
|
|
||||||
let alerts_data = data.alerts;
|
let alerts_data = data.alerts;
|
||||||
|
@ -225,6 +246,56 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
message.success("Email settings updated successfully");
|
message.success("Email settings updated successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const addNewCallbackCall = async (formValues: Record<string, any>) => {
|
||||||
|
if (!accessToken) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let new_callback = formValues?.callback
|
||||||
|
|
||||||
|
let env_vars: Record<string, string> = {};
|
||||||
|
// add all other variables
|
||||||
|
Object.entries(formValues).forEach(([key, value]) => {
|
||||||
|
if (key !== "callback") {
|
||||||
|
env_vars[key] = value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let payload = {
|
||||||
|
environment_variables: env_vars,
|
||||||
|
litellm_settings: {
|
||||||
|
success_callback: [new_callback],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
let newCallback = await setCallbacksCall(accessToken, payload);
|
||||||
|
message.success(`Callback ${new_callback} added successfully`);
|
||||||
|
setIsModalVisible(false);
|
||||||
|
form.resetFields();
|
||||||
|
setSelectedCallback(null);
|
||||||
|
} catch (error) {
|
||||||
|
message.error("Failed to add callback: " + error, 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const handleSelectedCallbackChange = (callbackObject: genericCallbackParams) => {
|
||||||
|
|
||||||
|
console.log("inside handleSelectedCallbackChange", callbackObject);
|
||||||
|
setSelectedCallback(callbackObject.litellm_callback_name);
|
||||||
|
|
||||||
|
console.log("all callbacks", allCallbacks);
|
||||||
|
if (selectedCallback) {
|
||||||
|
setSelectedCallbackParams(callbackObject.litellm_callback_params);
|
||||||
|
console.log("selectedCallbackParams", selectedCallbackParams);
|
||||||
|
} else {
|
||||||
|
setSelectedCallbackParams([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSaveAlerts = () => {
|
const handleSaveAlerts = () => {
|
||||||
if (!accessToken) {
|
if (!accessToken) {
|
||||||
return;
|
return;
|
||||||
|
@ -398,10 +469,7 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
return (
|
return (
|
||||||
<div className="w-full mx-4">
|
<div className="w-full mx-4">
|
||||||
<Grid numItems={1} className="gap-2 p-8 w-full mt-2">
|
<Grid numItems={1} className="gap-2 p-8 w-full mt-2">
|
||||||
<Callout
|
|
||||||
title="[UI] Presidio PII + Guardrails Coming Soon. https://docs.litellm.ai/docs/proxy/pii_masking"
|
|
||||||
color="sky"
|
|
||||||
></Callout>
|
|
||||||
<TabGroup>
|
<TabGroup>
|
||||||
<TabList variant="line" defaultValue="1">
|
<TabList variant="line" defaultValue="1">
|
||||||
<Tab value="1">Logging Callbacks</Tab>
|
<Tab value="1">Logging Callbacks</Tab>
|
||||||
|
@ -411,7 +479,8 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<Card>
|
<Title level={4}>Active Logging Callbacks</Title>
|
||||||
|
<Card className="w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
@ -471,6 +540,10 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</Card>
|
</Card>
|
||||||
|
<Button
|
||||||
|
onClick={() => setShowAddCallbacksModal(true)}>
|
||||||
|
Add Callback
|
||||||
|
</Button>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
|
@ -770,7 +843,81 @@ const Settings: React.FC<SettingsPageProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<Modal
|
||||||
|
title="Add Logging Callback"
|
||||||
|
visible={showAddCallbacksModal}
|
||||||
|
width={800}
|
||||||
|
onCancel= {() => setShowAddCallbacksModal(false)}
|
||||||
|
footer={null}
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
onFinish={addNewCallbackCall}
|
||||||
|
labelCol={{ span: 8 }}
|
||||||
|
wrapperCol={{ span: 16 }}
|
||||||
|
labelAlign="left"
|
||||||
|
>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<FormItem
|
||||||
|
label="Callback"
|
||||||
|
name="callback"
|
||||||
|
rules={[{ required: true, message: "Please select a callback" }]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
onChange={(value) => {
|
||||||
|
const selectedCallback = allCallbacks[value];
|
||||||
|
if (selectedCallback) {
|
||||||
|
console.log(selectedCallback.ui_callback_name);
|
||||||
|
handleSelectedCallbackChange(selectedCallback);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{allCallbacks &&
|
||||||
|
Object.values(allCallbacks).map((callback) => (
|
||||||
|
<SelectItem
|
||||||
|
key={callback.litellm_callback_name}
|
||||||
|
value={callback.litellm_callback_name}
|
||||||
|
>
|
||||||
|
{callback.ui_callback_name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
selectedCallbackParams && selectedCallbackParams.map((param) => (
|
||||||
|
<FormItem
|
||||||
|
label={param}
|
||||||
|
name={param}
|
||||||
|
rules={[{ required: true, message: "Please enter the value for " + param}]}
|
||||||
|
>
|
||||||
|
<TextInput type="password" />
|
||||||
|
</FormItem>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
<div style={{ textAlign: "right", marginTop: "10px" }}>
|
||||||
|
<Button2 htmlType="submit">Save</Button2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue