/* Quant-picking frontend. Catalog + fit data come live from the * LocalLLaMA explorer API; the best-quant choice per model comes from * rankQuants.js + quant_scores.json (measured KL benchmarks). */ "use strict"; const API = "https://codelion-local-model-explorer.hf.space"; const $ = (s, r = document) => r.querySelector(s); const $$ = (s, r = document) => [...r.querySelectorAll(s)]; let META = null, SCORES = null, runId = 0, offset = 0, total = 0, nofitDropped = 0, autoPages = 0, seenModels = []; function el(tag, cls, text) { const n = document.createElement(tag); if (cls) n.className = cls; if (text !== undefined) n.textContent = text; return n; } function opt(value, label, selected) { const o = document.createElement("option"); o.value = value; o.textContent = label; if (selected) o.selected = true; return o; } const gb = (v, d = 1) => v === null || v === undefined ? "?" : `${Number(v).toFixed(d)} GB`; const bytesGB = (b) => gb(b / 1e9); const params = (p) => p >= 1e9 ? `${+(p / 1e9).toFixed(p >= 1e10 ? 0 : 1)}B` : `${Math.round(p / 1e6)}M`; const compact = (n) => n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${Math.round(n / 1e3)}k` : String(n || 0); const ctxLabel = (c) => c >= 1024 ? `${Math.round(c / 1024)}k` : String(c); function rig() { const kind = $('input[name="kind"]:checked').value; const out = { kind, gpus: [], ram_gb: 32, vram_spare: +($("#vram-spare") || {}).value || 0, ram_spare: +($("#ram-spare") || {}).value || 0 }; if (kind === "gpu") { const one = (sel, vsel, csel, fb) => { const name = $(sel).value; const each = name === "custom" ? Math.max(1, Math.min(256, +$(vsel).value || fb)) : META.hardware.gpus[name]; return Array.from({ length: +$(csel).value || 1 }, () => each); }; out.gpus = one("#gpu", "#custom-vram", "#gpu-count", 24); if (!$("#gpu2-wrap").hidden) out.gpus = out.gpus.concat(one("#gpu2", "#custom-vram2", "#gpu2-count", 8)).slice(0, 16); out.ram_gb = +$("#ram").value; } else if (kind === "unified") { out.unified_system = $("#usys").value; out.ram_gb = +$("#umem").value; } else { out.ram_gb = +$("#ram").value; } return out; } function query(append) { const r = rig(); const pair = $("#kv").value; // upstream kv_type only accepts f16/q8_0/q4_0 with K=V. ask q8_0 and // rescale client-side (rescaleKvFits): q8_0-based scores and fits are // close to every smaller pair, so the page stays nearly consistent // (an f16 base would leave every score stale). f16/bf16 ask f16. const q8base = pair !== "f16/f16" && pair !== "bf16/bf16"; const rescaled = q8base ? kvScale(pair) * 16 / 8.5 < 1 : false; return { hardware: { kind: r.kind, gpus: r.gpus, ram_gb: r.ram_gb, ...(r.unified_system ? { unified_system: r.unified_system } : {}) }, context: +$("#ctx").value, kv_type: q8base ? "q8_0" : "f16", kv_pair: pair, min_bits: +$("#min-bits").value, sort: $("#sort").value, family: $("#family").value || null, size: $("#size").value || null, search: $("#search").value.trim() || null, moe_only: $("#moe-only").checked, vision_only: $("#vision-only").checked, fits_only: rescaled ? false : ($("#fits-only").checked || $("#sort").value === "best"), vram_only: rescaled ? false : (r.kind === "gpu" && $("#vram-only").checked), mmproj: $("#mmproj").value, offset: append ? offset : 0, limit: 24, }; } function rankWithReserve(allOptions, fam, r) { // rank headroom-kept options; when the reserve hides every fitting // quant, fall back to ranking everything so the card can name what // missed and by how much instead of showing nothing-fits. const fitOk = (o) => ({ ...o, fit_ok: o.fit && o.fit.tier !== "no" && o.fit.tier !== "no_vram" }); const { kept, hidden } = applyHeadroom(allOptions, headroomCaps(r), r.kind); let { pick, warnings } = rankOptions(kept.map(fitOk), fam, SCORES); let overReserve = false; if (!pick && hidden) { ({ pick, warnings } = rankOptions((allOptions || []).map(fitOk), fam, SCORES)); overReserve = !!pick; } return { pick, warnings, hidden, overReserve }; } function reserveNote(pick, r) { if (!pick || !pick.fit) return null; const caps = headroomCaps(r); const over = []; if (r.kind !== "cpu" && (pick.fit.gpu_gb || 0) > caps.vram) over.push(`${gb((pick.fit.gpu_gb || 0) - caps.vram)} VRAM`); if ((pick.fit.ram_gb || 0) > caps.ram) over.push(`${gb((pick.fit.ram_gb || 0) - caps.ram)} RAM`); if (!over.length) return null; return `Over your headroom reserve by ${over.join(" + ")} — lower "Keep free" to run it.`; } const SCORE_PARTS = [["fit", "Fit"], ["capacity", "Size"], ["popularity", "Downloads"], ["recency", "New"], ["community", "Reports"]]; function scoreTitle(m) { const w = META.score_weights || {}; return SCORE_PARTS.map(([k, l]) => `${l}: ${Math.round((m.components[k] || 0) * w[k] * 100)} of ${Math.round(w[k] * 100)}`).join("\n"); } function rail(fit, r) { if (!fit) return null; const box = el("div", "rail"); const pct = (v, cap) => `${Math.max(0, Math.min(100, (v / cap) * 100))}%`; const vram = r.kind === "gpu" ? r.gpus.reduce((a, v) => a + v, 0) : 0; const ram = r.ram_gb; if (r.kind === "unified") { const share = (META.hardware.unified_shares || {})[r.unified_system]; const cap = r.ram_gb * (share || (r.ram_gb <= 36 ? 0.67 : 0.75)); const pool = el("div", "pool"); pool.style.flex = "1"; const i = el("i", "gpu"); i.style.width = pct(fit.gpu_gb, cap); pool.append(i); if (fit.gpu_gb > cap) { const o = el("i", "over"); o.style.width = "30%"; pool.append(o); } box.append(pool); return box; } if (vram) { const pool = el("div", "pool"); pool.style.flex = `${vram / (vram + ram)}`; const i = el("i", "gpu"); i.style.width = pct(fit.gpu_gb, vram); pool.append(i); box.append(pool); } const ramPool = el("div", "pool"); ramPool.style.flex = `${ram / ((vram || 1) + ram)}`; const j = el("i", fit.tier === "gpu_moe" ? "exp" : "ram"); j.style.width = pct(fit.ram_gb, ram); ramPool.append(j); if (fit.tier === "no" || fit.tier === "no_vram") { const o = el("i", "over"); o.style.width = "30%"; ramPool.append(o); } box.append(ramPool); return box; } function fitText(fit) { if (!fit) return ""; const parts = [fit.label]; if (fit.tier !== "no" && fit.tier !== "no_vram") parts.push(`${gb(fit.gpu_gb)} GPU, ${gb(fit.ram_gb)} RAM`); return parts.join(" · "); } function card(m) { const c = el("div", "card"); const h = el("h3"); const btn = el("button", null, m.name); h.append(btn); c.append(h); const tags = [ m.params ? params(m.params) + (m.active_params ? ` (${params(m.active_params)} active)` : "") : null, m.moe ? "MoE" : null, m.vision ? "vision" : null, m.family, `${m.repo_count} GGUF repos`, `${compact(m.downloads)} downloads`, ].filter(Boolean).join(" · "); c.append(el("div", "meta", tags)); const side = el("div", "r-side"); const sc = el("span", "score", String(Math.round(m.score))); sc.title = scoreTitle(m) + "\nHardware ranking, not model quality."; side.append(sc, el("span", "muted", "score")); c.append(side); const status = el("p", "muted", "Ranking quants…"); c.append(status); btn.addEventListener("click", () => openDetail(m, query())); return { c, status }; } // the backend bakes the QUERIED kv type into run commands; rewrite the // flags to the picked K/V pair (asymmetric included). f16 needs no flags. function kvCmd(cmd, pair) { let [k, v] = String(pair || "f16/f16").split("/"); if (KV_BITS[k] === undefined) k = "f16"; if (KV_BITS[v] === undefined) v = "f16"; cmd = cmd.replace(/\s*(--cache-type-k|-ctk)([=\s]+)\S+/g, k === "f16" ? "" : ` -ctk ${k}`) .replace(/\s*(--cache-type-v|-ctv)([=\s]+)\S+/g, v === "f16" ? "" : ` -ctv ${v}`); if (k !== "f16" && !/(--cache-type-k|-ctk)([=\s]|$)/.test(cmd)) cmd += ` -ctk ${k}`; if (v !== "f16" && !/(--cache-type-v|-ctv)([=\s]|$)/.test(cmd)) cmd += ` -ctv ${v}`; return cmd; } function renderDetail(m, body, kvPair) { const d = m._detail, pick = m._pick; const g = d.geometry; const facts = [ d.params ? `${params(d.params)} parameters${d.active_params ? `, ${params(d.active_params)} active` : ""}` : null, g ? `${g.n_layers} layers` : null, g && g.moe ? `${g.expert_count} experts, ${g.expert_used} per token` : null, d.context_length ? `${ctxLabel(d.context_length)} native context` : null, g && g.notes && g.notes.length ? g.notes.join(", ") : null, ].filter(Boolean).join(" • "); if (facts) body.append(el("p", "muted", facts)); const opts = d.options || []; const sel = opts.find((o) => pick && o.repo === pick.repo && o.quant === pick.quant) || opts[0]; if (sel && sel.commands) { const row = el("div", "row"); const copy = el("button", "btn ghost", "Copy command"); // upstream still emits the old `llama-server` binary name; current llama.cpp renamed it. const pre = el("pre", "cmd", kvCmd((sel.commands["llama.cpp"] || "").replace(/llama-server/g, "llama serve"), kvPair)); copy.addEventListener("click", async () => { try { await navigator.clipboard.writeText(pre.textContent); copy.textContent = "Copied"; } catch { copy.textContent = "Select and copy"; } setTimeout(() => (copy.textContent = "Copy command"), 1500); }); row.append(el("span", "muted", `Run it (${sel.quant} from ${sel.repo.split("/")[0]}):`), copy); body.append(row, pre); if (sel.fit) body.append(el("div", "muted", fitText(sel.fit))); if (m._reserveNote) body.append(el("div", "warn", m._reserveNote)); } body.append(el("h3", null, `Every quant (${opts.length})`)); const hr = headroomNote(m); if (hr) body.append(el("p", "muted", hr)); if (d.hidden_below_min_bits) { body.append(el("p", "muted", `${d.hidden_below_min_bits} quant(s) hidden by the bit floor. Lower "Lowest quant to consider" to see them.`)); } const t = el("table", "quants"); const head = el("tr"); for (const [h, num] of [["Uploader", 0], ["Quant", 0], ["Size", 1], ["On your hardware", 0]]) { head.append(el("th", num ? "num" : null, h)); } const tb = el("tbody"); for (const o of [...opts].sort((a, b) => a.size - b.size)) { const tr = el("tr"); if (pick && o.quant === pick.quant && o.repo === pick.repo) tr.className = "is-pick"; const qtd = el("td"); qtd.append(el("b", null, o.quant)); if (pick && o.quant === pick.quant && o.repo === pick.repo) qtd.append(" ◀ pick"); const link = el("a", null, o.repo.split("/")[0]); link.href = o.url; link.target = "_blank"; link.rel = "noopener"; const utd = el("td"); utd.append(link); tr.append(utd, qtd, el("td", "num", bytesGB(o.size)), el("td", null, o.fit ? o.fit.label : "?")); tb.append(tr); } t.append(head, tb); body.append(t); if (d.kv_cache_gb) { body.append(el("h3", null, "KV cache")); const strip = el("div", "kv-strip"); for (const [ctx, v] of Object.entries(d.kv_cache_gb)) { const s = el("span", null, `${ctxLabel(+ctx)} `); s.append(el("b", null, gb(v, v < 10 ? 2 : 1))); strip.append(s); } body.append(strip); } const fm = d.other_formats || {}; const names = { mlx: "MLX", onnx: "ONNX", awq: "AWQ", gptq: "GPTQ", fp8: "FP8", exl3: "EXL3", exl2: "EXL2" }; const any = Object.keys(names).filter((k) => fm[k] && fm[k].length); if (any.length) { body.append(el("h3", null, "Other formats")); for (const k of any) { const p = el("p", "muted", `${names[k]} (${fm[k].length}): `); for (const id of fm[k].slice(0, 4)) { const a = el("a", null, id.split("/")[1] || id); a.href = `https://huggingface.co/${id}`; a.target = "_blank"; a.rel = "noopener"; p.append(a, " "); } body.append(p); } } const cm = d.community; if (cm && cm.bench_rows && cm.bench_rows.length) { body.append(el("h3", null, "Community benchmarks")); const bt = el("table", "quants"); const bh = el("tr"); for (const [h, num] of [["Quant", 0], ["Hardware", 0], ["Backend", 0], ["Prompt t/s", 1], ["Gen t/s", 1]]) { bh.append(el("th", num ? "num" : null, h)); } const bb = el("tbody"); for (const b of cm.bench_rows) { const tr = el("tr"); tr.append(el("td", null, b.quant || "?"), el("td", null, b.gpu_name || b.gpu_model || (b.vram_class ? `${b.vram_class} GB GPU` : "CPU")), el("td", null, b.backend || "?"), el("td", "num", b.prompt_tps ? String(Math.round(b.prompt_tps)) : "—"), el("td", "num", b.generation_tps ? b.generation_tps.toFixed(1) : "—")); bb.append(tr); } bt.append(bh, bb); body.append(bt); } } function headroomCaps(r) { // usable GB after keeping the spare free. the upstream estimator has // no headroom params, so this is a client-side filter on fit_gb. if (r.kind === "unified") { const share = (META.hardware.unified_shares || {})[r.unified_system]; const cap = r.ram_gb * (share || (r.ram_gb <= 36 ? 0.67 : 0.75)); return { vram: cap - r.ram_spare, ram: cap - r.ram_spare }; } const vram = r.kind === "gpu" ? r.gpus.reduce((a, v) => a + v, 0) : 0; return { vram: vram - r.vram_spare, ram: r.ram_gb - r.ram_spare }; } function applyHeadroom(options, caps, kind) { // drop options that fit the estimator but leave less than the spare // free, e.g. a 31.7GB-RAM fit on a 32GB box with a 2GB reserve. // already-failing tiers pass through: the ranker reports those. let hidden = 0; const kept = []; for (const o of options || []) { const fit = o.fit || {}; const okTier = fit.tier && fit.tier !== "no" && fit.tier !== "no_vram"; const over = (kind !== "cpu" && (fit.gpu_gb || 0) > caps.vram) || (fit.ram_gb || 0) > caps.ram; if (okTier && over) { hidden++; continue; } kept.push(o); } return { kept, hidden }; } // Nominal bits per cached element (quants carry block-scale overhead). // Merged bench: quant-bench/kv_scores.json (3 models, KL vs f16 @4k). const KV_BITS = { f16: 16, bf16: 16, q8_0: 8.5, q5_0: 5.5, q5_1: 6, q4_0: 4.5, q4_1: 5, iq4_nl: 4.4 }; const KV_FULL_TIERS = new Set(["gpu", "gpu_moe", "cpu", "unified", "ram"]); function kvScale(pair) { const [k, v] = String(pair || "f16/f16").split("/"); return ((KV_BITS[k] ?? 16) + (KV_BITS[v] ?? 16)) / 2 / 16; } // f16-base rescale: the upstream API only accepts f16/q8_0/q4_0 and one // type for both K and V, so always query f16 and scale the KV part. // KV bytes are exact math (2*layers*kv_heads*head_dim*ctx*bpe), verified // against the estimator's own kv_cache_gb; weights + per-model overhead // pass through untouched. Only full tiers and failing tiers are adjusted; // partial offloads keep the estimator's f16 numbers (conservative). function rescaleKvFits(d, pair, ctx, hw) { // ratio is against the queried base: q8_0 for everything below it, // f16 for f16/bf16 (ratio 1, no-op). see query(). const base = pair === "f16/f16" || pair === "bf16/bf16" ? 16 : 8.5; const ratio = kvScale(pair) * 16 / base; if (!(ratio < 1)) return; const kvf = d.kv_cache_gb && d.kv_cache_gb[String(ctx)]; if (!(kvf > 0)) return; const scaled = {}; for (const [c, g] of Object.entries(d.kv_cache_gb)) scaled[c] = g * ratio; d.kv_cache_gb = scaled; const delta = kvf * (1 - ratio); const vram = hw.kind === "gpu" ? hw.gpus.reduce((a, x) => a + x, 0) : 0; // per-model overhead + RAM constant: median over the estimator's own // full-gpu options (single-option calibration flips picks on 0.2GB // noise; the backend's implied overhead spans ~1.7-2.8 per model). let oh = 1.75, ramConst = 1.2; const gpuRefs = (d.options || []).filter((o) => o.fit && o.fit.tier === "gpu"); if (gpuRefs.length) { const med = (xs) => { const s = xs.filter((x) => x > 0).sort((a, b) => a - b); return s.length ? s[Math.floor(s.length / 2)] : null; }; oh = med(gpuRefs.map((o) => (o.fit.gpu_gb || 0) - o.size / 1e9 - kvf)) ?? oh; ramConst = med(gpuRefs.map((o) => o.fit.ram_gb || 0)) ?? ramConst; } else { const ref = (d.options || []).find((o) => o.fit && (o.fit.tier === "cpu" || o.fit.tier === "ram")); if (ref) oh = Math.max(0, (ref.fit.gpu_gb || ref.fit.ram_gb || 0) - ref.size / 1e9 - kvf); } const full = (o, tier, gpuGb, ramGb, label) => { o.fit.tier = tier; o.fit.gpu_gb = gpuGb; o.fit.ram_gb = ramGb; o.fit.label = label; o.fit.ngl = o.fit.layers; }; const promote = (o) => { // failing AND partial tiers: the estimator graded these under f16, // where nothing big fits whole. rebuild as full when the scaled // footprint fits; otherwise leave the estimator's numbers alone. const sizeGb = o.size / 1e9; const candGpu = sizeGb + kvf * ratio + oh; if (hw.kind === "cpu") { if (candGpu <= hw.ram_gb) full(o, "cpu", 0, candGpu, "Fits in RAM (CPU)"); } else if (hw.kind === "unified") { const share = (META.hardware.unified_shares || {})[hw.unified_system]; const cap = hw.ram_gb * (share || (hw.ram_gb <= 36 ? 0.67 : 0.75)); if (candGpu <= cap) full(o, "unified", candGpu, 0, "Fits in shared memory"); } else if (candGpu <= vram) { full(o, "gpu", candGpu, ramConst, "Fits on GPU"); } // deliberately no ram-tier promotion on gpu rigs: a CPU-resident pick // would outrank GPU picks on quality and recommend slower inference. // the estimator's partial/no tiers stand instead, as before. }; for (const o of d.options || []) { const fit = o.fit; if (!fit) continue; if (!KV_FULL_TIERS.has(fit.tier)) { promote(o); continue; } if (fit.tier === "gpu" || fit.tier === "gpu_moe") fit.gpu_gb -= delta; else if (fit.tier === "cpu" || fit.tier === "ram") fit.ram_gb -= delta; else if (fit.tier === "unified") fit.gpu_gb -= delta; } } function headroomNote(m) { if (!m._hiddenHeadroom) return null; const s = m._spares || {}; const bits = []; if (s.v) bits.push(`${s.v} GB VRAM`); if (s.r) bits.push(`${s.r} GB RAM`); return `${m._hiddenHeadroom} quant(s) hidden by the headroom reserve (${bits.join(" + ")} kept free). Lower it to see them.`; } function ensureDialog() { let dlg = $("#detail"); if (!dlg) { dlg = document.createElement("dialog"); dlg.id = "detail"; const x = el("button", "btn ghost small dlg-x", "Close"); x.addEventListener("click", () => dlg.close()); dlg.append(x, el("h3", "dlg-title"), el("div", "dlg-body")); dlg.addEventListener("click", (e) => { if (e.target === dlg) dlg.close(); }); document.body.append(dlg); } return dlg; } async function openDetail(m, q) { const dlg = ensureDialog(); const body = $(".dlg-body", dlg); $(".dlg-title", dlg).textContent = m.name; if (!m._detail || m._kvPair !== q.kv_pair || m._ctx !== q.context) { body.replaceChildren(el("p", "muted", "Loading quants…")); if (!dlg.open) dlg.showModal(); try { const d = await detailFor(m.key, q); const r = rig(); rescaleKvFits(d, q.kv_pair, q.context, q.hardware); const { pick, hidden, overReserve } = rankWithReserve(d.options, famGuess(m.key), r); m._detail = d; m._pick = pick; m._kvPair = q.kv_pair; m._ctx = q.context; m._hiddenHeadroom = hidden; m._overReserve = overReserve; m._reserveNote = overReserve ? reserveNote(pick, r) : null; m._spares = { v: r.vram_spare, r: r.ram_spare }; } catch (err) { body.replaceChildren(el("p", "muted", `Couldn't load quants (${String(err).slice(0, 100)}).`)); return; } } else if (!dlg.open) { dlg.showModal(); } body.replaceChildren(); renderDetail(m, body, q.kv_pair); } async function detailFor(key, q, signal) { const r = await fetch(`${API}/api/model`, { method: "POST", headers: { "content-type": "application/json" }, signal, body: JSON.stringify({ key, hardware: q.hardware, context: q.context, kv_type: q.kv_type, priority: "balanced", min_bits: q.min_bits, vram_only: q.vram_only, mmproj: q.mmproj }) }); // priority is the upstream estimator's required field; our client-side // pick is single-mode and ignores it. if (!r.ok) throw new Error(`model ${r.status}`); return r.json(); } function famGuess(key) { if (/qwen/i.test(key)) return "Qwen"; if (/gemma/i.test(key)) return "Gemma"; return null; } async function search(append) { const id = ++runId; const q = query(append); if (!append) offset = 0; const box = $("#results"); if (!append) box.replaceChildren(); $("#count").textContent = append ? $("#count").textContent : "Finding models…"; const ctrl = new AbortController(); const alive = () => id === runId; let res; try { const rr = await fetch(`${API}/api/recommend`, { method: "POST", headers: { "content-type": "application/json" }, signal: ctrl.signal, body: JSON.stringify(q) }); if (!rr.ok) throw new Error(`recommend ${rr.status}`); res = await rr.json(); } catch { if (alive()) $("#count").textContent = "Couldn't reach the catalog API. Try again."; return; } if (!alive()) return; total = res.total; offset += res.results.length; $("#count").textContent = `${total.toLocaleString()} models`; $("#more").hidden = offset >= total; const r = rig(); // best-sort promises fitting models, so non-fits are filtered server-side // (fits_only above) and dropped client-side (headroom residuals) below. const bestSort = q.sort === "best"; if (!append) { nofitDropped = 0; autoPages = 0; seenModels = []; } seenModels.push(...res.results); for (const m of res.results) { const ui = card(m); m._ui = ui; box.append(ui.c); } const queue = [...res.results]; async function worker() { while (alive() && queue.length) { const m = queue.shift(); try { const d = await detailFor(m.key, q, ctrl.signal); if (!alive()) return; rescaleKvFits(d, q.kv_pair, q.context, q.hardware); const { pick, warnings, hidden, overReserve } = rankWithReserve(d.options, famGuess(m.key), r); m._detail = d; m._pick = pick; m._hiddenHeadroom = hidden; m._overReserve = overReserve; m._reserveNote = overReserve ? reserveNote(pick, r) : null; m._spares = { v: r.vram_spare, r: r.ram_spare }; const ui = m._ui; if (!ui) continue; ui.status.replaceChildren(); if (pick && !(bestSort && overReserve)) { const line = el("div", "choice"); line.append(el("b", null, pick.quant), ` from ${pick.repo.split("/")[0]} — ${bytesGB(pick.size)}${pick.full === false ? " (partial offload)" : ""}`); ui.status.append(line); ui.status.append(el("div", "muted", fitText(pick.fit))); for (const w of warnings) ui.status.append(el("div", "warn", w)); if (m._reserveNote) ui.status.append(el("div", "warn", m._reserveNote)); const hr = headroomNote(m); if (hr && !overReserve) ui.status.append(el("div", "muted", hr)); const railEl = rail(pick.fit, r); if (railEl) ui.status.append(railEl); } else if (bestSort) { ui.c.remove(); nofitDropped++; } else { ui.status.textContent = warnings[0] || "Doesn't fit this hardware."; } } catch (err) { if (alive() && m._ui) m._ui.status.textContent = `Quant ranking failed (${String(err).slice(0, 100)}).`; } } } await Promise.all(Array.from({ length: 4 }, worker)); if (!alive()) return; // a best-sort batch can hide entirely (e.g. nothing but 35Bs on top at // tight headroom): page forward while the screen is still empty, bounded // so it can never run away. any new search or click stops the chain. if (bestSort && box.childElementCount === 0 && autoPages < 4 && offset < total) { autoPages++; search(true); return; } // the server can no longer pre-filter fits (it only speaks q8_0/f16), // so best-sort keeps server score order and the client drops whatever // has no pick. count what is shown — the server total is unfiltered. // the vram-only and fits-only checkboxes are enforced here too, since // their server-side equivalents are forced off while rescaling. if (bestSort || $("#fits-only").checked) { for (const m of seenModels) { if (!m._ui || !m._ui.c.isConnected) continue; if (!m._pick) { m._ui.c.remove(); nofitDropped++; } } } if ($("#vram-only").checked && r.kind === "gpu") { for (const m of seenModels) { if (!m._ui || !m._ui.c.isConnected) continue; if (!m._pick || !m._pick.fit || m._pick.fit.tier !== "gpu") { m._ui.c.remove(); nofitDropped++; } } } if (bestSort) { $("#count").textContent = `${box.childElementCount.toLocaleString()} models that fit your hardware`; } } let deb; function schedule(append) { clearTimeout(deb); deb = setTimeout(() => search(append || false), 250); } function syncKind() { const kind = $('input[name="kind"]:checked').value; $$("[data-show]").forEach((n) => { if (n.id === "gpu2-wrap") return; // toggle-owned, not kind-owned n.hidden = !n.dataset.show.split(" ").includes(kind); }); $("#custom-vram-field").hidden = kind !== "gpu" || $("#gpu").value !== "custom"; $("#custom-vram2-field").hidden = $("#gpu2").value !== "custom"; $("#gpu2-toggle").textContent = $("#gpu2-wrap").hidden ? "Add a different card" : "Remove the other card"; } async function boot() { try { META = await fetch(`${API}/api/meta`).then((r) => r.json()); SCORES = await fetch("quant_scores.json").then((r) => r.json()); } catch { $("#count").textContent = "Couldn't load. Check your connection and refresh."; return; } const H = META.hardware; const groups = (sel) => { for (const [label, names] of H.gpu_groups) { const g = document.createElement("optgroup"); g.label = label; for (const n of names) g.append(opt(n, `${n.replace(/^(NVIDIA|AMD|Intel) /, "")} (${H.gpus[n]} GB)`)); $(sel).append(g); } $(sel).append(opt("custom", "Other: enter VRAM")); }; groups("#gpu"); groups("#gpu2"); // Steam Hardware Survey defaults (Jul 2026): RTX 3060 most common GPU, // 16 GB most common RAM, 64k ctx per the bench follow-ups. $("#gpu").value = "NVIDIA RTX 3060 12GB"; $("#gpu2").value = "NVIDIA RTX 4060"; const vramSet = [...new Set(Object.values(H.gpus))].sort((a, b) => a - b); for (const sel of ["#custom-vram", "#custom-vram2"]) { for (const v of vramSet) $(sel).append(opt(v, `${v} GB`, v === 12)); } for (const sel of ["#gpu-count", "#gpu2-count"]) { for (const n of [1, 2, 3, 4, 6, 8]) $(sel).append(opt(n, n, n === 1)); } for (const v of H.ram) $("#ram").append(opt(v, `${v} GB`, v === 16)); for (const s of Object.keys(H.unified)) $("#usys").append(opt(s, s)); const syncMem = () => { const mems = H.unified[$("#usys").value] || []; $("#umem").replaceChildren(...mems.map((m) => opt(m, `${m} GB`))); }; $("#usys").addEventListener("change", () => { syncMem(); schedule(); }); syncMem(); for (const c of H.contexts) $("#ctx").append(opt(c, `${ctxLabel(c)} tokens`, c === 65536)); for (const f of META.families) $("#family").append(opt(f.family, `${f.family} (${f.count})`)); for (const s of META.sizes) $("#size").append(opt(s, s)); $("#kind").addEventListener("change", () => { syncKind(); schedule(); }); $("#gpu").addEventListener("change", syncKind); $("#gpu2").addEventListener("change", syncKind); $("#gpu2-toggle").addEventListener("click", () => { $("#gpu2-wrap").hidden = !$("#gpu2-wrap").hidden; syncKind(); schedule(); }); $("#more").addEventListener("click", () => search(true)); $("#search").addEventListener("input", () => schedule()); for (const sel of ["#gpu", "#custom-vram", "#gpu-count", "#gpu2", "#custom-vram2", "#gpu2-count", "#ram", "#usys", "#umem", "#ctx", "#kv", "#mmproj", "#min-bits", "#vram-spare", "#ram-spare", "#family", "#size", "#sort"]) { $(sel).addEventListener("change", () => schedule()); } for (const sel of ["#vram-only", "#fits-only", "#moe-only", "#vision-only"]) { $(sel).addEventListener("change", () => schedule()); } $$('input[name="kind"]').forEach((i) => i.addEventListener("change", () => schedule())); syncKind(); search(false); } boot();