mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
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
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:
parent
cc6044aacc
commit
9cf8ef4cec
2 changed files with 91 additions and 4 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue