Merge pull request #2255 from BerriAI/litellm_admin_ui_user_panel_load_time_high

[FEAT] proxy add pagination on /user/info endpoint (Admin UI does not load all users)
This commit is contained in:
Ishaan Jaff 2024-02-29 13:22:00 -08:00 committed by GitHub
commit e044d6332f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 91 additions and 8 deletions

View file

@ -2,7 +2,7 @@ import Image from '@theme/IdealImage';
import Tabs from '@theme/Tabs'; import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem'; import TabItem from '@theme/TabItem';
# 🔑 [BETA] Proxy UI # [BETA] Proxy UI
### **Create + delete keys through a UI** ### **Create + delete keys through a UI**
[Let users create their own keys](#setup-ssoauth-for-ui) [Let users create their own keys](#setup-ssoauth-for-ui)

View file

@ -1,4 +1,4 @@
# Virtual Keys, Users # 🔑 Virtual Keys, Users
Track Spend, Set budgets and create virtual keys for the proxy Track Spend, Set budgets and create virtual keys for the proxy
Grant other's temporary access to your proxy, with keys that expire after a set duration. Grant other's temporary access to your proxy, with keys that expire after a set duration.
@ -343,18 +343,83 @@ A key will be generated for the new user created
"key_name": null, "key_name": null,
"expires": null "expires": null
} }
``` ```
Request Params:
- keys: List[str] - List of keys to delete ## /user/info
### Request
#### View all Users
If you're trying to view all users, we recommend using pagination with the following args
- `view_all=true`
- `page=0` Optional(int) min = 0, default=0
- `page_size=25` Optional(int) min = 1, default = 25
```shell
curl -X GET "http://0.0.0.0:4000/user/info?view_all=true&page=0&page_size=25" -H "Authorization: Bearer sk-1234"
```
#### View specific user_id
```shell
curl -X GET "http://0.0.0.0:4000/user/info?user_id=228da235-eef0-4c30-bf53-5d6ac0d278c2" -H "Authorization: Bearer sk-1234"
```
### Response ### Response
View user spend, budget, models, keys and teams
```json ```json
{ {
"deleted_keys": ["sk-kdEXbIqZRwEeEiHwdg7sFA"] "user_id": "228da235-eef0-4c30-bf53-5d6ac0d278c2",
"user_info": {
"user_id": "228da235-eef0-4c30-bf53-5d6ac0d278c2",
"team_id": null,
"teams": [],
"user_role": "app_user",
"max_budget": null,
"spend": 200000.0,
"user_email": null,
"models": [],
"max_parallel_requests": null,
"tpm_limit": null,
"rpm_limit": null,
"budget_duration": null,
"budget_reset_at": null,
"allowed_cache_controls": [],
"model_spend": {
"chatgpt-v-2": 200000
},
"model_max_budget": {}
},
"keys": [
{
"token": "16c337f9df00a0e6472627e39a2ed02e67bc9a8a760c983c4e9b8cad7954f3c0",
"key_name": null,
"key_alias": null,
"spend": 200000.0,
"expires": null,
"models": [],
"aliases": {},
"config": {},
"user_id": "228da235-eef0-4c30-bf53-5d6ac0d278c2",
"team_id": null,
"permissions": {},
"max_parallel_requests": null,
"metadata": {},
"tpm_limit": null,
"rpm_limit": null,
"max_budget": null,
"budget_duration": null,
"budget_reset_at": null,
"allowed_cache_controls": [],
"model_spend": {
"chatgpt-v-2": 200000
},
"model_max_budget": {}
}
],
"teams": []
} }
``` ```
## Advanced ## Advanced

View file

@ -4329,6 +4329,14 @@ async def user_info(
default=False, default=False,
description="set to true to View all users. When using view_all, don't pass user_id", description="set to true to View all users. When using view_all, don't pass user_id",
), ),
page: Optional[int] = fastapi.Query(
default=0,
description="Page number for pagination. Only use when view_all is true",
),
page_size: Optional[int] = fastapi.Query(
default=25,
description="Number of items per page. Only use when view_all is true",
),
user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),
): ):
""" """
@ -4350,8 +4358,14 @@ async def user_info(
if user_id is not None: if user_id is not None:
user_info = await prisma_client.get_data(user_id=user_id) user_info = await prisma_client.get_data(user_id=user_id)
elif view_all == True: elif view_all == True:
if page is None:
page = 0
if page_size is None:
page_size = 25
offset = (page) * page_size # default is 0
limit = page_size # default is 10
user_info = await prisma_client.get_data( user_info = await prisma_client.get_data(
table_name="user", query_type="find_all" table_name="user", query_type="find_all", offset=offset, limit=limit
) )
return user_info return user_info
else: else:

View file

@ -641,6 +641,10 @@ class PrismaClient:
query_type: Literal["find_unique", "find_all"] = "find_unique", query_type: Literal["find_unique", "find_all"] = "find_unique",
expires: Optional[datetime] = None, expires: Optional[datetime] = None,
reset_at: Optional[datetime] = None, reset_at: Optional[datetime] = None,
offset: Optional[int] = None, # pagination, what row number to start from
limit: Optional[
int
] = None, # pagination, number of rows to getch when find_all==True
): ):
try: try:
response: Any = None response: Any = None
@ -776,7 +780,7 @@ class PrismaClient:
) )
else: else:
response = await self.db.litellm_usertable.find_many( # type: ignore response = await self.db.litellm_usertable.find_many( # type: ignore
order={"spend": "desc"}, order={"spend": "desc"}, take=limit, skip=offset
) )
return response return response
elif table_name == "spend": elif table_name == "spend":