mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
fix: expired-miss share over all measured turns + cost-optimization tab labels (#36037)
* fix(ui): make the expired-miss stat row a focusable tooltip trigger * fix: auto-router expired-miss percentage and cost-optimization tab labels - change expired-miss percentage denominator from return-to-tier misses to all measured turns (same_model + first_visit + return_to_tier). when auto-routers flip tiers rapidly within TTL, return-to-tier turns become hits and disappear from the miss count; the old metric reported only the rare failure population. the new metric contextualizes that population as a share of overall coverage - rename usage tab from 'Usage' to 'Overall' - rename auto-router-usage tab from 'Auto-Router Usage' to 'Auto-Router' - update component and unit tests to match new semantics
This commit is contained in:
parent
86890654c5
commit
34fc8d2ee7
6 changed files with 75 additions and 34 deletions
|
|
@ -155,21 +155,45 @@ describe("AutoRouterBenchmarksTab", () => {
|
|||
expect(screen.getByText(/turns measured/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("recomputes the expired-miss share from the miss counts", () => {
|
||||
it("computes the expired-miss share over every measured turn, not just return-to-tier misses", () => {
|
||||
mockHook({ data: response([group()]) });
|
||||
renderTab();
|
||||
|
||||
expect(screen.getByText("Expired-miss")).toBeInTheDocument();
|
||||
expect(screen.getByText("27.1%")).toBeInTheDocument();
|
||||
expect(screen.getByText("2.3%")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("hides the expired-miss row when every return turn hit", () => {
|
||||
it("exposes the whole expired-miss row as a focusable tooltip trigger", () => {
|
||||
mockHook({ data: response([group()]) });
|
||||
renderTab();
|
||||
|
||||
const trigger = screen.getByRole("button", { name: /Expired-miss/ });
|
||||
expect(trigger).toHaveTextContent("2.3%");
|
||||
});
|
||||
|
||||
it("shows a zero expired-miss share, rather than hiding the row, when every return turn hit", () => {
|
||||
const allHits = totals({
|
||||
cache: cache({ return_to_tier: { turns: 381, hits: 381, hit_rate_pct: 100 }, return_misses_expired: 0 }),
|
||||
});
|
||||
mockHook({ data: response([group(allHits)], allHits) });
|
||||
renderTab();
|
||||
|
||||
const trigger = screen.getByRole("button", { name: /Expired-miss/ });
|
||||
expect(trigger).toHaveTextContent("0.0%");
|
||||
});
|
||||
|
||||
it("hides the expired-miss row only when no turns were measured at all", () => {
|
||||
const empty = { turns: 0, hits: 0, hit_rate_pct: 0 };
|
||||
const nothingMeasured = {
|
||||
same_model: empty,
|
||||
first_visit: empty,
|
||||
return_to_tier: empty,
|
||||
return_misses_expired: 0,
|
||||
};
|
||||
const noTurns = totals({ cache: cache(nothingMeasured) });
|
||||
mockHook({ data: response([group(noTurns)], noTurns) });
|
||||
renderTab();
|
||||
|
||||
expect(screen.queryByText("Expired-miss")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -183,23 +183,27 @@ const CachingCard: React.FC<{ cache: AutoRouterCacheStats }> = ({ cache }) => {
|
|||
<p className="text-5xl font-semibold tracking-tight text-foreground">{pctLabel(cache.hit_rate_pct)}</p>
|
||||
</div>
|
||||
{expiredMissPct === null ? null : (
|
||||
<div className="flex items-baseline justify-between gap-2 border-t pt-3">
|
||||
<TooltipProvider delay={200}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<p className="cursor-default text-sm text-muted-foreground underline decoration-dotted underline-offset-2">
|
||||
Expired-miss
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
<TooltipContent className="max-w-64">
|
||||
percentage of return-to-tier cache misses caused by cache expiring
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<p className="font-medium tabular-nums text-foreground">{pctLabel(expiredMissPct)}</p>
|
||||
</div>
|
||||
<TooltipProvider delay={200}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger
|
||||
render={
|
||||
<button
|
||||
type="button"
|
||||
className="flex w-full cursor-default items-baseline justify-between gap-2 border-t pt-3 text-left"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span className="text-sm text-muted-foreground underline decoration-dotted underline-offset-2">
|
||||
Expired-miss
|
||||
</span>
|
||||
<span className="font-medium tabular-nums text-foreground">{pctLabel(expiredMissPct)}</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-64">
|
||||
share of all measured turns that missed cache because a return to an earlier tier came after its TTL
|
||||
lapsed
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,21 +17,21 @@ describe("CostOptimizationView", () => {
|
|||
it("renders the four cost-optimization tabs", () => {
|
||||
const { getByText } = renderView();
|
||||
|
||||
expect(getByText("Usage")).toBeInTheDocument();
|
||||
expect(getByText("Overall")).toBeInTheDocument();
|
||||
expect(getByText("Prompt Compression")).toBeInTheDocument();
|
||||
expect(getByText("Prompt Caching")).toBeInTheDocument();
|
||||
expect(getByText("Auto-Router Usage")).toBeInTheDocument();
|
||||
expect(getByText("Auto-Router")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("defaults to the Usage tab and switches the active tab on click", () => {
|
||||
it("defaults to the Overall tab and switches the active tab on click", () => {
|
||||
const { getByRole } = renderView();
|
||||
|
||||
expect(getByRole("tab", { name: "Usage" })).toHaveAttribute("aria-selected", "true");
|
||||
expect(getByRole("tab", { name: "Overall" })).toHaveAttribute("aria-selected", "true");
|
||||
expect(getByRole("tab", { name: "Prompt Compression" })).toHaveAttribute("aria-selected", "false");
|
||||
|
||||
fireEvent.click(getByRole("tab", { name: "Prompt Compression" }));
|
||||
|
||||
expect(getByRole("tab", { name: "Usage" })).toHaveAttribute("aria-selected", "false");
|
||||
expect(getByRole("tab", { name: "Overall" })).toHaveAttribute("aria-selected", "false");
|
||||
expect(getByRole("tab", { name: "Prompt Compression" })).toHaveAttribute("aria-selected", "true");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const CostOptimizationView: React.FC<CostOptimizationViewProps> = ({ accessToken
|
|||
const items = [
|
||||
{
|
||||
key: "usage",
|
||||
label: "Usage",
|
||||
label: "Overall",
|
||||
children: <UsageTab accessToken={accessToken} activity={activity} />,
|
||||
},
|
||||
{
|
||||
|
|
@ -37,7 +37,7 @@ const CostOptimizationView: React.FC<CostOptimizationViewProps> = ({ accessToken
|
|||
},
|
||||
{
|
||||
key: "autorouter-usage",
|
||||
label: "Auto-Router Usage",
|
||||
label: "Auto-Router",
|
||||
children: <AutoRouterBenchmarksTab accessToken={accessToken} />,
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -131,12 +131,25 @@ describe("bucketRows", () => {
|
|||
});
|
||||
|
||||
describe("expiredMissShare", () => {
|
||||
it("recomputes the expired share from the miss counts", () => {
|
||||
expect(expiredMissShare(cache())).toBeCloseTo((100 * 19) / 70);
|
||||
it("computes the expired share over every measured turn, not just return-to-tier misses", () => {
|
||||
expect(expiredMissShare(cache())).toBeCloseTo((100 * 19) / 818);
|
||||
});
|
||||
|
||||
it("is absent when every return turn hit", () => {
|
||||
expect(expiredMissShare(cache({ return_to_tier: { turns: 10, hits: 10, hit_rate_pct: 100 } }))).toBeNull();
|
||||
it("is zero, not absent, when every return turn hit", () => {
|
||||
expect(
|
||||
expiredMissShare(cache({ return_to_tier: { turns: 10, hits: 10, hit_rate_pct: 100 }, return_misses_expired: 0 })),
|
||||
).toBe(0);
|
||||
});
|
||||
|
||||
it("is absent only when no turns were measured at all", () => {
|
||||
const empty = { turns: 0, hits: 0, hit_rate_pct: 0 };
|
||||
const nothingMeasured = {
|
||||
same_model: empty,
|
||||
first_visit: empty,
|
||||
return_to_tier: empty,
|
||||
return_misses_expired: 0,
|
||||
};
|
||||
expect(expiredMissShare(cache(nothingMeasured))).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -91,9 +91,9 @@ export const bucketRows = (cache: AutoRouterCacheStats): BucketRow[] => {
|
|||
};
|
||||
|
||||
export const expiredMissShare = (cache: AutoRouterCacheStats): number | null => {
|
||||
const misses = cache.return_to_tier.turns - cache.return_to_tier.hits;
|
||||
if (misses <= 0) return null;
|
||||
return (100 * cache.return_misses_expired) / misses;
|
||||
const total = bucketTurnsTotal(cache);
|
||||
if (total <= 0) return null;
|
||||
return (100 * cache.return_misses_expired) / total;
|
||||
};
|
||||
|
||||
export const pctLabel = (value: number, digits: number = 1): string => `${value.toFixed(digits)}%`;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue