diff --git a/litellm/proxy/spend_tracking/cost_savings_endpoints.py b/litellm/proxy/spend_tracking/cost_savings_endpoints.py index 6df2705c1be..0703e27da4e 100644 --- a/litellm/proxy/spend_tracking/cost_savings_endpoints.py +++ b/litellm/proxy/spend_tracking/cost_savings_endpoints.py @@ -159,9 +159,14 @@ def compute_savings_amounts( ) -def _is_unpriced(cache_read_tokens: int, compression_saved_tokens: int, pricing: ModelPricing | None) -> bool: +def _is_unpriced( + cache_read_tokens: int, + cache_creation_tokens: int, + compression_saved_tokens: int, + pricing: ModelPricing | None, +) -> bool: if pricing is None: - return cache_read_tokens > 0 or compression_saved_tokens > 0 + return cache_read_tokens > 0 or cache_creation_tokens > 0 or compression_saved_tokens > 0 return cache_read_tokens > 0 and pricing.cache_read_cost_per_token is None @@ -208,6 +213,7 @@ def build_activity_response( for row in rows if _is_unpriced( row.cache_read_input_tokens, + row.cache_creation_input_tokens, row.compression_saved_tokens, pricing_by_key[(row.model, row.custom_llm_provider)], ) diff --git a/tests/test_litellm/proxy/spend_tracking/test_cost_savings_endpoints.py b/tests/test_litellm/proxy/spend_tracking/test_cost_savings_endpoints.py index 077277d3356..673f9f29bd4 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_cost_savings_endpoints.py +++ b/tests/test_litellm/proxy/spend_tracking/test_cost_savings_endpoints.py @@ -139,10 +139,11 @@ class TestBuildActivityResponse: rows = [ _row(model="mystery-model", custom_llm_provider="", cache_read_input_tokens=100), _row(model="no-cache-price-model", custom_llm_provider="", cache_read_input_tokens=100), + _row(model="mystery-write-only", custom_llm_provider="", cache_creation_input_tokens=100), _row(model="mystery-idle", custom_llm_provider="", spend=1.0), ] response = build_activity_response(rows, COST_MAP) - assert response.unpriced_models == ["mystery-model", "no-cache-price-model"] + assert response.unpriced_models == ["mystery-model", "mystery-write-only", "no-cache-price-model"] assert response.totals.cache_savings == 0.0 diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.test.tsx index f12118160ad..5c14e913e4d 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.test.tsx @@ -93,6 +93,11 @@ describe("formatUsd", () => { expect(formatUsd(0.002625)).toBe("$0.002625"); expect(formatUsd(1234.5)).toBe("$1,234.50"); }); + + it("puts the sign before the dollar symbol for negative net savings", () => { + expect(formatUsd(-1.23)).toBe("-$1.23"); + expect(formatUsd(-0.002625)).toBe("-$0.002625"); + }); }); describe("CostSavingsView", () => { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.tsx index 8ae1dfec965..ac7377d206e 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-savings/CostSavingsView.tsx @@ -29,11 +29,12 @@ const OPTIMIZATION_TAG_COLOR: Record = { export function formatUsd(value: number): string { if (value === 0) return "$0"; + const sign = value < 0 ? "-" : ""; const abs = Math.abs(value); if (abs >= 0.01) { - return `$${value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + return `${sign}$${abs.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } - return `$${value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`; + return `${sign}$${abs.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`; } function defaultDateRange(): DateRangeValue {