mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-15 23:31:29 +00:00
[Feature][Bug Fix] Decouple Azure OpenAI Deployment ID from model name via base_model to fix gpt5 model routing (#28490)
* feat(azure): decouple deployment ID from model name via base_model
Azure OpenAI deployments have arbitrary names (deployment IDs) that may
not match the underlying model. Previously, model-type detection
(o-series, gpt-5, etc.) relied on substring matching against the
deployment name, causing misrouted configs and rejected params when
deployment names were non-standard (e.g. 'my-deployment-id' for gpt-5.2).
This change extends the existing base_model field to drive model-type
detection, config selection, supported param resolution, and param
mapping throughout the Azure call path:
- _get_azure_config() uses base_model for is_o_series/is_gpt_5 checks
- get_provider_chat_config() threads base_model for Azure
- get_supported_openai_params() accepts and uses base_model
- get_optional_params() accepts base_model and passes it to all Azure
config method calls (get_supported_openai_params, map_openai_params)
- azure.py completion handler uses base_model for GPT-5 detection
- Config internal methods (e.g. is_model_gpt_5_2_model) now receive
base_model so features like logprobs are correctly enabled
Fully backward compatible - when base_model is unset, behavior is
identical. Existing o_series/ and gpt5_series/ prefix workarounds
continue to work.
Usage in proxy config:
model_list:
- model_name: my-gpt5
litellm_params:
model: azure/my-deployment-id
model_info:
base_model: azure/gpt-5.2
Fixes: non-standard deployment names like 'prefix-gpt-5.2' rejecting
logprobs/top_logprobs despite the underlying model supporting them.
* Addressing Greptile comments.
This commit is contained in:
parent
0168f0f259
commit
1c80fa9c3b
5 changed files with 354 additions and 26 deletions
|
|
@ -11,6 +11,7 @@ def get_supported_openai_params( # noqa: PLR0915
|
|||
request_type: Literal[
|
||||
"chat_completion", "embeddings", "transcription"
|
||||
] = "chat_completion",
|
||||
base_model: Optional[str] = None,
|
||||
) -> Optional[list]:
|
||||
"""
|
||||
Returns the supported openai params for a given model + provider
|
||||
|
|
@ -20,6 +21,11 @@ def get_supported_openai_params( # noqa: PLR0915
|
|||
get_supported_openai_params(model="anthropic.claude-3", custom_llm_provider="bedrock")
|
||||
```
|
||||
|
||||
Args:
|
||||
base_model: For Azure, the true underlying model (e.g. ``"azure/gpt-5.2"``)
|
||||
when the deployment name differs. Used for model-type detection so that
|
||||
non-standard deployment names route to the correct config.
|
||||
|
||||
Returns:
|
||||
- List if custom_llm_provider is mapped
|
||||
- None if unmapped
|
||||
|
|
@ -32,17 +38,21 @@ def get_supported_openai_params( # noqa: PLR0915
|
|||
|
||||
if custom_llm_provider in LlmProvidersSet:
|
||||
provider_config = litellm.ProviderConfigManager.get_provider_chat_config(
|
||||
model=model, provider=LlmProviders(custom_llm_provider)
|
||||
model=model,
|
||||
provider=LlmProviders(custom_llm_provider),
|
||||
base_model=base_model,
|
||||
)
|
||||
elif custom_llm_provider.split("/")[0] in LlmProvidersSet:
|
||||
provider_config = litellm.ProviderConfigManager.get_provider_chat_config(
|
||||
model=model, provider=LlmProviders(custom_llm_provider.split("/")[0])
|
||||
model=model,
|
||||
provider=LlmProviders(custom_llm_provider.split("/")[0]),
|
||||
base_model=base_model,
|
||||
)
|
||||
else:
|
||||
provider_config = None
|
||||
|
||||
if provider_config and request_type == "chat_completion":
|
||||
return provider_config.get_supported_openai_params(model=model)
|
||||
return provider_config.get_supported_openai_params(model=base_model or model)
|
||||
|
||||
if custom_llm_provider == "bedrock":
|
||||
return litellm.AmazonConverseConfig().get_supported_openai_params(model=model)
|
||||
|
|
@ -130,13 +140,18 @@ def get_supported_openai_params( # noqa: PLR0915
|
|||
model=model
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(model=model):
|
||||
_azure_detection_model = base_model or model
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(
|
||||
model=_azure_detection_model
|
||||
):
|
||||
return litellm.AzureOpenAIO1Config().get_supported_openai_params(
|
||||
model=model
|
||||
model=_azure_detection_model
|
||||
)
|
||||
elif litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(model=model):
|
||||
elif litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(
|
||||
model=_azure_detection_model
|
||||
):
|
||||
return litellm.AzureOpenAIGPT5Config().get_supported_openai_params(
|
||||
model=model
|
||||
model=_azure_detection_model
|
||||
)
|
||||
else:
|
||||
return litellm.AzureOpenAIConfig().get_supported_openai_params(model=model)
|
||||
|
|
|
|||
|
|
@ -239,7 +239,9 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM):
|
|||
)
|
||||
|
||||
data = {"model": None, "messages": messages, **optional_params}
|
||||
elif litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(model=model):
|
||||
elif litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(
|
||||
model=litellm_params.get("base_model") or model
|
||||
):
|
||||
data = litellm.AzureOpenAIGPT5Config().transform_request(
|
||||
model=model,
|
||||
messages=messages,
|
||||
|
|
|
|||
|
|
@ -1491,7 +1491,9 @@ def completion( # type: ignore # noqa: PLR0915
|
|||
provider.value for provider in LlmProviders
|
||||
]:
|
||||
provider_config = ProviderConfigManager.get_provider_chat_config(
|
||||
model=model, provider=LlmProviders(custom_llm_provider)
|
||||
model=model,
|
||||
provider=LlmProviders(custom_llm_provider),
|
||||
base_model=base_model,
|
||||
)
|
||||
|
||||
if provider_config is not None:
|
||||
|
|
@ -1550,6 +1552,7 @@ def completion( # type: ignore # noqa: PLR0915
|
|||
"safety_identifier": safety_identifier,
|
||||
"service_tier": service_tier,
|
||||
"allowed_openai_params": kwargs.get("allowed_openai_params"),
|
||||
"base_model": base_model,
|
||||
}
|
||||
optional_params = get_optional_params(
|
||||
**optional_param_args, **non_default_params
|
||||
|
|
@ -1766,7 +1769,12 @@ def completion( # type: ignore # noqa: PLR0915
|
|||
if max_retries is not None:
|
||||
optional_params["max_retries"] = max_retries
|
||||
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(model=model):
|
||||
# Use base_model (the true underlying model) for model-type
|
||||
# detection when the deployment name differs from the model name.
|
||||
_azure_detection_model = base_model or model
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(
|
||||
model=_azure_detection_model
|
||||
):
|
||||
## LOAD CONFIG - if set
|
||||
config = litellm.AzureOpenAIO1Config.get_config()
|
||||
for k, v in config.items():
|
||||
|
|
|
|||
|
|
@ -4019,16 +4019,23 @@ def get_optional_params( # noqa: PLR0915
|
|||
thinking: Optional[AnthropicThinkingParam] = None,
|
||||
web_search_options: Optional[OpenAIWebSearchOptions] = None,
|
||||
safety_identifier: Optional[str] = None,
|
||||
base_model: Optional[str] = None,
|
||||
**kwargs,
|
||||
):
|
||||
passed_params = locals().copy()
|
||||
special_params = passed_params.pop("kwargs")
|
||||
# Remove base_model from passed_params so it doesn't interfere with
|
||||
# non_default_params / _check_valid_arg — it's a routing hint, not an
|
||||
# OpenAI param.
|
||||
passed_params.pop("base_model", None)
|
||||
provider_config: Optional[BaseConfig] = None
|
||||
if custom_llm_provider is not None and custom_llm_provider in [
|
||||
provider.value for provider in LlmProviders
|
||||
]:
|
||||
provider_config = ProviderConfigManager.get_provider_chat_config(
|
||||
model=model, provider=LlmProviders(custom_llm_provider)
|
||||
model=model,
|
||||
provider=LlmProviders(custom_llm_provider),
|
||||
base_model=base_model,
|
||||
)
|
||||
non_default_params = pre_process_non_default_params(
|
||||
passed_params=passed_params,
|
||||
|
|
@ -4091,7 +4098,7 @@ def get_optional_params( # noqa: PLR0915
|
|||
sys.modules[__name__], "get_supported_openai_params"
|
||||
)
|
||||
supported_params = get_supported_openai_params(
|
||||
model=model, custom_llm_provider=custom_llm_provider
|
||||
model=model, custom_llm_provider=custom_llm_provider, base_model=base_model
|
||||
)
|
||||
if supported_params is None:
|
||||
supported_params = get_supported_openai_params(
|
||||
|
|
@ -4702,22 +4709,27 @@ def get_optional_params( # noqa: PLR0915
|
|||
),
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(model=model):
|
||||
_azure_detection_model = base_model or model
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(
|
||||
model=_azure_detection_model
|
||||
):
|
||||
optional_params = litellm.AzureOpenAIO1Config().map_openai_params(
|
||||
non_default_params=non_default_params,
|
||||
optional_params=optional_params,
|
||||
model=model,
|
||||
model=_azure_detection_model,
|
||||
drop_params=(
|
||||
drop_params
|
||||
if drop_params is not None and isinstance(drop_params, bool)
|
||||
else False
|
||||
),
|
||||
)
|
||||
elif litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(model=model):
|
||||
elif litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(
|
||||
model=_azure_detection_model
|
||||
):
|
||||
optional_params = litellm.AzureOpenAIGPT5Config().map_openai_params(
|
||||
non_default_params=non_default_params,
|
||||
optional_params=optional_params,
|
||||
model=model,
|
||||
model=_azure_detection_model,
|
||||
drop_params=(
|
||||
drop_params
|
||||
if drop_params is not None and isinstance(drop_params, bool)
|
||||
|
|
@ -4739,7 +4751,7 @@ def get_optional_params( # noqa: PLR0915
|
|||
optional_params = litellm.AzureOpenAIConfig().map_openai_params(
|
||||
non_default_params=non_default_params,
|
||||
optional_params=optional_params,
|
||||
model=model,
|
||||
model=_azure_detection_model,
|
||||
api_version=api_version, # type: ignore
|
||||
drop_params=(
|
||||
drop_params
|
||||
|
|
@ -8124,10 +8136,8 @@ class ProviderConfigManager:
|
|||
# Format: (factory_function, needs_model_parameter: bool)
|
||||
LlmProviders.OPENAI: (lambda: litellm.OpenAIGPTConfig(), False),
|
||||
LlmProviders.ANTHROPIC: (lambda: litellm.AnthropicConfig(), False),
|
||||
LlmProviders.AZURE: (
|
||||
lambda model: ProviderConfigManager._get_azure_config(model),
|
||||
True,
|
||||
),
|
||||
# AZURE is handled as a special case in get_provider_chat_config()
|
||||
# so that base_model can be threaded through for model-type detection.
|
||||
LlmProviders.AZURE_AI: (
|
||||
lambda model: ProviderConfigManager._get_azure_ai_config(model),
|
||||
True,
|
||||
|
|
@ -8267,11 +8277,19 @@ class ProviderConfigManager:
|
|||
}
|
||||
|
||||
@staticmethod
|
||||
def _get_azure_config(model: str) -> BaseConfig:
|
||||
"""Get Azure config based on model type."""
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(model=model):
|
||||
def _get_azure_config(model: str, base_model: Optional[str] = None) -> BaseConfig:
|
||||
"""Get Azure config based on model type.
|
||||
|
||||
When *base_model* is provided (e.g. ``"azure/gpt-5.2"``), it is used
|
||||
for model-type detection instead of *model* (the deployment name).
|
||||
This allows non-standard deployment names like ``"azure/foo"`` to be
|
||||
routed through the correct config when the user specifies the true
|
||||
underlying model via ``base_model``.
|
||||
"""
|
||||
detection_model = base_model or model
|
||||
if litellm.AzureOpenAIO1Config().is_o_series_model(model=detection_model):
|
||||
return litellm.AzureOpenAIO1Config()
|
||||
if litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(model=model):
|
||||
if litellm.AzureOpenAIGPT5Config.is_model_gpt_5_model(model=detection_model):
|
||||
return litellm.AzureOpenAIGPT5Config()
|
||||
return litellm.AzureOpenAIConfig()
|
||||
|
||||
|
|
@ -8329,13 +8347,18 @@ class ProviderConfigManager:
|
|||
|
||||
@staticmethod
|
||||
def get_provider_chat_config( # noqa: PLR0915
|
||||
model: str, provider: LlmProviders
|
||||
model: str,
|
||||
provider: LlmProviders,
|
||||
base_model: Optional[str] = None,
|
||||
) -> Optional[BaseConfig]:
|
||||
"""
|
||||
Returns the provider config for a given provider.
|
||||
|
||||
Uses O(1) dictionary lookup for fast provider resolution.
|
||||
Python classes take priority over JSON (they have custom overrides).
|
||||
|
||||
For Azure, *base_model* (when set) drives model-type detection so that
|
||||
non-standard deployment names still route to the correct config.
|
||||
"""
|
||||
# Handle OpenAI special cases (O-series and GPT-5 models)
|
||||
if provider == LlmProviders.OPENAI:
|
||||
|
|
@ -8344,6 +8367,12 @@ class ProviderConfigManager:
|
|||
if litellm.OpenAIGPT5Config.is_model_gpt_5_model(model=model):
|
||||
return litellm.OpenAIGPT5Config()
|
||||
|
||||
# Handle Azure before the generic map so base_model can be threaded through
|
||||
if provider == LlmProviders.AZURE:
|
||||
return ProviderConfigManager._get_azure_config(
|
||||
model=model, base_model=base_model
|
||||
)
|
||||
|
||||
# Initialize provider config map lazily (avoids circular imports)
|
||||
if ProviderConfigManager._PROVIDER_CONFIG_MAP is None:
|
||||
ProviderConfigManager._PROVIDER_CONFIG_MAP = (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,274 @@
|
|||
"""Tests for decoupling Azure deployment IDs from underlying model names.
|
||||
|
||||
When users name their Azure deployment something non-standard (e.g. "my-deployment-id"),
|
||||
setting ``base_model`` should drive model-type detection (o-series, gpt-5,
|
||||
etc.) so the correct config, supported params, and param mapping are used.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
import litellm
|
||||
from litellm.llms.azure.chat.gpt_5_transformation import AzureOpenAIGPT5Config
|
||||
from litellm.llms.azure.chat.o_series_transformation import AzureOpenAIO1Config
|
||||
from litellm.utils import ProviderConfigManager, get_optional_params
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# _get_azure_config — routes to the correct config based on base_model
|
||||
# ---------------------------------------------------------------------------
|
||||
class TestGetAzureConfigWithBaseModel:
|
||||
"""ProviderConfigManager._get_azure_config should use base_model for detection."""
|
||||
|
||||
def test_should_return_gpt5_config_when_base_model_is_gpt5(self):
|
||||
config = ProviderConfigManager._get_azure_config(
|
||||
model="my-deployment-id", base_model="azure/gpt-5.2"
|
||||
)
|
||||
assert isinstance(config, AzureOpenAIGPT5Config)
|
||||
|
||||
def test_should_return_o_series_config_when_base_model_is_o_series(self):
|
||||
config = ProviderConfigManager._get_azure_config(
|
||||
model="my-deployment-id", base_model="azure/o4-mini"
|
||||
)
|
||||
assert isinstance(config, AzureOpenAIO1Config)
|
||||
|
||||
def test_should_return_default_config_when_base_model_is_regular(self):
|
||||
config = ProviderConfigManager._get_azure_config(
|
||||
model="my-deployment-id", base_model="azure/gpt-4o"
|
||||
)
|
||||
assert type(config).__name__ == "AzureOpenAIConfig"
|
||||
|
||||
def test_should_fallback_to_model_when_base_model_is_none(self):
|
||||
config = ProviderConfigManager._get_azure_config(
|
||||
model="gpt-5.2", base_model=None
|
||||
)
|
||||
assert isinstance(config, AzureOpenAIGPT5Config)
|
||||
|
||||
def test_should_return_default_config_when_both_are_non_standard(self):
|
||||
config = ProviderConfigManager._get_azure_config(
|
||||
model="my-deployment-id", base_model=None
|
||||
)
|
||||
assert type(config).__name__ == "AzureOpenAIConfig"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# get_provider_chat_config — threads base_model through for Azure
|
||||
# ---------------------------------------------------------------------------
|
||||
class TestGetProviderChatConfigWithBaseModel:
|
||||
"""get_provider_chat_config should pass base_model to Azure config selection."""
|
||||
|
||||
def test_should_return_gpt5_config_for_custom_deployment_with_base_model(self):
|
||||
from litellm.types.utils import LlmProviders
|
||||
|
||||
config = ProviderConfigManager.get_provider_chat_config(
|
||||
model="my-deployment-id",
|
||||
provider=LlmProviders.AZURE,
|
||||
base_model="azure/gpt-5",
|
||||
)
|
||||
assert isinstance(config, AzureOpenAIGPT5Config)
|
||||
|
||||
def test_should_return_o_series_config_for_custom_deployment_with_base_model(self):
|
||||
from litellm.types.utils import LlmProviders
|
||||
|
||||
config = ProviderConfigManager.get_provider_chat_config(
|
||||
model="my-other-deployment",
|
||||
provider=LlmProviders.AZURE,
|
||||
base_model="azure/o3-mini",
|
||||
)
|
||||
assert isinstance(config, AzureOpenAIO1Config)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# get_supported_openai_params — base_model drives Azure param detection
|
||||
# ---------------------------------------------------------------------------
|
||||
class TestGetSupportedOpenAIParamsWithBaseModel:
|
||||
"""get_supported_openai_params should use base_model for Azure detection."""
|
||||
|
||||
def test_should_return_gpt5_params_for_custom_deployment_with_gpt5_base_model(
|
||||
self,
|
||||
):
|
||||
params = litellm.get_supported_openai_params(
|
||||
model="my-deployment-id",
|
||||
custom_llm_provider="azure",
|
||||
base_model="azure/gpt-5",
|
||||
)
|
||||
assert params is not None
|
||||
assert "reasoning_effort" in params
|
||||
# gpt-5 maps max_tokens -> max_completion_tokens, verifying we got GPT-5 config
|
||||
assert "max_completion_tokens" in params
|
||||
|
||||
def test_should_return_o_series_params_for_custom_deployment_with_o_series_base_model(
|
||||
self,
|
||||
):
|
||||
params = litellm.get_supported_openai_params(
|
||||
model="my-other-deployment",
|
||||
custom_llm_provider="azure",
|
||||
base_model="azure/o4-mini",
|
||||
)
|
||||
assert params is not None
|
||||
assert "reasoning_effort" in params
|
||||
|
||||
def test_should_return_regular_params_when_no_base_model(self):
|
||||
"""When base_model is not set and model is non-standard, default Azure config."""
|
||||
params = litellm.get_supported_openai_params(
|
||||
model="my-deployment-id",
|
||||
custom_llm_provider="azure",
|
||||
)
|
||||
assert params is not None
|
||||
# Default Azure config supports temperature
|
||||
assert "temperature" in params
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# get_optional_params — base_model drives Azure param mapping
|
||||
# ---------------------------------------------------------------------------
|
||||
class TestGetOptionalParamsWithBaseModel:
|
||||
"""get_optional_params should use base_model for Azure model-type detection."""
|
||||
|
||||
def test_should_map_max_tokens_for_custom_deployment_with_gpt5_base_model(self):
|
||||
"""A non-standard deployment name + gpt-5 base_model should map max_tokens -> max_completion_tokens."""
|
||||
params = get_optional_params(
|
||||
model="my-deployment-id",
|
||||
custom_llm_provider="azure",
|
||||
max_tokens=100,
|
||||
base_model="azure/gpt-5",
|
||||
)
|
||||
assert params.get("max_completion_tokens") == 100
|
||||
assert "max_tokens" not in params
|
||||
|
||||
def test_should_keep_max_tokens_for_custom_deployment_without_base_model(self):
|
||||
"""A non-standard deployment name without base_model should use default Azure config."""
|
||||
params = get_optional_params(
|
||||
model="my-deployment-id",
|
||||
custom_llm_provider="azure",
|
||||
max_tokens=100,
|
||||
api_version="2024-05-01-preview",
|
||||
)
|
||||
# Default AzureOpenAIConfig keeps max_tokens as-is (or maps based on api_version)
|
||||
assert "max_tokens" in params or "max_completion_tokens" in params
|
||||
|
||||
def test_should_support_reasoning_effort_for_custom_deployment_with_o_series_base_model(
|
||||
self,
|
||||
):
|
||||
"""A non-standard deployment name + o-series base_model should accept reasoning_effort."""
|
||||
params = get_optional_params(
|
||||
model="my-other-deployment",
|
||||
custom_llm_provider="azure",
|
||||
reasoning_effort="low",
|
||||
base_model="azure/o4-mini",
|
||||
)
|
||||
assert params.get("reasoning_effort") == "low"
|
||||
|
||||
def test_should_reject_temperature_for_custom_deployment_with_gpt5_base_model(
|
||||
self,
|
||||
):
|
||||
"""A non-standard deployment + gpt-5 base_model should reject temperature."""
|
||||
with pytest.raises(litellm.UnsupportedParamsError):
|
||||
get_optional_params(
|
||||
model="my-deployment-id",
|
||||
custom_llm_provider="azure",
|
||||
temperature=0.5,
|
||||
base_model="azure/gpt-5",
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Backward compatibility — existing patterns still work
|
||||
# ---------------------------------------------------------------------------
|
||||
class TestBackwardCompatibility:
|
||||
"""Existing model-name-based and prefix-based patterns must keep working."""
|
||||
|
||||
def test_should_detect_gpt5_from_model_name(self):
|
||||
config = ProviderConfigManager._get_azure_config(model="gpt-5.2")
|
||||
assert isinstance(config, AzureOpenAIGPT5Config)
|
||||
|
||||
def test_should_detect_gpt5_from_gpt5_series_prefix(self):
|
||||
config = ProviderConfigManager._get_azure_config(
|
||||
model="gpt5_series/my-deployment"
|
||||
)
|
||||
assert isinstance(config, AzureOpenAIGPT5Config)
|
||||
|
||||
def test_should_detect_o_series_from_model_name(self):
|
||||
config = ProviderConfigManager._get_azure_config(model="o4-mini")
|
||||
assert isinstance(config, AzureOpenAIO1Config)
|
||||
|
||||
def test_should_detect_o_series_from_o_series_prefix(self):
|
||||
config = ProviderConfigManager._get_azure_config(model="o_series/my-deployment")
|
||||
assert isinstance(config, AzureOpenAIO1Config)
|
||||
|
||||
def test_should_handle_gpt5_chat_model_correctly(self):
|
||||
"""gpt-5-chat models should NOT be routed to GPT-5 config."""
|
||||
config = ProviderConfigManager._get_azure_config(model="gpt-5-chat")
|
||||
assert type(config).__name__ == "AzureOpenAIConfig"
|
||||
|
||||
def test_base_model_overrides_model_detection(self):
|
||||
"""base_model should take priority over model for type detection."""
|
||||
# model looks like o-series, but base_model says gpt-5
|
||||
config = ProviderConfigManager._get_azure_config(
|
||||
model="o3-mini", base_model="azure/gpt-5.2"
|
||||
)
|
||||
assert isinstance(config, AzureOpenAIGPT5Config)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Deep config method awareness — base_model flows into config internals
|
||||
# ---------------------------------------------------------------------------
|
||||
class TestBaseModelFlowsIntoConfigInternals:
|
||||
"""base_model should be used by config internal methods (e.g. is_model_gpt_5_2_model)."""
|
||||
|
||||
def test_should_support_logprobs_for_prefixed_deployment_with_gpt52_base_model(
|
||||
self,
|
||||
):
|
||||
"""Deployment 'my-gpt-5.2' with base_model='azure/gpt-5.2' should support logprobs."""
|
||||
params = litellm.get_supported_openai_params(
|
||||
model="gpt5_series/my-gpt-5.2",
|
||||
custom_llm_provider="azure",
|
||||
base_model="azure/gpt-5.2",
|
||||
)
|
||||
assert params is not None
|
||||
assert "logprobs" in params
|
||||
assert "top_logprobs" in params
|
||||
|
||||
def test_should_support_logprobs_for_plain_deployment_with_gpt52_base_model(self):
|
||||
"""Deployment 'my-deployment-id' with base_model='azure/gpt-5.2' should support logprobs."""
|
||||
params = litellm.get_supported_openai_params(
|
||||
model="my-deployment-id",
|
||||
custom_llm_provider="azure",
|
||||
base_model="azure/gpt-5.2",
|
||||
)
|
||||
assert params is not None
|
||||
assert "logprobs" in params
|
||||
assert "top_logprobs" in params
|
||||
|
||||
def test_should_not_support_logprobs_for_gpt5_base_model(self):
|
||||
"""Deployment with base_model='azure/gpt-5' (not 5.2) should NOT support logprobs."""
|
||||
params = litellm.get_supported_openai_params(
|
||||
model="my-deployment-id",
|
||||
custom_llm_provider="azure",
|
||||
base_model="azure/gpt-5",
|
||||
)
|
||||
assert params is not None
|
||||
assert "logprobs" not in params
|
||||
assert "top_logprobs" not in params
|
||||
|
||||
def test_should_pass_logprobs_through_get_optional_params(self):
|
||||
"""logprobs should pass validation in get_optional_params when base_model is gpt-5.2."""
|
||||
params = get_optional_params(
|
||||
model="gpt5_series/my-gpt-5.2",
|
||||
custom_llm_provider="azure",
|
||||
logprobs=True,
|
||||
top_logprobs=5,
|
||||
base_model="azure/gpt-5.2",
|
||||
)
|
||||
assert params.get("logprobs") is True
|
||||
assert params.get("top_logprobs") == 5
|
||||
|
||||
def test_should_map_max_tokens_for_prefixed_deployment_with_gpt5_base_model(self):
|
||||
"""my-gpt-5.2 with base_model should correctly map max_tokens -> max_completion_tokens."""
|
||||
params = get_optional_params(
|
||||
model="gpt5_series/my-gpt-5.2",
|
||||
custom_llm_provider="azure",
|
||||
max_tokens=200,
|
||||
base_model="azure/gpt-5.2",
|
||||
)
|
||||
assert params.get("max_completion_tokens") == 200
|
||||
assert "max_tokens" not in params
|
||||
Loading…
Add table
Reference in a new issue