Skip to content

Commit 7225fc0

Browse files
authored
Fix key model alias (#16896)
1 parent e7751f0 commit 7225fc0

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

litellm/proxy/common_request_processing.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,15 @@ async def common_processing_pre_call_logic(
378378
):
379379
self.data["model"] = litellm.model_alias_map[self.data["model"]]
380380

381+
# Check key-specific aliases
382+
if (
383+
isinstance(self.data["model"], str)
384+
and user_api_key_dict.aliases
385+
and isinstance(user_api_key_dict.aliases, dict)
386+
and self.data["model"] in user_api_key_dict.aliases
387+
):
388+
self.data["model"] = user_api_key_dict.aliases[self.data["model"]]
389+
381390
self.data["litellm_call_id"] = request.headers.get(
382391
"x-litellm-call-id", str(uuid.uuid4())
383392
)

litellm/proxy/litellm_pre_call_utils.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,12 @@ async def add_litellm_data_to_request( # noqa: PLR0915
10531053
user_api_key_dict=user_api_key_dict,
10541054
)
10551055

1056+
# Key Model Aliases
1057+
_update_model_if_key_alias_exists(
1058+
data=data,
1059+
user_api_key_dict=user_api_key_dict,
1060+
)
1061+
10561062
verbose_proxy_logger.debug(
10571063
"[PROXY] returned data from litellm_pre_call_utils: %s", data
10581064
)
@@ -1108,6 +1114,33 @@ def _update_model_if_team_alias_exists(
11081114
return
11091115

11101116

1117+
def _update_model_if_key_alias_exists(
1118+
data: dict,
1119+
user_api_key_dict: UserAPIKeyAuth,
1120+
) -> None:
1121+
"""
1122+
Update the model if the key alias exists
1123+
1124+
If an alias map has been set on a key, then we want to make the request with the model the key alias is pointing to
1125+
1126+
eg.
1127+
- user calls `modelAlias`
1128+
- key.aliases = {
1129+
"modelAlias": "xai/grok-4-fast-non-reasoning"
1130+
}
1131+
- requested_model = "xai/grok-4-fast-non-reasoning"
1132+
"""
1133+
_model = data.get("model")
1134+
if (
1135+
_model
1136+
and user_api_key_dict.aliases
1137+
and isinstance(user_api_key_dict.aliases, dict)
1138+
and _model in user_api_key_dict.aliases
1139+
):
1140+
data["model"] = user_api_key_dict.aliases[_model]
1141+
return
1142+
1143+
11111144
def _get_enforced_params(
11121145
general_settings: Optional[dict], user_api_key_dict: UserAPIKeyAuth
11131146
) -> Optional[list]:

litellm/proxy/pass_through_endpoints/pass_through_endpoints.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ async def chat_completion_pass_through_endpoint( # noqa: PLR0915
197197
if data["model"] in litellm.model_alias_map:
198198
data["model"] = litellm.model_alias_map[data["model"]]
199199

200+
# Check key-specific aliases
201+
if (
202+
isinstance(data["model"], str)
203+
and user_api_key_dict.aliases
204+
and isinstance(user_api_key_dict.aliases, dict)
205+
and data["model"] in user_api_key_dict.aliases
206+
):
207+
data["model"] = user_api_key_dict.aliases[data["model"]]
208+
200209
### CALL HOOKS ### - modify incoming data before calling the model
201210
data = await proxy_logging_obj.pre_call_hook( # type: ignore
202211
user_api_key_dict=user_api_key_dict, data=data, call_type="text_completion"

tests/test_litellm/proxy/test_litellm_pre_call_utils.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
LiteLLMProxyRequestSetup,
1616
_get_dynamic_logging_metadata,
1717
_get_enforced_params,
18+
_update_model_if_key_alias_exists,
1819
add_litellm_data_to_request,
1920
check_if_token_is_service_account,
2021
)
@@ -1234,3 +1235,65 @@ async def test_request_guardrails_do_not_override_key_guardrails():
12341235
assert "guardrails" not in updated_data_empty
12351236
assert "key-guardrail-1" in requested_guardrails
12361237
assert len(requested_guardrails) == 1
1238+
1239+
1240+
def test_update_model_if_key_alias_exists():
1241+
"""
1242+
Test that _update_model_if_key_alias_exists properly updates the model when a key alias exists.
1243+
"""
1244+
# Test case 1: Key alias exists and matches model
1245+
data = {"model": "modelAlias", "messages": [{"role": "user", "content": "Hello"}]}
1246+
user_api_key_dict = UserAPIKeyAuth(
1247+
api_key="test-key",
1248+
aliases={"modelAlias": "xai/grok-4-fast-non-reasoning"},
1249+
)
1250+
_update_model_if_key_alias_exists(data=data, user_api_key_dict=user_api_key_dict)
1251+
assert data["model"] == "xai/grok-4-fast-non-reasoning"
1252+
1253+
# Test case 2: Key alias doesn't exist
1254+
data = {"model": "unknown-model", "messages": [{"role": "user", "content": "Hello"}]}
1255+
user_api_key_dict = UserAPIKeyAuth(
1256+
api_key="test-key",
1257+
aliases={"modelAlias": "xai/grok-4-fast-non-reasoning"},
1258+
)
1259+
original_model = data["model"]
1260+
_update_model_if_key_alias_exists(data=data, user_api_key_dict=user_api_key_dict)
1261+
assert data["model"] == original_model # Should remain unchanged
1262+
1263+
# Test case 3: Model is None
1264+
data = {"model": None, "messages": [{"role": "user", "content": "Hello"}]}
1265+
user_api_key_dict = UserAPIKeyAuth(
1266+
api_key="test-key",
1267+
aliases={"modelAlias": "xai/grok-4-fast-non-reasoning"},
1268+
)
1269+
_update_model_if_key_alias_exists(data=data, user_api_key_dict=user_api_key_dict)
1270+
assert data["model"] is None # Should remain None
1271+
1272+
# Test case 4: Model key doesn't exist in data
1273+
data = {"messages": [{"role": "user", "content": "Hello"}]}
1274+
user_api_key_dict = UserAPIKeyAuth(
1275+
api_key="test-key",
1276+
aliases={"modelAlias": "xai/grok-4-fast-non-reasoning"},
1277+
)
1278+
_update_model_if_key_alias_exists(data=data, user_api_key_dict=user_api_key_dict)
1279+
assert "model" not in data # Should not add model if it doesn't exist
1280+
1281+
# Test case 5: Multiple aliases, matching one
1282+
data = {"model": "alias1", "messages": [{"role": "user", "content": "Hello"}]}
1283+
user_api_key_dict = UserAPIKeyAuth(
1284+
api_key="test-key",
1285+
aliases={
1286+
"alias1": "model1",
1287+
"alias2": "model2",
1288+
"alias3": "model3",
1289+
},
1290+
)
1291+
_update_model_if_key_alias_exists(data=data, user_api_key_dict=user_api_key_dict)
1292+
assert data["model"] == "model1"
1293+
1294+
# Test case 6: Empty aliases dict
1295+
data = {"model": "modelAlias", "messages": [{"role": "user", "content": "Hello"}]}
1296+
user_api_key_dict = UserAPIKeyAuth(api_key="test-key", aliases={})
1297+
original_model = data["model"]
1298+
_update_model_if_key_alias_exists(data=data, user_api_key_dict=user_api_key_dict)
1299+
assert data["model"] == original_model # Should remain unchanged

0 commit comments

Comments
 (0)