-
-
Notifications
You must be signed in to change notification settings - Fork 11.7k
fix(proxy): resolve provider from deployment for multi-provider defaultconfig (#27516) #27517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1731,6 +1731,7 @@ async def add_litellm_data_to_request( # noqa: PLR0915 | |
| data=data, | ||
| user_api_key_dict=user_api_key_dict, | ||
| pre_alias_model_name=_pre_alias_model, | ||
| llm_router=llm_router, | ||
| ) | ||
|
|
||
| ## ENFORCED PARAMS CHECK | ||
|
|
@@ -1864,6 +1865,7 @@ def _apply_credential_overrides_from_model_config( | |
| data: dict, | ||
| user_api_key_dict: UserAPIKeyAuth, | ||
| pre_alias_model_name: Optional[str] = None, | ||
| llm_router: Optional[Router] = None, | ||
| ) -> None: | ||
| """ | ||
| Walk the model_config precedence chain in team/project metadata. | ||
|
|
@@ -1899,10 +1901,19 @@ def _apply_credential_overrides_from_model_config( | |
| if not project_model_config and not team_model_config: | ||
| return | ||
|
|
||
| # Extract provider hint from model name (e.g. "azure/gpt-4" -> "azure") | ||
| # Extract provider hint from model name (e.g. "azure/gpt-4" -> "azure"). | ||
| # When the user-facing name has no provider prefix, fall back to the | ||
| # deployment's litellm_params so multi-provider defaultconfig entries | ||
| # don't silently match the first dict key (#27516). | ||
| provider: Optional[str] = None | ||
| if "/" in model_name: | ||
| provider = model_name.split("/", 1)[0] | ||
| elif llm_router is not None: | ||
| provider = _resolve_provider_from_deployment( | ||
| llm_router=llm_router, | ||
| model_name=model_name, | ||
| pre_alias_model_name=pre_alias_model_name, | ||
| ) | ||
|
|
||
| credential_name = _resolve_credential_from_model_config( | ||
| model_name=model_name, | ||
|
|
@@ -1938,6 +1949,48 @@ def _apply_credential_overrides_from_model_config( | |
| ) | ||
|
|
||
|
|
||
| def _resolve_provider_from_deployment( | ||
| llm_router: Router, | ||
| model_name: str, | ||
| pre_alias_model_name: Optional[str] = None, | ||
| ) -> Optional[str]: | ||
| """ | ||
| Resolve a provider hint from the deployment's litellm_params when the | ||
| user-facing model name has no provider prefix. | ||
|
|
||
| Tries the post-alias name first (the resolved model group), then the | ||
| pre-alias name. Returns None if no deployment is found or the deployment | ||
| has no usable provider info. | ||
| """ | ||
| candidates = [model_name] | ||
| if pre_alias_model_name and pre_alias_model_name != model_name: | ||
| candidates.append(pre_alias_model_name) | ||
|
|
||
| for name in candidates: | ||
| try: | ||
| deployment = llm_router.get_deployment_by_model_group_name( | ||
| model_group_name=name | ||
| ) | ||
| except Exception: | ||
| deployment = None | ||
| if deployment is None: | ||
| continue | ||
|
|
||
| litellm_params = getattr(deployment, "litellm_params", None) | ||
| if litellm_params is None: | ||
| continue | ||
|
|
||
| custom_provider = getattr(litellm_params, "custom_llm_provider", None) | ||
| if custom_provider: | ||
| return custom_provider | ||
|
|
||
| deployment_model = getattr(litellm_params, "model", "") or "" | ||
|
Comment on lines
+1969
to
+1987
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if "/" in deployment_model: | ||
| return deployment_model.split("/", 1)[0] | ||
|
|
||
| return None | ||
|
|
||
|
|
||
| def _resolve_credential_from_model_config( | ||
| model_name: str, | ||
| project_model_config: Optional[dict], | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bare
except Exception: deployment = Nonediscards every error fromget_deployment_by_model_group_namewithout any log output. If the router raises unexpectedly (e.g., due to a programming error, corrupted model list, or wrong return type), the provider hint silently becomesNoneand credential selection silently falls back to dict-insertion-order — the very bug this PR is fixing. Averbose_proxy_logger.debugorwarningcall here would make production failures diagnosable without changing the graceful-fallback semantics.