Jonna Marie Matthiesen Copilot commited on
Commit
19a0613
Β·
1 Parent(s): 2d4b81f

Add accuracy table above filters for model families with accuracy data

Browse files

Add accuracy_file config key per model family pointing to a CSV with
accuracy benchmarks. When present, an accuracy table renders above the
filter buttons showing per-model scores with best values highlighted.
The table respects variant selection, filtering to active models.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Files changed (3) hide show
  1. app.js +86 -0
  2. config.json +2 -1
  3. index.html +3 -0
app.js CHANGED
@@ -59,6 +59,38 @@ async function loadFamilyData(familyKey) {
59
  // Current family's loaded data
60
  let DATA = [];
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  // ─── Config shortcuts ─────────────────────────────────────────────────────────
63
 
64
  const MODEL_COL = config.model_column;
@@ -705,6 +737,59 @@ function buildExperimentSetup() {
705
  });
706
  }
707
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  // ─── Render ───────────────────────────────────────────────────────────────────
709
 
710
  function render() {
@@ -729,6 +814,7 @@ function render() {
729
  (config.metrics.length <= 1 || !chartsShown) ? "none" : "";
730
  }
731
  buildTables(filtered, chartsShown);
 
732
  buildExperimentSetup();
733
  }
734
 
 
59
  // Current family's loaded data
60
  let DATA = [];
61
 
62
+ // ─── Accuracy data cache ──────────────────────────────────────────────────────
63
+
64
+ const accDataCache = {};
65
+
66
+ async function loadAccuracyData(filePath) {
67
+ if (!filePath) return null;
68
+ if (accDataCache[filePath]) return accDataCache[filePath];
69
+ try {
70
+ const text = await fetch(filePath).then(r => {
71
+ if (!r.ok) return null;
72
+ return r.text();
73
+ });
74
+ if (!text) return null;
75
+ const lines = text.replace(/\r/g, "").trim().split("\n");
76
+ const headers = lines[0].split(",");
77
+ const rows = lines.slice(1).map(line => {
78
+ const vals = line.split(",");
79
+ const row = {};
80
+ headers.forEach((h, i) => {
81
+ const raw = (vals[i] || "").trim();
82
+ row[h] = raw;
83
+ });
84
+ return row;
85
+ });
86
+ const result = { headers, rows };
87
+ accDataCache[filePath] = result;
88
+ return result;
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
93
+
94
  // ─── Config shortcuts ─────────────────────────────────────────────────────────
95
 
96
  const MODEL_COL = config.model_column;
 
737
  });
738
  }
739
 
740
+ // ─── Accuracy Table ───────────────────────────────────────────────────────────
741
+
742
+ async function buildAccuracyTable() {
743
+ const section = document.getElementById("accuracy-section");
744
+ section.innerHTML = "";
745
+ const familyCfg = config.model_families?.[activeFamilyKey()] || {};
746
+ const accFile = familyCfg.accuracy_file;
747
+ if (!accFile) return;
748
+
749
+ const accData = await loadAccuracyData(accFile);
750
+ if (!accData || !accData.rows.length) return;
751
+
752
+ // Filter to active models if a variant is selected
753
+ const activeModels = getActiveModelSet();
754
+ const rows = accData.rows.filter(r => activeModels.has(r[accData.headers[0]]));
755
+ if (!rows.length) return;
756
+
757
+ const modelCol = accData.headers[0];
758
+ const metricCols = accData.headers.slice(1);
759
+
760
+ const card = document.createElement("div");
761
+ card.className = "table-card";
762
+
763
+ let html = `<h3>Accuracy</h3><div class="table-scroll"><table><thead><tr>`;
764
+ html += `<th>MODEL</th>`;
765
+ html += metricCols.map(h => `<th class="metric-cell">${h}</th>`).join("");
766
+ html += `</tr></thead><tbody>`;
767
+
768
+ // Find best value per column (higher is better for accuracy)
769
+ const best = {};
770
+ metricCols.forEach(col => {
771
+ const vals = rows.map(r => parseFloat(r[col])).filter(v => !isNaN(v));
772
+ if (vals.length) best[col] = Math.max(...vals);
773
+ });
774
+
775
+ rows.forEach(r => {
776
+ const model = r[modelCol];
777
+ const modelColor = MODEL_COLORS[model]?.border || '#888';
778
+ html += `<tr><td class="model-cell"><span class="model-dot" style="background:${modelColor}"></span><a href="${LINK_PREFIX}${model}" target="_blank" rel="noopener" style="color:${modelColor}">${model}</a></td>`;
779
+ metricCols.forEach(col => {
780
+ const val = parseFloat(r[col]);
781
+ const isBest = !isNaN(val) && val === best[col];
782
+ const display = isNaN(val) ? (r[col] || "β€”") : val.toFixed(2);
783
+ html += `<td class="metric-cell">${isBest ? '<strong style="color: white; opacity: 0.7">' + display + '</strong>' : display}</td>`;
784
+ });
785
+ html += `</tr>`;
786
+ });
787
+
788
+ html += `</tbody></table></div>`;
789
+ card.innerHTML = html;
790
+ section.appendChild(card);
791
+ }
792
+
793
  // ─── Render ───────────────────────────────────────────────────────────────────
794
 
795
  function render() {
 
814
  (config.metrics.length <= 1 || !chartsShown) ? "none" : "";
815
  }
816
  buildTables(filtered, chartsShown);
817
+ buildAccuracyTable();
818
  buildExperimentSetup();
819
  }
820
 
config.json CHANGED
@@ -138,7 +138,8 @@
138
  "agx_orin": "Measurement setup: NVIDIA AI IoT vLLM 0.14.0 tegra, 256 tokens generated, 10 warm-up runs, averaged over 25 runs.",
139
  "orin_nano": "Measurement setup: NVIDIA AI IoT vLLM 0.14.0 tegra, 256 tokens generated, 10 warm-up runs, averaged over 25 runs."
140
  },
141
- "default_device": "orin_nano"
 
142
  },
143
  "Qwen3.5": {
144
  "data_file": "data/Qwen3.5.csv",
 
138
  "agx_orin": "Measurement setup: NVIDIA AI IoT vLLM 0.14.0 tegra, 256 tokens generated, 10 warm-up runs, averaged over 25 runs.",
139
  "orin_nano": "Measurement setup: NVIDIA AI IoT vLLM 0.14.0 tegra, 256 tokens generated, 10 warm-up runs, averaged over 25 runs."
140
  },
141
+ "default_device": "orin_nano",
142
+ "accuracy_file": "data/acc-Cosmos-Reason2.csv"
143
  },
144
  "Qwen3.5": {
145
  "data_file": "data/Qwen3.5.csv",
index.html CHANGED
@@ -28,6 +28,9 @@
28
  <p class="hero-sub" id="hero-sub">Compare throughput and latency across devices and model variants.</p>
29
  </header>
30
 
 
 
 
31
  <!-- Filters -->
32
  <section class="filters-bar" id="filters-bar"></section>
33
 
 
28
  <p class="hero-sub" id="hero-sub">Compare throughput and latency across devices and model variants.</p>
29
  </header>
30
 
31
+ <!-- Accuracy Table -->
32
+ <section id="accuracy-section"></section>
33
+
34
  <!-- Filters -->
35
  <section class="filters-bar" id="filters-bar"></section>
36