litellm/tests/unit/router_strategy
devin-ai-integration[bot] 49f4a59cc8
fix(router): keep latency routing alive when latency samples are unusable (#48216)
* fix(router): keep latency routing alive when latency samples are unusable

latency-based-routing ranks deployments by the average of the cached samples
and keeps everything within lowest_latency_buffer times the lowest. A negative
or NaN sample breaks that invariant, because the minimum no longer satisfies
its own bound. The candidate list then comes back empty and random.choice
raises IndexError, which turns every request to the group into a 500 until the
cache entry expires.

Samples come from completion_start_time - start_time, and that difference is
negative whenever the two timestamps invert. Production recorded samples
around -600s from successful calls.

Drop non-finite and negative samples before ranking, and fall back to every
candidate if the window is empty anyway, for example with a negative buffer.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: AaronHowell <111272993+AaronHowell@users.noreply.github.com>

* test(router): seed latency_normalized in the unusable TTFT fallback test

Main reads latency_normalized since #47727, so seeding latency left both deployments ranked at zero and the test picked at random.

Co-authored-by: Rick <26716961+Bytechoreographer@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(router): assert ranked latency after dropping unusable TTFT samples

Greptile on #48216: the new tests passed with the sample filter removed because the empty-window fallback alone saved them. They now assert _latency_per_deployment so unfiltered negative or NaN samples fail deterministically. Also adds Final to ttft_samples and drops a comment that restated the code

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(router): drop Final on a loop-local in latency ranking

basedpyright rejects Final on a variable assigned inside a loop, and the type_check_gate counts it as a new reportGeneralTypeIssues error

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(router): type the request kwargs in the unusable TTFT tests

Greptile on #48216: bare dict annotations. The tests now hold the metadata dict in a typed local and assert on it directly

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Rick <26716961+Bytechoreographer@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: AaronHowell <111272993+AaronHowell@users.noreply.github.com>
Co-authored-by: joshua <joshua@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-24 13:43:07 -07:00
..
adaptive_router fix(router): unregister strategy selectors from global callbacks on discard (#45795) 2026-10-21 02:39:36 +00:00
complexity_router feat(decisions): add Laya and Bespoke providers to the Add Model form (#45260) 2026-10-14 08:11:11 -07:00
__init__.py test: add __init__.py to intermediate tests/unit packages 2026-09-20 12:55:27 +00:00
test_auto_router.py feat(otel): trace auto-router configuration and classifier failures (#44926) 2026-10-06 15:40:34 -07:00
test_base_routing_strategy.py fix(router): unregister strategy selectors from global callbacks on discard (#45795) 2026-10-21 02:39:36 +00:00
test_budget_limiter.py fix(batches): retry confirmed pre-accounting failures (#47625) 2026-10-20 14:12:26 -07:00
test_budget_limiter_hotpath.py fix(router): unregister strategy selectors from global callbacks on discard (#45795) 2026-10-21 02:39:36 +00:00
test_complexity_router.py fix(secret_managers)!: resolve oidc/file and oidc/env refs in admin-configured api_key per request (#47341) 2026-10-20 01:43:59 +00:00
test_complexity_tier_predictor.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_fuse_presets.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_lar1_routing.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_least_busy.py test: move routing, caching and callback tests out of local_testing (#45761) 2026-10-10 09:33:09 -07:00
test_litellm_encoder.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_llm_v2.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_lowest_cost.py fix(router): price cost-based routing through model_info.base_model (#47617) 2026-10-20 22:20:16 +00:00
test_lowest_latency.py fix(router): keep latency routing alive when latency samples are unusable (#48216) 2026-10-24 13:43:07 -07:00
test_lowest_tpm_rpm.py test: move routing, caching and callback tests out of local_testing (#45761) 2026-10-10 09:33:09 -07:00
test_lowest_tpm_rpm_v2.py test: migrate legacy unit dirs and unrun folders into tests/unit, tests/integration and tests/e2e (#45940) 2026-10-11 06:24:57 -07:00
test_quality_router.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_router_routing_groups.py fix(router): normalize native Responses latency per output token (#47727) 2026-10-20 22:50:28 -07:00
test_router_routing_plugins.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_router_tag_regex_routing.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_router_tag_routing.py feat(proxy): map baggage values to budget tags (#47358) 2026-10-20 09:09:42 +00:00
test_savings_baseline.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_simple_shuffle.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00
test_stall_detector.py test: move tests/test_litellm core utils, routing, responses, caching and rust_bridge into tests/unit (#43199) 2026-09-25 17:10:13 -07:00