2024-01-19 04:42:14 +08:00
# What this tests?
## Unit Tests for the max parallel request limiter for the proxy
2024-07-14 08:15:20 +08:00
import asyncio
import os
import random
import sys
import time
2024-01-19 04:42:14 +08:00
import traceback
2024-07-14 08:15:20 +08:00
from datetime import datetime
2024-01-19 04:42:14 +08:00
from dotenv import load_dotenv
load_dotenv ( )
import os
sys . path . insert (
0 , os . path . abspath ( " ../.. " )
) # Adds the parent directory to the system path
2024-07-14 08:15:20 +08:00
from datetime import datetime
2024-01-19 04:42:14 +08:00
import pytest
2024-07-14 08:15:20 +08:00
2024-01-19 04:42:14 +08:00
import litellm
from litellm import Router
2024-10-14 19:04:01 +08:00
from litellm . caching . caching import DualCache
2024-07-14 08:15:20 +08:00
from litellm . proxy . _types import UserAPIKeyAuth
2024-02-03 02:15:33 +08:00
from litellm . proxy . hooks . parallel_request_limiter import (
_PROXY_MaxParallelRequestsHandler as MaxParallelRequestsHandler ,
)
2024-09-26 01:57:08 +08:00
from litellm . proxy . utils import InternalUsageCache , ProxyLogging , hash_token
2024-01-19 04:42:14 +08:00
## On Request received
## On Request success
## On Request failure
2024-05-16 11:16:11 +08:00
@pytest.mark.asyncio
async def test_global_max_parallel_requests ( ) :
"""
Test if ParallelRequestHandler respects ' global_max_parallel_requests '
data [ " metadata " ] [ " global_max_parallel_requests " ]
"""
global_max_parallel_requests = 0
_api_key = " sk-12345 "
_api_key = hash_token ( " sk-12345 " )
user_api_key_dict = UserAPIKeyAuth ( api_key = _api_key , max_parallel_requests = 100 )
local_cache = DualCache ( )
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-05-16 11:16:11 +08:00
for _ in range ( 3 ) :
try :
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = {
" metadata " : {
" global_max_parallel_requests " : global_max_parallel_requests
}
} ,
call_type = " " ,
)
pytest . fail ( " Expected call to fail " )
except Exception as e :
pass
2024-01-19 04:42:14 +08:00
@pytest.mark.asyncio
async def test_pre_call_hook ( ) :
"""
Test if cache updated on call being received
"""
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( " sk-12345 " )
2024-01-19 04:42:14 +08:00
user_api_key_dict = UserAPIKeyAuth ( api_key = _api_key , max_parallel_requests = 1 )
local_cache = DualCache ( )
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-01-19 04:42:14 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
2024-01-19 05:52:15 +08:00
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-01-19 04:42:14 +08:00
print (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
key = request_count_api_key
)
2024-01-19 04:42:14 +08:00
)
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 04:42:14 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 1
)
2024-01-19 07:25:29 +08:00
@pytest.mark.asyncio
async def test_pre_call_hook_rpm_limits ( ) :
"""
Test if error raised on hitting rpm limits
"""
_api_key = " sk-12345 "
2024-11-04 10:18:20 +08:00
_api_key = hash_token ( _api_key )
2024-01-19 07:25:29 +08:00
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key , max_parallel_requests = 1 , tpm_limit = 9 , rpm_limit = 1
)
local_cache = DualCache ( )
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-01-19 07:25:29 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
kwargs = { " litellm_params " : { " metadata " : { " user_api_key " : _api_key } } }
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = " " ,
start_time = " " ,
end_time = " " ,
)
## Expected cache val: {"current_requests": 0, "current_tpm": 0, "current_rpm": 1}
2024-02-27 10:06:13 +08:00
try :
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { } ,
call_type = " " ,
)
pytest . fail ( f " Expected call to fail " )
except Exception as e :
assert e . status_code == 429
2024-07-14 08:15:20 +08:00
@pytest.mark.asyncio
async def test_pre_call_hook_rpm_limits_retry_after ( ) :
"""
Test if rate limit error , returns ' retry_after '
"""
_api_key = " sk-12345 "
2024-11-04 10:18:20 +08:00
_api_key = hash_token ( _api_key )
2024-07-14 08:15:20 +08:00
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key , max_parallel_requests = 1 , tpm_limit = 9 , rpm_limit = 1
)
local_cache = DualCache ( )
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-07-14 08:15:20 +08:00
)
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
kwargs = { " litellm_params " : { " metadata " : { " user_api_key " : _api_key } } }
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = " " ,
start_time = " " ,
end_time = " " ,
)
## Expected cache val: {"current_requests": 0, "current_tpm": 0, "current_rpm": 1}
try :
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { } ,
call_type = " " ,
)
pytest . fail ( f " Expected call to fail " )
except Exception as e :
assert e . status_code == 429
assert hasattr ( e , " headers " )
assert " retry-after " in e . headers
2024-02-27 10:06:13 +08:00
@pytest.mark.asyncio
async def test_pre_call_hook_team_rpm_limits ( ) :
"""
Test if error raised on hitting team rpm limits
"""
litellm . set_verbose = True
_api_key = " sk-12345 "
_team_id = " unique-team-id "
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key ,
max_parallel_requests = 1 ,
tpm_limit = 9 ,
rpm_limit = 10 ,
team_rpm_limit = 1 ,
team_id = _team_id ,
)
local_cache = DualCache ( )
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-02-27 10:06:13 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
kwargs = {
" litellm_params " : {
" metadata " : { " user_api_key " : _api_key , " user_api_key_team_id " : _team_id }
}
}
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = " " ,
start_time = " " ,
end_time = " " ,
)
print ( f " local_cache: { local_cache } " )
## Expected cache val: {"current_requests": 0, "current_tpm": 0, "current_rpm": 1}
2024-01-19 07:25:29 +08:00
try :
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { } ,
call_type = " " ,
)
pytest . fail ( f " Expected call to fail " )
except Exception as e :
assert e . status_code == 429
@pytest.mark.asyncio
async def test_pre_call_hook_tpm_limits ( ) :
"""
Test if error raised on hitting tpm limits
"""
_api_key = " sk-12345 "
2024-11-04 10:18:20 +08:00
_api_key = hash_token ( _api_key )
2024-01-19 07:25:29 +08:00
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key , max_parallel_requests = 1 , tpm_limit = 9 , rpm_limit = 10
)
local_cache = DualCache ( )
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-01-19 07:25:29 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
kwargs = { " litellm_params " : { " metadata " : { " user_api_key " : _api_key } } }
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = litellm . ModelResponse ( usage = litellm . Usage ( total_tokens = 10 ) ) ,
start_time = " " ,
end_time = " " ,
)
## Expected cache val: {"current_requests": 0, "current_tpm": 0, "current_rpm": 1}
try :
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { } ,
call_type = " " ,
)
pytest . fail ( f " Expected call to fail " )
except Exception as e :
assert e . status_code == 429
2024-02-23 10:44:03 +08:00
@pytest.mark.asyncio
async def test_pre_call_hook_user_tpm_limits ( ) :
"""
Test if error raised on hitting tpm limits
"""
2024-05-27 23:48:23 +08:00
local_cache = DualCache ( )
2024-02-23 10:44:03 +08:00
# create user with tpm/rpm limits
2024-05-27 23:48:23 +08:00
user_id = " test-user "
2024-09-27 09:13:35 +08:00
user_obj = {
" tpm_limit " : 9 ,
" rpm_limit " : 10 ,
" user_id " : user_id ,
" user_email " : " user_email " ,
" max_budget " : None ,
}
2024-05-27 23:48:23 +08:00
local_cache . set_cache ( key = user_id , value = user_obj )
2024-02-23 10:44:03 +08:00
_api_key = " sk-12345 "
2024-11-04 10:18:20 +08:00
_api_key = hash_token ( _api_key )
2024-02-23 10:44:03 +08:00
user_api_key_dict = UserAPIKeyAuth (
2024-11-04 10:18:20 +08:00
api_key = _api_key , user_id = user_id , user_rpm_limit = 10 , user_tpm_limit = 9
2024-02-23 10:44:03 +08:00
)
res = dict ( user_api_key_dict )
print ( " dict user " , res )
2024-05-27 23:48:23 +08:00
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-02-23 10:44:03 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
kwargs = {
" litellm_params " : {
2024-05-27 23:48:23 +08:00
" metadata " : { " user_api_key_user_id " : user_id , " user_api_key " : " gm " }
2024-02-23 10:44:03 +08:00
}
}
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = litellm . ModelResponse ( usage = litellm . Usage ( total_tokens = 10 ) ) ,
start_time = " " ,
end_time = " " ,
)
## Expected cache val: {"current_requests": 0, "current_tpm": 0, "current_rpm": 1}
try :
2024-09-27 09:13:35 +08:00
print ( " cache=local_cache " , local_cache . in_memory_cache . cache_dict )
2024-02-23 10:44:03 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { } ,
call_type = " " ,
)
pytest . fail ( f " Expected call to fail " )
except Exception as e :
assert e . status_code == 429
2024-01-19 04:42:14 +08:00
@pytest.mark.asyncio
2024-11-06 01:19:38 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 1 )
2024-01-19 04:42:14 +08:00
async def test_success_call_hook ( ) :
"""
Test if on success , cache correctly decremented
"""
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( " sk-12345 " )
2024-01-19 04:42:14 +08:00
user_api_key_dict = UserAPIKeyAuth ( api_key = _api_key , max_parallel_requests = 1 )
local_cache = DualCache ( )
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-01-19 04:42:14 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
2024-01-19 05:52:15 +08:00
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 04:42:14 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 1
)
kwargs = { " litellm_params " : { " metadata " : { " user_api_key " : _api_key } } }
await parallel_request_handler . async_log_success_event (
kwargs = kwargs , response_obj = " " , start_time = " " , end_time = " "
)
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 0
)
@pytest.mark.asyncio
async def test_failure_call_hook ( ) :
"""
Test if on failure , cache correctly decremented
"""
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( _api_key )
2024-01-19 04:42:14 +08:00
user_api_key_dict = UserAPIKeyAuth ( api_key = _api_key , max_parallel_requests = 1 )
local_cache = DualCache ( )
2024-06-14 08:13:44 +08:00
parallel_request_handler = MaxParallelRequestsHandler (
2024-09-26 01:57:08 +08:00
internal_usage_cache = InternalUsageCache ( dual_cache = local_cache )
2024-06-14 08:13:44 +08:00
)
2024-01-19 04:42:14 +08:00
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
2024-01-19 05:52:15 +08:00
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 04:42:14 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 1
)
kwargs = {
" litellm_params " : { " metadata " : { " user_api_key " : _api_key } } ,
" exception " : Exception ( ) ,
}
await parallel_request_handler . async_log_failure_event (
kwargs = kwargs , response_obj = " " , start_time = " " , end_time = " "
)
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 0
)
"""
Test with Router
- normal call
- streaming call
- bad call
"""
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-01-19 04:42:14 +08:00
@pytest.mark.asyncio
async def test_normal_router_call ( ) :
model_list = [
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-turbo " ,
" api_key " : " os.environ/AZURE_FRANCE_API_KEY " ,
" api_base " : " https://openai-france-1234.openai.azure.com " ,
" rpm " : 1440 ,
} ,
" model_info " : { " id " : 1 } ,
} ,
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-35-turbo " ,
" api_key " : " os.environ/AZURE_EUROPE_API_KEY " ,
" api_base " : " https://my-endpoint-europe-berri-992.openai.azure.com " ,
" rpm " : 6 ,
} ,
" model_info " : { " id " : 2 } ,
} ,
]
router = Router (
model_list = model_list ,
set_verbose = False ,
num_retries = 3 ,
) # type: ignore
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( _api_key )
2024-01-19 04:42:14 +08:00
user_api_key_dict = UserAPIKeyAuth ( api_key = _api_key , max_parallel_requests = 1 )
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
2024-01-19 05:52:15 +08:00
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 04:42:14 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 1
)
# normal call
response = await router . acompletion (
model = " azure-model " ,
messages = [ { " role " : " user " , " content " : " Hey, how ' s it going? " } ] ,
metadata = { " user_api_key " : _api_key } ,
2024-02-09 13:45:24 +08:00
mock_response = " hello " ,
2024-01-19 04:42:14 +08:00
)
await asyncio . sleep ( 1 ) # success is done in a separate thread
print ( f " response: { response } " )
2024-01-19 05:52:15 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
== 0
)
2024-01-19 04:42:14 +08:00
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-01-19 07:25:29 +08:00
@pytest.mark.asyncio
async def test_normal_router_tpm_limit ( ) :
2024-02-07 04:44:30 +08:00
import logging
2024-07-14 08:15:20 +08:00
from litellm . _logging import verbose_proxy_logger
2024-02-07 04:44:30 +08:00
verbose_proxy_logger . setLevel ( level = logging . DEBUG )
2024-01-19 07:25:29 +08:00
model_list = [
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-turbo " ,
" api_key " : " os.environ/AZURE_FRANCE_API_KEY " ,
" api_base " : " https://openai-france-1234.openai.azure.com " ,
" rpm " : 1440 ,
} ,
" model_info " : { " id " : 1 } ,
} ,
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-35-turbo " ,
" api_key " : " os.environ/AZURE_EUROPE_API_KEY " ,
" api_base " : " https://my-endpoint-europe-berri-992.openai.azure.com " ,
" rpm " : 6 ,
} ,
" model_info " : { " id " : 2 } ,
} ,
]
router = Router (
model_list = model_list ,
set_verbose = False ,
num_retries = 3 ,
) # type: ignore
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( " sk-12345 " )
2024-01-19 07:25:29 +08:00
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key , max_parallel_requests = 10 , tpm_limit = 10
)
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-02-07 04:44:30 +08:00
print ( " Test: Checking current_requests for precise_minute= " , precise_minute )
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 07:25:29 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 07:25:29 +08:00
key = request_count_api_key
) [ " current_requests " ]
== 1
)
# normal call
response = await router . acompletion (
model = " azure-model " ,
messages = [ { " role " : " user " , " content " : " Write me a paragraph on the moon " } ] ,
metadata = { " user_api_key " : _api_key } ,
2024-02-07 04:44:30 +08:00
mock_response = " hello " ,
2024-01-19 07:25:29 +08:00
)
await asyncio . sleep ( 1 ) # success is done in a separate thread
print ( f " response: { response } " )
try :
2024-02-04 12:59:07 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-02-04 12:59:07 +08:00
key = request_count_api_key
) [ " current_tpm " ]
> 0
2024-01-19 07:25:29 +08:00
)
except Exception as e :
2024-02-06 22:46:49 +08:00
print ( " Exception on test_normal_router_tpm_limit " , e )
2024-01-19 07:25:29 +08:00
assert e . status_code == 429
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-01-19 04:42:14 +08:00
@pytest.mark.asyncio
async def test_streaming_router_call ( ) :
model_list = [
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-turbo " ,
" api_key " : " os.environ/AZURE_FRANCE_API_KEY " ,
" api_base " : " https://openai-france-1234.openai.azure.com " ,
" rpm " : 1440 ,
} ,
" model_info " : { " id " : 1 } ,
} ,
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-35-turbo " ,
" api_key " : " os.environ/AZURE_EUROPE_API_KEY " ,
" api_base " : " https://my-endpoint-europe-berri-992.openai.azure.com " ,
" rpm " : 6 ,
} ,
" model_info " : { " id " : 2 } ,
} ,
]
router = Router (
model_list = model_list ,
set_verbose = False ,
num_retries = 3 ,
) # type: ignore
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( " sk-12345 " )
2024-01-19 04:42:14 +08:00
user_api_key_dict = UserAPIKeyAuth ( api_key = _api_key , max_parallel_requests = 1 )
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
2024-01-19 05:52:15 +08:00
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 04:42:14 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 1
)
# streaming call
response = await router . acompletion (
model = " azure-model " ,
messages = [ { " role " : " user " , " content " : " Hey, how ' s it going? " } ] ,
stream = True ,
metadata = { " user_api_key " : _api_key } ,
2024-02-09 13:45:24 +08:00
mock_response = " hello " ,
2024-01-19 04:42:14 +08:00
)
async for chunk in response :
continue
await asyncio . sleep ( 1 ) # success is done in a separate thread
2024-01-19 05:52:15 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
== 0
2024-01-19 04:42:14 +08:00
)
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-01-19 07:25:29 +08:00
@pytest.mark.asyncio
async def test_streaming_router_tpm_limit ( ) :
2024-01-31 05:26:17 +08:00
litellm . set_verbose = True
2024-01-19 07:25:29 +08:00
model_list = [
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-turbo " ,
" api_key " : " os.environ/AZURE_FRANCE_API_KEY " ,
" api_base " : " https://openai-france-1234.openai.azure.com " ,
" rpm " : 1440 ,
} ,
" model_info " : { " id " : 1 } ,
} ,
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-35-turbo " ,
" api_key " : " os.environ/AZURE_EUROPE_API_KEY " ,
" api_base " : " https://my-endpoint-europe-berri-992.openai.azure.com " ,
" rpm " : 6 ,
} ,
" model_info " : { " id " : 2 } ,
} ,
]
router = Router (
model_list = model_list ,
set_verbose = False ,
num_retries = 3 ,
) # type: ignore
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( " sk-12345 " )
2024-01-19 07:25:29 +08:00
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key , max_parallel_requests = 10 , tpm_limit = 10
)
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 07:25:29 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 07:25:29 +08:00
key = request_count_api_key
) [ " current_requests " ]
== 1
)
# normal call
response = await router . acompletion (
model = " azure-model " ,
messages = [ { " role " : " user " , " content " : " Write me a paragraph on the moon " } ] ,
stream = True ,
metadata = { " user_api_key " : _api_key } ,
2024-02-09 13:45:24 +08:00
mock_response = " hello " ,
2024-01-19 07:25:29 +08:00
)
async for chunk in response :
continue
2024-01-31 05:26:17 +08:00
await asyncio . sleep ( 5 ) # success is done in a separate thread
2024-01-19 07:25:29 +08:00
2024-02-04 12:39:21 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-02-04 12:39:21 +08:00
key = request_count_api_key
) [ " current_tpm " ]
> 0
)
2024-01-19 07:25:29 +08:00
2024-01-19 04:42:14 +08:00
@pytest.mark.asyncio
2024-08-28 13:47:11 +08:00
@pytest.mark.flaky ( retries = 3 , delay = 1 )
2024-01-19 04:42:14 +08:00
async def test_bad_router_call ( ) :
2024-03-07 11:21:57 +08:00
litellm . set_verbose = True
2024-01-19 04:42:14 +08:00
model_list = [
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-turbo " ,
" api_key " : " os.environ/AZURE_FRANCE_API_KEY " ,
" api_base " : " https://openai-france-1234.openai.azure.com " ,
" rpm " : 1440 ,
} ,
" model_info " : { " id " : 1 } ,
} ,
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-35-turbo " ,
" api_key " : " os.environ/AZURE_EUROPE_API_KEY " ,
" api_base " : " https://my-endpoint-europe-berri-992.openai.azure.com " ,
" rpm " : 6 ,
} ,
" model_info " : { " id " : 2 } ,
} ,
]
router = Router (
model_list = model_list ,
set_verbose = False ,
num_retries = 3 ,
) # type: ignore
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( _api_key )
2024-01-19 04:42:14 +08:00
user_api_key_dict = UserAPIKeyAuth ( api_key = _api_key , max_parallel_requests = 1 )
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
2024-01-19 05:52:15 +08:00
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 04:42:14 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache ( # type: ignore
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
2024-01-19 04:42:14 +08:00
== 1
)
# bad streaming call
try :
response = await router . acompletion (
model = " azure-model " ,
messages = [ { " role " : " user2 " , " content " : " Hey, how ' s it going? " } ] ,
stream = True ,
metadata = { " user_api_key " : _api_key } ,
)
2024-10-02 07:44:20 +08:00
except Exception :
2024-01-19 04:42:14 +08:00
pass
2024-01-19 05:52:15 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache ( # type: ignore
2024-01-19 05:52:15 +08:00
key = request_count_api_key
) [ " current_requests " ]
== 0
2024-01-19 04:42:14 +08:00
)
2024-01-19 07:25:29 +08:00
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-01-19 07:25:29 +08:00
@pytest.mark.asyncio
async def test_bad_router_tpm_limit ( ) :
model_list = [
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-turbo " ,
" api_key " : " os.environ/AZURE_FRANCE_API_KEY " ,
" api_base " : " https://openai-france-1234.openai.azure.com " ,
" rpm " : 1440 ,
} ,
" model_info " : { " id " : 1 } ,
} ,
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-35-turbo " ,
" api_key " : " os.environ/AZURE_EUROPE_API_KEY " ,
" api_base " : " https://my-endpoint-europe-berri-992.openai.azure.com " ,
" rpm " : 6 ,
} ,
" model_info " : { " id " : 2 } ,
} ,
]
router = Router (
model_list = model_list ,
set_verbose = False ,
num_retries = 3 ,
) # type: ignore
_api_key = " sk-12345 "
2024-04-18 08:31:39 +08:00
_api_key = hash_token ( _api_key )
2024-01-19 07:25:29 +08:00
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key , max_parallel_requests = 10 , tpm_limit = 10
)
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-01-19 07:25:29 +08:00
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 07:25:29 +08:00
key = request_count_api_key
) [ " current_requests " ]
== 1
)
# bad call
try :
response = await router . acompletion (
model = " azure-model " ,
messages = [ { " role " : " user2 " , " content " : " Write me a paragraph on the moon " } ] ,
stream = True ,
metadata = { " user_api_key " : _api_key } ,
)
2024-10-02 07:44:20 +08:00
except Exception :
2024-01-19 07:25:29 +08:00
pass
await asyncio . sleep ( 1 ) # success is done in a separate thread
assert (
2024-06-14 08:13:44 +08:00
parallel_request_handler . internal_usage_cache . get_cache (
2024-01-19 07:25:29 +08:00
key = request_count_api_key
) [ " current_tpm " ]
== 0
)
2024-08-17 09:28:58 +08:00
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-08-17 09:28:58 +08:00
@pytest.mark.asyncio
async def test_bad_router_tpm_limit_per_model ( ) :
model_list = [
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-turbo " ,
" api_key " : " os.environ/AZURE_FRANCE_API_KEY " ,
" api_base " : " https://openai-france-1234.openai.azure.com " ,
" rpm " : 1440 ,
} ,
" model_info " : { " id " : 1 } ,
} ,
{
" model_name " : " azure-model " ,
" litellm_params " : {
" model " : " azure/gpt-35-turbo " ,
" api_key " : " os.environ/AZURE_EUROPE_API_KEY " ,
" api_base " : " https://my-endpoint-europe-berri-992.openai.azure.com " ,
" rpm " : 6 ,
} ,
" model_info " : { " id " : 2 } ,
} ,
]
router = Router (
model_list = model_list ,
set_verbose = False ,
num_retries = 3 ,
) # type: ignore
_api_key = " sk-12345 "
_api_key = hash_token ( _api_key )
model = " azure-model "
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key ,
max_parallel_requests = 10 ,
tpm_limit = 10 ,
2024-08-18 05:14:12 +08:00
metadata = {
" model_rpm_limit " : { model : 5 } ,
" model_tpm_limit " : { model : 5 } ,
} ,
2024-08-17 09:28:58 +08:00
)
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { " model " : model } ,
call_type = " " ,
)
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { model } :: { precise_minute } ::request_count "
2024-11-04 10:18:20 +08:00
await asyncio . sleep ( 1 )
2024-08-17 09:28:58 +08:00
print (
" internal usage cache: " ,
2024-09-26 01:57:08 +08:00
parallel_request_handler . internal_usage_cache . dual_cache . in_memory_cache . cache_dict ,
2024-08-17 09:28:58 +08:00
)
assert (
parallel_request_handler . internal_usage_cache . get_cache (
key = request_count_api_key
) [ " current_requests " ]
== 1
)
# bad call
try :
response = await router . acompletion (
model = model ,
messages = [ { " role " : " user2 " , " content " : " Write me a paragraph on the moon " } ] ,
stream = True ,
2024-08-19 00:57:31 +08:00
metadata = {
" user_api_key " : _api_key ,
" user_api_key_metadata " : {
" model_rpm_limit " : { model : 5 } ,
" model_tpm_limit " : { model : 5 } ,
} ,
} ,
2024-08-17 09:28:58 +08:00
)
2024-10-02 07:44:20 +08:00
except Exception :
2024-08-17 09:28:58 +08:00
pass
await asyncio . sleep ( 1 ) # success is done in a separate thread
assert (
parallel_request_handler . internal_usage_cache . get_cache (
key = request_count_api_key
) [ " current_tpm " ]
== 0
)
2024-08-18 00:16:01 +08:00
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-08-18 00:16:01 +08:00
@pytest.mark.asyncio
async def test_pre_call_hook_rpm_limits_per_model ( ) :
"""
Test if error raised on hitting rpm limits for a given model
"""
import logging
from litellm . _logging import (
verbose_logger ,
verbose_proxy_logger ,
verbose_router_logger ,
)
verbose_logger . setLevel ( logging . DEBUG )
verbose_proxy_logger . setLevel ( logging . DEBUG )
verbose_router_logger . setLevel ( logging . DEBUG )
_api_key = " sk-12345 "
_api_key = hash_token ( _api_key )
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key ,
max_parallel_requests = 100 ,
tpm_limit = 900000 ,
rpm_limit = 100000 ,
2024-08-18 05:14:12 +08:00
metadata = {
" model_rpm_limit " : { " azure-model " : 1 } ,
} ,
2024-08-18 00:16:01 +08:00
)
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict , cache = local_cache , data = { } , call_type = " "
)
model = " azure-model "
kwargs = {
" model " : model ,
2024-08-18 05:21:59 +08:00
" litellm_params " : {
2024-08-19 00:57:31 +08:00
" metadata " : {
" user_api_key " : _api_key ,
" model_group " : model ,
" user_api_key_metadata " : { " model_rpm_limit " : { " azure-model " : 1 } } ,
} ,
2024-08-18 05:21:59 +08:00
} ,
2024-08-18 00:16:01 +08:00
}
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = " " ,
start_time = " " ,
end_time = " " ,
)
## Expected cache val: {"current_requests": 0, "current_tpm": 0, "current_rpm": 1}
try :
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { " model " : model } ,
call_type = " " ,
)
pytest . fail ( f " Expected call to fail " )
except Exception as e :
assert e . status_code == 429
print ( " got error= " , e )
assert (
2024-12-13 12:13:14 +08:00
" limit reached Hit RPM limit for model: azure-model on LiteLLM Virtual Key user_api_key_hash: c11e7177eb60c80cf983ddf8ca98f2dc1272d4c612204ce9bedd2460b18939cc "
2024-08-18 00:16:01 +08:00
in str ( e )
)
2025-01-30 13:09:07 +08:00
@pytest.mark.flaky ( retries = 6 , delay = 2 )
2024-08-18 00:16:01 +08:00
@pytest.mark.asyncio
async def test_pre_call_hook_tpm_limits_per_model ( ) :
"""
Test if error raised on hitting tpm limits for a given model
"""
import logging
from litellm . _logging import (
verbose_logger ,
verbose_proxy_logger ,
verbose_router_logger ,
)
verbose_logger . setLevel ( logging . DEBUG )
verbose_proxy_logger . setLevel ( logging . DEBUG )
verbose_router_logger . setLevel ( logging . DEBUG )
_api_key = " sk-12345 "
_api_key = hash_token ( _api_key )
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key ,
max_parallel_requests = 100 ,
tpm_limit = 900000 ,
rpm_limit = 100000 ,
2024-08-18 05:14:12 +08:00
metadata = {
" model_tpm_limit " : { " azure-model " : 1 } ,
" model_rpm_limit " : { " azure-model " : 100 } ,
} ,
2024-08-18 00:16:01 +08:00
)
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
model = " azure-model "
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { " model " : model } ,
call_type = " " ,
)
kwargs = {
" model " : model ,
2024-08-18 05:21:59 +08:00
" litellm_params " : {
2024-08-19 00:57:31 +08:00
" metadata " : {
" user_api_key " : _api_key ,
" model_group " : model ,
" user_api_key_metadata " : {
" model_tpm_limit " : { " azure-model " : 1 } ,
" model_rpm_limit " : { " azure-model " : 100 } ,
} ,
}
2024-08-18 05:21:59 +08:00
} ,
2024-08-18 00:16:01 +08:00
}
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = litellm . ModelResponse ( usage = litellm . Usage ( total_tokens = 11 ) ) ,
start_time = " " ,
end_time = " " ,
)
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { model } :: { precise_minute } ::request_count "
print (
" internal usage cache: " ,
2024-09-26 01:57:08 +08:00
parallel_request_handler . internal_usage_cache . dual_cache . in_memory_cache . cache_dict ,
2024-08-18 00:16:01 +08:00
)
assert (
parallel_request_handler . internal_usage_cache . get_cache (
key = request_count_api_key
) [ " current_tpm " ]
== 11
)
assert (
parallel_request_handler . internal_usage_cache . get_cache (
key = request_count_api_key
) [ " current_rpm " ]
== 1
)
## Expected cache val: {"current_requests": 0, "current_tpm": 11, "current_rpm": "1"}
try :
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { " model " : model } ,
call_type = " " ,
)
pytest . fail ( f " Expected call to fail " )
except Exception as e :
assert e . status_code == 429
print ( " got error= " , e )
assert (
2024-12-13 12:13:14 +08:00
" request limit reached Hit TPM limit for model: azure-model on LiteLLM Virtual Key user_api_key_hash "
2024-08-18 00:16:01 +08:00
in str ( e )
)
2024-09-29 06:56:12 +08:00
@pytest.mark.asyncio
@pytest.mark.flaky ( retries = 6 , delay = 1 )
async def test_post_call_success_hook_rpm_limits_per_model ( ) :
"""
Test if openai - compatible x - ratelimit - * headers are added to the response
"""
import logging
from litellm import ModelResponse
from litellm . _logging import (
verbose_logger ,
verbose_proxy_logger ,
verbose_router_logger ,
)
verbose_logger . setLevel ( logging . DEBUG )
verbose_proxy_logger . setLevel ( logging . DEBUG )
verbose_router_logger . setLevel ( logging . DEBUG )
_api_key = " sk-12345 "
_api_key = hash_token ( _api_key )
user_api_key_dict = UserAPIKeyAuth (
api_key = _api_key ,
max_parallel_requests = 100 ,
tpm_limit = 900000 ,
rpm_limit = 100000 ,
metadata = {
" model_tpm_limit " : { " azure-model " : 1 } ,
" model_rpm_limit " : { " azure-model " : 100 } ,
} ,
)
local_cache = DualCache ( )
pl = ProxyLogging ( user_api_key_cache = local_cache )
pl . _init_litellm_callbacks ( )
print ( f " litellm callbacks: { litellm . callbacks } " )
parallel_request_handler = pl . max_parallel_request_limiter
model = " azure-model "
await parallel_request_handler . async_pre_call_hook (
user_api_key_dict = user_api_key_dict ,
cache = local_cache ,
data = { " model " : model } ,
call_type = " " ,
)
kwargs = {
" model " : model ,
" litellm_params " : {
" metadata " : {
" user_api_key " : _api_key ,
" model_group " : model ,
" user_api_key_metadata " : {
" model_tpm_limit " : { " azure-model " : 1 } ,
" model_rpm_limit " : { " azure-model " : 100 } ,
} ,
}
} ,
}
await parallel_request_handler . async_log_success_event (
kwargs = kwargs ,
response_obj = litellm . ModelResponse ( usage = litellm . Usage ( total_tokens = 11 ) ) ,
start_time = " " ,
end_time = " " ,
)
current_date = datetime . now ( ) . strftime ( " % Y- % m- %d " )
current_hour = datetime . now ( ) . strftime ( " % H " )
current_minute = datetime . now ( ) . strftime ( " % M " )
precise_minute = f " { current_date } - { current_hour } - { current_minute } "
request_count_api_key = f " { _api_key } :: { model } :: { precise_minute } ::request_count "
print ( f " request_count_api_key: { request_count_api_key } " )
current_cache = parallel_request_handler . internal_usage_cache . get_cache (
key = request_count_api_key
)
print ( " current cache: " , current_cache )
response = ModelResponse ( )
await parallel_request_handler . async_post_call_success_hook (
data = { } , user_api_key_dict = user_api_key_dict , response = response
)
hidden_params = getattr ( response , " _hidden_params " , { } ) or { }
print ( hidden_params )
assert " additional_headers " in hidden_params
assert " x-ratelimit-limit-requests " in hidden_params [ " additional_headers " ]
assert " x-ratelimit-remaining-requests " in hidden_params [ " additional_headers " ]
assert " x-ratelimit-limit-tokens " in hidden_params [ " additional_headers " ]
assert " x-ratelimit-remaining-tokens " in hidden_params [ " additional_headers " ]