mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-02 06:22:48 +00:00
Revert "Merge pull request #18790 from BerriAI/litellm_key_team_routing_3"
This reverts commitae26d8e68a, reversing changes made to864e8c6543.
This commit is contained in:
@@ -2155,10 +2155,6 @@ class LiteLLM_VerificationToken(LiteLLMPydanticObjectBase):
|
||||
rotation_interval: Optional[str] = None # How often to rotate (e.g., "30d", "90d")
|
||||
last_rotation_at: Optional[datetime] = None # When this key was last rotated
|
||||
key_rotation_at: Optional[datetime] = None # When this key should next be rotated
|
||||
router_settings: Optional[
|
||||
Dict
|
||||
] = None # Router settings for this key (Key > Team > Global precedence)
|
||||
|
||||
model_config = ConfigDict(protected_namespaces=())
|
||||
|
||||
|
||||
|
||||
@@ -616,26 +616,6 @@ class ProxyBaseLLMRequestProcessing:
|
||||
user_api_key_dict=user_api_key_dict, data=self.data, call_type=route_type # type: ignore
|
||||
)
|
||||
|
||||
# Apply hierarchical router_settings (Key > Team > Global)
|
||||
if llm_router is not None and proxy_config is not None:
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
|
||||
router_settings = await proxy_config._get_hierarchical_router_settings(
|
||||
user_api_key_dict=user_api_key_dict,
|
||||
prisma_client=prisma_client,
|
||||
)
|
||||
|
||||
# If router_settings found (from key, team, or global), apply them
|
||||
# This ensures key/team settings override global settings
|
||||
if router_settings is not None and router_settings:
|
||||
# Get model_list from current router
|
||||
model_list = llm_router.get_model_list()
|
||||
if model_list is not None:
|
||||
# Create user_config with model_list and router_settings
|
||||
# This creates a per-request router with the hierarchical settings
|
||||
user_config = {"model_list": model_list, **router_settings}
|
||||
self.data["user_config"] = user_config
|
||||
|
||||
if "messages" in self.data and self.data["messages"]:
|
||||
logging_obj.update_messages(self.data["messages"])
|
||||
|
||||
|
||||
@@ -3380,105 +3380,6 @@ class ProxyConfig:
|
||||
decrypted_variables[k] = decrypted_value
|
||||
return decrypted_variables
|
||||
|
||||
async def _get_hierarchical_router_settings(
|
||||
self,
|
||||
user_api_key_dict: Optional["UserAPIKeyAuth"],
|
||||
prisma_client: Optional[PrismaClient],
|
||||
) -> Optional[dict]:
|
||||
"""
|
||||
Get router_settings in priority order: Key > Team > Global
|
||||
|
||||
Returns:
|
||||
dict: Combined router_settings, or None if no settings found
|
||||
"""
|
||||
if prisma_client is None:
|
||||
return None
|
||||
|
||||
import json
|
||||
|
||||
import yaml
|
||||
|
||||
# 1. Try key-level router_settings
|
||||
if user_api_key_dict is not None:
|
||||
# Check if router_settings is available on the key object
|
||||
key_router_settings_value = getattr(
|
||||
user_api_key_dict, "router_settings", None
|
||||
)
|
||||
if key_router_settings_value is not None:
|
||||
key_router_settings = None
|
||||
if isinstance(key_router_settings_value, str):
|
||||
try:
|
||||
key_router_settings = yaml.safe_load(key_router_settings_value)
|
||||
except (yaml.YAMLError, json.JSONDecodeError):
|
||||
try:
|
||||
key_router_settings = json.loads(key_router_settings_value)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
elif isinstance(key_router_settings_value, dict):
|
||||
key_router_settings = key_router_settings_value
|
||||
|
||||
# If key has router_settings (non-empty dict), use it
|
||||
if (
|
||||
key_router_settings is not None
|
||||
and isinstance(key_router_settings, dict)
|
||||
and key_router_settings
|
||||
):
|
||||
return key_router_settings
|
||||
|
||||
# 2. Try team-level router_settings
|
||||
if user_api_key_dict is not None and user_api_key_dict.team_id is not None:
|
||||
try:
|
||||
team_obj = await prisma_client.db.litellm_teamtable.find_unique(
|
||||
where={"team_id": user_api_key_dict.team_id}
|
||||
)
|
||||
if team_obj is not None:
|
||||
team_router_settings_value = getattr(
|
||||
team_obj, "router_settings", None
|
||||
)
|
||||
if team_router_settings_value is not None:
|
||||
team_router_settings = None
|
||||
if isinstance(team_router_settings_value, str):
|
||||
try:
|
||||
team_router_settings = yaml.safe_load(
|
||||
team_router_settings_value
|
||||
)
|
||||
except (yaml.YAMLError, json.JSONDecodeError):
|
||||
try:
|
||||
team_router_settings = json.loads(
|
||||
team_router_settings_value
|
||||
)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
elif isinstance(team_router_settings_value, dict):
|
||||
team_router_settings = team_router_settings_value
|
||||
|
||||
# If team has router_settings (non-empty dict), use it
|
||||
if (
|
||||
team_router_settings is not None
|
||||
and isinstance(team_router_settings, dict)
|
||||
and team_router_settings
|
||||
):
|
||||
return team_router_settings
|
||||
except Exception:
|
||||
# If team lookup fails, continue to global settings
|
||||
pass
|
||||
|
||||
# 3. Try global router_settings
|
||||
try:
|
||||
db_router_settings = await prisma_client.db.litellm_config.find_first(
|
||||
where={"param_name": "router_settings"}
|
||||
)
|
||||
if (
|
||||
db_router_settings is not None
|
||||
and isinstance(db_router_settings.param_value, dict)
|
||||
and db_router_settings.param_value
|
||||
):
|
||||
return db_router_settings.param_value
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
async def _add_router_settings_from_db_config(
|
||||
self,
|
||||
config_data: dict,
|
||||
|
||||
@@ -77,84 +77,6 @@ class TestProxyBaseLLMRequestProcessing:
|
||||
pytest.fail("litellm_call_id is not a valid UUID")
|
||||
assert data_passed["litellm_call_id"] == returned_data["litellm_call_id"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_should_apply_hierarchical_router_settings_to_user_config(
|
||||
self, monkeypatch
|
||||
):
|
||||
processing_obj = ProxyBaseLLMRequestProcessing(data={})
|
||||
mock_request = MagicMock(spec=Request)
|
||||
mock_request.headers = {}
|
||||
|
||||
async def mock_add_litellm_data_to_request(*args, **kwargs):
|
||||
return {}
|
||||
|
||||
async def mock_common_processing_pre_call_logic(
|
||||
user_api_key_dict, data, call_type
|
||||
):
|
||||
data_copy = copy.deepcopy(data)
|
||||
return data_copy
|
||||
|
||||
mock_proxy_logging_obj = MagicMock(spec=ProxyLogging)
|
||||
mock_proxy_logging_obj.pre_call_hook = AsyncMock(
|
||||
side_effect=mock_common_processing_pre_call_logic
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
litellm.proxy.common_request_processing,
|
||||
"add_litellm_data_to_request",
|
||||
mock_add_litellm_data_to_request,
|
||||
)
|
||||
|
||||
mock_general_settings = {}
|
||||
mock_user_api_key_dict = MagicMock(spec=UserAPIKeyAuth)
|
||||
mock_proxy_config = MagicMock(spec=ProxyConfig)
|
||||
|
||||
mock_router_settings = {
|
||||
"routing_strategy": "least-busy",
|
||||
"timeout": 30.0,
|
||||
"num_retries": 3,
|
||||
}
|
||||
mock_proxy_config._get_hierarchical_router_settings = AsyncMock(
|
||||
return_value=mock_router_settings
|
||||
)
|
||||
|
||||
mock_model_list = [
|
||||
{"model_name": "gpt-3.5-turbo", "litellm_params": {"model": "gpt-3.5-turbo"}},
|
||||
{"model_name": "gpt-4", "litellm_params": {"model": "gpt-4"}},
|
||||
]
|
||||
mock_llm_router = MagicMock()
|
||||
mock_llm_router.get_model_list = MagicMock(return_value=mock_model_list)
|
||||
|
||||
mock_prisma_client = MagicMock()
|
||||
monkeypatch.setattr(
|
||||
"litellm.proxy.proxy_server.prisma_client",
|
||||
mock_prisma_client,
|
||||
)
|
||||
|
||||
route_type = "acompletion"
|
||||
|
||||
returned_data, logging_obj = await processing_obj.common_processing_pre_call_logic(
|
||||
request=mock_request,
|
||||
general_settings=mock_general_settings,
|
||||
user_api_key_dict=mock_user_api_key_dict,
|
||||
proxy_logging_obj=mock_proxy_logging_obj,
|
||||
proxy_config=mock_proxy_config,
|
||||
route_type=route_type,
|
||||
llm_router=mock_llm_router,
|
||||
)
|
||||
|
||||
mock_proxy_config._get_hierarchical_router_settings.assert_called_once_with(
|
||||
user_api_key_dict=mock_user_api_key_dict,
|
||||
prisma_client=mock_prisma_client,
|
||||
)
|
||||
mock_llm_router.get_model_list.assert_called_once()
|
||||
|
||||
assert "user_config" in returned_data
|
||||
user_config = returned_data["user_config"]
|
||||
assert user_config["model_list"] == mock_model_list
|
||||
assert user_config["routing_strategy"] == "least-busy"
|
||||
assert user_config["timeout"] == 30.0
|
||||
assert user_config["num_retries"] == 3
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_timeout_header_processing(self):
|
||||
"""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user