Files
litellm/tests/router_unit_tests/test_completion_no_copy.py
T

113 lines
3.6 KiB
Python

"""
Regression test for removing unnecessary dict.copy() in completion hot paths.
Verifies that spreading deployment["litellm_params"] directly (without copy)
doesn't cause side effects that mutate the deployment in router.model_list.
"""
import sys
import os
import pytest
sys.path.insert(0, os.path.abspath("../.."))
from litellm import Router
from unittest.mock import AsyncMock, Mock, patch
@pytest.mark.asyncio
async def test_acompletion_deployment_not_mutated():
"""
Test async completion doesn't mutate deployment when .copy() is removed.
Optimization: Remove deployment["litellm_params"].copy() in _acompletion
since data is only read and spread into input_kwargs dict.
"""
router = Router(
model_list=[
{
"model_name": "gpt-3.5",
"litellm_params": {
"model": "gpt-3.5-turbo",
"api_key": "test-key",
"temperature": 0.7,
},
}
]
)
deployment_before = router.get_deployment_by_model_group_name("gpt-3.5")
assert deployment_before is not None
original_params = deployment_before.litellm_params.model_dump()
with patch("litellm.acompletion", new_callable=AsyncMock) as mock_acompletion:
from litellm import ModelResponse
mock_acompletion.return_value = ModelResponse(
id="test",
choices=[{"message": {"role": "assistant", "content": "test"}, "index": 0}],
model="gpt-3.5-turbo",
usage={"prompt_tokens": 10, "completion_tokens": 20, "total_tokens": 30},
)
try:
await router.acompletion(
model="gpt-3.5",
messages=[{"role": "user", "content": "test"}],
)
except Exception:
pass
# Critical: Deployment params must be unchanged
deployment_after = router.get_deployment_by_model_group_name("gpt-3.5")
assert deployment_after is not None
assert deployment_after.litellm_params.model_dump() == original_params
def test_completion_deployment_not_mutated():
"""
Test sync completion doesn't mutate deployment when .copy() is removed.
Optimization: Remove deployment["litellm_params"].copy() in _completion
since data is only read and spread into input_kwargs dict.
"""
router = Router(
model_list=[
{
"model_name": "gpt-3.5",
"litellm_params": {
"model": "gpt-3.5-turbo",
"api_key": "test-key",
"max_tokens": 100,
},
}
]
)
deployment_before = router.get_deployment_by_model_group_name("gpt-3.5")
assert deployment_before is not None
original_params = deployment_before.litellm_params.model_dump()
with patch("litellm.completion", new_callable=Mock) as mock_completion:
from litellm import ModelResponse
mock_completion.return_value = ModelResponse(
id="test",
choices=[{"message": {"role": "assistant", "content": "test"}, "index": 0}],
model="gpt-3.5-turbo",
usage={"prompt_tokens": 10, "completion_tokens": 20, "total_tokens": 30},
)
try:
router.completion(
model="gpt-3.5",
messages=[{"role": "user", "content": "test"}],
)
except Exception:
pass
# Critical: Deployment params must be unchanged
deployment_after = router.get_deployment_by_model_group_name("gpt-3.5")
assert deployment_after is not None
assert deployment_after.litellm_params.model_dump() == original_params