From 5247d7b6a5de50df28a5e091c111d4d45e4d2023 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Mon, 29 Apr 2024 15:51:01 -0700 Subject: [PATCH 1/3] test - lowest latency router --- litellm/tests/test_lowest_latency_routing.py | 76 ++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/litellm/tests/test_lowest_latency_routing.py b/litellm/tests/test_lowest_latency_routing.py index 4b93853f41..24e6bb4c5d 100644 --- a/litellm/tests/test_lowest_latency_routing.py +++ b/litellm/tests/test_lowest_latency_routing.py @@ -555,3 +555,79 @@ async def test_lowest_latency_routing_with_timeouts(): # ALL the Requests should have been routed to the fast-endpoint assert deployments["fast-endpoint"] == 10 + + +@pytest.mark.asyncio +async def test_lowest_latency_routing_first_pick(): + """ + PROD Test: + - When all deployments are latency=0, it should randomly pick a deployment + - IT SHOULD NEVER PICK THE Very First deployment everytime all deployment latencies are 0 + - This ensures that after the ttl window resets it randomly picks a deployment + """ + import litellm + + litellm.set_verbose = True + + router = Router( + model_list=[ + { + "model_name": "azure-model", + "litellm_params": { + "model": "openai/fast-endpoint", + "api_base": "https://exampleopenaiendpoint-production.up.railway.app/", + "api_key": "fake-key", + }, + "model_info": {"id": "fast-endpoint"}, + }, + { + "model_name": "azure-model", + "litellm_params": { + "model": "openai/fast-endpoint-2", + "api_base": "https://exampleopenaiendpoint-production.up.railway.app/", + "api_key": "fake-key", + }, + "model_info": {"id": "fast-endpoint-2"}, + }, + { + "model_name": "azure-model", + "litellm_params": { + "model": "openai/fast-endpoint-2", + "api_base": "https://exampleopenaiendpoint-production.up.railway.app/", + "api_key": "fake-key", + }, + "model_info": {"id": "fast-endpoint-3"}, + }, + { + "model_name": "azure-model", + "litellm_params": { + "model": "openai/fast-endpoint-2", + "api_base": "https://exampleopenaiendpoint-production.up.railway.app/", + "api_key": "fake-key", + }, + "model_info": {"id": "fast-endpoint-4"}, + }, + ], + routing_strategy="latency-based-routing", + routing_strategy_args={"ttl": 0.0000000001}, + set_verbose=True, + debug_level="DEBUG", + ) # type: ignore + + deployments = {} + for _ in range(5): + response = await router.acompletion( + model="azure-model", messages=[{"role": "user", "content": "hello"}] + ) + print(response) + _picked_model_id = response._hidden_params["model_id"] + if _picked_model_id not in deployments: + deployments[_picked_model_id] = 1 + else: + deployments[_picked_model_id] += 1 + await asyncio.sleep(0.000000000005) + + print("deployments", deployments) + + # assert that len(deployments) >1 + assert len(deployments) > 1 From 3b0aa0537854dbb53dffe402569b4fe3722ce42c Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Mon, 29 Apr 2024 15:51:52 -0700 Subject: [PATCH 2/3] fix lowest latency - routing --- litellm/router_strategy/lowest_latency.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/litellm/router_strategy/lowest_latency.py b/litellm/router_strategy/lowest_latency.py index 19780f708d..cd5cea2e94 100644 --- a/litellm/router_strategy/lowest_latency.py +++ b/litellm/router_strategy/lowest_latency.py @@ -312,6 +312,8 @@ class LowestLatencyLoggingHandler(CustomLogger): except: input_tokens = 0 + all_deployments = random.sample(all_deployments.items(), len(all_deployments)) + all_deployments = dict(all_deployments) for item, item_map in all_deployments.items(): ## get the item from model list _deployment = None From 4cb4a7f06def393849f88d90d42adc02ed09ff61 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Mon, 29 Apr 2024 16:02:57 -0700 Subject: [PATCH 3/3] fix - lowest latency routing --- litellm/router_strategy/lowest_latency.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/litellm/router_strategy/lowest_latency.py b/litellm/router_strategy/lowest_latency.py index cd5cea2e94..eecf5578ce 100644 --- a/litellm/router_strategy/lowest_latency.py +++ b/litellm/router_strategy/lowest_latency.py @@ -312,7 +312,9 @@ class LowestLatencyLoggingHandler(CustomLogger): except: input_tokens = 0 - all_deployments = random.sample(all_deployments.items(), len(all_deployments)) + # randomly sample from all_deployments, incase all deployments have latency=0.0 + _items = all_deployments.items() + all_deployments = random.sample(list(_items), len(_items)) all_deployments = dict(all_deployments) for item, item_map in all_deployments.items(): ## get the item from model list