mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-17 00:17:16 +00:00
113 lines
3.6 KiB
Python
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
|