fix(fallback_utils): handle dictionary fallback configurations correctly in async_completion_with_fallbacks

This commit is contained in:
lorenzbaraldi 2026-05-19 13:58:32 +02:00
parent cff3e0b75e
commit f19c7ec14b
2 changed files with 46 additions and 2 deletions

View file

@ -47,8 +47,9 @@ async def async_completion_with_fallbacks(**kwargs):
completion_kwargs = safe_deep_copy(base_kwargs)
# Handle dictionary fallback configurations
if isinstance(fallback, dict):
model = fallback.pop("model", original_model)
completion_kwargs.update(fallback)
fallback_config = safe_deep_copy(dict(fallback))
model = fallback_config.pop("model", original_model)
completion_kwargs.update(fallback_config)
else:
model = fallback

View file

@ -0,0 +1,43 @@
import pytest
import litellm
from litellm.litellm_core_utils.fallback_utils import async_completion_with_fallbacks
@pytest.mark.asyncio
async def test_fallback_dict_not_mutated(monkeypatch):
fallback_dict = {"model": "fallback-model", "temperature": 0.2}
original_fallback_dict = dict(fallback_dict)
attempted_models: list[str] = []
async def _fake_acompletion(*, model: str, **kwargs):
attempted_models.append(model)
if model == "primary-model":
raise Exception("primary failed")
return {"model": model, "temperature": kwargs.get("temperature")}
monkeypatch.setattr(litellm, "acompletion", _fake_acompletion)
# Call 1: primary fails, fallback dict succeeds
response_1 = await async_completion_with_fallbacks(
model="primary-model",
kwargs={"fallbacks": [fallback_dict]},
)
assert response_1["model"] == "fallback-model"
assert fallback_dict == original_fallback_dict
# Call 2: re-use the same dict object; it should still work and remain unchanged
response_2 = await async_completion_with_fallbacks(
model="primary-model",
kwargs={"fallbacks": [fallback_dict]},
)
assert response_2["model"] == "fallback-model"
assert fallback_dict == original_fallback_dict
assert attempted_models == [
"primary-model",
"fallback-model",
"primary-model",
"fallback-model",
]