File size: 3,035 Bytes
046ace0
 
 
 
 
 
 
 
e706366
046ace0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"use strict";
(function () {
  const $ = (s) => document.querySelector(s);
  const el = (tag, cls, text) => { const n = document.createElement(tag); if (cls) n.className = cls; if (text != null) n.textContent = text; return n; };
  const LABELS = { sessions: "Visits", engaged_sessions: "Visits that opened a model", hardware_set: "Visits with hardware set", feedback: "Reports", benchmarks: "llama-bench results" };
  const CHARTS = [
    ["hardware_kinds", "Hardware type"], ["vram_classes", "GPU memory (GB, all cards)"], ["gpu_models", "Graphics cards"],
    ["gpu_counts", "Cards per machine"], ["ram_classes", "System or unified memory (GB)"], ["families", "Model families"],
    ["sizes", "Model sizes"], ["contexts", "Context length"], ["kv_types", "KV cache precision"], ["priorities", "Preference"], ["min_bits", "Lowest quant"],
    ["models_viewed", "Most opened models"], ["top_fits", "How the top result fit"], ["benchmark_backends", "Benchmark backends"],
  ];
  const KIND = { gpu: "GPU", unified: "Mac / unified", cpu: "CPU only" };
  const FIT = { gpu: "Fits on GPU", gpu_moe: "Experts in RAM", partial: "Partly on GPU", cpu: "CPU only", unified: "Fits (unified)", unified_tight: "Needs a raised limit", no: "Doesn't fit" };
  const fmt = (chart, k) => {
    if (chart === "hardware_kinds") return KIND[k] || k;
    if (chart === "top_fits") return FIT[k] || k;
    if (chart === "contexts" && typeof k === "number") return `${Math.round(k / 1024)}k`;
    return String(k);
  };
  function bars(chart, items) {
    const box = el("div", "bars");
    if (!items.length) { box.append(el("p", "scale-note", "Not enough data yet.")); return box; }
    const max = Math.max(...items.map((x) => x.count));
    for (const it of items) {
      const row = el("div", "bar");
      const track = el("div", "track");
      const fill = el("div", "fill");
      fill.style.width = `${(it.count / max) * 100}%`;
      track.append(fill);
      const k = el("span", "k", fmt(chart, it.key));
      k.title = k.textContent;
      row.append(k, track, el("span", "n", `${it.count.toLocaleString()} (${Math.round(it.share * 100)}%)`));
      box.append(row);
    }
    return box;
  }
  async function load() {
    let s;
    try {
      const r = await fetch("/api/stats");
      if (!r.ok) throw new Error(String(r.status));
      s = await r.json();
    } catch (e) {
      $("#updated").textContent = "Statistics couldn't be loaded. Refresh in a moment.";
      return;
    }
    $("#kmin").textContent = s.k_min;
    $("#totals").replaceChildren(...Object.entries(s.totals).map(([k, v]) => {
      const d = el("div", "total");
      d.append(el("b", null, v.toLocaleString()), el("span", null, LABELS[k] || k));
      return d;
    }));
    $("#charts").replaceChildren(...CHARTS.map(([key, title]) => {
      const c = el("section", "chart");
      c.append(el("h2", null, title), bars(key, s[key] || []));
      return c;
    }));
    $("#updated").textContent = `Updated ${new Date().toLocaleString()}.`;
  }
  load();
})();