fix(cost): bill auto image size at the default and fall back when image tokens are unpriceable
Some checks failed
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
LiteLLM Rust / rust-lint (push) Has been cancelled
LiteLLM Rust / rust-test (push) Has been cancelled
LiteLLM Rust / rust-wheel (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-09-22 02:13:29 +00:00
parent cc6044aacc
commit 9cf8ef4cec
2 changed files with 91 additions and 4 deletions

View file

@ -277,7 +277,7 @@ class StandardBuiltInToolCostTracking:
custom_llm_provider=custom_llm_provider or "openai",
quality=quality if isinstance(quality, str) and quality != "auto" else None,
n=1,
size=size if isinstance(size, str) else None,
size=size if isinstance(size, str) and size != "auto" else None,
)
except Exception as e: # noqa: BLE001 # pricing helpers raise bare Exception for unmapped models; bill 0.0
verbose_logger.debug("Could not price Responses API image_generation_call item: %s", e)
@ -294,19 +294,20 @@ class StandardBuiltInToolCostTracking:
model_info: Final = litellm.get_model_info(
model=tool_model, custom_llm_provider=custom_llm_provider or "openai"
)
except Exception as e: # noqa: BLE001 # get_model_info raises bare Exception for unmapped models; bill 0.0
except Exception as e: # noqa: BLE001 # get_model_info raises bare Exception for unmapped models; fall back
verbose_logger.debug("Could not resolve pricing for image tool model %s: %s", tool_model, e)
return 0.0
return None
image_gen: Final = tool_usage.image_gen
input_details: Final = image_gen.input_tokens_details
output_details: Final = image_gen.output_tokens_details
return (
token_cost: Final = (
(input_details.text_tokens if input_details else 0) * (model_info.get("input_cost_per_token") or 0)
+ (input_details.image_tokens if input_details else 0) * (model_info.get("input_cost_per_image_token") or 0)
+ (output_details.image_tokens if output_details else 0)
* (model_info.get("output_cost_per_image_token") or 0)
+ (output_details.text_tokens if output_details else 0) * (model_info.get("output_cost_per_token") or 0)
)
return token_cost if token_cost > 0 else None
@staticmethod
def _handle_image_generation_cost(response_object: object, custom_llm_provider: str | None) -> float:

View file

@ -990,3 +990,89 @@ def test_responses_zero_image_gen_tokens_fall_back_to_per_image_pricing(local_mo
)
)
assert cost > 0
def test_responses_auto_size_image_generation_call_billed_at_default_size(local_model_cost_map):
"""An image_generation_call with size "auto" bills at the default size instead of erroring to $0."""
from litellm.cost_calculator import default_image_cost_calculator
response = _openai_responses_response(
"gpt-5",
[
{
"type": "image_generation_call",
"id": "ig_1",
"status": "completed",
"quality": "high",
"size": "auto",
"result": "AAAA",
}
],
)
cost = StandardBuiltInToolCostTracking.get_cost_for_built_in_tools(
model="gpt-5",
response_object=response,
usage=None,
custom_llm_provider="openai",
standard_built_in_tools_params=None,
)
assert cost == pytest.approx(
default_image_cost_calculator(
model="gpt-image-1",
custom_llm_provider="openai",
quality="high",
n=1,
size=None,
)
)
assert cost > 0
def test_responses_image_gen_total_without_token_details_falls_back_to_per_image(local_model_cost_map):
"""A positive image_gen total with no token details falls back to per-image pricing, not $0."""
tool_model = "gpt-image-1"
quality = "low"
size = "1024x1024"
response = _openai_responses_response(
"gpt-5",
[
{
"type": "image_generation_call",
"id": "ig_1",
"status": "completed",
"quality": quality,
"size": size,
"result": "AAAA",
}
],
usage={
"input_tokens": 10,
"output_tokens": 5,
"total_tokens": 15,
"tool_usage": {"image_gen": {"input_tokens": 5, "output_tokens": 5, "total_tokens": 10}},
},
tools=[{"type": "image_generation", "model": tool_model, "quality": quality, "size": size}],
)
cost = StandardBuiltInToolCostTracking.get_cost_for_built_in_tools(
model="gpt-5",
response_object=response,
usage=None,
custom_llm_provider="openai",
standard_built_in_tools_params=None,
)
from litellm.cost_calculator import default_image_cost_calculator
assert cost == pytest.approx(
default_image_cost_calculator(
model=tool_model,
custom_llm_provider="openai",
quality=quality,
n=1,
size=size,
)
)
assert cost > 0