mirror of
https://github.com/tiennm99/litellm.git
synced 2026-07-28 10:20:18 +00:00
Add support for GPT 5 codex models (#14841)
* Add support for GPT 5 codex models * lint * fixes
This commit is contained in:
@@ -8,18 +8,24 @@ from .gpt_transformation import OpenAIGPTConfig
|
||||
|
||||
|
||||
class OpenAIGPT5Config(OpenAIGPTConfig):
|
||||
"""Configuration for gpt-5 models.
|
||||
"""Configuration for gpt-5 models including GPT-5-Codex variants.
|
||||
|
||||
Handles OpenAI API quirks for the gpt-5 series like:
|
||||
|
||||
- Mapping ``max_tokens`` -> ``max_completion_tokens``.
|
||||
- Dropping unsupported ``temperature`` values when requested.
|
||||
- Support for GPT-5-Codex models optimized for code generation.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def is_model_gpt_5_model(cls, model: str) -> bool:
|
||||
return "gpt-5" in model
|
||||
|
||||
@classmethod
|
||||
def is_model_gpt_5_codex_model(cls, model: str) -> bool:
|
||||
"""Check if the model is specifically a GPT-5 Codex variant."""
|
||||
return "gpt-5-codex" in model
|
||||
|
||||
def get_supported_openai_params(self, model: str) -> list:
|
||||
from litellm.utils import supports_tool_choice
|
||||
|
||||
@@ -38,7 +44,9 @@ class OpenAIGPT5Config(OpenAIGPTConfig):
|
||||
]
|
||||
|
||||
return [
|
||||
param for param in base_gpt_series_params if param not in non_supported_params
|
||||
param
|
||||
for param in base_gpt_series_params
|
||||
if param not in non_supported_params
|
||||
]
|
||||
|
||||
def map_openai_params(
|
||||
@@ -67,7 +75,7 @@ class OpenAIGPT5Config(OpenAIGPTConfig):
|
||||
else:
|
||||
raise litellm.utils.UnsupportedParamsError(
|
||||
message=(
|
||||
"gpt-5 models don't support temperature={}. Only temperature=1 is supported. To drop unsupported params set `litellm.drop_params = True`"
|
||||
"gpt-5 models (including gpt-5-codex) don't support temperature={}. Only temperature=1 is supported. To drop unsupported params set `litellm.drop_params = True`"
|
||||
).format(temperature_value),
|
||||
status_code=400,
|
||||
)
|
||||
|
||||
@@ -12727,6 +12727,81 @@
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"gpt-5-codex": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
"cache_read_input_token_cost_flex": 6.25e-08,
|
||||
"cache_read_input_token_cost_priority": 2.5e-07,
|
||||
"input_cost_per_token": 1.25e-06,
|
||||
"input_cost_per_token_flex": 6.25e-07,
|
||||
"input_cost_per_token_priority": 2.5e-06,
|
||||
"litellm_provider": "openai",
|
||||
"max_input_tokens": 400000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"metadata": {
|
||||
"notes": "GPT-5-Codex pricing placeholder - needs to be updated with actual OpenAI pricing"
|
||||
},
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1e-05,
|
||||
"output_cost_per_token_flex": 5e-06,
|
||||
"output_cost_per_token_priority": 2e-05,
|
||||
"supported_endpoints": [
|
||||
"/v1/responses"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"gpt-5-codex-latest": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
"cache_read_input_token_cost_flex": 6.25e-08,
|
||||
"cache_read_input_token_cost_priority": 2.5e-07,
|
||||
"input_cost_per_token": 1.25e-06,
|
||||
"input_cost_per_token_flex": 6.25e-07,
|
||||
"input_cost_per_token_priority": 2.5e-06,
|
||||
"litellm_provider": "openai",
|
||||
"max_input_tokens": 400000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"metadata": {
|
||||
"notes": "GPT-5-Codex-Latest pricing placeholder - needs to be updated with actual OpenAI pricing"
|
||||
},
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1e-05,
|
||||
"output_cost_per_token_flex": 5e-06,
|
||||
"output_cost_per_token_priority": 2e-05,
|
||||
"supported_endpoints": [
|
||||
"/v1/chat/completions",
|
||||
"/v1/batch",
|
||||
"/v1/responses"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"gpt-5-2025-08-07": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
"cache_read_input_token_cost_flex": 6.25e-08,
|
||||
|
||||
@@ -12727,6 +12727,34 @@
|
||||
"supports_tool_choice": true,
|
||||
"supports_vision": true
|
||||
},
|
||||
"gpt-5-codex": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
"input_cost_per_token": 1.25e-06,
|
||||
"litellm_provider": "openai",
|
||||
"max_input_tokens": 400000,
|
||||
"max_output_tokens": 128000,
|
||||
"max_tokens": 128000,
|
||||
"mode": "chat",
|
||||
"output_cost_per_token": 1e-05,
|
||||
"supported_endpoints": [
|
||||
"/v1/responses"
|
||||
],
|
||||
"supported_modalities": [
|
||||
"text",
|
||||
"image"
|
||||
],
|
||||
"supported_output_modalities": [
|
||||
"text"
|
||||
],
|
||||
"supports_function_calling": true,
|
||||
"supports_native_streaming": true,
|
||||
"supports_parallel_function_calling": true,
|
||||
"supports_prompt_caching": true,
|
||||
"supports_reasoning": true,
|
||||
"supports_response_schema": true,
|
||||
"supports_system_messages": true,
|
||||
"supports_tool_choice": true
|
||||
},
|
||||
"gpt-5-2025-08-07": {
|
||||
"cache_read_input_token_cost": 1.25e-07,
|
||||
"cache_read_input_token_cost_flex": 6.25e-08,
|
||||
|
||||
@@ -11,7 +11,9 @@ def config() -> AzureOpenAIGPT5Config:
|
||||
|
||||
def test_azure_gpt5_supports_reasoning_effort(config: AzureOpenAIGPT5Config):
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(model="gpt-5")
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(model="gpt5_series/my-deployment")
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(
|
||||
model="gpt5_series/my-deployment"
|
||||
)
|
||||
|
||||
|
||||
def test_azure_gpt5_maps_max_tokens(config: AzureOpenAIGPT5Config):
|
||||
@@ -46,3 +48,56 @@ def test_azure_gpt5_series_transform_request(config: AzureOpenAIGPT5Config):
|
||||
headers={},
|
||||
)
|
||||
assert request["model"] == "gpt-5"
|
||||
|
||||
|
||||
# GPT-5-Codex specific tests for Azure
|
||||
def test_azure_gpt5_codex_model_detection(config: AzureOpenAIGPT5Config):
|
||||
"""Test that Azure GPT-5-Codex models are correctly detected."""
|
||||
assert config.is_model_gpt_5_model("gpt-5-codex")
|
||||
assert config.is_model_gpt_5_model("gpt5_series/gpt-5-codex")
|
||||
|
||||
|
||||
def test_azure_gpt5_codex_supports_reasoning_effort(config: AzureOpenAIGPT5Config):
|
||||
"""Test that Azure GPT-5-Codex supports reasoning_effort parameter."""
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(model="gpt-5-codex")
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(
|
||||
model="gpt5_series/gpt-5-codex"
|
||||
)
|
||||
|
||||
|
||||
def test_azure_gpt5_codex_maps_max_tokens(config: AzureOpenAIGPT5Config):
|
||||
"""Test that Azure GPT-5-Codex correctly maps max_tokens to max_completion_tokens."""
|
||||
params = config.map_openai_params(
|
||||
non_default_params={"max_tokens": 150},
|
||||
optional_params={},
|
||||
model="gpt-5-codex",
|
||||
drop_params=False,
|
||||
api_version="2024-05-01-preview",
|
||||
)
|
||||
assert params["max_completion_tokens"] == 150
|
||||
assert "max_tokens" not in params
|
||||
|
||||
|
||||
def test_azure_gpt5_codex_temperature_error(config: AzureOpenAIGPT5Config):
|
||||
"""Test that Azure GPT-5-Codex raises error for unsupported temperature."""
|
||||
with pytest.raises(litellm.utils.UnsupportedParamsError):
|
||||
config.map_openai_params(
|
||||
non_default_params={"temperature": 0.8},
|
||||
optional_params={},
|
||||
model="gpt-5-codex",
|
||||
drop_params=False,
|
||||
api_version="2024-05-01-preview",
|
||||
)
|
||||
|
||||
|
||||
def test_azure_gpt5_codex_series_transform_request(config: AzureOpenAIGPT5Config):
|
||||
"""Test that Azure GPT-5-Codex series routing works correctly."""
|
||||
request = config.transform_request(
|
||||
model="gpt5_series/gpt-5-codex",
|
||||
messages=[],
|
||||
optional_params={},
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
assert request["model"] == "gpt-5-codex"
|
||||
|
||||
|
||||
@@ -2,16 +2,24 @@ import pytest
|
||||
|
||||
import litellm
|
||||
from litellm.llms.openai.openai import OpenAIConfig
|
||||
from litellm.llms.openai.chat.gpt_5_transformation import OpenAIGPT5Config
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def config() -> OpenAIConfig:
|
||||
return OpenAIConfig()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def gpt5_config() -> OpenAIGPT5Config:
|
||||
return OpenAIGPT5Config()
|
||||
|
||||
|
||||
def test_gpt5_supports_reasoning_effort(config: OpenAIConfig):
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(model="gpt-5")
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(model="gpt-5-mini")
|
||||
|
||||
|
||||
def test_gpt5_maps_max_tokens(config: OpenAIConfig):
|
||||
params = config.map_openai_params(
|
||||
non_default_params={"max_tokens": 10},
|
||||
@@ -52,3 +60,96 @@ def test_gpt5_unsupported_params_drop(config: OpenAIConfig):
|
||||
drop_params=True,
|
||||
)
|
||||
assert "top_p" not in params
|
||||
|
||||
|
||||
# GPT-5-Codex specific tests
|
||||
def test_gpt5_codex_model_detection(gpt5_config: OpenAIGPT5Config):
|
||||
"""Test that GPT-5-Codex models are correctly detected as GPT-5 models."""
|
||||
assert gpt5_config.is_model_gpt_5_model("gpt-5-codex")
|
||||
assert gpt5_config.is_model_gpt_5_codex_model("gpt-5-codex")
|
||||
|
||||
# Regular GPT-5 models should not be detected as codex
|
||||
assert not gpt5_config.is_model_gpt_5_codex_model("gpt-5")
|
||||
assert not gpt5_config.is_model_gpt_5_codex_model("gpt-5-mini")
|
||||
|
||||
|
||||
def test_gpt5_codex_supports_reasoning_effort(config: OpenAIConfig):
|
||||
"""Test that GPT-5-Codex supports reasoning_effort parameter."""
|
||||
assert "reasoning_effort" in config.get_supported_openai_params(model="gpt-5-codex")
|
||||
|
||||
|
||||
def test_gpt5_codex_maps_max_tokens(config: OpenAIConfig):
|
||||
"""Test that GPT-5-Codex correctly maps max_tokens to max_completion_tokens."""
|
||||
params = config.map_openai_params(
|
||||
non_default_params={"max_tokens": 100},
|
||||
optional_params={},
|
||||
model="gpt-5-codex",
|
||||
drop_params=False,
|
||||
)
|
||||
assert params["max_completion_tokens"] == 100
|
||||
assert "max_tokens" not in params
|
||||
|
||||
|
||||
def test_gpt5_codex_temperature_drop(config: OpenAIConfig):
|
||||
"""Test that GPT-5-Codex drops unsupported temperature values when drop_params=True."""
|
||||
params = config.map_openai_params(
|
||||
non_default_params={"temperature": 0.7},
|
||||
optional_params={},
|
||||
model="gpt-5-codex",
|
||||
drop_params=True,
|
||||
)
|
||||
assert "temperature" not in params
|
||||
|
||||
|
||||
def test_gpt5_codex_temperature_error(config: OpenAIConfig):
|
||||
"""Test that GPT-5-Codex raises error for unsupported temperature when drop_params=False."""
|
||||
with pytest.raises(
|
||||
litellm.utils.UnsupportedParamsError,
|
||||
match="gpt-5 models \\(including gpt-5-codex\\)",
|
||||
):
|
||||
config.map_openai_params(
|
||||
non_default_params={"temperature": 0.7},
|
||||
optional_params={},
|
||||
model="gpt-5-codex",
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
|
||||
|
||||
def test_gpt5_codex_temperature_one_allowed(config: OpenAIConfig):
|
||||
"""Test that GPT-5-Codex allows temperature=1."""
|
||||
params = config.map_openai_params(
|
||||
non_default_params={"temperature": 1.0},
|
||||
optional_params={},
|
||||
model="gpt-5-codex",
|
||||
drop_params=False,
|
||||
)
|
||||
assert params["temperature"] == 1.0
|
||||
|
||||
|
||||
def test_gpt5_codex_unsupported_params_drop(config: OpenAIConfig):
|
||||
"""Test that GPT-5-Codex drops unsupported parameters."""
|
||||
unsupported_params = [
|
||||
"top_p",
|
||||
"presence_penalty",
|
||||
"frequency_penalty",
|
||||
"logprobs",
|
||||
"top_logprobs",
|
||||
]
|
||||
|
||||
for param in unsupported_params:
|
||||
assert param not in config.get_supported_openai_params(model="gpt-5-codex")
|
||||
|
||||
|
||||
def test_gpt5_codex_supports_tool_choice(gpt5_config: OpenAIGPT5Config):
|
||||
"""Test that GPT-5-Codex supports tool_choice parameter."""
|
||||
supported_params = gpt5_config.get_supported_openai_params(model="gpt-5-codex")
|
||||
assert "tool_choice" in supported_params
|
||||
|
||||
|
||||
def test_gpt5_codex_supports_function_calling(config: OpenAIConfig):
|
||||
"""Test that GPT-5-Codex supports function calling parameters."""
|
||||
supported_params = config.get_supported_openai_params(model="gpt-5-codex")
|
||||
assert "functions" in supported_params
|
||||
assert "function_call" in supported_params
|
||||
assert "tools" in supported_params
|
||||
|
||||
Reference in New Issue
Block a user