Skip to content

fix(cost): honor an explicit zero cache-creation cost in batch pricing - #36723

Open
hsusul wants to merge 1 commit into
BerriAI:litellm_internal_stagingfrom
hsusul:fix-batch-cost-honor-zero-cache-creation
Open

fix(cost): honor an explicit zero cache-creation cost in batch pricing#36723
hsusul wants to merge 1 commit into
BerriAI:litellm_internal_stagingfrom
hsusul:fix-batch-cost-honor-zero-cache-creation

Conversation

@hsusul

@hsusul hsusul commented Aug 13, 2026

Copy link
Copy Markdown

TLDR

Problem this solves:

  • A model that prices cache-write (cache creation) tokens at an explicit 0.0 is billed at the plain input rate in batch cost, not at 0
  • batch_cost_calculator resolved the cache-write rate with model_info.get("cache_creation_input_token_cost") or input_cost_per_token, and the or short-circuits on a falsy 0.0, so a real zero rate looks like a missing key and falls through to the input rate

How it solves it:

  • Read the rate first, then use it whenever the key is present (including 0.0) and only fall back to input_cost_per_token when the key is absent (None)
  • This matches the sibling cache-read path in the same function, which already reads its rate through calculate_cost_component and treats a present 0.0 as a real price

User Flow

A user runs a batch job on a model whose config sets cache_creation_input_token_cost: 0 while input_cost_per_token is nonzero, and the request writes prompt-cache tokens. Before this change every cache-write token is billed at input_cost_per_token / 2; after it, those tokens are billed at 0

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
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • 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

batch_cost_calculator is pure given its usage and model_info, so the before/after is visible without a network call. A model with free cache writes and a nonzero input rate, writing 1000 cache tokens:

from litellm.types.utils import Usage, PromptTokensDetailsWrapper
from litellm.cost_calculator import batch_cost_calculator
usage = Usage(prompt_tokens=1000, completion_tokens=0, total_tokens=1000, prompt_tokens_details=PromptTokensDetailsWrapper(cached_tokens=0, cache_creation_tokens=1000))
model_info = {"input_cost_per_token": 1e-6, "output_cost_per_token": 2e-6, "cache_creation_input_token_cost": 0.0}
batch_cost_calculator(usage=usage, model="claude-3-5-sonnet-20241022", custom_llm_provider="anthropic", model_info=model_info)[0]

Before: 0.0005 (1000 cache-write tokens billed at input_cost_per_token / 2). After: 0.0

End-to-end QA a maintainer can run against a live proxy: register a model whose config carries cache_creation_input_token_cost: 0, submit a batch job that writes prompt-cache tokens, then confirm at http://localhost:4000/ui/?page=logs that the batch's prompt cost charges those cache-write tokens at 0 rather than the input rate

Type

🐛 Bug Fix

Changes

batch_cost_calculator in litellm/cost_calculator.py now distinguishes a missing cache_creation_input_token_cost from a present 0.0. This mirrors the same distinction the flat (non-batch) Dashscope path already makes, and the fix that #30749 applied to tiered pricing

Caveats (if any)

A missing cache_creation_input_token_cost still falls back to input_cost_per_token, so nothing changes for the common providers that do not declare a separate cache-write rate

QA runbook

Covered by two regression tests in tests/test_litellm/test_cost_calculator.py: an explicit 0.0 cache-creation cost bills at 0, while a missing key still falls back to the input rate. The zero-honoring test fails on the current code and passes after the fix

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

batch_cost_calculator resolved the cache-write rate with
`model_info.get("cache_creation_input_token_cost") or input_cost_per_token`,
so a model that prices cache writes at an explicit 0.0 was billed at the
plain input rate because `or` short-circuits on a falsy 0.0. The sibling
cache-read path already reads its rate through calculate_cost_component,
which treats a present 0.0 as a real price. Distinguish a missing key from a
present zero so the two cache buckets price consistently.
@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR corrects batch cache-write pricing so an explicit zero rate remains free while a missing rate still falls back to the standard input price

  • Replaces truthiness-based fallback with an explicit None check
  • Adds focused regression tests for zero-valued and missing cache-creation rates
  • Reformats the existing cost-calculator test module without changing its assertions

Confidence Score: 5/5

The PR appears safe to merge, with the corrected pricing distinction covered by focused regression tests

The changed calculation preserves the existing missing-rate fallback while correctly honoring zero as a valid configured price, and the tests exercise both branches directly

Important Files Changed

Filename Overview
litellm/cost_calculator.py Correctly distinguishes an explicit zero cache-creation rate from an absent rate in batch pricing
tests/test_litellm/test_cost_calculator.py Adds network-independent regression coverage for explicit-zero and missing-rate behavior; remaining changes are formatting-only

Reviews (1): Last reviewed commit: "fix(cost): honor an explicit zero cache-..." | Re-trigger Greptile

@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing hsusul:fix-batch-cost-honor-zero-cache-creation (be16df7) with litellm_internal_staging (6209b89)1

Open in CodSpeed

Footnotes

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

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