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
This commit is contained in:
Shreshth Kharbanda 2026-09-23 13:30:57 -07:00
parent e0af9917a1
commit 1fbaa3d790
4 changed files with 16 additions and 8 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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:

View file

@ -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():