From 1fbaa3d7905c5bd8ee057bf688d4670c91683506 Mon Sep 17 00:00:00 2001 From: Shreshth Kharbanda Date: Wed, 23 Sep 2026 13:30:57 -0700 Subject: [PATCH] fix(azure_ai): price FLUX.2-flex pixels per 1024x1024 megapixel The Flex row stored 0.05 / 1,000,000 per pixel, so a 1024x1024 image billed 0.0524288 instead of 0.05. Azure and Black Forest Labs define one megapixel as 1,048,576 pixels, so the rate is 0.05 / 1048576, exact in float64. Tests that pinned the old literal now derive the rate from the catalog and assert the invariant our code owns: one 1024x1024 image prices at exactly one megapixel --- litellm/model_prices_and_context_window_backup.json | 2 +- model_prices_and_context_window.json | 2 +- .../test_azure_ai_flux2_image_generation.py | 12 ++++++++---- .../test_azure_ai_image_edit_transformation.py | 8 ++++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 4a058eafd1f..74f52a488de 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -10963,7 +10963,7 @@ ] }, "azure_ai/FLUX.2-flex": { - "input_cost_per_pixel": 5e-08, + "input_cost_per_pixel": 4.76837158203125e-08, "litellm_provider": "azure_ai", "max_input_tokens": 32000, "max_tokens": 32000, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 4a058eafd1f..74f52a488de 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -10963,7 +10963,7 @@ ] }, "azure_ai/FLUX.2-flex": { - "input_cost_per_pixel": 5e-08, + "input_cost_per_pixel": 4.76837158203125e-08, "litellm_provider": "azure_ai", "max_input_tokens": 32000, "max_tokens": 32000, diff --git a/tests/test_litellm/llms/azure_ai/image_generation/test_azure_ai_flux2_image_generation.py b/tests/test_litellm/llms/azure_ai/image_generation/test_azure_ai_flux2_image_generation.py index fdd21c87732..54713e1a5eb 100644 --- a/tests/test_litellm/llms/azure_ai/image_generation/test_azure_ai_flux2_image_generation.py +++ b/tests/test_litellm/llms/azure_ai/image_generation/test_azure_ai_flux2_image_generation.py @@ -28,6 +28,10 @@ def use_local_model_cost_map(monkeypatch): _invalidate_model_cost_lowercase_map() +def _flex_pixel_rate() -> float: + return litellm.model_cost["azure_ai/FLUX.2-flex"]["input_cost_per_pixel"] + + @pytest.mark.parametrize( ("model", "provider_path"), [ @@ -127,7 +131,7 @@ def test_flux2_flex_model_info(): assert model_info["max_input_tokens"] == 32000 assert model_info["max_tokens"] == 32000 assert model_info["supported_endpoints"] == ["/v1/images/generations", "/v1/images/edits"] - assert catalog_info["input_cost_per_pixel"] == 5e-08 + assert catalog_info["input_cost_per_pixel"] * 1024 * 1024 == pytest.approx(0.05) assert catalog_info["supported_modalities"] == ["text", "image"] assert catalog_info["supported_output_modalities"] == ["image"] @@ -148,7 +152,7 @@ def test_flux2_flex_cost_uses_generated_megapixels(): call_type="image_generation", ) - assert cost == pytest.approx(5e-08 * 2048 * 1024 * 2) + assert cost == pytest.approx(_flex_pixel_rate() * 2048 * 1024 * 2) @pytest.mark.parametrize("model", ("FLUX-1.1-pro", "FLUX.1-Kontext-pro")) @@ -189,7 +193,7 @@ def test_flux2_cost_uses_mapped_dimensions_after_response_transformation(dimensi completion_response=response, optional_params=params, call_type="image_generation", - ) == pytest.approx(5e-08 * 2048 * 1024 * 2) + ) == pytest.approx(_flex_pixel_rate() * 2048 * 1024 * 2) def test_flux2_flex_cost_accepts_lowercase_model_spelling(): @@ -202,7 +206,7 @@ def test_flux2_flex_cost_accepts_lowercase_model_spelling(): call_type="image_generation", ) - assert cost == pytest.approx(5e-08 * 1536 * 1024 * 2) + assert cost == pytest.approx(_flex_pixel_rate() * 1536 * 1024 * 2) def test_flux2_flex_cost_prefers_deployment_input_cost_per_pixel() -> None: diff --git a/tests/unit/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py b/tests/unit/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py index 51ba2c34cd7..5efdf1232a0 100644 --- a/tests/unit/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py +++ b/tests/unit/llms/azure_ai/image_edit/test_azure_ai_image_edit_transformation.py @@ -144,7 +144,9 @@ def test_flux2_image_edit_rejects_too_many_references(model: str, reference_imag ) -@pytest.mark.parametrize("dimensions", ({"size": "2048x1024"}, {"width": 2048, "height": 1024}, {"width": "2048", "height": "1024"})) +@pytest.mark.parametrize( + "dimensions", ({"size": "2048x1024"}, {"width": 2048, "height": 1024}, {"width": "2048", "height": "1024"}) +) @pytest.mark.usefixtures("local_model_cost_map") def test_flux2_image_edit_preserves_controls_and_pixel_cost(dimensions: Mapping[str, int | str]): def respond(request: httpx.Request) -> httpx.Response: @@ -175,7 +177,9 @@ def test_flux2_image_edit_preserves_controls_and_pixel_cost(dimensions: Mapping[ **dimensions, ) - assert response._hidden_params["response_cost"] == pytest.approx(5e-08 * 2048 * 1024 * 2) + assert response._hidden_params["response_cost"] == pytest.approx( + litellm.model_cost["azure_ai/FLUX.2-flex"]["input_cost_per_pixel"] * 2048 * 1024 * 2 + ) def test_flux2_image_edit_accepts_and_drops_openai_only_parameters():