diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.test.tsx index 006da4f2725..2820a9dce83 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.test.tsx @@ -187,10 +187,10 @@ describe("AutoRouterBenchmarksTab", () => { }); it.each([ - { spend: 20665.28, classifier_cost: 342.18, turns: 140815, llm: "$20,323.10", cost: "$342.18" }, - { spend: 0, classifier_cost: 0, turns: 0, llm: "$0.00", cost: "$0.00" }, - { spend: 0.002, classifier_cost: 0.0004, turns: 100, llm: "$0.0016", cost: "$0.0004" }, - ])("shows total classification cost across $turns turns without a per-turn rate", ({ llm, cost, ...values }) => { + { spend: 20665.28, classifier_cost: 342.18, turns: 140815, llm: "$20,323.10", cost: "$342.18", rate: "$2.43" }, + { spend: 0, classifier_cost: 0, turns: 0, llm: "$0.00", cost: "$0.00", rate: "$0.00" }, + { spend: 0.002, classifier_cost: 0.0004, turns: 100, llm: "$0.0016", cost: "$0.0004", rate: "$0.0040" }, + ])("shows total classification cost and its rate across $turns turns", ({ llm, cost, rate, ...values }) => { const stats = totals({ ...values, saved_spend: 10126.28, baseline_spend: values.spend + 10126.28 }); mockHook({ data: response([group(stats)], stats) }); renderTab(); @@ -201,7 +201,7 @@ describe("AutoRouterBenchmarksTab", () => { .map((node) => node.textContent) .slice(1, 3), ).toEqual([llm, cost]); - expect(screen.queryByText(/1K turns/)).not.toBeInTheDocument(); + expect(screen.getByText(`(${rate} / 1K turns)`)).toBeInTheDocument(); expect(screen.getAllByText("$10,126.28").length).toBeGreaterThan(0); }); @@ -237,7 +237,7 @@ describe("AutoRouterBenchmarksTab", () => { expect(terms).toEqual([ "Actual auto-router spend", "LLM spend", - "Classification cost", + "Classification cost($2.00 / 1K turns)", "Estimated spend at highest-tier model", ]); expect(values).toEqual(["$359.86", "$353.71", "$6.15", "$2,534.45"]); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.tsx index 33ad1bfe555..ce5ab1c6776 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/AutoRouterBenchmarksTab.tsx @@ -30,7 +30,7 @@ import { type BenchmarkView, type BucketRow, } from "./autoRouterBenchmarks"; -import { formatRangeLabel, usd } from "./costOptimizationUtils"; +import { classificationRatePer1kTurns, formatRangeLabel, usd } from "./costOptimizationUtils"; import ShadowEvalSection from "./ShadowEvalSection"; import TierTurnsChart from "./TierTurnsChart"; import { useAutoRouterBenchmarks } from "./useAutoRouterBenchmarks"; @@ -52,9 +52,17 @@ const Metric: React.FC<{ label: string; value: string; hint?: string }> = ({ lab ); -const SpendRow: React.FC<{ label: string; value: string; subdued?: boolean }> = ({ label, value, subdued }) => ( +const SpendRow: React.FC<{ label: string; value: string; hint?: string; subdued?: boolean }> = ({ + label, + value, + hint, + subdued, +}) => (
Compares your actual routed spend with the estimated cost of using only the most expensive model configured in the auto-router. It accounts for both the cache savings from staying on one model and the added cache costs from - switching models. Savings are net of recorded LLM classification cost, which is included in actual spend. The - range counts whole sessions that overlap it, so totals can differ slightly from the Overall tab, which buckets - savings by UTC day. + switching models. Savings are net of recorded LLM classification cost, which is included in actual spend. + Classification cost per 1K turns is averaged over all auto-router turns, including those that skip + classification. The range counts whole sessions that overlap it, so totals can differ slightly from the Overall + tab, which buckets savings by UTC day.