mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-13 15:07:47 +00:00
Litellm UI improvements 04 26 2025 p1 (#10346)
* fix(provider_info_helpers.tsx): fix together ai provider name * fix(user_edit_view.tsx): all admin to edit user's personal models * fix(model_dashboard.tsx): fix model filtering by team id check * fix(proxy_server.py): support returning available models for a user on `/model_group/info` Fixes issue where personal key with 'all team models' would see all proxy models (not just the ones user can call) * test(test_models.py): add unit test for model group info check on personal key
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
model_list:
|
||||
- model_name: gpt-3.5-turbo
|
||||
litellm_params:
|
||||
model: azure/chatgpt-v-3
|
||||
api_base: https://openai-gpt-4-test-v-1.openai.azure.com/
|
||||
api_version: "2023-05-15"
|
||||
api_key: os.environ/AZURE_API_KEY
|
||||
- model_name: "gpt-4o-azure"
|
||||
litellm_params:
|
||||
model: azure/gpt-4o
|
||||
|
||||
@@ -217,6 +217,7 @@ from litellm.proxy.litellm_pre_call_utils import add_litellm_data_to_request
|
||||
from litellm.proxy.management_endpoints.budget_management_endpoints import (
|
||||
router as budget_management_router,
|
||||
)
|
||||
from litellm.proxy.management_endpoints.common_utils import _user_has_admin_view
|
||||
from litellm.proxy.management_endpoints.customer_endpoints import (
|
||||
router as customer_router,
|
||||
)
|
||||
@@ -6376,6 +6377,7 @@ async def model_group_info(
|
||||
raise HTTPException(
|
||||
status_code=500, detail={"error": "LLM Router is not loaded in"}
|
||||
)
|
||||
|
||||
## CHECK IF MODEL RESTRICTIONS ARE SET AT KEY/TEAM LEVEL ##
|
||||
model_access_groups: Dict[str, List[str]] = defaultdict(list)
|
||||
if llm_router is None:
|
||||
@@ -6389,11 +6391,36 @@ async def model_group_info(
|
||||
proxy_model_list=proxy_model_list,
|
||||
model_access_groups=model_access_groups,
|
||||
)
|
||||
team_models = get_team_models(
|
||||
team_models=user_api_key_dict.team_models,
|
||||
proxy_model_list=proxy_model_list,
|
||||
model_access_groups=model_access_groups,
|
||||
)
|
||||
team_models = []
|
||||
if (
|
||||
not user_api_key_dict.team_id
|
||||
and user_api_key_dict.user_id is not None
|
||||
and not _user_has_admin_view(user_api_key_dict)
|
||||
):
|
||||
if prisma_client is None:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail={"error": CommonProxyErrors.db_not_connected_error.value},
|
||||
)
|
||||
user_object = await prisma_client.db.litellm_usertable.find_first(
|
||||
where={"user_id": user_api_key_dict.user_id}
|
||||
)
|
||||
user_object_typed = LiteLLM_UserTable(**user_object.model_dump())
|
||||
user_models = []
|
||||
if user_object is not None:
|
||||
user_models = get_team_models(
|
||||
team_models=user_object_typed.models,
|
||||
proxy_model_list=proxy_model_list,
|
||||
model_access_groups=model_access_groups,
|
||||
)
|
||||
team_models = user_models
|
||||
else:
|
||||
team_models = get_team_models(
|
||||
team_models=user_api_key_dict.team_models,
|
||||
proxy_model_list=proxy_model_list,
|
||||
model_access_groups=model_access_groups,
|
||||
)
|
||||
|
||||
all_models_str = get_complete_model_list(
|
||||
key_models=key_models,
|
||||
team_models=team_models,
|
||||
|
||||
@@ -446,6 +446,23 @@ async def test_add_model_run_health():
|
||||
# cleanup
|
||||
await delete_model(session=session, model_id=model_id)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_personal_models_for_user():
|
||||
"""
|
||||
Test /models endpoint with team
|
||||
"""
|
||||
from test_users import new_user
|
||||
async with aiohttp.ClientSession() as session:
|
||||
# Creat a user
|
||||
user_data = await new_user(session=session, i=0, models=["gpt-3.5-turbo"])
|
||||
user_id = user_data["user_id"]
|
||||
user_api_key = user_data["key"]
|
||||
|
||||
model_group_info = await get_model_group_info(session=session, key=user_api_key)
|
||||
print(model_group_info)
|
||||
|
||||
assert len(model_group_info["data"]) == 1
|
||||
assert model_group_info["data"][0]["model_group"] == "gpt-3.5-turbo"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_model_group_info_e2e():
|
||||
|
||||
@@ -1211,7 +1211,7 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||
data={modelData.data.filter(
|
||||
(model: any) => (
|
||||
(selectedModelGroup === "all" || model.model_name === selectedModelGroup || !selectedModelGroup) &&
|
||||
(selectedTeamFilter === "all" || model.team_id === selectedTeamFilter || !selectedTeamFilter)
|
||||
(selectedTeamFilter === "all" || model.model_info["team_id"] === selectedTeamFilter || !selectedTeamFilter)
|
||||
)
|
||||
)}
|
||||
isLoading={false}
|
||||
|
||||
@@ -51,7 +51,7 @@ export const provider_map: Record<string, string> = {
|
||||
Cerebras: "cerebras",
|
||||
Sambanova: "sambanova",
|
||||
Perplexity: "perplexity",
|
||||
TogetherAI: "togetherai",
|
||||
TogetherAI: "together_ai",
|
||||
Openrouter: "openrouter",
|
||||
FireworksAI: "fireworks_ai"
|
||||
};
|
||||
|
||||
@@ -120,7 +120,7 @@ export function UserEditView({
|
||||
mode="multiple"
|
||||
placeholder="Select models"
|
||||
style={{ width: "100%" }}
|
||||
disabled={!all_admin_roles.includes(userData.user_info?.user_role || "")}
|
||||
disabled={!all_admin_roles.includes(userRole || "")}
|
||||
|
||||
>
|
||||
<Select.Option key="all-proxy-models" value="all-proxy-models">
|
||||
|
||||
Reference in New Issue
Block a user