Skip to content

fix(pricing): add undated azure aliases for gpt-audio-mini and gpt-realtime-mini - #37867

Merged
tin-berri merged 6 commits into
litellm_internal_stagingfrom
litellm_pr33291_azure_audio_price_aliases
Aug 22, 2026
Merged

fix(pricing): add undated azure aliases for gpt-audio-mini and gpt-realtime-mini#37867
tin-berri merged 6 commits into
litellm_internal_stagingfrom
litellm_pr33291_azure_audio_price_aliases

Conversation

@tin-berri

@tin-berri tin-berri commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Note

This is a copy of #33291 by @mihidumh, pushed to a litellm_-prefixed branch so the full CircleCI pipeline (which doesn't run on fork PRs) can execute. Commit authorship is preserved, so full credit goes to the original author

TLDR

Problem this solves:

  • Price map has no azure/gpt-audio-mini or azure/gpt-realtime-mini key
  • Azure deployments carry admin-chosen names, so model_info.base_model is what prices them
  • base_model: azure/gpt-audio-mini pins the lookup to a key that isn't there
  • The lookup raises This model isn't mapped yet, the proxy swallows it, and the call is logged at $0
  • Realtime sessions on azure/gpt-realtime-mini hit the same missing key with or without base_model, so they log $0 too

How it solves it:

  • Add both undated keys mirroring their -2025-10-06 dated entries
  • Keep the packaged backup map byte-for-byte in sync
  • Test pins each alias to its dated entry in both maps, so drift fails CI

User Flow

Before: a team pricing an Azure audio deployment through base_model gets no cost header at all and $0 spend, on calls Azure does invoice them for

  1. The proxy admin creates an Azure deployment of gpt-audio-mini under their own name, audio-mini-prod, registers it as model: azure/audio-mini-prod with model_info.base_model: azure/gpt-audio-mini so the gateway knows what to price it as, and restarts the proxy
  2. Their app sends POST https://litellm-domain/v1/chat/completions with "model": "audio-mini", "modalities": ["text", "audio"], an audio config, and a short prompt
  3. A 200 comes back with the spoken reply, and the usage block shows real counts, with the completion tokens split into text and audio
  4. The response carries no x-litellm-response-cost header at all, and x-litellm-response-cost-original, -input, -output, and x-litellm-key-spend all read 0.0
  5. They open https://litellm-domain/ui/?page=logs and that request shows $0 spend
  6. Key, team, and budget limits keyed on spend never trip, however much audio the team generates

After: the same call comes back priced, so the header and the logs page match what Azure charges

  1. The proxy admin creates an Azure deployment of gpt-audio-mini under their own name, audio-mini-prod, registers it as model: azure/audio-mini-prod with model_info.base_model: azure/gpt-audio-mini so the gateway knows what to price it as, and restarts the proxy
  2. Their app sends POST https://litellm-domain/v1/chat/completions with "model": "audio-mini", "modalities": ["text", "audio"], an audio config, and a short prompt
  3. A 200 comes back with the spoken reply, and the usage block shows real counts, with the completion tokens split into text and audio
  4. The response now carries x-litellm-response-cost with a non-zero figure, billing text at $0.60 per million in and $2.40 per million out, and audio at $10 per million in and $20 per million out
  5. They open https://litellm-domain/ui/?page=logs and that request shows the real spend
  6. Budgets and rate limits keyed on spend behave as configured

Relevant issues

Fixes #33170

Linear ticket

Resolves LIT-5990

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)

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

Live proxy against real Azure on both legs, real audio generation, real spend. Same config, same request, only the commit the proxy booted from differs.

audio-mini-prod is a real Azure deployment of gpt-audio-mini created under an admin-chosen name, which is exactly why model_info.base_model is what prices it:

model_list:
  - model_name: audio-mini
    litellm_params:
      model: azure/audio-mini-prod
      api_base: os.environ/AZURE_API_BASE
      api_key: os.environ/AZURE_API_KEY
      api_version: "2025-04-01-preview"
    model_info:
      base_model: azure/gpt-audio-mini

general_settings:
  master_key: sk-1234

Before, at merge base 0a5fa4fdc6599eb236c8116f9ce77e1ec29f83ae

curl -sS -m 180 -D headers.txt -o body.json \
  -X POST http://localhost:49117/v1/chat/completions \
  -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' \
  -d '{"model":"audio-mini","modalities":["text","audio"],"audio":{"voice":"alloy","format":"wav"},"messages":[{"role":"user","content":"Say hello in five words"}]}'
grep -iE '^(HTTP/|x-litellm-)' headers.txt
HTTP/1.1 200 OK
x-litellm-call-id: ba2545fb-493a-4044-9620-adf127bc89b9
x-litellm-model-id: 1ac40176d38b5e599737c9a62f93effef92adcf44fd2865cbdd5792416c017b9
x-litellm-model-name: azure/audio-mini-prod
x-litellm-model-api-base: https://<redacted>.services.ai.azure.com
x-litellm-version: 1.99.0
x-litellm-response-cost-original: 0.0
x-litellm-response-cost-discount-amount: 0.0
x-litellm-response-cost-margin-amount: 0.0
x-litellm-response-cost-margin-percent: 0.0
x-litellm-response-cost-input: 0.0
x-litellm-response-cost-output: 0.0
x-litellm-response-cost-tool-usage: 0.0
x-litellm-key-spend: 0.0
x-litellm-response-duration-ms: 760.146
x-litellm-model-group: audio-mini
x-litellm-attempted-retries: 0
x-litellm-attempted-fallbacks: 0

No x-litellm-response-cost header at all, and every cost field reads 0.0, against a response that really did generate audio:

"usage": {"completion_tokens":51,"prompt_tokens":12,"total_tokens":63,
  "completion_tokens_details":{"audio_tokens":37,"text_tokens":14,"reasoning_tokens":0},
  "prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0,"text_tokens":12,"image_tokens":0}}

Transcript "Hello to you right now.", with audio.data carrying a real wav payload starting UklGRv////9XQVZFZm10

After, at e1c97eb3ee4570320ccf58c4fb6285e7c81a4692 (the PR tip)

curl -sS -m 180 -D - http://127.0.0.1:45623/v1/chat/completions \
  -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' \
  -d '{"model":"audio-mini","modalities":["text","audio"],"audio":{"voice":"alloy","format":"wav"},"messages":[{"role":"user","content":"Say hello in five words"}]}'
HTTP/1.1 200 OK
x-litellm-call-id: 42d0ba5c-89b2-4d5c-9554-516e1e8a3f74
x-litellm-model-id: 10bc6bba59114493c8bb0e5c5dc0345538816f5ea56a81d1911773347be24992
x-litellm-model-name: azure/audio-mini-prod
x-litellm-model-api-base: https://<redacted>.services.ai.azure.com
x-litellm-version: 1.99.0
x-litellm-response-cost: 0.0013032
x-litellm-response-cost-original: 0.0013032
x-litellm-response-cost-discount-amount: 0.0
x-litellm-response-cost-margin-amount: 0.0
x-litellm-response-cost-margin-percent: 0.0
x-litellm-response-cost-input: 7.2e-06
x-litellm-response-cost-output: 0.001296
x-litellm-response-cost-tool-usage: 0.0
x-litellm-key-spend: 0.0013032
x-litellm-response-duration-ms: 1753.59
llm_provider-x-ms-served-model: gpt-audio-mini-2025-10-06
llm_provider-x-ms-region: East US 2
x-litellm-model-group: audio-mini
x-litellm-attempted-retries: 0
x-litellm-attempted-fallbacks: 0
"usage": {"completion_tokens":78,"prompt_tokens":12,"total_tokens":90,
  "completion_tokens_details":{"audio_tokens":63,"text_tokens":15,"reasoning_tokens":0},
  "prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0,"text_tokens":12,"image_tokens":0}}

Transcript "Hello to you, my friend!". The arithmetic is exact on all three figures: input 12 * 6e-07 = 7.2e-06, output 15 * 2.4e-06 + 63 * 2e-05 = 0.001296, total 0.0013032

Realtime sessions, the same flip, with no base_model involved

A second A/B ran a real proxy at the merge base and at this tip against a live Azure gpt-realtime-mini deployment, drove a websocket session on /v1/realtime, and read the spend rows back out of each side's Postgres.

Base:

model                   | model_group              | call_type  | spend | prompt | completion
azure/gpt-realtime-mini | realtime-undated         | _arealtime | 0     | 112    | 5
azure/gpt-realtime-mini | realtime-dated-basemodel | _arealtime | 0     | 112    | 5

Head:

model                   | model_group              | call_type  | spend     | prompt | completion
azure/gpt-realtime-mini | realtime-undated         | _arealtime | 4.464e-05 | 112    | 5
azure/gpt-realtime-mini | realtime-dated-basemodel | _arealtime | 4.464e-05 | 112    | 5

Identical sessions and identical token counts, logged at $0 before and at a real figure after. The realtime path dials the deployment's own azure/gpt-realtime-mini, so it needs no base_model to hit the missing key

Nothing that already worked changed

The same A/B compared both sides across the map-reading surfaces. /v1/models is byte-identical between base and head, with and without include_metadata and return_wildcard_routes, so no new model is exposed to clients. Chat audio deployments that already billed correctly bill the same rates on both sides. The only endpoints that differ are the ones that report model metadata (/model/info, /model_group/info, /model/deprecations), and each differs only by the two new keys' own data.

Two reporting surfaces move in the fix's direction. /model/deprecations listed an undated Azure deployment under the OpenAI entry before (litellm_provider: openai, 2027-01-20) and lists it under the Azure entry now (azure, 2027-04-06). /health probes an azure/gpt-realtime-mini deployment as a realtime model rather than a chat one, and it reports healthy on both sides.

Observed alongside the runs, none of it caused or made worse by this PR:

  • Azure 400s text-only requests to a gpt-audio-mini deployment
  • Text tokens bill on top of audio tokens
  • Azure returns the underlying model and version, not the deployment
  • Without base_model, the same deployment already billed correctly

The one thing this PR does change beyond the header is /v1/model/info, which reported 0 prices and mode: null for both aliases before

Type

🐛 Bug Fix

Caveats (if any)

  • Alias mirrors the only dated Azure entry, -2025-10-06
  • It carries that entry's deprecation_date, matching most undated map keys
  • A newer dated Azure snapshot would need the alias repointed
  • Realtime sessions on azure/gpt-realtime-mini go from zero recorded spend to charged. Anyone running that deployment today will see spend appear where their dashboards read $0, and key or team budgets that could never be reached before can now trip
  • The realtime cost path never consults model_info.base_model. It resolves from the model the session reports and the deployment's own model name, which is why adding the undated alias is what fixes it, and why pinning base_model on a realtime deployment does nothing for cost either way. That behavior is pre-existing and untouched here
  • A deployment pinned to azure/gpt-realtime-mini now reports mode: realtime, so /health probes it over a websocket instead of as a chat model. That is the correct probe for it, but a deployment that answers chat probes while websockets are blocked would flip from healthy to unhealthy on upgrade
  • Azure rejects text-only requests to a gpt-audio-mini deployment with a 400, so every call in the flow above carries audio on one side

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

Note

Low Risk
Data-only pricing map plus tests; no auth or request-path changes. Realtime alias now reports mode realtime, which can change health-check probing for that base_model.

Overview
Fixes Azure audio/realtime spend being logged at $0 when deployments are priced via base_model: azure/gpt-audio-mini or azure/gpt-realtime-mini (issue #33170). Those undated keys were missing, so cost lookup failed and the proxy swallowed the error.

Adds both aliases as exact mirrors of the dated -2025-10-06 entries in the root and packaged cost maps (chat + audio for audio-mini; realtime + cache/image costs for realtime-mini). Tests require the aliases to exist, match their dated counterparts field-for-field, and stay in sync across both JSON files.

Reviewed by Cursor Bugbot for commit e1c97eb. Bugbot is set up for automated code reviews on this repo. Configure here.

@tin-berri
tin-berri requested a review from mateo-berri as a code owner August 21, 2026 18:01
@tin-berri

Copy link
Copy Markdown
Contributor Author

@greptileai can you reply here with a score and why that score?

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Score: 5/5

This is a clean, well-scoped bug fix with strong evidence of the production issue and a correct solution. Here's why:

What's right:

  • Correct fix: The undated azure/gpt-audio-mini and azure/gpt-realtime-mini entries are exact mirrors of their dated -2025-10-06 counterparts — matching the established pattern used for OpenAI's undated aliases in the same file.
  • Both files updated: Both model_prices_and_context_window.json and the packaged backup are kept in sync, which is what the repo's own check_files_match.py enforces.
  • Tests are solid: The parametrized test covers both the field-level equality check and a full byte-for-byte mirror check (model_map[undated] == model_map[dated]), so future drift between dated/undated pairs will be caught. The autouse fixture correctly uses LITELLM_LOCAL_MODEL_COST_MAP to avoid network calls, matching the established test pattern in the repo.
  • Zero production code changed: No risk of regressions — this is a pure data addition.
  • Production evidence provided: The PR description includes a concrete repro trace (spend logs billing text tokens at $0), manual verification with custom pricing, and a before/after jq proof — this is unusually thorough for a pricing alias PR.

Minor observation (not a blocker): The test_undated_azure_audio_alias_matches_dated_entry test is largely a subset of test_undated_azure_audio_alias_is_exact_mirror — the first test is redundant once the second exists. That said, the first test's explicit > 0 assertion on individual cost fields is a useful guard against a future entry where a field is present but zero, so keeping both is defensible.

Bottom line: Minimal blast radius, clear root cause, production-verified fix, strong test coverage. Ready to merge.

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds undated Azure aliases for gpt-audio-mini and gpt-realtime-mini, keeping the canonical and packaged pricing maps synchronized.

  • Mirrors each alias from its dated 2025-10-06 entry, including text, audio, cache, capability, and endpoint metadata.
  • Adds regression coverage for pricing-map parity and realtime-mode classification.
  • The shared pricing-map fixture now clears get_model_info caching before and after each alias test, resolving the previously reported isolation issue.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
model_prices_and_context_window.json Adds canonical undated Azure audio and realtime-mini aliases that exactly mirror their dated entries.
litellm/model_prices_and_context_window_backup.json Keeps the packaged fallback pricing map synchronized with the canonical map.
tests/test_litellm/test_azure_audio_price_aliases.py Verifies alias pricing, full metadata parity, and synchronization between both maps using the cache-clearing shared fixture.
tests/test_litellm/test_gpt_realtime_mode.py Extends realtime-only model coverage to the new undated Azure realtime alias.

Reviews (3): Last reviewed commit: "test(pricing): assert the azure audio al..." | Re-trigger Greptile

Comment thread tests/test_litellm/test_azure_audio_price_aliases.py Outdated
Comment thread tests/test_litellm/test_azure_audio_price_aliases.py Outdated
mihidumh and others added 4 commits August 21, 2026 11:36
…altime-mini

Azure deployments are commonly created against the undated model name,
and the cost-tracking docs say to set base_model to azure/<model> — but
only the dated -2025-10-06 entries existed for these two models (the
openai provider has undated aliases for both). base_model:
azure/gpt-audio-mini therefore resolved to nothing and, depending on the
fallback path, text tokens billed at $0 while audio tokens billed fine.

Mirror the -2025-10-06 entries as undated aliases, exactly like the
undated openai entries mirror their newest dated variant.

Fixes #33170

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r dated entries

Review follow-up: COST_FIELDS missed realtime-specific cost keys
(cache_creation_input_audio_token_cost, cache_read_input_token_cost,
input_cost_per_image). Full-entry equality catches drift on every field.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e-mini alias

Upstream changed the dated entry's mode from chat to realtime after this
branch was cut; the undated alias must stay a byte-for-byte mirror.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tin-berri
tin-berri force-pushed the litellm_pr33291_azure_audio_price_aliases branch from e189a58 to 23c3a13 Compare August 21, 2026 18:38
@codspeed-hq

codspeed-hq Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_pr33291_azure_audio_price_aliases (e1c97eb) with litellm_internal_staging (9c558df)1

Open in CodSpeed

Footnotes

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

@tin-berri

Copy link
Copy Markdown
Contributor Author

Pushed two updates since the last review: (1) rebased onto latest litellm_internal_staging (the branch predated the ruff-tests.toml lint config, which failed the lint job), and (2) addressed both inline findings in 805224a — the test now uses the shared local_model_cost_map conftest fixture (clears get_model_info's lru_cache both directions) and the redundant comment is removed.

@greptileai can you reply here with a score and why that score?

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Score: 5/5

The PR is clean and correct. Here's the breakdown:

What's right:

  • Both JSON files (model_prices_and_context_window.json and the backup) are updated identically and in sync — the prior sync chore commit resolved the pre-existing drift.
  • The new entries are exact mirrors of the dated -2025-10-06 counterparts (byte-for-byte, as confirmed by test_undated_azure_audio_alias_is_exact_mirror). All cost fields, capability flags, modality lists, and endpoint arrays match.
  • The test suite uses the local_model_cost_map conftest fixture (shared, clears the LRU cache both ways) — no bespoke cache patching.
  • Two complementary test functions: one checks the specific cost fields + provider/mode, the other enforces full structural identity and surfaces any future drift on the key diff in the assertion message. That's good defensive coverage.
  • The fix is correctly scoped — no router changes, no proxy code, just the pricing map — which is exactly the right place for this per the repo's conventions.

No issues remaining: the two previous inline findings (fixture usage and redundant comment) were both addressed in the latest push. Nothing left to block this.

@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@tin-berri

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 805224a. Configure here.

@mateo-berri

Copy link
Copy Markdown
Contributor

@greptileai

…ot just the backup

The alias test ran under the local_model_cost_map fixture, which pins
litellm.model_cost to the packaged backup. A proxy left on its defaults fetches
the root map instead, and that copy is what ships to the CDN, so an alias
present in only one of the two files still bills $0 for every proxy reading the
other. That is the same failure this file exists to prevent, and nothing caught
it: dropping azure/gpt-audio-mini from the root map alone left the whole file
green.

Assert the root map directly, assert it agrees with the backup, and add
azure/gpt-realtime-mini to REALTIME_ONLY_GPT_MODELS so the new realtime key also
gets the root-map mode and endpoint checks its dated sibling already had.
@mateo-berri

Copy link
Copy Markdown
Contributor

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor

bugbot run

@cursor cursor Bot 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e1c97eb. Configure here.

@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.

LGTM. Thanks!

@tin-berri
tin-berri merged commit 4e19127 into litellm_internal_staging Aug 22, 2026
73 checks passed
@tin-berri
tin-berri deleted the litellm_pr33291_azure_audio_price_aliases branch August 22, 2026 01:44
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.

[Bug]: price map missing undated azure aliases azure/gpt-audio-mini and azure/gpt-realtime-mini

3 participants