feat: gpu compare#351
Merged
Merged
Conversation
Issue #267. New top-level route that renders any pair of GPUs from the HW_REGISTRY as a focused, indexable head-to-head comparison. - `/compare/[slug]` is server-rendered (`force-dynamic`) and reads from the same `cachedQuery` blob cache used by `/api/v1/benchmarks`, so the existing `/api/v1/invalidate` endpoint (which calls `purgeAll()` → `blobPurge()` + `revalidateTag('db')`) also flushes the compare pages on each ingest. No time-based revalidation. - Slug = `<a>-vs-<b>`. Canonical = alphabetical; non-canonical slugs redirect (307) to canonical so we get one URL per pair. - JSON-LD `ItemList` of `Product` entries with vendor, architecture, TDP, and best-in-class throughput / TTFT / TPOT pulled from the actual benchmark data — consumable by search engines and LLMs. - Reuses `<InferenceProvider>` + `<InferenceChartDisplay>` so the chart, table, controls, PNG/CSV export, pan/zoom, and unofficial-run overlay path all carry over unchanged. - Server picks `(precision, sequence)` defaults that maximise overlap between the two GPUs in the pair (so `/compare/h100-vs-h200` lands on FP8 instead of the global FP4 default which has no Hopper data). New `initialModel` / `initialSequence` / `initialPrecisions` props on `GlobalFilterProvider` take effect only when the URL has no override. - `InferenceProvider` gains `initialActiveHwTypes` to seed the legend filter from the slug. The existing `pendingActiveHwTypes` consumer now understands bare GPU prefixes (e.g. `h100`) in addition to full framework-suffixed hwKeys, so we can pass `[a, b]` without knowing which framework configs exist. - OG image generator at `/compare/[slug]/opengraph-image` produces a vendor-coloured side-by-side `A vs B` PNG. - Sitemap includes all C(n, 2) canonical pairs. - 14 unit tests for slug parse / canonicalize / pair-enumeration. Verified in Playwright: - /compare/h100-vs-h200 → FP8 auto-selected, H100/H200 active in legend, others dimmed; both charts render real data. - /compare/b200-vs-mi355x (cross-vendor) → both shown, real data. - /compare/h200-vs-h100 → 307 → /compare/h100-vs-h200. - /compare/a100-vs-h100 → 404. - OG image renders correctly. Co-authored-by: functionstackx <functionstackx@users.noreply.github.com>
…ring-array widening
…ical-redirect E2E
… hydration mismatch
…ors, applyIfEnum/applyIfMatches helpers
… shareable-link state
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ensitive script regex)
5 tasks
functionstackx
added a commit
that referenced
this pull request
May 26, 2026
…ible redirects (#382) * feat(compare): extend SSR /compare to all models with model-prefixed URLs PR #351 introduced /compare/[a]-vs-[b] but hardcoded DeepSeek R1 as the only model the SSR fetch, OG image, JSON-LD, and metadata understand. This adds a model prefix to the slug so every model the dashboard knows about gets its own SSR'd, indexable comparison page for every GPU pair. URL format ========== - New canonical: /compare/{model-slug}-{a}-vs-{b} - Bare-slug back-compat: /compare/{a}-vs-{b} -> one-hop 307 to /compare/deepseek-r1-{a}-vs-{b} so PR #351 inbound links still resolve. - Query params survive the redirect (?i_seq=1k/1k&i_prec=fp8 etc.) — the prior redirect logic dropped them, which would have broken bare-slug shared links. Model slug registry (packages/app/src/lib/compare-slug.ts): deepseek-r1, deepseek-v4, kimi-k26, qwen-3-5, glm-5-1, minimax-m27, llama-3-3-70b, gptoss-120b (8 canonical slugs). Alias slugs that 307 to the canonical version (family-level shortcuts + older-version supersession): deepseek -> deepseek-r1 kimi, kimi-k25 -> kimi-k26 glm, glm-5 -> glm-5-1 (same architecture, newer point release wins) minimax, minimax-m25 -> minimax-m27 qwen -> qwen-3-5 llama -> llama-3-3-70b gptoss -> gptoss-120b URL slugs are deliberately finer-grained than the dashboard's display-grouped model dropdown — kimi-k25 and kimi-k26 are distinct slugs even though both DB keys roll up to one "Kimi-K2.5" display option in the UI. Each slug queries a single dbKey so the data shown matches the URL exactly. Parser ====== parseCompareSlug now returns { model, a, b, isLegacyBareSlug, isAliasModel }. GPU keys contain no hyphens (h100, gb200, mi355x), so the parser finds the {model}/{a} split by lastIndexOf('-') in the left half — unambiguous even when the model slug contains hyphens like deepseek-r1 or glm-5-1. The page-level handler issues one 307 to the fully canonical URL for any combination of (bare slug + alias model + non-canonical GPU order). Per-model data fetch ==================== getCachedBenchmarks(parsed.model.dbKeys) replaces the hardcoded ['dsr1']. The query cache is already keyed on the dbKeys array, so each model gets its own cache slot with zero extra cache work. generateStaticParams + sitemap ============================== allCanonicalCompareSlugs() emits the (canonical models × pairs) cross product = 8 * 36 = 288 entries. Sitemap jumps from 36 to 288 URLs. Index page (compare/page.tsx) becomes one section per model, each with the existing NVIDIA-vs-NVIDIA / AMD-vs-AMD / cross-vendor sub-grid. OG image + metadata + JSON-LD + page header =========================================== - OG eyebrow now reads "{model.label} · Head-to-head GPU benchmark" - Page metadata title is "{model.label} — {GPU label} Inference Benchmark" - JSON-LD ItemList.name and Dataset.name include the model name, and each comparison Observation includes a Model PropertyValue so search engines understand "this is a per-model comparison" - Page-client header eyebrow shows "{model.label} · GPU comparison" above the H1 so the URL-grouping is legible without scanning the URL. Tests ===== - compare-slug.test.ts: 32 unit tests covering new canonical form, alias resolution (every alias key), bare-slug detection, every canonical model round-trip through parser + canonicalizer, rejection cases (unknown model, unknown GPU, same GPU twice, malformed). - compare-redirect.cy.ts: 9 e2e cases covering bare-slug redirect, alias redirect (kimi -> kimi-k26), older-version redirect (kimi-k25 -> kimi-k26, glm-5 -> glm-5-1), reversed GPU order through any redirect class, query-param preservation, and non-deepseek canonical slugs serving without redirect. - compare-table.cy.ts + url-params.cy.ts: visit canonical model-prefixed URLs directly so assertions are about the rendered page, not interleaved with bare-slug redirects. Backward compatibility ====================== Every URL form that worked under PR #351 — /compare/h100-vs-h200, /compare/h200-vs-h100 (non-canonical), uppercase — keeps working via the one-hop 307 redirect chain. ?g_model= URL param still overrides the slug-derived model on the SSR side for advanced sharers. Manual verification (dev server): - 307 Location headers correct for all 5 redirect classes - Query params preserved: ?i_seq=1k/1k&i_prec=fp8 -> ?i_seq=1k%2F1k&i_prec=fp8 - Invalid model slug -> 404 - Sitemap count: exactly 288 compare URLs - /compare index: 200 OK Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(compare): filter index, sitemap, and SSG params by real benchmark coverage Only emit /compare/<model>-<a>-vs-<b> URLs where both GPUs actually have benchmark rows for that model in Neon. Avoids 156 empty pair cards in the index and ~123 unreachable sitemap entries (288 -> 165). - compare-availability.ts: cached server-side helper using getAvailabilityData - compare/page.tsx: async, filtered modelsWithPairs, per-model card sections - sitemap.ts: async, only canonical (model, pair) combos with data - [slug]/page.tsx + opengraph-image.tsx: generateStaticParams now async + filtered - compare-slug.ts: kimi-k26 / glm-5-1 / minimax-m27 dbKeys now include both point releases so the canonical slug pulls existing data while staying forward-compatible with the newer DB key when it arrives Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(compare): show both point-release versions in shared-arch slug labels When a canonical compare slug groups two model point releases sharing one architecture (kimi-k26 -> [k2.5, k2.6], glm-5-1 -> [5, 5.1], minimax-m27 -> [m2.5, m2.7]), the header, OG image, metadata title, and index card section now read "Kimi K2.5/K2.6" / "GLM 5/5.1" / "MiniMax M2.5/M2.7" instead of just the newer-version name. Makes it obvious the page covers both versions' benchmark data, not only the newer one. The minimax-m25 -> minimax-m27 alias redirect already worked via the existing COMPARE_MODEL_ALIASES map; verified live. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(compare): switch slug redirects from 307 to 308 (permanent) Bare-slug -> deepseek-r1, alias model -> canonical, older version -> newer version, and non-canonical GPU order -> alphabetical are all permanent decisions for this URL space. Using next/navigation's permanentRedirect() returns 308 instead of 307, letting search engines consolidate link equity onto the canonical URL instead of keeping the alias indexed separately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #267
Supersedes #332