Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #460.
This commit is contained in:
@@ -1,7 +1,24 @@
|
||||
import type { ReactElement } from "react";
|
||||
import { Card, SectionHeader, ProgressBar, type ProgressBarVariant } from "@mosaic/ui";
|
||||
import type { TokenBudgetEntry } from "@/lib/api/dashboard";
|
||||
|
||||
interface ModelBudget {
|
||||
export interface TokenBudgetProps {
|
||||
budgets?: TokenBudgetEntry[] | undefined;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Helpers */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
const VARIANT_CYCLE: ProgressBarVariant[] = ["blue", "teal", "purple", "amber"];
|
||||
|
||||
function formatTokenCount(n: number): string {
|
||||
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
|
||||
if (n >= 1_000) return `${(n / 1_000).toFixed(0)}K`;
|
||||
return String(n);
|
||||
}
|
||||
|
||||
interface ModelBudgetDisplay {
|
||||
id: string;
|
||||
label: string;
|
||||
usage: string;
|
||||
@@ -9,39 +26,28 @@ interface ModelBudget {
|
||||
variant: ProgressBarVariant;
|
||||
}
|
||||
|
||||
const models: ModelBudget[] = [
|
||||
{
|
||||
id: "sonnet",
|
||||
label: "claude-3-5-sonnet",
|
||||
usage: "2.1M / 3M",
|
||||
value: 70,
|
||||
variant: "blue",
|
||||
},
|
||||
{
|
||||
id: "haiku",
|
||||
label: "claude-3-haiku",
|
||||
usage: "890K / 5M",
|
||||
value: 18,
|
||||
variant: "teal",
|
||||
},
|
||||
{
|
||||
id: "gpt4o",
|
||||
label: "gpt-4o",
|
||||
usage: "320K / 1M",
|
||||
value: 32,
|
||||
variant: "purple",
|
||||
},
|
||||
{
|
||||
id: "llama",
|
||||
label: "local/llama-3.3",
|
||||
usage: "unlimited",
|
||||
value: 55,
|
||||
variant: "amber",
|
||||
},
|
||||
];
|
||||
function mapBudgetToDisplay(entry: TokenBudgetEntry, index: number): ModelBudgetDisplay {
|
||||
const percent = entry.limit > 0 ? Math.round((entry.used / entry.limit) * 100) : 0;
|
||||
const usage =
|
||||
entry.limit > 0
|
||||
? `${formatTokenCount(entry.used)} / ${formatTokenCount(entry.limit)}`
|
||||
: "unlimited";
|
||||
|
||||
return {
|
||||
id: entry.model,
|
||||
label: entry.model,
|
||||
usage,
|
||||
value: percent,
|
||||
variant: VARIANT_CYCLE[index % VARIANT_CYCLE.length] ?? "blue",
|
||||
};
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Components */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
interface ModelRowProps {
|
||||
model: ModelBudget;
|
||||
model: ModelBudgetDisplay;
|
||||
}
|
||||
|
||||
function ModelRow({ model }: ModelRowProps): ReactElement {
|
||||
@@ -84,14 +90,27 @@ function ModelRow({ model }: ModelRowProps): ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
export function TokenBudget(): ReactElement {
|
||||
export function TokenBudget({ budgets }: TokenBudgetProps): ReactElement {
|
||||
const displayModels = budgets ? budgets.map(mapBudgetToDisplay) : [];
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<SectionHeader title="Token Budget" subtitle="Usage by model" />
|
||||
<div>
|
||||
{models.map((model) => (
|
||||
<ModelRow key={model.id} model={model} />
|
||||
))}
|
||||
{displayModels.length > 0 ? (
|
||||
displayModels.map((model) => <ModelRow key={model.id} model={model} />)
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
padding: "24px 0",
|
||||
textAlign: "center",
|
||||
fontSize: "0.8rem",
|
||||
color: "var(--muted)",
|
||||
}}
|
||||
>
|
||||
No budget data
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user