This commit is contained in:
Soroush Ahmadi 2026-09-12 08:24:02 -04:00 committed by GitHub
commit c99a8e5817
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 46 additions and 5 deletions

View file

@ -310,6 +310,17 @@ def _transcription_usage_has_token_details(
return (prompt_tokens_val > 0) or (completion_tokens_val > 0)
def _coerce_token_count(value: float | str | None) -> int:
if value is None:
return 0
if isinstance(value, str):
try:
return int(value)
except ValueError:
return 0
return int(value)
def cost_per_token(
model: str = "",
prompt_tokens: int = 0,
@ -367,14 +378,17 @@ def cost_per_token(
if model is None:
raise Exception("Invalid arg. Model cannot be none.")
prompt_token_count = _coerce_token_count(prompt_tokens)
completion_token_count = _coerce_token_count(completion_tokens)
## RECONSTRUCT USAGE BLOCK ##
if usage_object is not None:
usage_block = usage_object
else:
usage_block = Usage(
prompt_tokens=prompt_tokens,
completion_tokens=completion_tokens,
total_tokens=prompt_tokens + completion_tokens,
prompt_tokens=prompt_token_count,
completion_tokens=completion_token_count,
total_tokens=prompt_token_count + completion_token_count,
cache_creation_input_tokens=cache_creation_input_tokens,
cache_read_input_tokens=cache_read_input_tokens,
)
@ -418,13 +432,13 @@ def cost_per_token(
# Anthropic reports prompt_tokens as input_tokens (excluding cache tokens).
# Adjust so the helper's "prompt_tokens includes cache tokens" invariant holds.
_normalized_prompt_tokens = float(prompt_tokens)
_normalized_prompt_tokens = float(prompt_token_count)
if _is_anthropic_style:
_normalized_prompt_tokens += _cache_read_tokens + _cache_creation_tokens
response_cost: Final = _cost_per_token_custom_pricing_helper(
prompt_tokens=_normalized_prompt_tokens,
completion_tokens=completion_tokens,
completion_tokens=completion_token_count,
response_time_ms=response_time_ms,
cached_tokens=_cache_read_tokens,
cache_creation_tokens=_cache_creation_tokens,

View file

@ -4768,3 +4768,30 @@ def test_collect_and_combine_realtime_usage_stores_partitioned_text_tokens() ->
assert combined.completion_tokens_details.reasoning_tokens == 95
assert combined.completion_tokens_details.text_tokens == 38
assert combined.completion_tokens_details.audio_tokens == 0
def test_cost_per_token_none_token_counts_cost_zero():
prompt_cost, completion_cost = cost_per_token(
model="gpt-4o-mini", prompt_tokens=None, completion_tokens=None
)
assert prompt_cost == 0.0
assert completion_cost == 0.0
def test_cost_per_token_string_token_counts_coerced():
prompt_cost, completion_cost = cost_per_token(
model="gpt-4o-mini", prompt_tokens="10", completion_tokens=5
)
expected_prompt, expected_completion = cost_per_token(
model="gpt-4o-mini", prompt_tokens=10, completion_tokens=5
)
assert prompt_cost == expected_prompt
assert completion_cost == expected_completion
def test_cost_per_token_garbage_string_counts_cost_zero():
prompt_cost, completion_cost = cost_per_token(
model="gpt-4o-mini", prompt_tokens="abc", completion_tokens=5
)
expected_prompt, _ = cost_per_token(
model="gpt-4o-mini", prompt_tokens=0, completion_tokens=5
)
assert prompt_cost == expected_prompt