From c5936799b0c440da8238eb43774a084a9c521f23 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Fri, 18 Apr 2025 18:03:08 -0700 Subject: [PATCH] fix(tag_management_endpoints.py): return dynamic tags from db on `/tag/list` --- .../tag_management_endpoints.py | 27 ++++++++++++++++++- litellm/types/tag_management.py | 21 +++++++++++++++ .../src/components/new_usage.tsx | 7 ++--- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/litellm/proxy/management_endpoints/tag_management_endpoints.py b/litellm/proxy/management_endpoints/tag_management_endpoints.py index ff8274a038..7c731400fb 100644 --- a/litellm/proxy/management_endpoints/tag_management_endpoints.py +++ b/litellm/proxy/management_endpoints/tag_management_endpoints.py @@ -25,6 +25,7 @@ from litellm.proxy.management_endpoints.common_daily_activity import ( get_daily_activity, ) from litellm.types.tag_management import ( + LiteLLM_DailyTagSpendTable, TagConfig, TagDeleteRequest, TagInfoRequest, @@ -315,9 +316,33 @@ async def list_tags( raise HTTPException(status_code=500, detail="Database not connected") try: + ## QUERY STORED TAGS ## tags_config = await _get_tags_config(prisma_client) list_of_tags = list(tags_config.values()) - return list_of_tags + + ## QUERY DYNAMIC TAGS ## + dynamic_tags = await prisma_client.db.litellm_dailytagspend.find_many( + distinct=["tag"], + ) + + dynamic_tags_list = [ + LiteLLM_DailyTagSpendTable(**dynamic_tag.model_dump()) + for dynamic_tag in dynamic_tags + ] + + dynamic_tag_config = [ + TagConfig( + name=tag.tag, + description="This is just a spend tag that was passed dynamically in a request. It does not control any LLM models.", + models=None, + created_at=tag.created_at.isoformat(), + updated_at=tag.updated_at.isoformat(), + ) + for tag in dynamic_tags_list + if tag.tag not in tags_config + ] + + return list_of_tags + dynamic_tag_config except Exception as e: raise HTTPException(status_code=500, detail=str(e)) diff --git a/litellm/types/tag_management.py b/litellm/types/tag_management.py index e530b37cab..a3615b658c 100644 --- a/litellm/types/tag_management.py +++ b/litellm/types/tag_management.py @@ -1,3 +1,4 @@ +from datetime import datetime from typing import Dict, List, Optional from pydantic import BaseModel @@ -30,3 +31,23 @@ class TagDeleteRequest(BaseModel): class TagInfoRequest(BaseModel): names: List[str] + + +class LiteLLM_DailyTagSpendTable(BaseModel): + id: str + tag: str + date: str + api_key: str + model: str + model_group: Optional[str] + custom_llm_provider: Optional[str] + prompt_tokens: int + completion_tokens: int + cache_read_input_tokens: int + cache_creation_input_tokens: int + spend: float + api_requests: int + successful_requests: int + failed_requests: int + created_at: datetime + updated_at: datetime diff --git a/ui/litellm-dashboard/src/components/new_usage.tsx b/ui/litellm-dashboard/src/components/new_usage.tsx index 03f09695a5..ffccbef85b 100644 --- a/ui/litellm-dashboard/src/components/new_usage.tsx +++ b/ui/litellm-dashboard/src/components/new_usage.tsx @@ -18,6 +18,7 @@ import { import { AreaChart } from "@tremor/react"; import { userDailyActivityCall, tagListCall } from "./networking"; +import { Tag } from "./tag_management/types"; import ViewUserSpend from "./view_user_spend"; import TopKeyView from "./top_key_view"; import { ActivityMetrics, processActivityData } from './activity_metrics'; @@ -58,9 +59,9 @@ const NewUsagePage: React.FC = ({ return; } const tags = await tagListCall(accessToken); - setAllTags(Object.keys(tags).map((tag) => ({ - label: tag, - value: tag + setAllTags(Object.values(tags).map((tag: Tag) => ({ + label: tag.name, + value: tag.name }))); };