[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:
Ishaan Jaff
2025-08-15 12:18:13 -07:00
committed by GitHub
parent f5a1c14929
commit 4a10eeb75e
2 changed files with 74 additions and 6 deletions
@@ -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