Skip to content

fix(pricing): correct cached-token and limit fields on the realtime cost-map entries - #40018

Closed
marty-sullivan wants to merge 3 commits into
BerriAI:mainfrom
cu-aaii:fix-realtime-cost-map-residuals
Closed

marty-sullivan wants to merge 3 commits into
BerriAI:mainfrom
cu-aaii:fix-realtime-cost-map-residuals

Conversation

@marty-sullivan

@marty-sullivan marty-sullivan commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Three Gemini Live entries claim caching Google marks unsupported
  • Two of them price a cached read nothing publishes
  • The GA native-audio entry advertises an 8x oversized context window
  • It also claims three capabilities its own model card refuses
  • azure/gpt-realtime-2 prices one side of its cached-audio meter

How it solves it:

  • Drop the cached rate, set supports_prompt_caching: false
  • Take limits and capability flags from Google's model card
  • Add the cached-audio write rate from Azure's published meter
  • Tests that fail 8 of 9 cases against the base map

This revision reverses the 5e-08 cached rate the last review asked for, on that review's own reasoning. 7.5e-08 was refused because nothing published backs it, and nothing published backs 5e-08 either: the flat 90% discount is read off Gemini rows that sell caching, and this family does not sell it. Google's context-caching page names no Live model in either its implicit or explicit supported-model list, its pricing page prints N/A in both cached-input columns for every "Gemini 2.5 Flash Live API" row where plain 2.5 Flash carries $0.03, and the model card says "Context caching Not supported" outright. So the rate comes out instead of being rescaled, and the supports_prompt_caching: true that made an absent rate look like a pricing gap becomes false

On "not on the linked pricing pages": that page is the source upstream's own merged gemini-live-2.5-flash-native-audio entry already names, and it renders its tables in JavaScript, so anything that does not execute JS reports no prices at all. The shared setup below has the curl -sL that returns them, and the vendor reads there are the whole basis of this PR. Every value comes from a page a reviewer can open, with no rate inference anywhere. The azure/gpt-realtime-2 half is unchanged from the revision that was already accepted

User Flow

Before: a developer building on the GA Gemini Live model plans against the gateway's own catalog, and the numbers in it that matter are all wrong

  1. They read the catalog with GET https://litellm-domain/v1/model/info, and the gemini-live-2.5-flash-native-audio entry reports max_input_tokens: 1048576, supports_response_schema: true, supports_url_context: true, supports_pdf_input: true and supports_prompt_caching: true
  2. They size an 800,000-token prompt against that window. Google's card for this model ID gives a 128K context window, so the ceiling they planned against is eight times the real one and the prompt cannot fit
  3. They wire up a JSON response schema, a URL-context tool and a PDF attachment, because the catalog said all three were supported. Google's card marks structured output and URL context not supported and lists no document MIME type at all
  4. Reading supports_prompt_caching: true, they restructure their prompts around a shared prefix to earn the cached discount, replay a 7,021-token prefix across sessions minutes apart, and get no cached tokens reported back on any of them
  5. They check what a cached read would have cost on gemini-live-2.5-flash-preview-native-audio-09-2025: POST https://litellm-domain/spend/calculate with 100,000 cached and 1,000 fresh input tokens returns {"cost":0.008}, charging the cached tokens at $0.075 per 1M
  6. Nothing they can reach from the gateway tells them this model has a 128K window and no cache

After: the same catalog reports what Google documents, so the developer plans against the real limits and never chases a cache that does not exist

  1. The same GET https://litellm-domain/v1/model/info now reports max_input_tokens: 131072, supports_response_schema: false, supports_url_context: false, supports_pdf_input: false and supports_prompt_caching: false
  2. They size a 120,000-token prompt, which is inside the window Google documents
  3. They skip the response schema, the URL tool and the PDF attachment, because the catalog now says the model refuses all three
  4. They skip the shared-prefix restructuring, because the catalog says the model has no prompt caching
  5. The same POST https://litellm-domain/spend/calculate with 100,000 cached and 1,000 fresh input tokens returns {"cost":0.0005}, the fresh tokens alone at $0.50 per 1M
  6. Every limit and capability they planned against matches Google's own card for that model ID

Relevant issues

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Tests are three functions in tests/test_litellm/test_cost_calculator.py, nine cases in total. They check that no cached rate is present on any of the three Live entries and that a cached-token bill lands at the fresh-input total, that supports_prompt_caching answers false on all three with gemini-2.5-flash as a control so a swallowed lookup error cannot read as a pass, that the corrected limits and capability flags come back through both the bare and the vertex_ai/-prefixed name, and that the gpt-realtime-2 family agrees a cached audio read implies an equal cached audio write

Reverting the two map files to the merge base fails 8 of those 9 cases. The ninth asserts the GA entry carries no cached rate, which it already does not, because that is the state the two preview siblings are being brought to

tests/test_litellm/test_cost_calculator.py is 177 passed. Across the five files this change can reach (that file plus test_gemini_tts_native_audio_pricing.py, test_model_prices_schema.py, test_gpt_realtime_mode.py and test_utils.py) it is 618 passed, and 8 failed with 610 passed once the maps go back to the base. The three lint and type budget gates all report within ceiling and no budget file is touched

azure/gpt-realtime-2 is absent from the user flow above because nothing reads either audio cache key, so no caller observes a difference. It changes what the map declares, which is why its test is a family invariant rather than a billing assertion

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Shared setup. A proxy on the local cost map, with the two preview entries and azure/gpt-realtime-2 alongside the GA model, so one /v1/model/info read covers every entry this PR touches:

model_list:
  - model_name: gemini-live-2.5-flash-native-audio
    litellm_params:
      model: vertex_ai/gemini-live-2.5-flash-native-audio
      vertex_project: dummy-project
      vertex_location: global
  - model_name: gemini-live-preview-vertex
    litellm_params:
      model: vertex_ai/gemini-live-2.5-flash-preview-native-audio-09-2025
      vertex_project: dummy-project
      vertex_location: us-central1
  - model_name: gemini-live-preview-ai-studio
    litellm_params:
      model: gemini/gemini-live-2.5-flash-preview-native-audio-09-2025
      api_key: dummy-key
  - model_name: azure-gpt-realtime-2
    litellm_params:
      model: azure/gpt-realtime-2
      api_base: https://dummy.openai.azure.com
      api_key: dummy-key

general_settings:
  master_key: sk-proof-1234
LITELLM_LOCAL_MODEL_COST_MAP=True python litellm/proxy/proxy_cli.py --config proof_config.yaml --port 4111

The vendor reads below are the sources for every value in this PR. They are identical on both runs, so they sit here rather than being repeated under Before and After

Google's Vertex pricing page 301s to cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing and renders its tables in JavaScript. Fetching it with anything that does not execute JS returns navigation chrome and no prices, which is worth knowing before checking the cached columns. curl -sL returns them as ordinary <table> markup:

curl -sL 'https://cloud.google.com/vertex-ai/generative-ai/pricing' | python3 -c '
import sys,re,html
h=sys.stdin.read()
i=h.find("Gemini 2.5 Flash Live API")
ts=h.rfind("<table",0,i); te=h.find("</table>",i)
rows=[" | ".join(re.sub(r"\s+"," ",html.unescape(re.sub(r"<[^>]+>","",x))).strip()
      for x in re.findall(r"<t[hd][^>]*>(.*?)</t[hd]>", r, re.S))
      for r in re.findall(r"<tr[^>]*>(.*?)</tr>", h[ts:te+8], re.S)]
print(rows[0]); print(*rows[5:7], sep="\n"); print(*rows[11:18], sep="\n")'
Model | Type | Token Price <= 200K tokens | Price > 200K tokens | Price <= 200K cached input tokens | Price > 200K cached input tokens
Gemini 2.5 Flash | Input (text, image, video) | $0.30 | $0.30 | $0.03 | $0.03
 | Audio Input | $1.00 | $0.30 | $0.10 | $0.10
Gemini 2.5 Flash Live API | Input text | $0.50 | $0.50 | N/A | N/A
 | Input (video, image) | $3.00 | $3.00 | N/A | N/A
 | Audio Input | $3.00 | $3.00 | N/A | N/A
 | Text output | $2.00 | $2.00 | N/A | N/A
 | 1M output audio tokens | $12.00 | $12.00 | N/A | N/A
Gemini 2.5 Flash Lite | Input (text, image, video) | $0.10 | $0.10 | $0.01 | $0.01
 | Audio Input | $0.30 | $0.30 | $0.03 | $0.03

Every Live row is N/A in both cached-input columns, and the two Gemini 2.5 rows either side of it carry real cached prices, so the N/A is a statement about this product rather than a page that omits cached pricing. That is the same page the merged entry already cites:

jq '."gemini-live-2.5-flash-native-audio".source' model_prices_and_context_window.json
"https://cloud.google.com/vertex-ai/generative-ai/pricing"

Google's context-caching page carries the supported-model lists, and no Live or native-audio model is in either one. It also sets the minimum prefix a cache needs, which the replay in the user flow is well past:

curl -sL 'https://cloud.google.com/vertex-ai/generative-ai/docs/context-cache/context-cache-overview' | python3 -c '
import sys,re,html
h=re.sub(r"<(script|style)[^>]*>.*?</\1>","",sys.stdin.read(),flags=re.S)
t=re.sub(r"\s+"," ",html.unescape(re.sub(r"<[^>]+>"," ",h)))
for kind in ("Implicit","Explicit"):
    m=re.search(kind+r" caching is supported when using the following models:(.*?)(Implicit caching also|When to use)",t,re.S)
    print(kind+":", m.group(1).replace("Click to expand supported models","").strip())
i=t.find("Minimum cache token count"); print(t[i:t.find("Maximum size of content",i)].strip())'
Implicit: Gemini 3.8 Flash Gemini 3.7 Flash Gemini 3.6 Flash Gemini 3.5 Flash-Lite Gemini 3.5 Flash Gemini 3.1 Pro preview Gemini 3.1 Flash-Lite Image (Nano Banana 2 Lite) Gemini 3.1 Flash-Lite Gemini 3.1 Flash Image Gemini 3 Pro Image Gemini 3 Flash preview Gemini 2.5 Pro Gemini 2.5 Flash-Lite Gemini 2.5 Flash
Explicit: Gemini 3.8 Flash Gemini 3.7 Flash Gemini 3.6 Flash Gemini 3.5 Flash-Lite Gemini 3.5 Flash Gemini 3.1 Pro preview Gemini 3.1 Flash-Lite Gemini 3 Flash preview Gemini 2.5 Pro Gemini 2.5 Flash-Lite Gemini 2.5 Flash
Minimum cache token count for implicit and explicit caching Gemini 3 family models: 4,096 tokens Gemini 3.0 Flash Preview, 3.1 Pro Preview, 3.7 Flash, and 3.8 Flash (implicit caching only): 6,144 tokens Gemini 2 family models: 2,048 tokens

Google's model card for model ID gemini-live-2.5-flash-native-audio gives the limits and the three capability answers, and its footer reads "Last updated 2026-09-03 UTC":

curl -sL 'https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/2-5-flash-live-api' \
  | python3 -c 'import sys,re,html; t=re.sub(r"\s+"," ",html.unescape(re.sub(r"<[^>]+>"," ",sys.stdin.read()))); i=t.find("Token limits"); print(t[i:i+300])'
Token limits Context window 128K Maximum output tokens 64K Maximum concurrent sessions 1000 Capabilities Thinking Not supported System instructions Supported Gemini Live API Supported Structured output Not supported Context caching Not supported Count Tokens Not supported RAG Engine Not supported Ch

The same card lists MIME types for image, video and audio and no document type anywhere on the page, which is where supports_pdf_input: false comes from:

curl -sL 'https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/gemini/2-5-flash-live-api' | grep -c 'application/pdf'
0

Azure publishes the cached-audio meter for the gpt-realtime-2 deployment:

curl -sS -G "https://prices.azure.com/api/retail/prices" \
  --data-urlencode "currencyCode=USD" \
  --data-urlencode "\$filter=contains(meterName,'gpt-realtime-2 Audio cd inp')" \
  | jq -r '.Items[] | "\(.meterName)  \(.retailPrice)  \(.unitOfMeasure)"' | sort -u
gpt-realtime-2 Audio cd inp Gl 1M Tokens  0.4  1M

Before (168a005)

Context caching on the three Gemini Live entries

  1. Ask the running proxy what it declares about caching:
curl -s http://127.0.0.1:4111/v1/model/info -H 'Authorization: Bearer sk-proof-1234' \
  | jq -c '.data[] | select(.litellm_params.model | contains("gemini-live"))
           | {model: .litellm_params.model,
              cache_read_input_token_cost: .model_info.cache_read_input_token_cost,
              supports_prompt_caching: .model_info.supports_prompt_caching}'
{"model":"vertex_ai/gemini-live-2.5-flash-native-audio","cache_read_input_token_cost":null,"supports_prompt_caching":true}
{"model":"vertex_ai/gemini-live-2.5-flash-preview-native-audio-09-2025","cache_read_input_token_cost":7.5E-8,"supports_prompt_caching":true}
{"model":"gemini/gemini-live-2.5-flash-preview-native-audio-09-2025","cache_read_input_token_cost":7.5E-8,"supports_prompt_caching":true}

All three advertise prompt caching. Two of them price a cached read at 7.5e-08, a rate that appears on no Google page, and the GA entry advertises caching with no cached price at all

  1. Price 100,000 cached and 1,000 fresh input tokens on each:
for m in vertex_ai/gemini-live-2.5-flash-native-audio \
         vertex_ai/gemini-live-2.5-flash-preview-native-audio-09-2025 \
         gemini/gemini-live-2.5-flash-preview-native-audio-09-2025; do
  printf '%s  ' "$m"
  curl -s -X POST http://127.0.0.1:4111/spend/calculate -H 'Authorization: Bearer sk-proof-1234' \
    -H 'Content-Type: application/json' \
    -d "{\"completion_response\": {\"model\": \"$m\", \"usage\": {\"prompt_tokens\": 101000, \"completion_tokens\": 0, \"prompt_tokens_details\": {\"cached_tokens\": 100000}}}}"
  echo
done
vertex_ai/gemini-live-2.5-flash-native-audio  {"cost":0.0005}
vertex_ai/gemini-live-2.5-flash-preview-native-audio-09-2025  {"cost":0.008}
gemini/gemini-live-2.5-flash-preview-native-audio-09-2025  {"cost":0.008}

The GA entry charges $0.0005, the fresh tokens alone, while claiming to support caching. The two preview entries charge $0.008, which is $0.0075 of invented cached-token cost

Limits and capabilities on gemini-live-2.5-flash-native-audio

  1. Read the limits and the three capability flags the card speaks to:
curl -s http://127.0.0.1:4111/v1/model/info -H 'Authorization: Bearer sk-proof-1234' \
  | jq '.data[] | select(.model_name=="gemini-live-2.5-flash-native-audio") | .model_info
        | {max_input_tokens, max_output_tokens, max_tokens,
           supports_pdf_input, supports_response_schema, supports_url_context}'
{
  "max_input_tokens": 1048576,
  "max_output_tokens": 65535,
  "max_tokens": 65535,
  "supports_pdf_input": true,
  "supports_response_schema": true,
  "supports_url_context": true
}

max_input_tokens is 1,048,576 against the card's "Context window 128K", eight times too large, and it is the field a caller uses to decide whether a request fits. max_output_tokens is 65535 against "Maximum output tokens 64K", which is 65536. All three capability flags say true where the card says not supported or lists no MIME type

Cached audio on azure/gpt-realtime-2

  1. Read both audio cache fields across the whole gpt-realtime-2 family:
jq -c 'to_entries | map(select(.key | test("^(azure/)?gpt-realtime-2(\\.1)?(-mini)?$")))
       | map({(.key): [.value.cache_read_input_audio_token_cost, .value.cache_creation_input_audio_token_cost]})
       | add' model_prices_and_context_window.json
{"azure/gpt-realtime-2":[4E-7,null],"azure/gpt-realtime-2.1":[4E-7,4E-7],"azure/gpt-realtime-2.1-mini":[3E-7,3E-7],"gpt-realtime-2":[4E-7,4E-7],"gpt-realtime-2.1":[4E-7,4E-7],"gpt-realtime-2.1-mini":[3E-7,3E-7]}

azure/gpt-realtime-2 is the only member of the family with a cached audio read and no matching write, for a deployment whose meter publishes 0.4 for exactly one cached-audio rate

  1. Confirm neither key reaches a caller:
curl -s http://127.0.0.1:4111/v1/model/info -H 'Authorization: Bearer sk-proof-1234' \
  | jq -c '.data[] | select(.model_name=="azure-gpt-realtime-2") | .model_info
           | {cache_read_input_audio_token_cost, cache_creation_input_audio_token_cost}'
{"cache_read_input_audio_token_cost":null,"cache_creation_input_audio_token_cost":null}

Both read null because get_model_info carries neither audio cache key, which is why this half changes what the map declares and no bill

After (9058a84)

Context caching on the three Gemini Live entries

  1. Ask the running proxy what it declares about caching:
curl -s http://127.0.0.1:4111/v1/model/info -H 'Authorization: Bearer sk-proof-1234' \
  | jq -c '.data[] | select(.litellm_params.model | contains("gemini-live"))
           | {model: .litellm_params.model,
              cache_read_input_token_cost: .model_info.cache_read_input_token_cost,
              supports_prompt_caching: .model_info.supports_prompt_caching}'
{"model":"vertex_ai/gemini-live-2.5-flash-native-audio","cache_read_input_token_cost":null,"supports_prompt_caching":false}
{"model":"vertex_ai/gemini-live-2.5-flash-preview-native-audio-09-2025","cache_read_input_token_cost":null,"supports_prompt_caching":false}
{"model":"gemini/gemini-live-2.5-flash-preview-native-audio-09-2025","cache_read_input_token_cost":null,"supports_prompt_caching":false}

No entry prices a cached read and none claims caching, which is what all three vendor pages say

  1. Price 100,000 cached and 1,000 fresh input tokens on each:
for m in vertex_ai/gemini-live-2.5-flash-native-audio \
         vertex_ai/gemini-live-2.5-flash-preview-native-audio-09-2025 \
         gemini/gemini-live-2.5-flash-preview-native-audio-09-2025; do
  printf '%s  ' "$m"
  curl -s -X POST http://127.0.0.1:4111/spend/calculate -H 'Authorization: Bearer sk-proof-1234' \
    -H 'Content-Type: application/json' \
    -d "{\"completion_response\": {\"model\": \"$m\", \"usage\": {\"prompt_tokens\": 101000, \"completion_tokens\": 0, \"prompt_tokens_details\": {\"cached_tokens\": 100000}}}}"
  echo
done
vertex_ai/gemini-live-2.5-flash-native-audio  {"cost":0.0005}
vertex_ai/gemini-live-2.5-flash-preview-native-audio-09-2025  {"cost":0.0005}
gemini/gemini-live-2.5-flash-preview-native-audio-09-2025  {"cost":0.0005}

All three now charge the same $0.0005, and the flag says why: there is no cache to discount, so the fresh-input total is the whole bill

Limits and capabilities on gemini-live-2.5-flash-native-audio

  1. Read the limits and the three capability flags the card speaks to:
curl -s http://127.0.0.1:4111/v1/model/info -H 'Authorization: Bearer sk-proof-1234' \
  | jq '.data[] | select(.model_name=="gemini-live-2.5-flash-native-audio") | .model_info
        | {max_input_tokens, max_output_tokens, max_tokens,
           supports_pdf_input, supports_response_schema, supports_url_context}'
{
  "max_input_tokens": 131072,
  "max_output_tokens": 65536,
  "max_tokens": 65536,
  "supports_pdf_input": false,
  "supports_response_schema": false,
  "supports_url_context": false
}

131072 is the card's 128K, 65536 is its 64K, and the three flags match "Structured output Not supported", "URL context Not supported" and a MIME list with no document type

Cached audio on azure/gpt-realtime-2

  1. Read both audio cache fields across the whole gpt-realtime-2 family:
jq -c 'to_entries | map(select(.key | test("^(azure/)?gpt-realtime-2(\\.1)?(-mini)?$")))
       | map({(.key): [.value.cache_read_input_audio_token_cost, .value.cache_creation_input_audio_token_cost]})
       | add' model_prices_and_context_window.json
{"azure/gpt-realtime-2":[4E-7,4E-7],"azure/gpt-realtime-2.1":[4E-7,4E-7],"azure/gpt-realtime-2.1-mini":[3E-7,3E-7],"gpt-realtime-2":[4E-7,4E-7],"gpt-realtime-2.1":[4E-7,4E-7],"gpt-realtime-2.1-mini":[3E-7,3E-7]}

Every family member now reports its cached audio write at the same rate as its read, and azure/gpt-realtime-2 lands on the 0.4 its own meter publishes

  1. Confirm neither key reaches a caller:
curl -s http://127.0.0.1:4111/v1/model/info -H 'Authorization: Bearer sk-proof-1234' \
  | jq -c '.data[] | select(.model_name=="azure-gpt-realtime-2") | .model_info
           | {cache_read_input_audio_token_cost, cache_creation_input_audio_token_cost}'
{"cache_read_input_audio_token_cost":null,"cache_creation_input_audio_token_cost":null}

Unchanged, as expected. No bill moves on this half

Type

🐛 Bug Fix

Caveats (if any)

Medium

  • Reverses this PR's own earlier 5e-08 cached rate, which a review asked for
    • Same reasoning, carried one step further: nothing published backs any cached rate on this family, so it comes out rather than being rescaled
  • Removes cache_read_input_token_cost from two entries that ship it today
    • Cached reads on them bill $0 instead of $0.075 per 1M. Nothing has been observed reporting cached tokens on a Live session, so no bill is expected to move
    • If Google ever does start reporting them, they bill $0 until a published rate exists. That is the same state the merged GA entry is already in
  • First false in the map for supports_pdf_input and supports_url_context
    • 563 and 59 entries carry true and none carried false, so these are the first vendor-documented refusals for either field. supports_response_schema already has 81, and supports_prompt_caching 40

Low

  • The two *-preview-native-audio-09-2025 entries keep max_input_tokens: 1048576
    • Their source is the Gemini API pricing page, a different surface with its own published limits, so only their cached fields change here rather than being assumed to match the Vertex card
  • cache_creation_input_audio_token_cost still surfaces nowhere
    • get_model_info carries neither audio cache key, so the Azure half corrects what the map declares and changes no bill
  • supports_prompt_caching is set to false rather than deleted
    • An absent key reads back as None, which is how the map spells "nobody checked" across the 2,788 entries that omit it, where false records the vendor's documented no. Both places that act on the flag gate on is True, so nothing behaves differently either way

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

@marty-sullivan
marty-sullivan requested a review from a team September 6, 2026 06:50
@greptile-apps

greptile-apps Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR corrects pricing, token limits, and capability metadata for Gemini Live and Azure realtime models, with focused regression coverage.

  • Removes unsupported Gemini Live cached-input pricing and marks prompt caching unsupported
  • Corrects the GA Gemini Live token limits and unsupported capability flags
  • Adds the missing Azure cached-audio creation rate
  • Tests the updated metadata and resulting cost calculations

Confidence Score: 5/5

The PR appears safe to merge because the pricing and capability corrections have focused regression coverage and no blocking issue remains.

The cached-token regression test is present, and the test docstrings were reduced to concise descriptions. Both previous threads were manually resolved without explanatory replies.

Important Files Changed

Filename Overview
model_prices_and_context_window.json Corrects the primary model cost map’s cached-token pricing, limits, and capability metadata.
litellm/model_prices_and_context_window_backup.json Keeps the backup cost map synchronized with the primary map.
tests/test_litellm/test_cost_calculator.py Adds focused regression tests for cached-token billing, capability discovery, limits, and realtime audio cache rates.

Reviews (5): Last reviewed commit: "test(cost): trim the docstrings on the r..." | Re-trigger Greptile

Comment thread model_prices_and_context_window.json
@codspeed

codspeed Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing cu-aaii:fix-realtime-cost-map-residuals (82c626e) with litellm_internal_staging (a1e7293)1

Open in CodSpeed

Footnotes

  1. No successful run was found on litellm_internal_staging (a2b7868) during the generation of this report, so a1e7293 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@marty-sullivan

Copy link
Copy Markdown
Contributor Author

@greptileai added the cached-token regression test you flagged. It fails against the unfixed cost map, and the file now passes at 139.

@codecov

codecov Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mateo-berri mateo-berri left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! The Azure half checks out, but I think the gemini rate is wrong

azure/gpt-realtime-2

  • I pulled Azure's retail meters myself -> gpt-realtime-2 Audio cd inp Gl is 0.4, so 4e-07 is right
  • Nothing in the cost calculator reads either audio cache key today, so this half is consistency-only, as you say

gemini-live-2.5-flash-native-audio

  • The bug is real. I ran the base map and 100k cached tokens bill $0.00, so thanks for catching it
  • But 7.5e-08 is 15% of this model's 5e-07 input rate, and I don't think anything published backs it
  • Google's pricing page carries no cached-input row for the Live native-audio models, so the siblings aren't really a source
  • Every current Gemini 2.5 entry in our map prices cache reads at 10% of input: 3e-07 -> 3e-08, 1e-07 -> 1e-08, 1.25e-06 -> 1.25e-07
  • That tracks Google's published 90% discount, e.g. 2.5 Flash is $0.30 input against $0.03 cached
  • 7.5e-08 came in with the sibling entry in #16183, back when its input rate was 3e-07, so it was 25% then
  • gemini-2.5-flash was already 3e-08 by that point, and d565860 later corrected the input to 5e-07 without rescaling the cached rate
  • So I think this wants 5e-08, and the two preview siblings want the same correction here rather than being cited as the source

On the test

  • The model_info[...] equality asserts are shape checks, and the cache_read_input_token_cost one raises before the billing assert ever runs
  • Dropping them leaves the cost assertion, which is the part with teeth, and stops the constant being pinned in two places

Happy to merge once the rate is settled and it's green

@marty-sullivan marty-sullivan changed the title fix(pricing): add the missing cache rates on two realtime cost-map entries fix(pricing): fix the cached-token rates on the realtime cost-map entries Sep 6, 2026
@marty-sullivan

Copy link
Copy Markdown
Contributor Author

@mateo-berri agreed, 5e-08. Google's flat 90% discount confirms it, so both preview siblings are corrected too, and the shape asserts are gone.

@marty-sullivan

Copy link
Copy Markdown
Contributor Author

@greptileai rate corrected to 5e-08 per review, preview siblings fixed alongside, shape asserts dropped. Please re-review.

@marty-sullivan
marty-sullivan force-pushed the fix-realtime-cost-map-residuals branch from 5c150d1 to c382c37 Compare September 7, 2026 08:37
azure/gpt-realtime-2 was the only member of the gpt-realtime-2 family priced
on one side of its cached-audio meter. Azure publishes that meter as
"gpt-realtime-2 Audio cd inp Gl 1M Tokens" at 0.4 per 1M and charges the
same rate for the write that populates the cache and the read that hits it,
so cache_creation_input_audio_token_cost lands at 4e-07, matching
azure/gpt-realtime-2.1, azure/gpt-realtime-2.1-mini and the openai
gpt-realtime-2 entry. No cost path reads that field yet, so this corrects
what get_model_info reports rather than what anything bills.

The gemini Live entries go the other way. Google's Vertex context-caching
page publishes separate supported-model lists for implicit and explicit
caching, and no Live or native-audio model is in either one. Its pricing
page prints N/A in both cached-input columns for every Gemini 2.5 Flash
Live API row, where plain 2.5 Flash and 2.5 Flash-Lite both carry real
cached prices, and the Vertex model card for the family marks context
caching not supported outright. Vertex never reports cachedContentTokenCount
on a Live session either, including for a byte-identical 7,021-token prefix
replayed across sessions minutes apart, which is well past the 2,048-token
minimum the same page sets for the Gemini 2 family.

So the 7.5e-08 on the two preview siblings priced something the provider does
not sell, and supports_prompt_caching on all three claimed a capability the
model does not have. The rate comes out. The flag is set to false rather than
removed, because get_model_info maps an absent key to None, and None is how
this map spells "nobody checked" across the 2,788 entries that omit it, where
false records the vendor's documented no. Both readers of the flag gate on
`is True`, so nothing bills or behaves differently either way.

Only the cached fields change on the two 09-2025 preview entries. Their
source field points at the Gemini API pricing page rather than the Vertex
one, so they describe a different surface with its own published limits, and
their context windows are left alone rather than assumed to match the Vertex
model card that drives the GA entry.

Tests cover all three halves: the family invariant that a cached audio read
implies an equal cached audio write, a cached count on a Live entry leaving
the bill at the fresh-input total instead of adding the old 7.5e-08, and
supports_prompt_caching answering false for all three entries while still
answering true for 2.5 Flash, so the false cannot be a swallowed lookup
error.
…bilities

Google's model card for model ID gemini-live-2.5-flash-native-audio gives a
128K context window and 64K maximum output tokens, and marks structured
output, context caching and URL context as not supported. Its modality list
is text in and out, image in, audio in and out, and video in, with no
document input of any kind.

The entry advertised a 1M context window, an off-by-one 65535 output cap, and
three capability flags the vendor marks unsupported. Context caching is the
fourth and is handled in the cached-fields change alongside its two preview
siblings.

Both the bare id and vertex_ai/gemini-live-2.5-flash-native-audio resolve to
this single entry, so the test drives the corrected values through both.
@marty-sullivan
marty-sullivan force-pushed the fix-realtime-cost-map-residuals branch from c382c37 to 9058a84 Compare September 7, 2026 09:26
@marty-sullivan marty-sullivan changed the title fix(pricing): fix the cached-token rates on the realtime cost-map entries fix(pricing): correct cached-token and limit fields on the realtime cost-map entries Sep 7, 2026
@marty-sullivan

Copy link
Copy Markdown
Contributor Author

@greptileai reworked and rebased: the Live cached rate now comes out entirely, plus the native-audio entry's limits and capability flags

@marty-sullivan

Copy link
Copy Markdown
Contributor Author

@mateo-berri digging further flipped this: Google lists Live under neither caching mode and prices N/A, so the rate comes out rather than moving to 5e-08

Comment thread tests/test_litellm/test_cost_calculator.py Outdated
Each of the four tests this PR added carried several lines of rationale for
why the map was wrong. Cut them to one line saying what the test pins, and
keep the two facts that explain a number rather than the change: the cached
tokens dropping out of the bill, and why the 2.5 Flash control has to be
there, both now assertion messages where they fire
@marty-sullivan

Copy link
Copy Markdown
Contributor Author

@greptileai trimmed the four docstrings to one line each, moving the two load-bearing facts into assertion messages instead

@greptile-apps

greptile-apps Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

That addresses my concern. Keeping each docstring as a concise purpose statement and moving the load-bearing rationale into assertion messages makes the tests clearer while preserving useful failure diagnostics. No further changes needed.

@marty-sullivan

Copy link
Copy Markdown
Contributor Author

Thanks, you were right twice: 7.5e-08 had nothing behind it, and the $0.00 was worth catching

Chasing the published number only confirmed what you noticed. Vertex's table prints N/A in both cached columns on every Gemini 2.5 Flash Live API row, the same row that sources every other rate here. Two rows below, non-Live Flash reads $0.30 against $0.03, so your 90% rule holds wherever Google publishes a cached price. Live is not one, and the model card is blunter: "Context caching Not supported"

So 5e-08 fails the same test 7.5e-08 did. The map mostly agrees already: 10 of its 12 Gemini realtime entries carry no cached rate, and the 2 that do are the preview siblings you flagged as not a source

supports_prompt_caching false records the vendor's no, since an absent key reads back as None

I also dropped the gemini-live-2.5-flash entry: the card names only the native-audio Model ID, the bare id is undocumented now, and we are retiring it on our side anyway

@marty-sullivan

Copy link
Copy Markdown
Contributor Author

@greptileai please re-score. Both P2s are addressed: the cached-token regression test landed and the docstrings were trimmed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants