mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-11 21:46:22 +00:00
[Feat] Team Member Rate Limits - show team member tpm/rpm limits (#13662)
* show team member tpm/rpm limits * ui - allow setting team settings
This commit is contained in:
@@ -106,6 +106,8 @@ export interface TeamData {
|
||||
team_member_budget_table: {
|
||||
max_budget: number;
|
||||
budget_duration: string;
|
||||
tpm_limit: number | null;
|
||||
rpm_limit: number | null;
|
||||
} | null;
|
||||
};
|
||||
keys: any[];
|
||||
@@ -352,6 +354,11 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
updateData.team_member_key_duration = values.team_member_key_duration;
|
||||
}
|
||||
|
||||
if (values.team_member_tpm_limit !== undefined || values.team_member_rpm_limit !== undefined) {
|
||||
updateData.team_member_tpm_limit = sanitizeNumeric(values.team_member_tpm_limit);
|
||||
updateData.team_member_rpm_limit = sanitizeNumeric(values.team_member_rpm_limit);
|
||||
}
|
||||
|
||||
// Handle object_permission updates
|
||||
const { servers, accessGroups } = values.mcp_servers_and_groups || {
|
||||
servers: [],
|
||||
@@ -582,6 +589,8 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
rpm_limit: info.rpm_limit,
|
||||
max_budget: info.max_budget,
|
||||
budget_duration: info.budget_duration,
|
||||
team_member_tpm_limit: info.team_member_budget_table?.tpm_limit,
|
||||
team_member_rpm_limit: info.team_member_budget_table?.rpm_limit,
|
||||
guardrails: info.metadata?.guardrails || [],
|
||||
metadata: info.metadata
|
||||
? JSON.stringify(
|
||||
@@ -656,6 +665,30 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
<TextInput placeholder="e.g., 30d" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Team Member TPM Limit"
|
||||
name="team_member_tpm_limit"
|
||||
tooltip="Default tokens per minute limit for an individual team member. This limit applies to all requests the user makes within this team. Can be overridden per member."
|
||||
>
|
||||
<NumericalInput
|
||||
step={1}
|
||||
style={{ width: "100%" }}
|
||||
placeholder="e.g., 1000"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Team Member RPM Limit"
|
||||
name="team_member_rpm_limit"
|
||||
tooltip="Default requests per minute limit for an individual team member. This limit applies to all requests the user makes within this team. Can be overridden per member."
|
||||
>
|
||||
<NumericalInput
|
||||
step={1}
|
||||
style={{ width: "100%" }}
|
||||
placeholder="e.g., 100"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Reset Budget" name="budget_duration">
|
||||
<Select placeholder="n/a">
|
||||
<Select.Option value="24h">daily</Select.Option>
|
||||
@@ -811,6 +844,14 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
Key Duration:{" "}
|
||||
{info.metadata?.team_member_key_duration || "No Limit"}
|
||||
</div>
|
||||
<div>
|
||||
TPM Limit:{" "}
|
||||
{info.team_member_budget_table?.tpm_limit || "No Limit"}
|
||||
</div>
|
||||
<div>
|
||||
RPM Limit:{" "}
|
||||
{info.team_member_budget_table?.rpm_limit || "No Limit"}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Text className="font-medium">Organization ID</Text>
|
||||
|
||||
@@ -75,10 +75,25 @@ const TeamMembersComponent: React.FC<TeamMembersComponentProps> = ({
|
||||
return formatNumber(maxBudget);
|
||||
};
|
||||
|
||||
// Helper function to get rate limits for a user
|
||||
const getUserRateLimits = (userId: string | null): string => {
|
||||
if (!userId) return 'No Limits';
|
||||
const membership = teamData.team_memberships.find(tm => tm.user_id === userId);
|
||||
const rpmLimit = membership?.litellm_budget_table?.rpm_limit;
|
||||
const tpmLimit = membership?.litellm_budget_table?.tpm_limit;
|
||||
|
||||
const rpmText = rpmLimit ? `${formatNumber(rpmLimit)} RPM` : null;
|
||||
const tpmText = tpmLimit ? `${formatNumber(tpmLimit)} TPM` : null;
|
||||
|
||||
const limits = [rpmText, tpmText].filter(Boolean);
|
||||
return limits.length > 0 ? limits.join(' / ') : 'No Limits';
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Card className="w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]">
|
||||
<Table>
|
||||
<Card className="w-full mx-auto flex-auto overflow-auto max-h-[50vh]">
|
||||
<div className="overflow-x-auto">
|
||||
<Table className="min-w-full">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeaderCell>User ID</TableHeaderCell>
|
||||
@@ -91,7 +106,13 @@ const TeamMembersComponent: React.FC<TeamMembersComponentProps> = ({
|
||||
</Tooltip>
|
||||
</TableHeaderCell>
|
||||
<TableHeaderCell>Team Member Budget (USD)</TableHeaderCell>
|
||||
<TableHeaderCell></TableHeaderCell>
|
||||
<TableHeaderCell>Team Member Rate Limits
|
||||
{" "}
|
||||
<Tooltip title="Rate limits for this member's usage within this team.">
|
||||
<InfoCircleOutlined />
|
||||
</Tooltip>
|
||||
</TableHeaderCell>
|
||||
<TableHeaderCell className="sticky right-0 bg-white z-10 border-l border-gray-200">Actions</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
@@ -114,8 +135,11 @@ const TeamMembersComponent: React.FC<TeamMembersComponentProps> = ({
|
||||
<Text className="font-mono">{getUserBudget(member.user_id) ? `$${formatNumberWithCommas(Number(getUserBudget(member.user_id)), 4)}` : 'No Limit'}</Text>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Text className="font-mono">{getUserRateLimits(member.user_id)}</Text>
|
||||
</TableCell>
|
||||
<TableCell className="sticky right-0 bg-white z-10 border-l border-gray-200">
|
||||
{canEditTeam && (
|
||||
<>
|
||||
<div className="flex gap-2">
|
||||
<Icon
|
||||
icon={PencilAltIcon}
|
||||
size="sm"
|
||||
@@ -123,19 +147,22 @@ const TeamMembersComponent: React.FC<TeamMembersComponentProps> = ({
|
||||
setSelectedEditMember(member);
|
||||
setIsEditMemberModalVisible(true);
|
||||
}}
|
||||
className="cursor-pointer hover:text-blue-600"
|
||||
/>
|
||||
<Icon
|
||||
icon={TrashIcon}
|
||||
size="sm"
|
||||
onClick={() => handleMemberDelete(member)}
|
||||
className="cursor-pointer hover:text-red-600"
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Table>
|
||||
</div>
|
||||
</Card>
|
||||
<TremorButton onClick={() => setIsAddMemberModalVisible(true)}>
|
||||
Add Member
|
||||
|
||||
Reference in New Issue
Block a user