mlx-model-explorer / static /index.html
codelion's picture
Deploy MLX Model Explorer (private test)
13b1a91 verified
Raw
History Blame
16.6 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>MLX Model Explorer</title>
<meta name="description" content="Find an MLX model that fits your Mac. Compare mlx-community models by memory, quantization, popularity and community experience.">
<meta name="color-scheme" content="light dark">
<link rel="stylesheet" href="/static/styles.css">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%2317212B'/%3E%3Crect x='6' y='13' width='11' height='6' rx='1.5' fill='%234F86C6'/%3E%3Crect x='17' y='13' width='5' height='6' rx='1.5' fill='%239C7FD6'/%3E%3Crect x='24.5' y='9' width='1.5' height='14' rx='.75' fill='%23fff'/%3E%3C/svg%3E">
</head>
<body>
<a class="skip" href="#results">Skip to results</a>
<header class="top">
<div class="shell top-row">
<a class="brand" href="/" aria-label="MLX Model Explorer home">
<svg class="brand-mark" viewBox="0 0 32 32" aria-hidden="true"><rect x="3" y="12" width="14" height="8" rx="2" class="fill-w"/><rect x="17" y="12" width="6" height="8" rx="2" class="fill-kv"/><rect x="26" y="7" width="2" height="18" rx="1" class="fill-limit"/></svg>
<span>MLX Model Explorer</span>
</a>
<nav aria-label="Sections">
<a href="#benchmark">Benchmark</a>
<a href="#methodology">How it works</a>
<a href="#privacy">Privacy</a>
<a href="/stats">Community stats</a>
</nav>
</div>
</header>
<main>
<section class="hero shell" aria-labelledby="hero-title">
<div class="hero-copy">
<h1 id="hero-title">Find an MLX model that fits your Mac.</h1>
<p class="lede">Every model in <a href="https://huggingface.co/mlx-community" target="_blank" rel="noopener">mlx-community</a>, sized against the memory your GPU can actually use: weights, KV cache for your context, and runtime overhead.</p>
</div>
<figure class="budget" id="budget" aria-live="polite">
<figcaption class="budget-head">
<span class="budget-mac" id="budget-mac">Pick your Mac's memory to see what fits</span>
<span class="budget-usable" id="budget-usable"></span>
</figcaption>
<div class="budget-track" id="budget-track" role="img" aria-label="Memory budget">
<span class="seg seg-w" id="seg-w"></span><span class="seg seg-kv" id="seg-kv"></span><span class="seg seg-oh" id="seg-oh"></span>
<span class="limit" id="budget-limit" hidden></span>
</div>
<div class="budget-foot">
<p class="budget-model" id="budget-model">Loading models</p>
<ul class="legend" aria-label="Legend">
<li><i class="sw seg-w"></i>Weights</li>
<li><i class="sw seg-kv"></i>KV cache</li>
<li><i class="sw seg-oh"></i>Overhead</li>
<li><i class="sw sw-limit"></i>GPU limit</li>
</ul>
</div>
</figure>
</section>
<div class="shell workspace">
<aside class="rail" aria-label="Filters">
<form id="query" autocomplete="off">
<fieldset class="group">
<legend>Your Mac's memory</legend>
<div class="chips" id="ram-chips" role="radiogroup" aria-label="Mac memory"></div>
<div class="detect-row">
<button type="button" id="detect" class="ghost">Detect my machine</button>
<span class="hint" id="ram-hint">Or pick it above.</span>
</div>
<div id="hw-out" class="hw" hidden>
<p class="hw-estimate" id="hw-estimate"></p>
<dl class="hw-facts" id="hw-facts"></dl>
<p class="fine">A browser estimate, not an MLX benchmark. Browsers can't read unified memory size.</p>
<button type="button" id="full-bench" class="ghost small" disabled>Run 20-second GPU test</button>
<progress id="bench-progress" max="100" value="0" hidden></progress>
<p id="bench-out" class="fine" aria-live="polite"></p>
</div>
<p id="hw-error" class="note" hidden></p>
</fieldset>
<fieldset class="group">
<legend>Context length</legend>
<div class="chips tight" id="context-chips" role="radiogroup" aria-label="Context length"></div>
</fieldset>
<details class="more-filters" id="more-filters" open>
<summary>Family, size, quantization and priority</summary>
<fieldset class="group">
<legend>Model family</legend>
<div class="chips" id="family-chips" role="radiogroup" aria-label="Model family"></div>
<label class="more-family">
<span class="sr-only">More families</span>
<select id="family-more"><option value="">More families</option></select>
</label>
</fieldset>
<fieldset class="group">
<legend>Size</legend>
<div class="chips tight" id="size-chips" role="radiogroup" aria-label="Size"></div>
</fieldset>
<fieldset class="group">
<legend>Quantization</legend>
<div class="chips tight" id="quant-chips" role="radiogroup" aria-label="Quantization"></div>
</fieldset>
<fieldset class="group">
<legend>What matters most</legend>
<div class="chips" id="priority-chips" role="radiogroup" aria-label="Priority"></div>
</fieldset>
<fieldset class="group">
<label class="field">Name contains
<input type="search" id="search" maxlength="80" placeholder="coder, instruct, vl">
</label>
<label class="check"><input type="checkbox" id="non-llm"> Include speech, image and embedding models</label>
</fieldset>
</details>
</form>
</aside>
<section class="results" id="results" aria-labelledby="res-title">
<div class="results-head">
<div>
<h2 id="res-title">Models</h2>
<p id="summary" class="summary"></p>
</div>
<div class="tabs" role="tablist" aria-label="Sort" id="sort">
<button role="tab" data-sort="recommended" aria-selected="true">Best fit</button>
<button role="tab" data-sort="popular" aria-selected="false">Popular</button>
<button role="tab" data-sort="recent" aria-selected="false">Recent</button>
<button role="tab" data-sort="community" aria-selected="false">Community tested</button>
<button role="tab" data-sort="all" aria-selected="false">A–Z</button>
</div>
</div>
<div id="notices"></div>
<ol id="list" class="rows"></ol>
<button type="button" id="more" class="ghost wide" hidden>Show more models</button>
</section>
</div>
<div class="shell prose-grid">
<section id="benchmark" class="prose" aria-labelledby="bench-h">
<h2 id="bench-h">Measure a model on your Mac</h2>
<p>The GPU test above runs in your browser. This one runs MLX. The script loads a model with <code>mlx-lm</code>, measures prompt speed, generation speed, time to first token and peak memory, and prints the result. It sends nothing unless you add <code>--submit</code>, and it shows you the exact payload first.</p>
<label class="field">Model
<input id="bench-model" type="text" maxlength="200" value="mlx-community/Qwen3-0.6B-4bit" spellcheck="false">
</label>
<pre class="cmd"><code id="bench-cmd"></code></pre>
<div class="actions-row">
<button type="button" id="copy-cmd" class="ghost">Copy command</button>
<a href="/bench/mlx_explorer_bench.py" download>Download mlx_explorer_bench.py</a>
</div>
<details>
<summary>Paste a result you already ran</summary>
<textarea id="bench-json" rows="6" maxlength="4000" spellcheck="false" placeholder='{"event_type": "mlx_benchmark_submission", ...}'></textarea>
<button type="button" id="bench-submit" class="solid">Submit result</button>
<p id="bench-submit-out" class="fine" aria-live="polite"></p>
</details>
</section>
<section id="methodology" class="prose" aria-labelledby="meth-h">
<h2 id="meth-h">How it works</h2>
<details><summary>What does 4-bit mean?</summary>
<p>Quantization stores each weight with fewer bits. A 16-bit model uses about 2 bytes per parameter. A 4-bit model uses about half a byte, plus a scale and offset per group of 64 weights (roughly 4.5 bits in total). Fewer bits mean a smaller download and less memory, usually with some loss in quality that varies by model and method. <em>Mixed</em> models keep sensitive layers at higher precision and are labelled by their base width, e.g. "4-bit mixed".</p>
</details>
<details><summary>Why memory decides what runs</summary>
<p>On Apple Silicon the whole model must fit in the unified memory the GPU may use. By default macOS allows roughly two-thirds of RAM on Macs with 36 GB or less and about three-quarters on larger ones (adjustable with <code>sudo sysctl iogpu.wired_limit_mb=…</code>). A model that doesn't fit fails to load or crawls while swapping.</p>
</details>
<details><summary>Why context length matters</summary>
<p>Every token in context stores a key and a value for each attention layer: the KV cache, <code>2 × layers × kv_heads × head_dim × tokens × 2 bytes</code>. For an 8B model at 32k tokens that's about 4.5 GB, as much as its 4-bit weights. Sliding-window and linear-attention layers need far less. Weight quantization doesn't shrink the KV cache, and a model's maximum context comes from its architecture and training, not its quantization.</p>
</details>
<details><summary>What the browser GPU test measures</summary>
<p>A short WebGPU compute workload (matrix multiplications and a large buffer copy) that gives a relative score for grouping hardware. It is not MLX, not LLM inference and not tokens per second, and it varies with browser, power mode and background load.</p>
</details>
<details><summary>Where community numbers come from</summary>
<p>From people running the benchmark script on their own Macs, plus optional "how did it work" reports. Submissions are validated. Implausible values, such as generation faster than a Mac's memory bandwidth allows, are flagged and excluded from rankings.</p>
</details>
<details><summary>How "Best fit" is scored</summary>
<p>Each matching model gets a 0 to 100 score from these components, weighted by what matters most to you:</p>
<ul>
<li><strong>Fit:</strong> estimated weights (exact file sizes when available) + KV cache at your context + about 1 GB overhead, against GPU-usable memory. Comfortable under 70%, Likely under 85%, Borderline under 100%, Unlikely above.</li>
<li><strong>Quantization:</strong> quality prefers more bits, minimum memory prefers fewer, balanced prefers 4 to 6.</li>
<li><strong>Context:</strong> headroom left at your context, and whether the model's config supports that length.</li>
<li><strong>Capacity:</strong> among models that fit, more parameters usually means a more capable model. Ignored when you prioritize speed or least memory.</li>
<li><strong>Popularity</strong> (downloads and likes, log scale), <strong>recency</strong>, and <strong>community data</strong> once people contribute.</li>
</ul>
<p>The score never considers who uploaded a model or what it's called. Speed is never predicted without real measurements. Scoring version <code id="engine-version">heuristic-v1</code>. For knowledge-quality evaluations of models on MLX, see the <a href="https://huggingface.co/spaces/mlx-community/mlx-benchmark-leaderboard" target="_blank" rel="noopener">MLX Benchmark Leaderboard</a>.</p>
</details>
</section>
<section id="privacy" class="prose" aria-labelledby="priv-h">
<h2 id="priv-h">Privacy and data</h2>
<p>We collect anonymous model-selection and optional benchmark data to improve MLX Model Explorer and community recommendations. It's published as the <a id="dataset-link" href="https://huggingface.co/datasets/mlx-community/mlx-model-explorer-data" target="_blank" rel="noopener">mlx-model-explorer-data</a> dataset.</p>
<ul>
<li><strong>Collected:</strong> the filters you choose, models you open or compare, coarse hardware class (GPU vendor and architecture, core count, browser and OS family), test scores, and feedback you send.</li>
<li><strong>Never collected:</strong> name, email, IP address, location, cookies, user-agent strings or device fingerprints. Links, emails and phone numbers are stripped from notes.</li>
<li><strong>Session ID:</strong> random, lives only in this tab, and is gone when you close it.</li>
<li>The <a href="/stats">stats page</a> only shows groups of five or more.</li>
</ul>
<label class="check"><input type="checkbox" id="optout"> Don't send any data from this browser</label>
<p id="gpc-note" class="fine" hidden>Your browser sends a Global Privacy Control or Do Not Track signal, so nothing is sent unless you untick the box above.</p>
</section>
</div>
</main>
<footer class="shell foot">
<span>A community tool for <a href="https://github.com/ml-explore/mlx" target="_blank" rel="noopener">MLX</a> on Apple Silicon.</span>
<span id="cat-status"></span>
<span>Version <span id="app-version"></span></span>
</footer>
<div id="compare-tray" class="tray" hidden>
<span id="compare-count"></span>
<button type="button" id="compare-open" class="solid">Compare</button>
<button type="button" id="compare-clear" class="ghost">Clear</button>
</div>
<dialog id="detail" class="sheet" aria-labelledby="d-title">
<div class="sheet-head">
<h2 id="d-title"></h2>
<button type="button" class="close" data-close aria-label="Close">×</button>
</div>
<div id="d-body" class="sheet-body"></div>
</dialog>
<dialog id="compare" class="modal" aria-labelledby="c-title">
<div class="sheet-head">
<h2 id="c-title">Compare models</h2>
<button type="button" class="close" data-close aria-label="Close">×</button>
</div>
<div id="c-body" class="sheet-body"></div>
</dialog>
<template id="feedback-tpl">
<form class="feedback">
<h3>Have you tried this model?</h3>
<div class="chips">
<label class="chip"><input type="radio" name="tried" value="yes"><span>Yes</span></label>
<label class="chip"><input type="radio" name="tried" value="no"><span>No</span></label>
<label class="chip"><input type="radio" name="tried" value="planning"><span>Planning to</span></label>
</div>
<div class="fb-yes" hidden>
<h4>How did it work?</h4>
<div class="chips">
<label class="chip"><input type="radio" name="outcome" value="q:excellent"><span>Excellent</span></label>
<label class="chip"><input type="radio" name="outcome" value="q:good"><span>Good</span></label>
<label class="chip"><input type="radio" name="outcome" value="q:acceptable"><span>Acceptable</span></label>
<label class="chip"><input type="radio" name="outcome" value="f:too_slow"><span>Too slow</span></label>
<label class="chip"><input type="radio" name="outcome" value="f:too_much_memory"><span>Too much memory</span></label>
<label class="chip"><input type="radio" name="outcome" value="f:low_quality"><span>Quality wasn't good enough</span></label>
<label class="chip"><input type="radio" name="outcome" value="f:didnt_run"><span>Didn't run</span></label>
</div>
<div class="fb-grid">
<label class="field">Mac memory<select name="ram"><option value="">Optional</option></select></label>
<label class="field">Chip<select name="chip"><option value="">Optional</option></select></label>
<label class="field">Tokens per second<input name="tps" type="number" min="0.1" max="2000" step="0.1" inputmode="decimal" placeholder="Optional"></label>
<label class="field">Context used<select name="ctx"><option value="">Optional</option></select></label>
</div>
<label class="field">Notes, up to 280 characters, no personal info
<textarea name="notes" rows="2" maxlength="280"></textarea>
</label>
</div>
<div class="actions-row">
<button type="submit" class="solid">Send report</button>
<span class="fb-out fine" aria-live="polite"></span>
</div>
</form>
</template>
<script src="/static/webgpu.js"></script>
<script src="/static/app.js"></script>
</body>
</html>