SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%
12.3 KB · 205 lines tsx
Raw Blame History
1import Link from 'next/link';2import { CompareButton } from '@/components/compare/compare-button';3import { ComparabilityBadge, ConfigChipEl, OpennessChip, TrustBadge } from '@/components/models/badges';4import { configChipsOf, fmtScoreUnit, refToSummary } from '@/components/models/shared';5import { FrontierLineChart } from './client-charts';6import { ScrollX } from '@/components/models/scroll-x';7import { EntityLink } from '@/components/ui/entity';8import { Pagination } from '@/components/ui/pagination';9import { SourceCell } from '@/components/ui/provenance';10import { Note } from '@/components/ui/section';11import { EmptyState } from '@/components/ui/unavailable';12import { cn } from '@/lib/cn';13import { fmtDate, fmtInt, fmtSigned } from '@/lib/format';14import { routes } from '@/lib/site';15import type { BenchmarkFrontierPayload, Group, LeaderboardRow } from '@/lib/types';1617/*18  Leaderboard 2.0 (server): one row per canonical model — rank (+Δ vs closed rows) · model · score bar · trust · config chips ·19  comparability vs leader · evaluated/observed · source · History · Compare. Mobile stacks (rank + model + score first).20*/2122export function Leaderboard2({ rows, group, total, limit, offset, makeHref, historyHref, activeModel, unit }: { rows: LeaderboardRow[]; group: Group | null; total: number; limit: number; offset: number; makeHref: (offset: number) => string; historyHref: (slug: string) => string; activeModel?: string; unit?: string | null }) {23  if (!rows.length) return <EmptyState title="No result in this group with these filters">Relax the trust / organization filters or pick another comparability group.</EmptyState>;24  const hib = rows[0]?.higher_is_better !== false;25  const scores = rows.map((r) => r.score).filter(Number.isFinite);26  const max = Math.max(...scores);27  const min = Math.min(...scores);28  const width = (s: number) => {29    if (!Number.isFinite(s) || max <= 0) return 0;30    const v = hib ? s / max : min > 0 ? min / s : 0;31    return Math.max(2, Math.min(100, v * 100));32  };33  const u = unit ?? rows[0]?.unit ?? null;34  const leader = rows.find((r) => r.rank === 1) ?? rows[0];35  return (36    <>37      <ScrollX>38      <table className="data-table stack compact" data-leaderboard>39        <caption className="sr-only">Leaderboard</caption>40        <thead>41          <tr>42            <th scope="col" className="w-12">43              #44            </th>45            <th scope="col">Model</th>46            <th scope="col" className="num">47              Score48            </th>49            <th scope="col">Trust</th>50            <th scope="col">Configuration</th>51            <th scope="col">vs leader</th>52            <th scope="col">Evaluated</th>53            <th scope="col">Source</th>54            <th scope="col" className="text-right">55              <span className="sr-only">Actions</span>56            </th>57          </tr>58        </thead>59        <tbody>60          {rows.map((r) => {61            const on = activeModel === r.model.slug;62            const chips = configChipsOf(r.config, group?.config ?? null, 4);63            const openness = typeof r.model.attributes?.openness === 'string' ? r.model.attributes.openness : null;64            return (65              <tr key={r.result_id} className={cn(on && 'bg-accent-soft/40')} data-model={r.model.slug}>66                <td className="tnum text-ink-3" data-label="Rank">67                  <span className="font-medium text-ink">{fmtInt(r.rank)}</span>68                  {r.delta_rank !== null && r.delta_rank !== 0 && (69                    <span className={cn('ml-1 text-[11px]', r.delta_rank > 0 ? 'text-positive' : 'text-danger')} title={`Rank moved ${fmtSigned(r.delta_rank)} vs the closed rows of this group${r.previous_rank ? ` (was ${r.previous_rank})` : ''}`}>70                      {r.delta_rank > 0 ? '▲' : '▼'}71                      {Math.abs(r.delta_rank)}72                    </span>73                  )}74                </td>75                <td className="primary">76                  <span className="flex flex-wrap items-center gap-x-2 gap-y-0.5">77                    <EntityLink e={{ ...r.model, entity_type: 'model' }} />78                    {openness && <OpennessChip openness={openness} />}79                  </span>80                  <span className="block text-[11px] text-ink-3">81                    {r.model.organization?.name ?? ''}82                    {typeof r.model.attributes?.family === 'string' ? ` · ${r.model.attributes.family}` : ''}83                    {r.n_rows > 1 ? ` · best of ${r.n_rows} rows` : ''}84                  </span>85                </td>86                <td className="num tnum font-medium" data-label="Score">87                  <span className="inline-flex flex-col items-end gap-1">88                    <span>{fmtScoreUnit(r.score, u)}</span>89                    <span className="block h-1 w-24 overflow-hidden rounded-sm bg-surface-2" aria-hidden>90                      <span className="block h-full" style={{ width: `${width(r.score)}%`, background: 'var(--type-benchmark)' }} />91                    </span>92                  </span>93                </td>94                <td data-label="Trust">95                  <TrustBadge level={r.trust_level} label={r.trust_label} />96                </td>97                <td data-label="Configuration">98                  <span className="flex flex-wrap gap-1">{chips.length ? chips.map((c) => <ConfigChipEl key={c.key} k={c.key} v={c.value} kind={c.kind} />) : <span className="text-xs text-ink-3">group defaults</span>}</span>99                </td>100                <td data-label="vs leader">101                  {r.rank === 1 ? <span className="text-xs font-medium text-positive">leader</span> : <ComparabilityBadge level={r.comparability} reasons={r.comparability_reasons} />}102                  {leader && r.rank !== 1 && <span className="tnum block text-[11px] text-ink-3">{(hib ? r.score - leader.score : leader.score - r.score).toFixed(Math.abs(r.score - leader.score) < 10 ? 2 : 1)}{u === '%' ? ' pt' : ''}</span>}103                </td>104                <td data-label="Evaluated" className="tnum whitespace-nowrap text-xs text-ink-2" title={r.evaluated_at ? undefined : `Observed ${fmtDate(r.observed_at)}; the source gave no evaluation date`}>105                  {r.evaluated_at ? fmtDate(r.evaluated_at) : <span className="text-ink-3">obs. {fmtDate(r.observed_at)}</span>}106                </td>107                <td data-label="Source">108                  <SourceCell url={r.source_url} tier={r.tier} />109                </td>110                <td className="text-right">111                  <span className="inline-flex flex-wrap items-center justify-end gap-1">112                    <Link href={historyHref(r.model.slug)} className={cn('inline-flex h-7 items-center border px-1.5 text-xs whitespace-nowrap', on ? 'border-accent bg-accent-soft text-accent' : 'border-rule text-ink-2 hover:border-rule-strong hover:text-ink')} aria-pressed={on}>113                      History114                    </Link>115                    <CompareButton e={refToSummary(r.model)} size="sm" label="" />116                  </span>117                </td>118              </tr>119            );120          })}121        </tbody>122      </table>123      </ScrollX>124      <Pagination total={total} limit={limit} offset={offset} makeHref={makeHref} className="mt-4" />125      <Note className="mt-3">126        One row per canonical model — its best current row inside this comparability group (effort variants are folded into the model). Bars are relative to the page's best score{hib ? '' : ' (lower is better)'}. “vs leader” reads comparability: partially comparable = same task, conditions differ (reasoning effort, temperature, judge). <Link href="/methodology#benchmarks" className="link">Rules →</Link>127      </Note>128    </>129  );130}131132/** Frontier over time: a point each time a new best appeared in the group; markers = leader changes. */133export function FrontierChart({ frontier, group, unit }: { frontier: BenchmarkFrontierPayload | null; group: Group | null; unit?: string | null }) {134  if (!frontier) return <Note>Frontier history unavailable.</Note>;135  const series = frontier.series.find((s) => (group ? s.group.config_key === group.config_key && s.group.metric === group.metric : s.primary)) ?? frontier.series.find((s) => s.primary) ?? frontier.series[0];136  if (!series) return <Note>No frontier history for this group.</Note>;137  const pts = series.points.map((p) => ({ x: new Date(p.date), y: p.score, p })).filter((x) => !Number.isNaN(x.x.getTime())).sort((a, b) => a.x.getTime() - b.x.getTime());138  const days = new Set(pts.map((p) => p.x.toISOString().slice(0, 10)));139  return (140    <div data-frontier-chart>141      {pts.length < 2 || days.size < 2 ? (142        <Note>143          {pts.length === 0 ? 'No leader recorded yet.' : `${fmtInt(pts.length)} leader change${pts.length === 1 ? '' : 's'} recorded, all dated ${fmtDate(pts[0]?.p.date)} — the frontier line needs at least two distinct dates.`} The corpus is young: every result was first observed on the same day, so leader changes will separate in time as sources are re-crawled.144        </Note>145      ) : (146        <FrontierLineChart points={pts.map((p) => ({ x: p.p.date, y: p.y }))} unit={unit ?? null} label={`Frontier of ${frontier.benchmark.name}`} />147      )}148      {pts.length > 0 && (149        <ol className="mt-3 divide-y divide-rule border-y border-rule text-sm">150          {[...pts].reverse().slice(0, 8).map((p) => (151            <li key={p.p.result_id} className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-baseline gap-x-3 py-1.5">152              <span className="tnum font-medium">{fmtScoreUnit(p.y, unit)}</span>153              <span className="min-w-0 truncate">154                <EntityLink e={{ ...p.p.model, entity_type: 'model' }} /> <span className="text-xs text-ink-3">{p.p.model.organization?.name ?? ''}</span> <TrustBadge level={p.p.trust_level} className="ml-1" />155              </span>156              <span className="tnum text-xs text-ink-2">{fmtDate(p.p.date)}</span>157            </li>158          ))}159        </ol>160      )}161      <Note className="mt-2">{frontier.methodology}</Note>162    </div>163  );164}165166/** Group picker: links when ≤ 8 groups, else a GET <select> — always server-rendered. */167export function GroupPicker({ groups, active, makeHref, slug, hidden }: { groups: Group[]; active: Group | null; makeHref: (g: Group) => string; slug: string; hidden: Record<string, string | undefined> }) {168  if (groups.length <= 1) return active ? <p className="text-xs text-ink-2">{active.label}</p> : null;169  const sorted = [...groups].sort((a, b) => b.model_count - a.model_count);170  if (sorted.length <= 8)171    return (172      <ul className="space-y-px" data-group-picker>173        {sorted.map((g) => {174          const on = active?.config_key === g.config_key && active?.metric === g.metric;175          return (176            <li key={`${g.metric}:${g.config_key}`}>177              <Link href={makeHref(g)} className={cn('flex min-h-8 items-start justify-between gap-2 px-1 py-1 text-[12px] leading-4 hover:bg-surface-2', on ? 'bg-surface-2 font-medium text-ink' : 'text-ink-2')} aria-current={on ? 'true' : undefined} title={g.label}>178                <span className="min-w-0">179                  <span className="block">{g.metric}</span>180                  <span className="mono block truncate text-[10.5px] font-normal text-ink-3">{Object.entries(g.config).map(([k, v]) => `${k}=${String(v)}`).join(' · ') || 'default'}</span>181                </span>182                <span className="tnum shrink-0 text-[11px] text-ink-3">{fmtInt(g.model_count)}</span>183              </Link>184            </li>185          );186        })}187      </ul>188    );189  return (190    <form action={routes.benchmark(slug)} method="get" className="space-y-2" data-group-picker>191      {Object.entries(hidden).map(([k, v]) => (v ? <input key={k} type="hidden" name={k} value={v} /> : null))}192      <select name="group" defaultValue={active ? `${active.metric}|${active.config_key}` : ''} className="h-9 w-full border border-rule bg-surface px-2 text-[12px] text-ink focus:border-accent focus:outline-none" aria-label="Comparability group">193        {sorted.map((g) => (194          <option key={`${g.metric}:${g.config_key}`} value={`${g.metric}|${g.config_key}`}>195            {g.label} ({g.model_count})196          </option>197        ))}198      </select>199      <button type="submit" className="inline-flex h-8 w-full items-center justify-center bg-ink px-3 text-[12px] font-medium text-canvas hover:opacity-90">200        Show group201      </button>202    </form>203  );204}205