fix(time_to_first_token.tsx): require enterprise license for usage

This commit is contained in:
Krrish Dholakia 2024-05-22 19:20:30 -07:00
parent 3400596dd2
commit 8d1067c81c
6 changed files with 69 additions and 38 deletions

View file

@ -35,8 +35,11 @@ class LicenseCheck:
return False return False
def is_premium(self) -> bool: def is_premium(self) -> bool:
if self.license_str is None: try:
if self.license_str is None:
return False
elif self._verify(license_str=self.license_str):
return True
return False
except Exception as e:
return False return False
elif self._verify(license_str=self.license_str):
return True
return False

View file

@ -174,7 +174,6 @@ except Exception as e:
_license_check = LicenseCheck() _license_check = LicenseCheck()
premium_user: bool = _license_check.is_premium() premium_user: bool = _license_check.is_premium()
ui_link = f"/ui/" ui_link = f"/ui/"
ui_message = ( ui_message = (
f"👉 [```LiteLLM Admin Panel on /ui```]({ui_link}). Create, Edit Keys with SSO" f"👉 [```LiteLLM Admin Panel on /ui```]({ui_link}). Create, Edit Keys with SSO"
@ -9587,6 +9586,7 @@ async def fallback_login(request: Request):
"/login", include_in_schema=False "/login", include_in_schema=False
) # hidden since this is a helper for UI sso login ) # hidden since this is a helper for UI sso login
async def login(request: Request): async def login(request: Request):
global premium_user
try: try:
import multipart import multipart
except ImportError: except ImportError:
@ -9662,6 +9662,7 @@ async def login(request: Request):
"user_email": user_id, "user_email": user_id,
"user_role": "app_admin", # this is the path without sso - we can assume only admins will use this "user_role": "app_admin", # this is the path without sso - we can assume only admins will use this
"login_method": "username_password", "login_method": "username_password",
"premium_user": premium_user,
}, },
"secret", "secret",
algorithm="HS256", algorithm="HS256",
@ -9712,7 +9713,7 @@ def get_image():
@app.get("/sso/callback", tags=["experimental"]) @app.get("/sso/callback", tags=["experimental"])
async def auth_callback(request: Request): async def auth_callback(request: Request):
"""Verify login""" """Verify login"""
global general_settings, ui_access_mode global general_settings, ui_access_mode, premium_user
microsoft_client_id = os.getenv("MICROSOFT_CLIENT_ID", None) microsoft_client_id = os.getenv("MICROSOFT_CLIENT_ID", None)
google_client_id = os.getenv("GOOGLE_CLIENT_ID", None) google_client_id = os.getenv("GOOGLE_CLIENT_ID", None)
generic_client_id = os.getenv("GENERIC_CLIENT_ID", None) generic_client_id = os.getenv("GENERIC_CLIENT_ID", None)
@ -9992,6 +9993,7 @@ async def auth_callback(request: Request):
"user_email": user_email, "user_email": user_email,
"user_role": user_role, "user_role": user_role,
"login_method": "sso", "login_method": "sso",
"premium_user": premium_user,
}, },
"secret", "secret",
algorithm="HS256", algorithm="HS256",

View file

@ -20,6 +20,7 @@ import { Typography } from "antd";
const CreateKeyPage = () => { const CreateKeyPage = () => {
const { Title, Paragraph } = Typography; const { Title, Paragraph } = Typography;
const [userRole, setUserRole] = useState(""); const [userRole, setUserRole] = useState("");
const [premiumUser, setPremiumUser] = useState(false);
const [userEmail, setUserEmail] = useState<null | string>(null); const [userEmail, setUserEmail] = useState<null | string>(null);
const [teams, setTeams] = useState<null | any[]>(null); const [teams, setTeams] = useState<null | any[]>(null);
const [keys, setKeys] = useState<null | any[]>(null); const [keys, setKeys] = useState<null | any[]>(null);
@ -68,6 +69,10 @@ const CreateKeyPage = () => {
} else { } else {
console.log(`User Email is not set ${decoded}`); console.log(`User Email is not set ${decoded}`);
} }
if (decoded.premium_user) {
setPremiumUser(decoded.premium_user);
}
} }
} }
}, [token]); }, [token]);
@ -104,6 +109,7 @@ const CreateKeyPage = () => {
userRole={userRole} userRole={userRole}
userEmail={userEmail} userEmail={userEmail}
showSSOBanner={showSSOBanner} showSSOBanner={showSSOBanner}
premiumUser={premiumUser}
/> />
<div className="flex flex-1 overflow-auto"> <div className="flex flex-1 overflow-auto">
<div className="mt-8"> <div className="mt-8">
@ -134,6 +140,7 @@ const CreateKeyPage = () => {
accessToken={accessToken} accessToken={accessToken}
modelData={modelData} modelData={modelData}
setModelData={setModelData} setModelData={setModelData}
premiumUser={premiumUser}
/> />
) : page == "llm-playground" ? ( ) : page == "llm-playground" ? (
<ChatUI <ChatUI

View file

@ -91,6 +91,7 @@ interface ModelDashboardProps {
userID: string | null; userID: string | null;
modelData: any; modelData: any;
setModelData: any; setModelData: any;
premiumUser: boolean;
} }
interface EditModelModalProps { interface EditModelModalProps {
@ -233,6 +234,7 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
userID, userID,
modelData = { data: [] }, modelData = { data: [] },
setModelData, setModelData,
premiumUser,
}) => { }) => {
const [pendingRequests, setPendingRequests] = useState<any[]>([]); const [pendingRequests, setPendingRequests] = useState<any[]>([]);
const [form] = Form.useForm(); const [form] = Form.useForm();
@ -1609,6 +1611,7 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
streamingModelMetricsCategories streamingModelMetricsCategories
} }
customTooltip={customTooltip} customTooltip={customTooltip}
premiumUser={premiumUser}
/> />
</TabPanel> </TabPanel>
</TabPanels> </TabPanels>

View file

@ -1,17 +1,19 @@
import React from "react"; import React from "react";
import { LineChart } from "@tremor/react"; import { LineChart, Callout, Button } from "@tremor/react";
interface TimeToFirstTokenProps { interface TimeToFirstTokenProps {
modelMetrics: any[]; modelMetrics: any[];
modelMetricsCategories: string[]; modelMetricsCategories: string[];
customTooltip: any; customTooltip: any;
premiumUser: boolean;
} }
const TimeToFirstToken: React.FC<TimeToFirstTokenProps> = ({ const TimeToFirstToken: React.FC<TimeToFirstTokenProps> = ({
modelMetrics, modelMetrics,
modelMetricsCategories, modelMetricsCategories,
customTooltip, customTooltip,
premiumUser,
}) => { }) => {
return ( return premiumUser ? (
<LineChart <LineChart
title="Time to First token (s)" title="Time to First token (s)"
className="h-72" className="h-72"
@ -23,6 +25,18 @@ const TimeToFirstToken: React.FC<TimeToFirstTokenProps> = ({
connectNulls={true} connectNulls={true}
customTooltip={customTooltip} customTooltip={customTooltip}
/> />
) : (
<div>
<Callout title="Premium Feature" color="teal" className="mt-2 mb-4">
Premium features are available for users with a specific license, please
contact LiteLLM to unlock this limitation.
</Callout>
<Button variant="primary">
<a href="https://forms.gle/W3U4PZpJGFHWtHyA9" target="_blank">
Get in touch
</a>
</Button>
</div>
); );
}; };

View file

@ -3,8 +3,8 @@
import Link from "next/link"; import Link from "next/link";
import Image from "next/image"; import Image from "next/image";
import React, { useState } from "react"; import React, { useState } from "react";
import type { MenuProps } from 'antd'; import type { MenuProps } from "antd";
import { Dropdown, Space } from 'antd'; import { Dropdown, Space } from "antd";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { import {
Button, Button,
@ -23,28 +23,32 @@ interface NavbarProps {
userRole: string | null; userRole: string | null;
userEmail: string | null; userEmail: string | null;
showSSOBanner: boolean; showSSOBanner: boolean;
premiumUser: boolean;
} }
const Navbar: React.FC<NavbarProps> = ({ const Navbar: React.FC<NavbarProps> = ({
userID, userID,
userRole, userRole,
userEmail, userEmail,
showSSOBanner, showSSOBanner,
premiumUser,
}) => { }) => {
console.log("User ID:", userID); console.log("User ID:", userID);
console.log("userEmail:", userEmail); console.log("userEmail:", userEmail);
console.log("showSSOBanner:", showSSOBanner); console.log("showSSOBanner:", showSSOBanner);
console.log("premiumUser:", premiumUser);
// const userColors = require('./ui_colors.json') || {}; // const userColors = require('./ui_colors.json') || {};
const isLocal = process.env.NODE_ENV === "development"; const isLocal = process.env.NODE_ENV === "development";
const imageUrl = isLocal ? "http://localhost:4000/get_image" : "/get_image"; const imageUrl = isLocal ? "http://localhost:4000/get_image" : "/get_image";
const items: MenuProps['items'] = [ const items: MenuProps["items"] = [
{ {
key: '1', key: "1",
label: ( label: (
<> <>
<p>Role: {userRole}</p> <p>Role: {userRole}</p>
<p>ID: {userID}</p> <p>ID: {userID}</p>
<p>Premium User: {String(premiumUser)}</p>
</> </>
), ),
}, },
@ -68,41 +72,39 @@ const Navbar: React.FC<NavbarProps> = ({
</div> </div>
</div> </div>
<div className="text-right mx-4 my-2 absolute top-0 right-0 flex items-center justify-end space-x-2"> <div className="text-right mx-4 my-2 absolute top-0 right-0 flex items-center justify-end space-x-2">
{showSSOBanner ? ( {showSSOBanner ? (
<div
<div style={{
// border: '1px solid #391085',
padding: '6px',
borderRadius: '8px', // Added border-radius property
}}
>
<a
href="https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat"
target="_blank"
style={{ style={{
"fontSize": "14px", // border: '1px solid #391085',
"textDecoration": "underline" padding: "6px",
borderRadius: "8px", // Added border-radius property
}} }}
> >
Request hosted proxy <a
</a> href="https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat"
target="_blank"
style={{
fontSize: "14px",
textDecoration: "underline",
}}
>
Request hosted proxy
</a>
</div> </div>
) : null} ) : null}
<div style={{ <div
border: '1px solid #391085', style={{
padding: '6px', border: "1px solid #391085",
borderRadius: '8px', // Added border-radius property padding: "6px",
borderRadius: "8px", // Added border-radius property
}} }}
> >
<Dropdown menu={{ items }} > <Dropdown menu={{ items }}>
<Space> <Space>{userEmail}</Space>
{userEmail} </Dropdown>
</Space>
</Dropdown>
</div> </div>
</div> </div>
</nav> </nav>
); );
}; };