mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-17 20:18:10 +00:00
Merge pull request #21739 from BerriAI/litellm_credential_tag_prefix
[Feature] UI - Usage: Prefix credential tags, update Tag usage banner
This commit is contained in:
+3
-2
@@ -2024,9 +2024,10 @@ class Router:
|
||||
"litellm_credential_name"
|
||||
)
|
||||
if credential_name:
|
||||
credential_tag = f"Credential: {credential_name}"
|
||||
existing_tags = kwargs[metadata_variable_name].get("tags") or []
|
||||
if credential_name not in existing_tags:
|
||||
existing_tags.append(credential_name)
|
||||
if credential_tag not in existing_tags:
|
||||
existing_tags.append(credential_tag)
|
||||
kwargs[metadata_variable_name]["tags"] = existing_tags
|
||||
|
||||
kwargs["model_info"] = model_info
|
||||
|
||||
@@ -2211,13 +2211,13 @@ def test_credential_name_injected_as_tag():
|
||||
)
|
||||
router._update_kwargs_with_deployment(deployment=deployment, kwargs=kwargs)
|
||||
|
||||
assert "xAI" in kwargs["metadata"]["tags"]
|
||||
assert "Credential: xAI" in kwargs["metadata"]["tags"]
|
||||
assert "A.101" in kwargs["metadata"]["tags"]
|
||||
|
||||
|
||||
def test_credential_name_not_duplicated_in_tags():
|
||||
"""
|
||||
Test that if the credential name already exists in the tags list,
|
||||
Test that if the credential tag already exists in the tags list,
|
||||
it is not duplicated.
|
||||
"""
|
||||
router = litellm.Router(
|
||||
@@ -2232,13 +2232,13 @@ def test_credential_name_not_duplicated_in_tags():
|
||||
],
|
||||
)
|
||||
|
||||
kwargs: dict = {"metadata": {"tags": ["xAI", "A.101"]}}
|
||||
kwargs: dict = {"metadata": {"tags": ["Credential: xAI", "A.101"]}}
|
||||
deployment = router.get_deployment_by_model_group_name(
|
||||
model_group_name="xai-model"
|
||||
)
|
||||
router._update_kwargs_with_deployment(deployment=deployment, kwargs=kwargs)
|
||||
|
||||
assert kwargs["metadata"]["tags"].count("xAI") == 1
|
||||
assert kwargs["metadata"]["tags"].count("Credential: xAI") == 1
|
||||
|
||||
|
||||
def test_credential_name_not_injected_when_absent():
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
Text,
|
||||
Title
|
||||
} from "@tremor/react";
|
||||
import { Alert, Segmented, Select, Tooltip } from "antd";
|
||||
import { Alert, Segmented, Select, Tooltip, Typography } from "antd";
|
||||
import { useDebouncedState } from "@tanstack/react-pacer/debouncer";
|
||||
import React, { useCallback, useEffect, useMemo, useState, type UIEvent } from "react";
|
||||
|
||||
@@ -142,10 +142,8 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
const [modelViewType, setModelViewType] = useState<"groups" | "individual">("groups");
|
||||
const [isCloudZeroModalOpen, setIsCloudZeroModalOpen] = useState(false);
|
||||
const [isGlobalExportModalOpen, setIsGlobalExportModalOpen] = useState(false);
|
||||
const [showOrganizationBanner, setShowOrganizationBanner] = useState(true);
|
||||
const [showCustomerBanner, setShowCustomerBanner] = useState(true);
|
||||
const [usageView, setUsageView] = useState<UsageOption>("global");
|
||||
const [showAgentBanner, setShowAgentBanner] = useState(true);
|
||||
const [showCredentialBanner, setShowCredentialBanner] = useState(true);
|
||||
const [topKeysLimit, setTopKeysLimit] = useState<number>(5);
|
||||
const [topModelsLimit, setTopModelsLimit] = useState<number>(5);
|
||||
const getAllTags = async () => {
|
||||
@@ -805,33 +803,20 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
{/* Organization Usage Panel */}
|
||||
|
||||
{usageView === "organization" && (
|
||||
<>
|
||||
{showOrganizationBanner && (
|
||||
<Alert
|
||||
banner
|
||||
type="info"
|
||||
message="Organization usage is a new feature."
|
||||
description="Spend is tracked from feature launch and previous data isn't backfilled, so only future usage appears here."
|
||||
closable
|
||||
onClose={() => setShowOrganizationBanner(false)}
|
||||
className="mb-5"
|
||||
/>
|
||||
)}
|
||||
<EntityUsage
|
||||
accessToken={accessToken}
|
||||
entityType="organization"
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
dateValue={dateValue}
|
||||
entityList={
|
||||
organizations?.map((organization) => ({
|
||||
label: organization.organization_alias,
|
||||
value: organization.organization_id,
|
||||
})) || null
|
||||
}
|
||||
premiumUser={premiumUser}
|
||||
/>
|
||||
</>
|
||||
<EntityUsage
|
||||
accessToken={accessToken}
|
||||
entityType="organization"
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
dateValue={dateValue}
|
||||
entityList={
|
||||
organizations?.map((organization) => ({
|
||||
label: organization.organization_alias,
|
||||
value: organization.organization_id,
|
||||
})) || null
|
||||
}
|
||||
premiumUser={premiumUser}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Team Usage Panel */}
|
||||
@@ -854,72 +839,65 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
|
||||
{/* Customer Usage Panel */}
|
||||
{usageView === "customer" && (
|
||||
<EntityUsage
|
||||
accessToken={accessToken}
|
||||
entityType="customer"
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
entityList={
|
||||
customers?.map((customer) => ({
|
||||
label: customer.alias || customer.user_id,
|
||||
value: customer.user_id,
|
||||
})) || null
|
||||
}
|
||||
premiumUser={premiumUser}
|
||||
dateValue={dateValue}
|
||||
/>
|
||||
)}
|
||||
{/* Tag Usage Panel */}
|
||||
{usageView === "tag" && (
|
||||
<>
|
||||
{showCustomerBanner && (
|
||||
{showCredentialBanner && (
|
||||
<Alert
|
||||
banner
|
||||
type="info"
|
||||
message="Customer usage is a new feature."
|
||||
description="Spend is tracked from feature launch and previous data isn't backfilled, so only future usage appears here."
|
||||
message="Reusable credentials are automatically tracked as tags"
|
||||
description={
|
||||
<Typography.Text>
|
||||
When a reusable credential is used, it will appear as a tag prefixed with{" "}
|
||||
<Typography.Text code>Credential: </Typography.Text>
|
||||
in this view.
|
||||
</Typography.Text>
|
||||
}
|
||||
closable
|
||||
onClose={() => setShowCustomerBanner(false)}
|
||||
onClose={() => setShowCredentialBanner(false)}
|
||||
className="mb-5"
|
||||
/>
|
||||
)}
|
||||
<EntityUsage
|
||||
accessToken={accessToken}
|
||||
entityType="customer"
|
||||
entityType="tag"
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
entityList={
|
||||
customers?.map((customer) => ({
|
||||
label: customer.alias || customer.user_id,
|
||||
value: customer.user_id,
|
||||
})) || null
|
||||
}
|
||||
entityList={allTags}
|
||||
premiumUser={premiumUser}
|
||||
dateValue={dateValue}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{/* Tag Usage Panel */}
|
||||
{usageView === "tag" && (
|
||||
{usageView === "agent" && (
|
||||
<EntityUsage
|
||||
accessToken={accessToken}
|
||||
entityType="tag"
|
||||
entityType="agent"
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
entityList={allTags}
|
||||
entityList={
|
||||
agentsResponse?.agents?.map((agent) => ({ label: agent.agent_name, value: agent.agent_id })) || null
|
||||
}
|
||||
premiumUser={premiumUser}
|
||||
dateValue={dateValue}
|
||||
/>
|
||||
)}
|
||||
{usageView === "agent" && (
|
||||
<>
|
||||
{showAgentBanner && (
|
||||
<Alert
|
||||
banner
|
||||
type="info"
|
||||
message="Agent usage (A2A) is a new feature."
|
||||
description="Spend is tracked from feature launch and previous data isn't backfilled, so only future usage appears here."
|
||||
closable
|
||||
onClose={() => setShowAgentBanner(false)}
|
||||
className="mb-5"
|
||||
/>
|
||||
)}
|
||||
<EntityUsage
|
||||
accessToken={accessToken}
|
||||
entityType="agent"
|
||||
userID={userID}
|
||||
userRole={userRole}
|
||||
entityList={
|
||||
agentsResponse?.agents?.map((agent) => ({ label: agent.agent_name, value: agent.agent_id })) || null
|
||||
}
|
||||
premiumUser={premiumUser}
|
||||
dateValue={dateValue}
|
||||
/>{" "}
|
||||
</>
|
||||
)}
|
||||
{/* User Agent Activity Panel */}
|
||||
{usageView === "user-agent-activity" && (
|
||||
<UserAgentActivity accessToken={accessToken} userRole={userRole} dateValue={dateValue} />
|
||||
|
||||
Reference in New Issue
Block a user