litellm/litellm
tin-berri ca0b951a43
feat(spend): report prompt caching savings as total and gateway-attributed (#38134)
* feat(spend): report prompt caching savings as total and gateway-attributed

`prompt_caching_savings_spend` credited every cached request, including caching a
client asked for with its own `cache_control` and caching a provider does implicitly,
so the number overstated what the gateway had any hand in.

Gating that column in place would have fixed the overstatement by changing what the
column means, leaving rows written before the change saying "all caching savings" and
rows after saying "gateway-injected only" with nothing to tell them apart, and forcing
a decision about rewriting history. It also breaks the cache-leakage estimate on the
dashboard, whose numerator would be gated while its denominator, the cached token
counts, would not, so the rate it extrapolates from would be quietly diluted.

Report both instead. `prompt_caching_savings_spend` keeps meaning every net dollar
caching saved, which is what a customer means by "what did caching save me", and the
new `gateway_injected_caching_savings_spend` carries the subset litellm caused by
injecting the breakpoints itself. Both are derived from the same marker, so this
changes what is done with it rather than how it is obtained.

The attributed figure is normally the smaller of the two, being a subset of the same
requests, but not always: a request that writes cache it never reads has negative net
savings, and excluding such a request can lift the attributed figure above the total.

Also stops the marker riding into a fallback leg. The fallback rebuild spread the
failed attempt's metadata forward, so a deployment that injected nothing inherited the
marker and was credited anyway, which silently restored the very overstatement this
separates out.

* fix(bedrock): credit gateway caching where the tool cachePoint is placed (#38478)

The savings marker records breakpoints litellm placed, and a tool_config
injection point becomes one only in the converse transform, and only when the
request carries tools. The prompt hook cannot see either condition, so marking
on the point's presence credited request shapes that cached nothing, while
Bedrock tool caching the gateway did cause went uncredited.

Record it at the placement site instead. The marker's reader also resolves its
bucket by value now: litellm_params declares litellm_metadata as None on every
request, so asking the shared name resolver named a bucket that was not there
and the mark was dropped.
2026-08-28 00:19:06 -07:00
..
a2a_protocol fix(a2a): speak the 0.3 dialect to servers with mis-cased protocol bindings 2026-08-24 10:51:14 -07:00
anthropic_interface chore(lint): strip inert type: ignore comments and zero LIT009, LIT010, LIT011 headroom 2026-08-05 02:37:24 -07:00
assistants chore(lint): clear grandfathered over-limit lint drift and ratchet budgets down 2026-08-05 12:18:13 -07:00
batch_completion feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
batches chore(typing): tighten annotations added in the last day and ratchet budgets 2026-08-23 07:49:54 +00:00
caching fix(caching): treat an empty cache namespace as no namespace 2026-08-26 13:48:45 -07:00
completion_extras fix(anthropic): carry tool_reference tool results through the guardrail translation round trip 2026-08-26 22:35:46 -07:00
compression chore(lint): strip inert type: ignore comments and zero LIT009, LIT010, LIT011 headroom 2026-08-05 02:37:24 -07:00
containers chore(typing): drop 1.3k basedpyright errors across 30 Any hotspot files 2026-08-16 03:56:02 +00:00
endpoints/speech/speech_to_completion_bridge fix(speech): keep proxy metadata and completion cost through the TTS completion bridge 2026-08-26 15:12:41 -07:00
evals chore(typing): remove 914 basedpyright Any errors across 16 hotspot files 2026-08-10 01:24:40 -07:00
experimental_mcp_client feat(mcp): let a resolved OAuth token target a custom upstream header (#38456) 2026-08-27 14:32:01 -07:00
files fix(batches): accept litellm_proxy in files and batches provider type literals 2026-08-18 13:28:06 -07:00
fine_tuning Merge branch 'litellm_internal_staging' into litellm_remove_types_ruff_exclusion 2026-08-05 11:05:33 -07:00
google_genai refactor(google_genai): pick the stream logging endpoint type at construction 2026-08-26 17:18:44 -07:00
images Merge origin/litellm_internal_staging into litellm_fix_36493_image_video_routes 2026-08-24 11:58:22 -07:00
integrations feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
interactions feat(vertex_ai): add native Vertex AI Interactions API support 2026-08-25 09:55:13 -07:00
litellm_core_utils feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
llms feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
models refactor(repositories): type prisma table access with one generic protocol 2026-08-25 12:14:17 +00:00
ocr fix(ocr): reject invalid req_format values as 400 on the SDK path 2026-08-17 15:49:18 -07:00
passthrough fix(bedrock_mantle): register a Bedrock runtime passthrough config so /bedrock/model/<deployment>/invoke works 2026-08-25 10:10:38 -07:00
proxy feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
proxy_auth feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
rag chore(typing): remove 914 basedpyright Any errors across 16 hotspot files 2026-08-10 01:24:40 -07:00
realtime_api fix(health): probe Azure GA realtime path for transcription-only models 2026-08-26 12:14:52 -07:00
repositories feat(proxy): opt-in budget rollover carrying overage into the next window (#38514) 2026-08-27 12:46:09 -07:00
rerank_api fix(together_ai): default endpoints to api.together.ai instead of api.together.xyz 2026-08-25 10:18:55 -07:00
responses feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
router_strategy fix(complexity_router): route client housekeeping calls to the cheapest tier (#38598) 2026-08-27 22:55:09 -07:00
router_utils fix(anthropic): handle per-level reasoning_effort flags without supports_reasoning (#38618) 2026-08-27 22:19:22 -07:00
rust_bridge feat(rust): route /chat/completions through the Rust core for anthropic and bedrock (#37241) 2026-08-20 16:15:24 -07:00
sandbox feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
search chore(lint): strip inert type: ignore comments and zero LIT009, LIT010, LIT011 headroom 2026-08-05 02:37:24 -07:00
secret_managers fix(azure): prefer workload identity over managed identity 2026-08-20 13:45:56 -07:00
skills chore(lint): strip inert type: ignore comments and zero LIT009, LIT010, LIT011 headroom 2026-08-05 02:37:24 -07:00
types feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
vector_store_files chore(lint): clear grandfathered over-limit lint drift and ratchet budgets down 2026-08-05 12:18:13 -07:00
vector_stores refactor(repositories): type prisma table access with one generic protocol 2026-08-25 12:14:17 +00:00
videos refactor(videos): make video upload param keyword-only on public edit fns 2026-08-24 15:55:07 -07:00
__init__.py feat(proxy): opt-in budget rollover carrying overage into the next window (#38514) 2026-08-27 12:46:09 -07:00
_internal_context.py feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
_lazy_imports.py fix(lint): bring basedpyright rule counts back under their budget limits 2026-08-05 10:23:02 -07:00
_lazy_imports_registry.py fix(together_ai): route chat completions through a dedicated TogetherAIChatConfig 2026-08-25 11:44:06 -07:00
_logging.py fix(logging): stop stream-based log collectors classifying INFO logs as errors (#38476) 2026-08-27 17:42:00 -07:00
_redis.py refactor(redis): drop docstrings restating the code 2026-08-26 10:45:56 -07:00
_redis_credential_provider.py chore(lint): strip inert type: ignore comments and zero LIT009, LIT010, LIT011 headroom 2026-08-05 02:37:24 -07:00
_service_logger.py chore(lint): clear grandfathered over-limit lint drift and ratchet budgets down 2026-08-05 12:18:13 -07:00
_uuid.py chore(lint): strip inert type: ignore comments and zero LIT009, LIT010, LIT011 headroom 2026-08-05 02:37:24 -07:00
_version.py
anthropic_beta_headers_config.json
anthropic_beta_headers_manager.py feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
blog_posts.json
budget_manager.py feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
constants.py fix(presidio): chunk oversized text before /analyze so large content blocks do not fail (#38483) 2026-08-27 17:41:55 -07:00
cost.json
cost_calculator.py Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_together_cache_pricing 2026-08-27 14:29:46 -07:00
exceptions.py feat(proxy): redact or drop individual batch records instead of rejecting the file (#37561) 2026-08-20 13:12:55 -07:00
main.py feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
model_prices_and_context_window_backup.json Merge pull request #38100 from FelipeRodriguesGare/bugfix/tencent-thinking-extra-body 2026-08-27 18:23:11 -07:00
policy_templates_backup.json
provider_endpoints_support_backup.json fix(scx-ai): use the published scx.ai rates and the scx_ai docs url 2026-08-21 17:28:12 +10:00
py.typed
router.py feat(spend): report prompt caching savings as total and gateway-attributed (#38134) 2026-08-28 00:19:06 -07:00
scheduler.py feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
setup_wizard.py chore(lint): strip inert type: ignore comments and zero LIT009, LIT010, LIT011 headroom 2026-08-05 02:37:24 -07:00
timeout.py feat(lint): enforce Final on locals and freeze function parameters (LIT010, LIT011) 2026-08-04 12:54:39 -07:00
utils.py feat(model_prices): let a map entry declare its exact reasoning_effort levels (#38481) 2026-08-27 15:38:01 -07:00