fix(xai): correct cached token cost calculation for xAI models (#19772)

* fix(azure): use generic cost calculator for audio token pricing

Azure audio models were charging audio output tokens at the text token
rate instead of the correct audio token rate. This resulted in costs
being ~6.65x lower than expected.

The fix replaces Azure's custom cost calculation logic with the generic
cost calculator that properly handles text, audio, cached, reasoning,
and image tokens.

Fixes #19764

* fix(xai): correct cached token cost calculation for xAI models

- Fix double-counting issue where xAI reports text_tokens = prompt_tokens
  (including cached), causing tokens to be charged twice
- Add cache_read_input_token_cost to xAI grok-3 and grok-3-mini model variants
- Detection: when text_tokens + cached_tokens > prompt_tokens, recalculate
  text_tokens = prompt_tokens - cached_tokens

xAI pricing (25% of input for cached):
- grok-3 variants: $0.75/M cached (input $3/M)
- grok-3-mini variants: $0.075/M cached (input $0.30/M)
This commit is contained in:
Cesar Garcia 2026-01-27 02:00:35 -03:00 • committed by GitHub
parent 16f456ad82
commit e4a557d95f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 5 deletions

View file

@ -566,14 +566,28 @@ def generic_cost_per_token( # noqa: PLR0915
if usage.prompt_tokens_details:
prompt_tokens_details = _parse_prompt_tokens_details(usage)
## EDGE CASE - text tokens not set inside PromptTokensDetails
## EDGE CASE - text tokens not set or includes cached tokens (double-counting)
## Some providers (like xAI) report text_tokens = prompt_tokens (including cached)
## We detect this when: text_tokens + cached_tokens + other > prompt_tokens
## Ref: https://github.com/BerriAI/litellm/issues/19680, #14874, #14875
if prompt_tokens_details["text_tokens"] == 0:
cache_hit = prompt_tokens_details["cache_hit_tokens"]
text_tokens = prompt_tokens_details["text_tokens"]
audio_tokens = prompt_tokens_details["audio_tokens"]
cache_creation = prompt_tokens_details["cache_creation_tokens"]
image_tokens = prompt_tokens_details["image_tokens"]
# Check for double-counting: sum of details > prompt_tokens means overlap
total_details = text_tokens + cache_hit + audio_tokens + cache_creation + image_tokens
has_double_counting = cache_hit > 0 and total_details > usage.prompt_tokens
if text_tokens == 0 or has_double_counting:
text_tokens = (
usage.prompt_tokens
- prompt_tokens_details["cache_hit_tokens"]
- prompt_tokens_details["audio_tokens"]
- prompt_tokens_details["cache_creation_tokens"]
- cache_hit
- audio_tokens
- cache_creation
- image_tokens
)
prompt_tokens_details["text_tokens"] = text_tokens

View file

@ -30382,6 +30382,7 @@
"supports_web_search": true
},
"xai/grok-3": {
"cache_read_input_token_cost": 7.5e-07,
"input_cost_per_token": 3e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30396,6 +30397,7 @@
"supports_web_search": true
},
"xai/grok-3-beta": {
"cache_read_input_token_cost": 7.5e-07,
"input_cost_per_token": 3e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30410,6 +30412,7 @@
"supports_web_search": true
},
"xai/grok-3-fast-beta": {
"cache_read_input_token_cost": 1.25e-06,
"input_cost_per_token": 5e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30424,6 +30427,7 @@
"supports_web_search": true
},
"xai/grok-3-fast-latest": {
"cache_read_input_token_cost": 1.25e-06,
"input_cost_per_token": 5e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30438,6 +30442,7 @@
"supports_web_search": true
},
"xai/grok-3-latest": {
"cache_read_input_token_cost": 7.5e-07,
"input_cost_per_token": 3e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30452,6 +30457,7 @@
"supports_web_search": true
},
"xai/grok-3-mini": {
"cache_read_input_token_cost": 7.5e-08,
"input_cost_per_token": 3e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30467,6 +30473,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-beta": {
"cache_read_input_token_cost": 7.5e-08,
"input_cost_per_token": 3e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30482,6 +30489,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-fast": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 6e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30497,6 +30505,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-fast-beta": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 6e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30512,6 +30521,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-fast-latest": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 6e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30527,6 +30537,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-latest": {
"cache_read_input_token_cost": 7.5e-08,
"input_cost_per_token": 3e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,

View file

@ -30384,6 +30384,7 @@
"supports_web_search": true
},
"xai/grok-3": {
"cache_read_input_token_cost": 7.5e-07,
"input_cost_per_token": 3e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30398,6 +30399,7 @@
"supports_web_search": true
},
"xai/grok-3-beta": {
"cache_read_input_token_cost": 7.5e-07,
"input_cost_per_token": 3e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30412,6 +30414,7 @@
"supports_web_search": true
},
"xai/grok-3-fast-beta": {
"cache_read_input_token_cost": 1.25e-06,
"input_cost_per_token": 5e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30426,6 +30429,7 @@
"supports_web_search": true
},
"xai/grok-3-fast-latest": {
"cache_read_input_token_cost": 1.25e-06,
"input_cost_per_token": 5e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30440,6 +30444,7 @@
"supports_web_search": true
},
"xai/grok-3-latest": {
"cache_read_input_token_cost": 7.5e-07,
"input_cost_per_token": 3e-06,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30454,6 +30459,7 @@
"supports_web_search": true
},
"xai/grok-3-mini": {
"cache_read_input_token_cost": 7.5e-08,
"input_cost_per_token": 3e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30469,6 +30475,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-beta": {
"cache_read_input_token_cost": 7.5e-08,
"input_cost_per_token": 3e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30484,6 +30491,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-fast": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 6e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30499,6 +30507,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-fast-beta": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 6e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30514,6 +30523,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-fast-latest": {
"cache_read_input_token_cost": 1.5e-07,
"input_cost_per_token": 6e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,
@ -30529,6 +30539,7 @@
"supports_web_search": true
},
"xai/grok-3-mini-latest": {
"cache_read_input_token_cost": 7.5e-08,
"input_cost_per_token": 3e-07,
"litellm_provider": "xai",
"max_input_tokens": 131072,