LeenAlQadi commited on
Commit
bcff379
·
1 Parent(s): c814975

UI polish: table options grouping, column visibility redesign, model size fixes

Browse files
Files changed (3) hide show
  1. app.py +1 -1
  2. backend/data_loader.py +17 -1
  3. frontend/leaderboard.html +72 -69
app.py CHANGED
@@ -55,7 +55,7 @@ def update_leaderboard_cache():
55
 
56
  if "Model Size" in df.columns:
57
  size_series = pd.to_numeric(df["Model Size"], errors="coerce")
58
- df["Model Size"] = size_series.apply(lambda v: int(v) if pd.notna(v) else "Unknown")
59
 
60
  if "Hub ❤️" in df.columns:
61
  likes_series = pd.to_numeric(df["Hub ❤️"], errors="coerce")
 
55
 
56
  if "Model Size" in df.columns:
57
  size_series = pd.to_numeric(df["Model Size"], errors="coerce")
58
+ df["Model Size"] = size_series.apply(lambda v: round(float(v), 1) if pd.notna(v) else "Unknown")
59
 
60
  if "Hub ❤️" in df.columns:
61
  likes_series = pd.to_numeric(df["Hub ❤️"], errors="coerce")
backend/data_loader.py CHANGED
@@ -1198,6 +1198,22 @@ def load_benchmark_details(
1198
  }
1199
 
1200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1201
  def _fetch_hf_metadata(model_name: str) -> Dict[str, Any]:
1202
  try:
1203
  info = API.model_info(repo_id=model_name, token=hf_api_token)
@@ -1215,7 +1231,7 @@ def _fetch_hf_metadata(model_name: str) -> Dict[str, Any]:
1215
  if model_size == 0:
1216
  safetensors = getattr(info, "safetensors", None)
1217
  if not safetensors or not safetensors.get("total"):
1218
- model_size = None
1219
 
1220
  return {
1221
  "License": license_name,
 
1198
  }
1199
 
1200
 
1201
+ # Manual size overrides (in billions) for models where HF API returns no safetensors metadata.
1202
+ _MODEL_SIZE_OVERRIDES: Dict[str, float] = {
1203
+ "Qwen/Qwen2.5-14B-Instruct": 14.0,
1204
+ "Qwen/Qwen2.5-32B-Instruct": 32.0,
1205
+ "Qwen/Qwen3-30B-A3B-Instruct-2507": 30.0,
1206
+ "Qwen/Qwen3-235B-A22B-Instruct-2507": 235.0,
1207
+ "google/gemma-3-270m-it": 0.27,
1208
+ "google/gemma-3-1b-it": 1.0,
1209
+ "google/gemma-3-1b-pt": 1.0,
1210
+ "google/gemma-3-4b-it": 4.0,
1211
+ "google/gemma-3-12b-it": 12.0,
1212
+ "google/gemma-3-27b-pt": 27.0,
1213
+ "microsoft/Phi-4-mini-instruct": 3.8,
1214
+ }
1215
+
1216
+
1217
  def _fetch_hf_metadata(model_name: str) -> Dict[str, Any]:
1218
  try:
1219
  info = API.model_info(repo_id=model_name, token=hf_api_token)
 
1231
  if model_size == 0:
1232
  safetensors = getattr(info, "safetensors", None)
1233
  if not safetensors or not safetensors.get("total"):
1234
+ model_size = _MODEL_SIZE_OVERRIDES.get(model_name)
1235
 
1236
  return {
1237
  "License": license_name,
frontend/leaderboard.html CHANGED
@@ -687,72 +687,68 @@
687
  data-lucide="rotate-ccw" class="w-3 h-3"></i> Reset</button>
688
  </div>
689
 
690
- <!-- Section 1: Ranking Mode -->
691
- <div class="mb-5">
692
- <h4 class="text-xs font-bold text-slate-400 mb-3 flex items-center gap-2">
693
- Ranking Mode
694
- <div class="relative tooltip-trigger group cursor-help">
695
- <i data-lucide="info"
696
- class="w-3.5 h-3.5 text-slate-400 hover:text-slate-600 dark:hover:text-slate-200"></i>
697
- <div
698
- class="tooltip-content invisible opacity-0 absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-48 p-2 bg-slate-800 text-white text-xs rounded shadow-lg transition-all z-50 text-left pointer-events-none">
699
- <p>
700
- <strong>Global Rank:</strong> shows the rank based on the global average across all benchmarks.<br>
701
- <strong>Current View Rank:</strong> updates the rank based on the current sort and filters.
702
- </p>
703
- <div
704
- class="absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-slate-800">
705
  </div>
706
  </div>
 
 
 
 
 
 
707
  </div>
708
-
709
- </h4>
710
- <div class="flex flex-wrap gap-1.5">
711
- <button onclick="window.setRankMode('static')" id="rankBtnStatic"
712
- class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-indigo-50 border-indigo-400 text-indigo-600 dark:bg-indigo-900/30 dark:border-indigo-500 dark:text-indigo-300">Global Rank</button>
713
- <button onclick="window.setRankMode('dynamic')" id="rankBtnDynamic"
714
- class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-white border-slate-200 text-slate-500 hover:bg-slate-50 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-600">Current View Rank</button>
715
  </div>
716
- </div>
717
 
718
- <!-- Section 2: Avg Score Calc -->
719
- <div>
720
- <h4 class="text-xs font-bold text-slate-400 mb-3 flex items-center gap-2">
721
- Average Score Calculation
722
- <div class="relative tooltip-trigger group cursor-help">
723
- <i data-lucide="info"
724
- class="w-3.5 h-3.5 text-slate-400 hover:text-slate-600 dark:hover:text-slate-200"></i>
725
- <div
726
- class="tooltip-content invisible opacity-0 absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-48 p-2 bg-slate-800 text-white text-xs rounded shadow-lg transition-all z-50 text-left pointer-events-none">
727
- <p>
728
- <strong>Global Average:</strong> Calculates the average across all benchmarks.<br>
729
- <strong>Filtered Average:</strong> Recalculates the average using only the currently visible evaluation columns.
730
- </p>
731
- <div
732
- class="absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-slate-800">
733
  </div>
734
  </div>
735
-
 
 
 
 
 
736
  </div>
737
- </h4>
738
- <div class="flex flex-wrap gap-1.5">
739
- <button onclick="window.setAvgMode('all')" id="avgBtnAll"
740
- class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-indigo-50 border-indigo-400 text-indigo-600 dark:bg-indigo-900/30 dark:border-indigo-500 dark:text-indigo-300">Global Average</button>
741
- <button onclick="window.setAvgMode('visible')" id="avgBtnVisible"
742
- class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-white border-slate-200 text-slate-500 hover:bg-slate-50 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-600">Filtered Average</button>
743
  </div>
744
  </div>
745
 
746
- <!-- Section 3: Task Type -->
747
- <div class="mt-5">
748
- <h4 class="text-xs font-bold text-slate-400 mb-2">Task Type</h4>
749
- <div id="taskTypeFilterBtns" class="flex flex-wrap gap-1.5"></div>
750
- </div>
 
 
 
 
751
 
752
- <!-- Section 4: Domain -->
753
- <div class="mt-5">
754
- <h4 class="text-xs font-bold text-slate-400 mb-2">Domain</h4>
755
- <div id="domainFilterBtns" class="flex flex-wrap gap-1.5"></div>
 
756
  </div>
757
 
758
  </div>
@@ -763,21 +759,19 @@
763
  <i data-lucide="book-open" id="colMenuIcon" class="h-5 w-5"></i> <span>Column Visibility</span>
764
  </button>
765
  <div id="colMenu"
766
- class="hidden absolute top-10 right-0 z-50 w-80 p-4 bg-white dark:bg-slate-800 rounded-xl shadow-xl border border-slate-200 dark:border-slate-700">
767
  <div class="flex justify-between items-center mb-4 pb-2 border-b border-slate-100 dark:border-slate-700">
768
- <span class="text-sm font-bold text-slate-700 dark:text-slate-200">Visible Columns</span>
769
  <button onclick="window.resetColumns()"
770
  class="text-xs text-indigo-600 hover:text-indigo-700 dark:text-indigo-400 font-medium flex items-center gap-1"><i
771
  data-lucide="rotate-ccw" class="w-3 h-3"></i> Reset</button>
772
  </div>
773
- <div class="mb-5">
774
- <h4 class="text-xs font-bold text-slate-400 mb-2 flex justify-between">Eval Scores <span
775
- id="count-scores" class="text-slate-500"></span></h4>
776
  <div id="colListScores" class="flex flex-wrap gap-2"></div>
777
  </div>
778
- <div>
779
- <h4 class="text-xs font-bold text-slate-400 mb-2 flex justify-between">Model Details <span
780
- id="count-details" class="text-slate-500"></span></h4>
781
  <div id="colListDetails" class="flex flex-wrap gap-2"></div>
782
  </div>
783
  </div>
@@ -1067,14 +1061,16 @@ taskTypes: [], // [] = All; otherwise selected subset
1067
  $('#searchInput').addEventListener('keyup', applyFilters);
1068
 
1069
  // Close menus on outside click
 
 
1070
  document.addEventListener('click', e => {
1071
- const t = e.target;
1072
  // Col Menu
1073
- if (!$('#colMenu').classList.contains('hidden') && !$('#colMenu').contains(t) && !$('#colMenuTrigger').contains(t)) {
1074
  toggleColMenu();
1075
  }
1076
  // Table Ops Menu
1077
- if (!$('#tableOpsMenu').classList.contains('hidden') && !$('#tableOpsMenu').contains(t) && !$('#tableOpsTrigger').contains(t)) {
1078
  toggleTableOps();
1079
  }
1080
  });
@@ -1955,7 +1951,15 @@ window.toggleExpandText = function (idBase, btn) {
1955
  if (key === "Model Size") {
1956
  def.formatter = (c) => {
1957
  const n = toNumber(c);
1958
- return gridjs.html(`<span class="font-mono">${n === null ? "Unknown" : `${Math.floor(n)}B`}</span>`);
 
 
 
 
 
 
 
 
1959
  };
1960
  }
1961
 
@@ -2072,10 +2076,10 @@ window.toggleExpandText = function (idBase, btn) {
2072
  function buildColMenuDOM() {
2073
  const addBtns = (grp, el) => {
2074
  $(el).innerHTML = '';
2075
- tableColumns.filter(c => c.group === grp && !["_link", "T", "Type", "Full Type", "Precision"].includes(c.id)).forEach(c => {
2076
  const b = document.createElement('button');
2077
  b.innerText = c.id.includes("Average") ? "Average" : (c.id === "Model Size Filter" ? "Params" : c.id);
2078
- b.className = `px-2 py-1 text-xs font-medium rounded-md border transition-all select-none ${!c.hidden ? "bg-indigo-600 text-white border-indigo-600" : "bg-white text-slate-600 border-slate-200 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300"}`;
2079
  b.onclick = (e) => {
2080
  e.stopPropagation();
2081
  c.hidden = !c.hidden;
@@ -2085,7 +2089,6 @@ window.toggleExpandText = function (idBase, btn) {
2085
  };
2086
  $(el).appendChild(b);
2087
  });
2088
- $(`#count-${grp}`).innerText = `(${tableColumns.filter(x => x.group === grp && !x.hidden).length}/${tableColumns.filter(x => x.group === grp).length})`;
2089
  };
2090
  addBtns('scores', '#colListScores'); addBtns('details', '#colListDetails');
2091
  }
 
687
  data-lucide="rotate-ccw" class="w-3 h-3"></i> Reset</button>
688
  </div>
689
 
690
+ <!-- Group 1: View Options -->
691
+ <p class="text-xs font-semibold text-slate-500 dark:text-slate-400 mb-2">View Options</p>
692
+ <div class="mb-4 p-3 rounded-xl border border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-800/60">
693
+
694
+ <!-- Section 1: Ranking Mode -->
695
+ <div class="mb-4">
696
+ <h4 class="text-xs font-bold text-slate-400 mb-2 flex items-center gap-2">
697
+ Ranking Mode
698
+ <div class="relative tooltip-trigger group cursor-help">
699
+ <i data-lucide="info" class="w-3.5 h-3.5 text-slate-400 hover:text-slate-600 dark:hover:text-slate-200"></i>
700
+ <div class="tooltip-content invisible opacity-0 absolute top-full left-1/2 -translate-x-1/2 mt-2 w-52 p-3 bg-white/75 dark:bg-slate-700/60 backdrop-blur-sm text-slate-500 dark:text-slate-400 text-[9px] rounded-lg shadow-sm border border-slate-200/60 dark:border-slate-600/50 transition-all z-50 text-left pointer-events-none">
701
+ <div class="absolute bottom-full left-1/2 -translate-x-1/2 border-4 border-transparent border-b-slate-200 dark:border-b-slate-600"></div>
702
+ <p class="mb-1"><span class="font-bold text-slate-600 dark:text-slate-300">Global Rank:</span> shows the rank based on the global average across all benchmarks.</p>
703
+ <p><span class="font-bold text-slate-600 dark:text-slate-300">Current View Rank:</span> updates the rank based on the current sort and filters.</p>
 
704
  </div>
705
  </div>
706
+ </h4>
707
+ <div class="flex flex-wrap gap-1.5">
708
+ <button onclick="window.setRankMode('static')" id="rankBtnStatic"
709
+ class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-indigo-50 border-indigo-400 text-indigo-600 dark:bg-indigo-900/30 dark:border-indigo-500 dark:text-indigo-300">Global Rank</button>
710
+ <button onclick="window.setRankMode('dynamic')" id="rankBtnDynamic"
711
+ class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-white border-slate-200 text-slate-500 hover:bg-slate-50 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-600">Current View Rank</button>
712
  </div>
 
 
 
 
 
 
 
713
  </div>
 
714
 
715
+ <!-- Section 2: Avg Score Calc -->
716
+ <div>
717
+ <h4 class="text-xs font-bold text-slate-400 mb-2 flex items-center gap-2">
718
+ Average Score Calculation
719
+ <div class="relative tooltip-trigger group cursor-help">
720
+ <i data-lucide="info" class="w-3.5 h-3.5 text-slate-400 hover:text-slate-600 dark:hover:text-slate-200"></i>
721
+ <div class="tooltip-content invisible opacity-0 absolute top-full left-1/2 -translate-x-1/2 mt-2 w-52 p-3 bg-white/75 dark:bg-slate-700/60 backdrop-blur-sm text-slate-500 dark:text-slate-400 text-[9px] rounded-lg shadow-sm border border-slate-200/60 dark:border-slate-600/50 transition-all z-50 text-left pointer-events-none">
722
+ <div class="absolute bottom-full left-1/2 -translate-x-1/2 border-4 border-transparent border-b-slate-200 dark:border-b-slate-600"></div>
723
+ <p class="mb-1"><span class="font-bold text-slate-600 dark:text-slate-300">Global Average:</span> calculates the average across all benchmarks.</p>
724
+ <p><span class="font-bold text-slate-600 dark:text-slate-300">Filtered Average:</span> recalculates using only the currently visible evaluation columns.</p>
 
 
 
 
 
725
  </div>
726
  </div>
727
+ </h4>
728
+ <div class="flex flex-wrap gap-1.5">
729
+ <button onclick="window.setAvgMode('all')" id="avgBtnAll"
730
+ class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-indigo-50 border-indigo-400 text-indigo-600 dark:bg-indigo-900/30 dark:border-indigo-500 dark:text-indigo-300">Global Average</button>
731
+ <button onclick="window.setAvgMode('visible')" id="avgBtnVisible"
732
+ class="px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none bg-white border-slate-200 text-slate-500 hover:bg-slate-50 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-600">Filtered Average</button>
733
  </div>
 
 
 
 
 
 
734
  </div>
735
  </div>
736
 
737
+ <!-- Group 2: Benchmark Filters -->
738
+ <p class="text-xs font-semibold text-slate-500 dark:text-slate-400 mb-2">Benchmark Filters</p>
739
+ <div class="p-3 rounded-xl border border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-800/60">
740
+
741
+ <!-- Section 3: Task Type -->
742
+ <div class="mb-4">
743
+ <h4 class="text-xs font-bold text-slate-400 mb-2">Task Type</h4>
744
+ <div id="taskTypeFilterBtns" class="flex flex-wrap gap-1.5"></div>
745
+ </div>
746
 
747
+ <!-- Section 4: Domain -->
748
+ <div>
749
+ <h4 class="text-xs font-bold text-slate-400 mb-2">Domain</h4>
750
+ <div id="domainFilterBtns" class="flex flex-wrap gap-1.5"></div>
751
+ </div>
752
  </div>
753
 
754
  </div>
 
759
  <i data-lucide="book-open" id="colMenuIcon" class="h-5 w-5"></i> <span>Column Visibility</span>
760
  </button>
761
  <div id="colMenu"
762
+ class="hidden absolute top-10 right-0 z-50 w-80 p-4 bg-white dark:bg-slate-800 rounded-xl shadow-xl border border-slate-200 dark:border-slate-700 max-h-[80vh] overflow-y-auto">
763
  <div class="flex justify-between items-center mb-4 pb-2 border-b border-slate-100 dark:border-slate-700">
764
+ <span class="text-sm font-bold text-slate-700 dark:text-slate-200">Column Visibility</span>
765
  <button onclick="window.resetColumns()"
766
  class="text-xs text-indigo-600 hover:text-indigo-700 dark:text-indigo-400 font-medium flex items-center gap-1"><i
767
  data-lucide="rotate-ccw" class="w-3 h-3"></i> Reset</button>
768
  </div>
769
+ <p class="text-xs font-semibold text-slate-500 dark:text-slate-400 mb-2">Benchmarks</p>
770
+ <div class="mb-4 p-3 rounded-xl border border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-800/60">
 
771
  <div id="colListScores" class="flex flex-wrap gap-2"></div>
772
  </div>
773
+ <p class="text-xs font-semibold text-slate-500 dark:text-slate-400 mb-2">Model Details</p>
774
+ <div class="p-3 rounded-xl border border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-800/60">
 
775
  <div id="colListDetails" class="flex flex-wrap gap-2"></div>
776
  </div>
777
  </div>
 
1061
  $('#searchInput').addEventListener('keyup', applyFilters);
1062
 
1063
  // Close menus on outside click
1064
+ // Use composedPath() so clicks on dynamically re-rendered children
1065
+ // (e.g. filter pills rebuilt via innerHTML) still count as "inside".
1066
  document.addEventListener('click', e => {
1067
+ const path = e.composedPath();
1068
  // Col Menu
1069
+ if (!$('#colMenu').classList.contains('hidden') && !path.includes($('#colMenu')) && !path.includes($('#colMenuTrigger'))) {
1070
  toggleColMenu();
1071
  }
1072
  // Table Ops Menu
1073
+ if (!$('#tableOpsMenu').classList.contains('hidden') && !path.includes($('#tableOpsMenu')) && !path.includes($('#tableOpsTrigger'))) {
1074
  toggleTableOps();
1075
  }
1076
  });
 
1951
  if (key === "Model Size") {
1952
  def.formatter = (c) => {
1953
  const n = toNumber(c);
1954
+ const label = n === null ? "Unknown" : n < 1 ? `${Math.round(n * 1000)}M` : `${Math.round(n)}B`;
1955
+ return gridjs.html(`<div class="flex justify-center"><span class="inline-block min-w-[6rem] text-center px-2 py-1 rounded-md border text-xs font-mono font-medium shadow-sm bg-slate-100 text-slate-600 border-slate-300 dark:bg-slate-700 dark:text-slate-300 dark:border-slate-500">${label}</span></div>`);
1956
+ };
1957
+ }
1958
+
1959
+ if (key === "License") {
1960
+ def.formatter = (c) => {
1961
+ const label = (c && c !== "Unknown") ? c : "Unknown";
1962
+ return gridjs.html(`<div class="flex justify-center"><span class="inline-block min-w-[6rem] text-center px-2 py-1 rounded-md border text-xs font-medium shadow-sm bg-slate-100 text-slate-600 border-slate-300 dark:bg-slate-700 dark:text-slate-300 dark:border-slate-500 max-w-[160px] truncate" title="${label}">${label}</span></div>`);
1963
  };
1964
  }
1965
 
 
2076
  function buildColMenuDOM() {
2077
  const addBtns = (grp, el) => {
2078
  $(el).innerHTML = '';
2079
+ tableColumns.filter(c => c.group === grp && !["_link", "T", "Type", "Full Type", "Precision", "Hub ❤️", "Revision"].includes(c.id)).forEach(c => {
2080
  const b = document.createElement('button');
2081
  b.innerText = c.id.includes("Average") ? "Average" : (c.id === "Model Size Filter" ? "Params" : c.id);
2082
+ b.className = `px-3 py-1.5 rounded-lg border text-xs font-medium cursor-pointer transition-all select-none ${!c.hidden ? "bg-indigo-50 border-indigo-400 text-indigo-600 dark:bg-indigo-900/30 dark:border-indigo-500 dark:text-indigo-300" : "bg-white border-slate-200 text-slate-500 hover:bg-slate-50 dark:bg-slate-700 dark:border-slate-600 dark:text-slate-300 dark:hover:bg-slate-600"}`;
2083
  b.onclick = (e) => {
2084
  e.stopPropagation();
2085
  c.hidden = !c.hidden;
 
2089
  };
2090
  $(el).appendChild(b);
2091
  });
 
2092
  };
2093
  addBtns('scores', '#colListScores'); addBtns('details', '#colListDetails');
2094
  }