Spaces:
Running
Running
| "use client"; | |
| import type { ReactElement } from "react"; | |
| import { | |
| CartesianGrid, | |
| ResponsiveContainer, | |
| Scatter, | |
| ScatterChart, | |
| Tooltip, | |
| XAxis, | |
| YAxis, | |
| ZAxis, | |
| } from "recharts"; | |
| import ProvenanceChip from "@/components/ui/ProvenanceChip"; | |
| import { categoryLabels, fmt } from "@/lib/data"; | |
| import type { ModelRow } from "@/lib/types"; | |
| import { | |
| CHART_AXIS_LABEL, | |
| CHART_AXIS_TICK, | |
| CHART_LABEL_FILL, | |
| CHART_LABEL_KNOCKOUT, | |
| categoryColor, | |
| isApiCategory, | |
| shortName, | |
| } from "./compare-utils"; | |
| interface EffDatum { | |
| rtfx: number; | |
| wer: number; | |
| paramsB: number; | |
| model: ModelRow; | |
| } | |
| function renderBubble(props: unknown): ReactElement { | |
| const { cx, cy, size, payload } = props as { | |
| cx?: number; | |
| cy?: number; | |
| size?: number; | |
| payload?: EffDatum; | |
| }; | |
| if (typeof cx !== "number" || typeof cy !== "number" || !payload) { | |
| return <g />; | |
| } | |
| const color = categoryColor[payload.model.category]; | |
| const r = Math.max(Math.sqrt((size ?? 64) / Math.PI), 4); | |
| const side = r * Math.SQRT2; // diamond with the same half-diagonal | |
| return ( | |
| <g> | |
| {isApiCategory(payload.model.category) ? ( | |
| <rect | |
| x={cx - side / 2} | |
| y={cy - side / 2} | |
| width={side} | |
| height={side} | |
| transform={`rotate(45 ${cx} ${cy})`} | |
| style={{ fill: color }} | |
| fillOpacity={0.14} | |
| stroke={color} | |
| strokeWidth={1.25} | |
| /> | |
| ) : ( | |
| <circle | |
| cx={cx} | |
| cy={cy} | |
| r={r} | |
| style={{ fill: color }} | |
| fillOpacity={0.14} | |
| stroke={color} | |
| strokeWidth={1.25} | |
| /> | |
| )} | |
| <circle cx={cx} cy={cy} r={1.6} style={{ fill: color }} /> | |
| <text | |
| x={cx} | |
| y={cy - r - 6} | |
| textAnchor="middle" | |
| style={{ | |
| fill: CHART_LABEL_FILL, | |
| fontSize: 11, | |
| fontFamily: "var(--font-mono), 'IBM Plex Mono', monospace", | |
| ...CHART_LABEL_KNOCKOUT, | |
| }} | |
| > | |
| {shortName(payload.model)} | |
| </text> | |
| </g> | |
| ); | |
| } | |
| function EffTooltip(props: unknown) { | |
| const { active, payload } = props as { | |
| active?: boolean; | |
| payload?: ReadonlyArray<{ payload?: EffDatum }>; | |
| }; | |
| const d = payload?.[0]?.payload; | |
| if (!active || !d) return null; | |
| return ( | |
| <div className="glass depth-2 min-w-48 rounded-sm bg-surface-2/85 px-3 py-2.5"> | |
| <p className="text-sm leading-snug text-text">{d.model.name}</p> | |
| <p className="num mt-0.5 text-[11px] tracking-wide text-muted"> | |
| {d.model.org} · {categoryLabels[d.model.category]} | |
| </p> | |
| <dl className="num mt-2 space-y-1 text-[12px]"> | |
| <div className="flex items-baseline justify-between gap-6"> | |
| <dt className="text-muted">RTFx</dt> | |
| <dd className="text-text">{fmt(d.rtfx)}×</dd> | |
| </div> | |
| <div className="flex items-baseline justify-between gap-6"> | |
| <dt className="text-muted">WER</dt> | |
| <dd className="text-text">{fmt(d.wer)}</dd> | |
| </div> | |
| <div className="flex items-baseline justify-between gap-6"> | |
| <dt className="text-muted">Params</dt> | |
| <dd className="text-text">{fmt(d.paramsB, 3)}B</dd> | |
| </div> | |
| </dl> | |
| </div> | |
| ); | |
| } | |
| export interface EfficiencySectionProps { | |
| models: ModelRow[]; | |
| /** Name of the dataset the comparison is scoped to (e.g. "ViMedCSS"). */ | |
| datasetName?: string; | |
| } | |
| export default function EfficiencySection({ | |
| models, | |
| datasetName = "ViMedCSS", | |
| }: EfficiencySectionProps) { | |
| const data: EffDatum[] = models.flatMap((m) => { | |
| const s = m.metrics?.test; | |
| if (typeof s?.rtfx !== "number" || typeof s?.wer !== "number") return []; | |
| return [{ rtfx: s.rtfx, wer: s.wer, paramsB: m.paramsB ?? 0.1, model: m }]; | |
| }); | |
| const running = models.filter((m) => m.provenance === "running"); | |
| /* a sparse plot reads as broken unless the gap is named: when most | |
| systems are unmeasured, say so inside the plot itself */ | |
| const unmeasured = models.length - data.length; | |
| const sparse = data.length > 0 && unmeasured > models.length / 2; | |
| return ( | |
| <section aria-label="Efficiency: throughput against accuracy"> | |
| <div className="glass depth-2 spotlight-card rounded-sm p-5"> | |
| {data.length > 0 ? ( | |
| <figure> | |
| <div | |
| className="relative h-[360px] w-full" | |
| role="img" | |
| aria-label={`Bubble chart of RTFx throughput against WER on the ${datasetName} Test split; bubble area scales with parameter count. ${data.length} platform-measured models plotted.`} | |
| > | |
| {sparse && ( | |
| <p className="num absolute top-10 left-16 z-10 max-w-[34ch] rounded-sm border border-dashed border-line bg-surface/70 px-2.5 py-1.5 text-[11px] leading-relaxed tracking-wide text-muted"> | |
| {data.length} of {models.length} systems measured — RTFx only | |
| ships with platform-verified runs; the rest of this plane is | |
| the evidence gap, not the field. | |
| </p> | |
| )} | |
| <ResponsiveContainer width="100%" height="100%"> | |
| <ScatterChart | |
| margin={{ top: 28, right: 36, bottom: 16, left: 8 }} | |
| > | |
| <CartesianGrid stroke="var(--line)" strokeWidth={1} /> | |
| <XAxis | |
| type="number" | |
| dataKey="rtfx" | |
| name="RTFx" | |
| domain={[0, "auto"]} | |
| tick={CHART_AXIS_TICK} | |
| tickLine={{ stroke: "var(--line)" }} | |
| axisLine={{ stroke: "var(--line)" }} | |
| label={{ | |
| value: "RTFX × · BETTER →", | |
| position: "insideBottomRight", | |
| offset: -8, | |
| style: CHART_AXIS_LABEL, | |
| }} | |
| /> | |
| <YAxis | |
| type="number" | |
| dataKey="wer" | |
| name="WER" | |
| domain={[15, 65]} | |
| tick={CHART_AXIS_TICK} | |
| tickLine={{ stroke: "var(--line)" }} | |
| axisLine={{ stroke: "var(--line)" }} | |
| width={44} | |
| label={{ | |
| value: "WER % · ↓ BETTER", | |
| angle: -90, | |
| position: "insideLeft", | |
| offset: 8, | |
| style: { ...CHART_AXIS_LABEL, textAnchor: "middle" }, | |
| }} | |
| /> | |
| <ZAxis | |
| type="number" | |
| dataKey="paramsB" | |
| range={[80, 640]} | |
| name="Params (B)" | |
| /> | |
| <Tooltip | |
| cursor={{ stroke: "var(--line)", strokeDasharray: "3 3" }} | |
| content={EffTooltip} | |
| /> | |
| <Scatter data={data} shape={renderBubble} /> | |
| </ScatterChart> | |
| </ResponsiveContainer> | |
| </div> | |
| <figcaption className="hairline-t mt-4 pt-3 text-[13px] text-muted"> | |
| RTFx = audio seconds ÷ wall seconds, measured on platform | |
| hardware. Bubble area scales with parameter count. {datasetName}{" "} | |
| test split · normalizer v0.1. | |
| </figcaption> | |
| </figure> | |
| ) : ( | |
| /* slim status banner — the tall canvas is reserved for real data */ | |
| <div className="flex flex-wrap items-center gap-x-4 gap-y-2 rounded-sm border border-dashed border-line bg-surface-2/40 px-4 py-3"> | |
| <span | |
| aria-hidden | |
| className="pulse-dot inline-block size-2 shrink-0 rounded-full bg-accent" | |
| /> | |
| <p | |
| className="num text-[12px] tracking-[0.18em] text-muted" | |
| title="Throughput is only recorded when this platform executes the model itself; paper-imported rows never carry RTFx." | |
| > | |
| AWAITING PILOT DATA — RTFX REQUIRES A PLATFORM-VERIFIED RUN | |
| </p> | |
| {running.length > 0 && ( | |
| <ul className="flex flex-wrap items-center gap-x-4 gap-y-2"> | |
| {running.map((m) => ( | |
| <li key={m.slug} className="flex items-center gap-2"> | |
| <span className="num text-[12px] text-text">{m.name}</span> | |
| <ProvenanceChip provenance={m.provenance} /> | |
| </li> | |
| ))} | |
| </ul> | |
| )} | |
| </div> | |
| )} | |
| </div> | |
| </section> | |
| ); | |
| } | |