From b2080ec9affc685938c2ba8cd11407fd83d6d567 Mon Sep 17 00:00:00 2001 From: Cole McIntosh <82463175+colesmcintosh@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:56:05 -0600 Subject: [PATCH] feat: add input_fidelity parameter for OpenAI image generation (#12662) * feat: add input_fidelity parameter for OpenAI image generation - Add input_fidelity to OpenAIImageGenerationOptionalParams type - Update image_generation function signature to accept input_fidelity - Add input_fidelity to default_params in get_optional_params_image_gen - Include input_fidelity in openai_params list for proper handling - Update documentation with input_fidelity parameter description - Add test for input_fidelity parameter functionality This enables control over how closely the model follows the input prompt for gpt-image-1 model, improving prompt adherence and image quality. * feat: add input_fidelity to optional parameters for image generation - Include input_fidelity in the list of OpenAIImageGenerationOptionalParams - This addition enhances the flexibility of image generation by allowing control over input fidelity. * test: enhance test for gpt-image-1 with input_fidelity parameter - Update test_gpt_image_1_with_input_fidelity to include mocking of OpenAI response - Validate that the OpenAI client is called with correct parameters, including input_fidelity - Improve response validation to ensure expected output structure and values --- docs/my-website/docs/image_generation.md | 2 + litellm/images/main.py | 3 + .../image_generation/gpt_transformation.py | 1 + litellm/types/llms/openai.py | 1 + litellm/utils.py | 2 + .../image_gen_tests/test_image_generation.py | 63 +++++++++++++++++++ 6 files changed, 72 insertions(+) diff --git a/docs/my-website/docs/image_generation.md b/docs/my-website/docs/image_generation.md index b16c60f55b..33e4c7b4cc 100644 --- a/docs/my-website/docs/image_generation.md +++ b/docs/my-website/docs/image_generation.md @@ -124,6 +124,8 @@ Any non-openai params, will be treated as provider-specific params, and sent in - `size`: *string (optional)* The size of the generated images. Must be one of `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto` (default value) for `gpt-image-1`, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`. +- `input_fidelity`: *string (optional)* Controls how closely the model follows the input prompt. Supported for `gpt-image-1` model. Higher fidelity may improve prompt adherence but could affect generation speed. + - `timeout`: *integer* - The maximum time, in seconds, to wait for the API to respond. Defaults to 600 seconds (10 minutes). - `user`: *string (optional)* A unique identifier representing your end-user, diff --git a/litellm/images/main.py b/litellm/images/main.py index 8da4ce3d59..cf9ea7a662 100644 --- a/litellm/images/main.py +++ b/litellm/images/main.py @@ -111,6 +111,7 @@ def image_generation( # noqa: PLR0915 size: Optional[str] = None, style: Optional[str] = None, user: Optional[str] = None, + input_fidelity: Optional[str] = None, timeout=600, # default to 10 minutes api_key: Optional[str] = None, api_base: Optional[str] = None, @@ -168,6 +169,7 @@ def image_generation( # noqa: PLR0915 "quality", "size", "style", + "input_fidelity", ] litellm_params = all_litellm_params default_params = openai_params + litellm_params @@ -195,6 +197,7 @@ def image_generation( # noqa: PLR0915 size=size, style=style, user=user, + input_fidelity=input_fidelity, custom_llm_provider=custom_llm_provider, provider_config=image_generation_config, **non_default_params, diff --git a/litellm/llms/openai/image_generation/gpt_transformation.py b/litellm/llms/openai/image_generation/gpt_transformation.py index 1cee13784e..150cffba21 100644 --- a/litellm/llms/openai/image_generation/gpt_transformation.py +++ b/litellm/llms/openai/image_generation/gpt_transformation.py @@ -16,6 +16,7 @@ class GPTImageGenerationConfig(BaseImageGenerationConfig): ) -> List[OpenAIImageGenerationOptionalParams]: return [ "background", + "input_fidelity", "moderation", "n", "output_compression", diff --git a/litellm/types/llms/openai.py b/litellm/types/llms/openai.py index 97c940c71a..1955bfac5f 100644 --- a/litellm/types/llms/openai.py +++ b/litellm/types/llms/openai.py @@ -903,6 +903,7 @@ OpenAIImageVariationOptionalParams = Literal["n", "size", "response_format", "us OpenAIImageGenerationOptionalParams = Literal[ "background", + "input_fidelity", "moderation", "n", "output_compression", diff --git a/litellm/utils.py b/litellm/utils.py index 82cea70e52..fb87a4551c 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -2451,6 +2451,7 @@ def get_optional_params_image_gen( size: Optional[str] = None, style: Optional[str] = None, user: Optional[str] = None, + input_fidelity: Optional[str] = None, custom_llm_provider: Optional[str] = None, additional_drop_params: Optional[bool] = None, provider_config: Optional[BaseImageGenerationConfig] = None, @@ -2487,6 +2488,7 @@ def get_optional_params_image_gen( "size": None, "style": None, "user": None, + "input_fidelity": None, } non_default_params = _get_non_default_params( diff --git a/tests/image_gen_tests/test_image_generation.py b/tests/image_gen_tests/test_image_generation.py index b2e95ff966..cc277f7481 100644 --- a/tests/image_gen_tests/test_image_generation.py +++ b/tests/image_gen_tests/test_image_generation.py @@ -242,3 +242,66 @@ async def test_aimage_generation_bedrock_with_optional_params(): else: pytest.fail(f"An exception occurred - {str(e)}") + +@pytest.mark.asyncio +async def test_gpt_image_1_with_input_fidelity(): + """Test gpt-image-1 with input_fidelity parameter (mocked)""" + from unittest.mock import AsyncMock, patch + + # Mock OpenAI response + mock_openai_response = { + "created": 1703658209, + "data": [ + { + "url": "https://example.com/generated_image.png" + } + ] + } + + # Create a proper mock response object + class MockResponse: + def model_dump(self): + return mock_openai_response + + # Create a mock client with the images.generate method + mock_client = AsyncMock() + mock_client.images.generate = AsyncMock(return_value=MockResponse()) + + # Capture the actual arguments sent to OpenAI client + captured_args = None + captured_kwargs = None + + async def capture_generate_call(*args, **kwargs): + nonlocal captured_args, captured_kwargs + captured_args = args + captured_kwargs = kwargs + return MockResponse() + + mock_client.images.generate.side_effect = capture_generate_call + + # Mock the _get_openai_client method to return our mock client + with patch.object(litellm.main.openai_chat_completions, '_get_openai_client', return_value=mock_client): + response = await litellm.aimage_generation( + prompt="A cute baby sea otter", + model="gpt-image-1", + input_fidelity="high", + quality="medium", + size="1024x1024", + ) + + # Validate the response + assert response is not None + assert response.created == 1703658209 + assert response.data is not None + assert len(response.data) == 1 + assert response.data[0].url == "https://example.com/generated_image.png" + + # Validate that the OpenAI client was called with correct parameters + mock_client.images.generate.assert_called_once() + assert captured_kwargs is not None + assert captured_kwargs["model"] == "gpt-image-1" + assert captured_kwargs["prompt"] == "A cute baby sea otter" + assert captured_kwargs["input_fidelity"] == "high" + assert captured_kwargs["quality"] == "medium" + assert captured_kwargs["size"] == "1024x1024" +