From 9acf527e96285e434628a62a958e0b5d248d543c Mon Sep 17 00:00:00 2001 From: gorquan Date: Fri, 10 Jul 2026 16:00:42 +0800 Subject: [PATCH] fix(pricing): remove gpt-image-2 text output cost --- ...odel_prices_and_context_window_backup.json | 4 --- model_prices_and_context_window.json | 4 --- .../test_gpt_image_cost_calculator.py | 19 +++--------- tests/test_litellm/test_utils.py | 29 +++++++++++++++++-- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index a6f59abc140..ae7061e5b96 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -7195,7 +7195,6 @@ "input_cost_per_image_token": 8e-06, "litellm_provider": "azure", "mode": "image_generation", - "output_cost_per_token": 1e-05, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ "/v1/images/generations", @@ -7210,7 +7209,6 @@ "input_cost_per_image_token": 8e-06, "litellm_provider": "azure", "mode": "image_generation", - "output_cost_per_token": 1e-05, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ "/v1/images/generations", @@ -22189,7 +22187,6 @@ "input_cost_per_token": 5e-06, "litellm_provider": "openai", "mode": "image_generation", - "output_cost_per_token": 1e-05, "input_cost_per_image_token": 8e-06, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ @@ -22204,7 +22201,6 @@ "input_cost_per_token": 5e-06, "litellm_provider": "openai", "mode": "image_generation", - "output_cost_per_token": 1e-05, "input_cost_per_image_token": 8e-06, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 08a452be844..54ba292b950 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -7195,7 +7195,6 @@ "input_cost_per_image_token": 8e-06, "litellm_provider": "azure", "mode": "image_generation", - "output_cost_per_token": 1e-05, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ "/v1/images/generations", @@ -7210,7 +7209,6 @@ "input_cost_per_image_token": 8e-06, "litellm_provider": "azure", "mode": "image_generation", - "output_cost_per_token": 1e-05, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ "/v1/images/generations", @@ -22264,7 +22262,6 @@ "input_cost_per_token": 5e-06, "litellm_provider": "openai", "mode": "image_generation", - "output_cost_per_token": 1e-05, "input_cost_per_image_token": 8e-06, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ @@ -22279,7 +22276,6 @@ "input_cost_per_token": 5e-06, "litellm_provider": "openai", "mode": "image_generation", - "output_cost_per_token": 1e-05, "input_cost_per_image_token": 8e-06, "output_cost_per_image_token": 3e-05, "supported_endpoints": [ diff --git a/tests/test_litellm/test_gpt_image_cost_calculator.py b/tests/test_litellm/test_gpt_image_cost_calculator.py index c371f7442be..0eb962e8712 100644 --- a/tests/test_litellm/test_gpt_image_cost_calculator.py +++ b/tests/test_litellm/test_gpt_image_cost_calculator.py @@ -175,8 +175,7 @@ class TestGPTImageCostCalculator: image_tokens=500, ), completion_tokens_details=CompletionTokensDetailsWrapper( - text_tokens=1000, - image_tokens=4000, + image_tokens=5000, ), ) @@ -192,12 +191,7 @@ class TestGPTImageCostCalculator: custom_llm_provider="openai", ) - # GPT Image 2 pricing: - # Text input: 100 * $5/1M = 0.0005 - # Image input: 500 * $8/1M = 0.004 - # Text output: 1000 * $10/1M = 0.01 - # Image output: 4000 * $30/1M = 0.12 - expected_cost = 0.0005 + 0.004 + 0.01 + 0.12 + expected_cost = 100 * 5e-6 + 500 * 8e-6 + 5000 * 3e-5 assert abs(cost - expected_cost) < 1e-6, f"Expected {expected_cost}, got {cost}" @@ -432,10 +426,7 @@ class TestGPTImage2OutputImageTokensNoBreakdown: f"are likely being priced at the text output_cost_per_token rate." ) - def test_gpt_image_2_chat_usage_without_breakdown_is_costed_not_zero(self): - """A chat ``Usage`` with ``completion_tokens_details=None`` must still be - costed via ``generic_cost_per_token`` (output at the text rate) rather than - erroring or silently returning 0.0.""" + def test_gpt_image_2_chat_usage_without_breakdown_uses_image_rate(self): from litellm.llms.openai.image_generation.cost_calculator import ( cost_calculator, ) @@ -463,9 +454,7 @@ class TestGPTImage2OutputImageTokensNoBreakdown: custom_llm_provider="openai", ) - # No output breakdown -> output priced at the text rate (output_cost_per_token): - # text in 100*$5/1M + image in 500*$8/1M + output 5000*$10/1M - expected_cost = 100 * 5e-6 + 500 * 8e-6 + 5000 * 1e-5 + expected_cost = 100 * 5e-6 + 500 * 8e-6 + 5000 * 3e-5 assert abs(cost - expected_cost) < 1e-6, f"Expected {expected_cost}, got {cost}" diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index 1a5c419754b..33b8bacc1f4 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -247,7 +247,7 @@ def test_gpt_image_2_provider_and_model_info(local_model_cost_map): assert model_info["mode"] == "image_generation" assert model_info["input_cost_per_token"] == 5e-06 assert model_info["input_cost_per_image_token"] == 8e-06 - assert model_info["output_cost_per_token"] == 1e-05 + assert model_info["output_cost_per_token"] == 0 assert model_info["output_cost_per_image_token"] == 3e-05 assert ( "/v1/images/generations" @@ -271,6 +271,7 @@ def test_gpt_image_2_snapshot_model_info(local_model_cost_map): model_info = litellm.get_model_info(model="gpt-image-2-2026-04-21") assert model_info["litellm_provider"] == "openai" assert model_info["mode"] == "image_generation" + assert model_info["output_cost_per_token"] == 0 assert model_info["output_cost_per_image_token"] == 3e-05 @@ -289,10 +290,34 @@ def test_azure_gpt_image_2_model_info(local_model_cost_map): assert model_info["mode"] == "image_generation" assert model_info["input_cost_per_token"] == 5e-06 assert model_info["input_cost_per_image_token"] == 8e-06 - assert model_info["output_cost_per_token"] == 1e-05 + assert model_info["output_cost_per_token"] == 0 assert model_info["output_cost_per_image_token"] == 3e-05 +def test_gpt_image_2_cost_maps_have_no_text_output_price(): + repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")) + cost_map_paths = ( + os.path.join(repo_root, "model_prices_and_context_window.json"), + os.path.join( + repo_root, "litellm", "model_prices_and_context_window_backup.json" + ), + ) + model_names = ( + "gpt-image-2", + "gpt-image-2-2026-04-21", + "azure/gpt-image-2", + "azure/gpt-image-2-2026-04-21", + ) + + for cost_map_path in cost_map_paths: + with open(cost_map_path) as cost_map_file: + cost_map = json.load(cost_map_file) + + for model_name in model_names: + assert "output_cost_per_token" not in cost_map[model_name] + assert cost_map[model_name]["output_cost_per_image_token"] == 3e-05 + + def test_all_model_configs(): from litellm.llms.vertex_ai.vertex_ai_partner_models.ai21.transformation import ( VertexAIAi21Config,