Merge pull request #4139 from BerriAI/litellm_fix_budget_exceeded_error_code

fix(proxy_server.py): use consistent 400-status code error code for exceeded budget errors
This commit is contained in:
Krish Dholakia 2024-06-11 18:36:58 -07:00 committed by GitHub
commit 30d269f93a
6 changed files with 30 additions and 24 deletions

View file

@ -15,7 +15,6 @@ from functools import partial
import dotenv, traceback, random, asyncio, time, contextvars import dotenv, traceback, random, asyncio, time, contextvars
from copy import deepcopy from copy import deepcopy
import httpx import httpx
import litellm import litellm
from ._logging import verbose_logger from ._logging import verbose_logger
from litellm import ( # type: ignore from litellm import ( # type: ignore

View file

@ -151,8 +151,8 @@ def common_checks(
and route != "/models" and route != "/models"
): ):
if global_proxy_spend > litellm.max_budget: if global_proxy_spend > litellm.max_budget:
raise Exception( raise litellm.BudgetExceededError(
f"ExceededBudget: LiteLLM Proxy has exceeded its budget. Current spend: {global_proxy_spend}; Max Budget: {litellm.max_budget}" current_cost=global_proxy_spend, max_budget=litellm.max_budget
) )
return True return True

View file

@ -1078,8 +1078,9 @@ async def user_api_key_auth(
_user_id = _user.get("user_id", None) _user_id = _user.get("user_id", None)
if user_current_spend > user_max_budget: if user_current_spend > user_max_budget:
raise Exception( raise litellm.BudgetExceededError(
f"ExceededBudget: User {_user_id} has exceeded their budget. Current spend: {user_current_spend}; Max Budget: {user_max_budget}" current_cost=user_current_spend,
max_budget=user_max_budget,
) )
else: else:
# Token exists, not expired now check if its in budget for the user # Token exists, not expired now check if its in budget for the user
@ -1110,9 +1111,11 @@ async def user_api_key_auth(
) )
if user_current_spend > user_max_budget: if user_current_spend > user_max_budget:
raise Exception( raise litellm.BudgetExceededError(
f"ExceededBudget: User {valid_token.user_id} has exceeded their budget. Current spend: {user_current_spend}; Max Budget: {user_max_budget}" current_cost=user_current_spend,
max_budget=user_max_budget,
) )
# Check 3. Check if user is in their team budget # Check 3. Check if user is in their team budget
if valid_token.team_member_spend is not None: if valid_token.team_member_spend is not None:
if prisma_client is not None: if prisma_client is not None:
@ -1146,8 +1149,9 @@ async def user_api_key_auth(
) )
if team_member_budget is not None and team_member_budget > 0: if team_member_budget is not None and team_member_budget > 0:
if valid_token.team_member_spend > team_member_budget: if valid_token.team_member_spend > team_member_budget:
raise Exception( raise litellm.BudgetExceededError(
f"ExceededBudget: Crossed spend within team. UserID: {valid_token.user_id}, in team {valid_token.team_id} has exceeded their budget. Current spend: {valid_token.team_member_spend}; Max Budget: {team_member_budget}" current_cost=valid_token.team_member_spend,
max_budget=team_member_budget,
) )
# Check 3. If token is expired # Check 3. If token is expired
@ -1205,8 +1209,9 @@ async def user_api_key_auth(
#################################### ####################################
if valid_token.spend >= valid_token.max_budget: if valid_token.spend >= valid_token.max_budget:
raise Exception( raise litellm.BudgetExceededError(
f"ExceededTokenBudget: Current spend for token: {valid_token.spend}; Max Budget for Token: {valid_token.max_budget}" current_cost=valid_token.spend,
max_budget=valid_token.max_budget,
) )
# Check 5. Token Model Spend is under Model budget # Check 5. Token Model Spend is under Model budget
@ -1242,8 +1247,9 @@ async def user_api_key_auth(
): ):
current_model_spend = model_spend[0]["_sum"]["spend"] current_model_spend = model_spend[0]["_sum"]["spend"]
current_model_budget = max_budget_per_model[current_model] current_model_budget = max_budget_per_model[current_model]
raise Exception( raise litellm.BudgetExceededError(
f"ExceededModelBudget: Current spend for model: {current_model_spend}; Max Budget for Model: {current_model_budget}" current_cost=current_model_spend,
max_budget=current_model_budget,
) )
# Check 6. Team spend is under Team budget # Check 6. Team spend is under Team budget
@ -1267,8 +1273,9 @@ async def user_api_key_auth(
) )
if valid_token.team_spend >= valid_token.team_max_budget: if valid_token.team_spend >= valid_token.team_max_budget:
raise Exception( raise litellm.BudgetExceededError(
f"ExceededTokenBudget: Current Team Spend: {valid_token.team_spend}; Max Budget for Team: {valid_token.team_max_budget}" current_cost=valid_token.team_spend,
max_budget=valid_token.team_max_budget,
) )
# Check 8: Additional Common Checks across jwt + key auth # Check 8: Additional Common Checks across jwt + key auth

View file

@ -471,7 +471,7 @@ def test_call_with_user_over_budget(prisma_client):
asyncio.run(test()) asyncio.run(test())
except Exception as e: except Exception as e:
error_detail = e.message error_detail = e.message
assert "Authentication Error, ExceededBudget:" in error_detail assert "Budget has been exceeded" in error_detail
print(vars(e)) print(vars(e))
@ -652,7 +652,7 @@ def test_call_with_proxy_over_budget(prisma_client):
error_detail = e.message error_detail = e.message
else: else:
error_detail = traceback.format_exc() error_detail = traceback.format_exc()
assert "Authentication Error, ExceededBudget:" in error_detail assert "Budget has been exceeded" in error_detail
print(vars(e)) print(vars(e))
@ -730,7 +730,7 @@ def test_call_with_user_over_budget_stream(prisma_client):
asyncio.run(test()) asyncio.run(test())
except Exception as e: except Exception as e:
error_detail = e.message error_detail = e.message
assert "Authentication Error, ExceededBudget:" in error_detail assert "Budget has been exceeded" in error_detail
print(vars(e)) print(vars(e))
@ -827,7 +827,7 @@ def test_call_with_proxy_over_budget_stream(prisma_client):
asyncio.run(test()) asyncio.run(test())
except Exception as e: except Exception as e:
error_detail = e.message error_detail = e.message
assert "Authentication Error, ExceededBudget:" in error_detail assert "Budget has been exceeded" in error_detail
print(vars(e)) print(vars(e))
@ -1362,7 +1362,7 @@ def test_call_with_key_over_budget(prisma_client):
error_detail = e.message error_detail = e.message
else: else:
error_detail = str(e) error_detail = str(e)
assert "Authentication Error, ExceededTokenBudget:" in error_detail assert "Budget has been exceeded" in error_detail
print(vars(e)) print(vars(e))
@ -1476,7 +1476,7 @@ def test_call_with_key_over_model_budget(prisma_client):
# print(f"Error - {str(e)}") # print(f"Error - {str(e)}")
traceback.print_exc() traceback.print_exc()
error_detail = e.message error_detail = e.message
assert "Authentication Error, ExceededModelBudget:" in error_detail assert "Budget has been exceeded!" in error_detail
print(vars(e)) print(vars(e))
@ -1637,7 +1637,7 @@ async def test_call_with_key_over_budget_stream(prisma_client):
except Exception as e: except Exception as e:
print("Got Exception", e) print("Got Exception", e)
error_detail = e.message error_detail = e.message
assert "Authentication Error, ExceededTokenBudget:" in error_detail assert "Budget has been exceeded" in error_detail
print(vars(e)) print(vars(e))

View file

@ -664,7 +664,7 @@ async def test_key_crossing_budget():
response = await chat_completion(session=session, key=key) response = await chat_completion(session=session, key=key)
pytest.fail("Should have failed - Key crossed it's budget") pytest.fail("Should have failed - Key crossed it's budget")
except Exception as e: except Exception as e:
assert "ExceededTokenBudget: Current spend for token:" in str(e) assert "Budget has been exceeded!" in str(e)
@pytest.mark.skip(reason="AWS Suspended Account") @pytest.mark.skip(reason="AWS Suspended Account")

View file

@ -578,4 +578,4 @@ async def test_users_in_team_budget():
except Exception as e: except Exception as e:
print("got exception, this is expected") print("got exception, this is expected")
print(e) print(e)
assert "Crossed spend within team" in str(e) assert "Budget has been exceeded" in str(e)