This Vite + TypeScript app recreates the InferenceX Token Throughput per GPU vs. Interactivity chart with editable custom data. It focuses on matching the
reference chart behavior while letting users paste table data, import benchmark
artifacts, and tune line/point styling.
npm install
npm run devOpen the printed localhost URL. For a production build:
npm run build
npm run previewEach curve is edited as a Line Project. Line-level fields are shared by all points in that curve:
Line ID: unique curve id.Name: legend label.Model: model filter value, for exampleDeepSeek-R1-0528.ISL/OSL: sequence length filter value, for exampleISL 8192 / OSL 1024.Precision: precision filter value, for examplefp4orfp8.MTP:MTPorNon-MTP; also drives filtering and vendor color grouping.Title: longer tooltip/title metadata.Marker: default point marker for the line.Precisionfollows the precision-based default shape.Line Type: solid, dashed, dotted, dash-dot, long dash, or custom dasharray.Color: automatic vendor color, color picker, or a vibrant standard-color preset swatch.
Point rows are edited in each line's table and support Excel/Google Sheets paste. Required point columns:
Interactivity: X axis, tokens per second per user.Throughput/GPU: Y axis, tokens per second per GPU.
Optional point columns:
Marker: per-point marker override.Defaultinherits the line marker.Prefill GPUs,Decode GPUs: used for split GPU labels.Prefill TP,Prefill EP,Prefill DPADecode TP,Decode EP,Decode DPAConcurrency: shown in tooltip and used for point identity.Note: tooltip/source metadata.
Example TSV:
Marker Interactivity Throughput/GPU Prefill GPUs Decode GPUs Prefill TP Prefill EP Prefill DPA Decode TP Decode EP Decode DPA Concurrency Note
Default 11.75 7397.06 4 8 4 4 true 8 8 true 4096 date 2026-05-07
Star 15.51 4893.40 4 8 4 4 true 8 8 true 2048 highlighted pointLine and point edits are auto-rendered after a short debounce, so the chart
updates without pressing Render Chart. The button remains available for an
immediate redraw.
The top controls filter by Model, ISL/OSL, Precision, and MTP. Defaults
select the first available value rather than showing all values.
The legend panel includes:
- line visibility search and toggles
- per-filter active-line memory for each
Model/ISL/OSL/Precision/MTPview - hover-only
Onlyactions for quickly isolating one line - hover-only locate actions for jumping from a legend line to its Line Project
Show all linesbelow the line list to reactivate every line in the current filtered viewLog ScaleOptimal OnlyHide LabelsHigh ContrastParallelism LabelsGradient LabelsLine LabelsBetter Direction, which follows the active X-axis metric and points toward the preferred throughput/metric corner
By default, Optimal Only is enabled and Gradient Labels / Line Labels are
disabled.
Newly added, copied, or imported lines are activated automatically in the current view.
The data panel can import benchmark output from a GitHub Actions run URL. Paste a run URL such as:
https://github.com/owner/repo/actions/runs/123456789
Downloading run artifacts always requires a GitHub token, even for public repos. Pick the token type by who owns the repo:
- Repo you own, or an org you can configure: a fine-grained PAT with only the
Actions: Read-onlypermission, granted to that repository. - Private repo owned by another account (you are a collaborator/admin): a classic
PAT with the
reposcope. Fine-grained tokens are scoped to a single resource owner and cannot reach it.
Tick Remember token in this browser to save the token to localStorage under
the inferencex-curve:github-token:v1 key (this browser only, stored in plain
text, and never included in exported data). A progress bar shows artifact
download status while importing.
Imported artifacts are staged in a review panel before they are added. You can
edit line fields, change MTP or Marker, select/deselect lines, discard the
preview, or append selected lines to the current data.
The importer normalizes common InferenceX artifact fields:
- model prefixes and paths such as
dsr1ordeepseek-ai/DeepSeek-R1-0528map toDeepSeek-R1-0528 spec_method/spec_decodingmap toMTPorNon-MTPhwvalues such asmi355x-amdsnormalize to the chart hardware key
The InferenceX Sync panel can keep chart data aligned with the public
InferenceX API without editing src/exampleData.ts.
On first open, if no browser data exists, the app tries to load the default
InferenceX sync configuration from the API. If the request fails or no matching
rows are returned, it falls back to the bundled exampleSeries. On later opens,
the app checks for updates once and stages the result, but it does not overwrite
the current chart until you click Update.
For each enabled sync config, the API may return historical rows across many
dates. Sync mirrors the upstream chart behavior by keeping only the newest
source rows. Curves group by model / sequence or scenario / precision /
hardware / framework / MTP. disagg is point-level metadata, so aggregated and
disaggregated rows for the same config are combined into one curve after each
disagg branch is reduced to its newest available date.
The panel actions are:
Check Updates: fetch enabled sync configs and stage any new or changed lines.Update: apply staged API data to the chart. User-created, CSV-imported, and GitHub-imported lines are kept unless they share the stable InferenceX sync line id.Manage Configs: enable, disable, remove, reset, or add sync configs.
Config management uses live availability data from the API. The Add Config
form defaults ISL/OSL, Precision, Framework, and MTP to All; clicking
Add Config expands those selections into only the real combinations returned
by availability, then automatically runs Check Updates. The user still needs
to click Update before the new data is applied to the chart.
Disagg is not a config selector. Availability rows that differ only by
disagg=true or disagg=false create one sync config and one stable line id;
the original value remains available on every imported point.
Sync configs, fingerprints, timestamps, and staged status metadata are saved in
the normal browser data payload under localStorage key
inferencex-curve:user-data:v1. The GitHub token remains separate under
inferencex-curve:github-token:v1.
The InferenceX API serves the official site from the same origin
(inferencex.semianalysis.com), so it never needs CORS headers and does not send
an Access-Control-Allow-Origin header. This app is different:
- Local
npm run devworks because the Vite dev server proxies/inferencex-apito the API (seevite.config.ts), so the browser only makes same-origin requests. - The deployed GitHub Pages site (
duyi-wang.github.io) is a static site on a different origin. Its browser requests to the API are cross-origin, and because the API sends noAccess-Control-Allow-Originheader, the browser blocks the response. This is a browser security mechanism: the missing header is a response header controlled by the API server, so the frontend cannot add or fake it, and theOriginrequest header cannot be overridden from JavaScript.
When this happens, the Sync panel reports an explicit CORS error (rather than a generic "Failed to fetch") with these workarounds:
- Temporary, no infrastructure: install and enable a CORS-unblocking browser extension (e.g. "Allow CORS" / "CORS Unblock"), then retry. This relaxes the check in your own browser only; it does not change anything for other visitors.
- Permanent: route requests through a proxy you control. Server-to-server requests are not subject to CORS, so a proxy (e.g. a free Cloudflare Worker that forwards to the API and adds CORS headers) makes Sync work for everyone. A build /CI snapshot approach (fetch the API in GitHub Actions and ship the JSON same-origin with the site) is an alternative when live, on-click freshness is not required.
Import File (next to Import Action Data) loads a local .csv, .tsv,
.json, .jsonl, .ndjson, or .zip file through the same review panel. Zip
files are unpacked in the browser, so a downloaded GitHub Actions artifact zip
can be imported directly. This round-trips a file produced by Download CSV:
line fields, point Interactivity / Throughput/GPU, markers, custom colors
(from the Color Mode / Resolved Color columns), concurrency, parallelism,
and notes are restored. Derived columns (Total GPUs, Included in Chart,
Active Line, Point Index, Roofline Point) are ignored on import. The same
parser also accepts raw benchmark JSON/CSV exports.
For external integrations or agent-generated files, use
docs/import-csv.md as the CSV/TSV import contract. It
lists the recommended headers, required fields, optional empty fields, aliases,
and raw benchmark fallback format.
The independent Plot Tool workspace imports a smaller generic Pareto CSV
format with required Line ID, Line Name, X, and Y columns plus optional
color, line type, marker, and layer metadata. Its import preview requires an
explicit Replace choice for any Line ID already in the workspace.
See docs/import-plot-tool-csv.md for the full
column contract, defaults, quoting rules, validation errors, conflict workflow,
examples, and CSV round-trip behavior. This format is not interchangeable with
the InferenceX benchmark CSV/TSV contract above.
Reusable chart logic lives in src/inferenceCurveChart.ts.
- Points are filtered to finite
interactivityandthroughputvalues. - The upper-left Pareto roofline keeps optimal points only.
- Rooflines use
d3.curveMonotoneX. - Line colors are automatically grouped by vendor: NVIDIA green family, AMD red family, with MTP variants treated separately.
- Point labels use split prefill/decode GPU counts when available.
- Marker rendering supports circle, square, triangle, diamond, star, plus, and cross.
- Zoom, pan, reset zoom, PNG export, and CSV export are available.
The InferenceX Bus/Race Car and Donkey/Elytra overlays are intentionally not included.
src/main.ts: UI, data editor, CSV handling, GitHub Actions import, and InferenceX sync state wiring.src/inferenceXSync.ts: public InferenceX API client, availability parsing, benchmark filtering, fingerprints, and sync line generation.src/inferenceCurveChart.ts: D3 chart rendering and curve logic.src/exampleData.ts: offline fallback DeepSeek R1 0528 example series.src/styles.css: application and chart styling.vite.config.ts: Vite base path and dev proxy for/inferencex-api.docs/import-csv.md: CSV/TSV import contract for external integrations.docs/import-plot-tool-csv.md: generic Plot Tool CSV import/export contract.AGENTS.md: contributor guidance for coding agents.