Skip to content

fix(cost): bill audio input once when both per-token and per-second rates exist - #41158

Closed
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
litellm_vertex_embedding_audio_double_bill
Closed

devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
litellm_vertex_embedding_audio_double_bill

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

How it solves it:

  • When audio tokens have a per-token rate, skip the per-second audio charge
  • Per-second audio still applies for models with no per-token audio rate
  • Updates the two embedding tests to the per-token audio price from the Vertex page

User Flow

Before: a user embedding an audio clip on Vertex is overcharged for the audio

  1. They send POST https://litellm-domain/v1/embeddings with "model": "vertex_ai/gemini-embedding-2" and a 2 second audio file
  2. Vertex reports 64 audio tokens and the response comes back 200
  3. https://litellm-domain/ui/?page=logs shows $0.000736 for the request, which is 64 tokens at $6.50/1M plus 2 seconds at $0.00016/s stacked together

After: the same request is billed once

  1. They send the same POST https://litellm-domain/v1/embeddings with "model": "vertex_ai/gemini-embedding-2" and the same clip
  2. Vertex reports 64 audio tokens and the response comes back 200
  3. https://litellm-domain/ui/?page=logs shows $0.000416, which is 64 tokens at $6.50/1M

Relevant issues

Fixes the Vertex AI / Run tests failure on #41154 (generated pricing sync PR). Do not edit that PR; this lands independently

Raw provider evidence, fetched with curl -sL "https://cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing?x=$RANDOM" and parsed from the HTML table for "Gemini Embedding 2 (Unified Multimodal, Preview)":

Input text   | Online $0.20 / 1M tokens  | Batch $0.10 / 1M tokens
Input image  | Online $0.45 / 1M tokens  | Batch $0.225 / 1M tokens
Input video  | Online $12.00 / 1M tokens | Batch $6.00 / 1M tokens
Input audio  | Online $6.50 / 1M tokens  | Batch $3.25 / 1M tokens

Google now prices audio per token ($6.50/1M = 6.5e-6 per token). The older per-second rate in the catalog (0.00016/s at 32 tokens/s = 5e-6 per token) is not what the page publishes, so the per-token rate wins whenever it exists

Affected release

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)

Screenshots / Proof of Fix

Cost math only, no provider call needed. Shared script cost_check.py:

import litellm
from litellm.types.utils import Usage, PromptTokensDetailsWrapper
from litellm.litellm_core_utils.llm_cost_calc.utils import generic_cost_per_token
u = Usage(prompt_tokens=64, completion_tokens=0, total_tokens=64,
          prompt_tokens_details=PromptTokensDetailsWrapper(text_tokens=0, audio_tokens=64, audio_length_seconds=2.0))
print(generic_cost_per_token(model="gemini-embedding-2", usage=u, custom_llm_provider="vertex_ai")[0])

Before (b67137b)

  1. LITELLM_LOCAL_MODEL_COST_MAP=True uv run python cost_check.py
  2. Output: 0.000736 (64 * 6.5e-6 + 2 * 0.00016, audio billed twice)

After (e5391c8)

  1. LITELLM_LOCAL_MODEL_COST_MAP=True uv run python cost_check.py
  2. Output: 0.000416 (64 * 6.5e-6)

Type

🐛 Bug Fix

Caveats (if any)

Low

  • Video is still billed per second; the Vertex page now lists video per token, follow-up for the pricing sync parser

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

Link to Devin session: https://app.devin.ai/sessions/10c57e7b5dec41e29684a8c42c5c6aab
Open in Devin Desktop: https://app.devin.ai/desktop/session/10c57e7b5dec41e29684a8c42c5c6aab?variant=devin

…ates exist

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot requested a review from a team September 15, 2026 00:52
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codspeed

codspeed Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_vertex_embedding_audio_double_bill (e5391c8) with main (b67137b)

Open in CodSpeed

@greptile-apps

greptile-apps Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR prevents audio input from being charged by both token count and duration when both rates are configured.

  • Detects whether nonzero audio-token usage has an applicable per-token rate.
  • Skips duration-based audio billing when token-based billing applies.
  • Retains duration billing for models without a per-token audio rate.
  • Adds focused regression coverage and updates Vertex Gemini embedding expectations to the catalog’s token rate.

Confidence Score: 5/5

The PR appears safe to merge; the billing precedence is consistent with the configured rates and is covered in both directions.

No actionable failures remain: the rate probe and charge use identical fallback semantics, per-second billing remains available when token pricing is absent, and the modified Vertex tests accurately reflect catalog pricing.

Important Files Changed

Filename Overview
litellm/litellm_core_utils/llm_cost_calc/utils.py Adds consistent per-token precedence to prevent duplicate audio input charges while preserving per-second fallback.
tests/test_litellm/litellm_core_utils/llm_cost_calc/test_llm_cost_calc_utils.py Covers both dual-rate token precedence and duration-only fallback behavior.
tests/test_litellm/llms/vertex_ai/gemini_embeddings/test_batch_embed_content_transformation.py Updates Vertex Gemini embedding cost assertions to the configured per-audio-token rate without weakening modality-accounting checks.

Reviews (1): Last reviewed commit: "fix(cost): bill audio input once when bo..." | Re-trigger Greptile

@codecov

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Superseded: main moved gemini-embedding-2 to per-token rates (ce83fac, a28ea22, 4a8ec7b) and fixed the same tests. Closing.

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.

1 participant