luisrui commited on
Commit
9a5742a
·
1 Parent(s): 56bf2c2

Surface modality filter on the UI: family column + status line showing required capability and eligible-candidate count

Browse files
Files changed (2) hide show
  1. app.py +32 -6
  2. recommend.py +17 -0
app.py CHANGED
@@ -12,9 +12,14 @@ import os
12
  import traceback
13
 
14
  import gradio as gr
 
15
  import pandas as pd
16
 
17
- from recommend import default_recommender
 
 
 
 
18
 
19
 
20
  # Load once at module import time so the model is warm before the first request.
@@ -59,11 +64,14 @@ def _format_size(size_b: float) -> str:
59
  return f"{size_b * 1_000_000:.0f}K"
60
 
61
 
 
 
 
62
  def recommend_ui(dataset_description: str, task: str, metric: str, top_k: int,
63
  min_size: float, max_size: float, official_only: bool, hf_only: bool,
64
  api_key: str):
65
  if not (dataset_description or "").strip():
66
- return pd.DataFrame(columns=["rank", "model", "score", "size", "popularity", "link"]), \
67
  "Please enter a dataset description."
68
 
69
  api_key = (api_key or "").strip()
@@ -104,13 +112,26 @@ def recommend_ui(dataset_description: str, task: str, metric: str, top_k: int,
104
  rows.append({
105
  "rank": r.rank,
106
  "model": r.model_name,
 
107
  "score": round(r.score, 4),
108
  "size": _format_size(r.size_b),
109
  "popularity": r.popularity,
110
  "link": link,
111
  })
112
- df = pd.DataFrame(rows, columns=["rank", "model", "score", "size", "popularity", "link"])
113
- return df, f"Returned top-{len(rows)} of {len(RECOMMENDER.model_names)} candidates."
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
 
116
  with gr.Blocks(title="ModelLens · Finding the Best Model for Your Task", theme=gr.themes.Soft()) as demo:
@@ -121,6 +142,11 @@ with gr.Blocks(title="ModelLens · Finding the Best Model for Your Task", theme=
121
  the top candidates from a pool of **47k+** HuggingFace models. Backed by the
122
  ablation_no_id MLPMetric checkpoint trained on `unified_augmented`.
123
 
 
 
 
 
 
124
  > **BYO OpenAI key.** This Space embeds your dataset description with
125
  > `text-embedding-3-small`.
126
  """
@@ -178,10 +204,10 @@ with gr.Blocks(title="ModelLens · Finding the Best Model for Your Task", theme=
178
  with gr.Column(scale=3):
179
  status = gr.Markdown("")
180
  table = gr.Dataframe(
181
- headers=["rank", "model", "score", "size", "popularity", "link"],
182
  interactive=False,
183
  wrap=True,
184
- datatype=["number", "str", "number", "str", "number", "markdown"],
185
  )
186
 
187
  run_btn.click(
 
12
  import traceback
13
 
14
  import gradio as gr
15
+ import numpy as np
16
  import pandas as pd
17
 
18
+ from recommend import (
19
+ caps_bits_to_labels,
20
+ default_recommender,
21
+ _task_required_caps_bits,
22
+ )
23
 
24
 
25
  # Load once at module import time so the model is warm before the first request.
 
64
  return f"{size_b * 1_000_000:.0f}K"
65
 
66
 
67
+ _TABLE_COLS = ["rank", "model", "family", "score", "size", "popularity", "link"]
68
+
69
+
70
  def recommend_ui(dataset_description: str, task: str, metric: str, top_k: int,
71
  min_size: float, max_size: float, official_only: bool, hf_only: bool,
72
  api_key: str):
73
  if not (dataset_description or "").strip():
74
+ return pd.DataFrame(columns=_TABLE_COLS), \
75
  "Please enter a dataset description."
76
 
77
  api_key = (api_key or "").strip()
 
112
  rows.append({
113
  "rank": r.rank,
114
  "model": r.model_name,
115
+ "family": r.family or "—",
116
  "score": round(r.score, 4),
117
  "size": _format_size(r.size_b),
118
  "popularity": r.popularity,
119
  "link": link,
120
  })
121
+ df = pd.DataFrame(rows, columns=_TABLE_COLS)
122
+
123
+ # Surface what the modality filter is doing so the user can see why
124
+ # certain candidates were (or weren't) eligible.
125
+ caps_bits = _task_required_caps_bits(task)
126
+ caps_labels = caps_bits_to_labels(caps_bits)
127
+ n_compat = int(((RECOMMENDER.model_caps_bits & caps_bits) != 0).sum())
128
+ caps_str = ", ".join(f"`{c}`" for c in caps_labels) if caps_labels else "any"
129
+ status = (
130
+ f"Task **{task}** requires model capability: {caps_str} → "
131
+ f"**{n_compat:,}** of {len(RECOMMENDER.model_names):,} candidates eligible. "
132
+ f"Returned top-{len(rows)}."
133
+ )
134
+ return df, status
135
 
136
 
137
  with gr.Blocks(title="ModelLens · Finding the Best Model for Your Task", theme=gr.themes.Soft()) as demo:
 
142
  the top candidates from a pool of **47k+** HuggingFace models. Backed by the
143
  ablation_no_id MLPMetric checkpoint trained on `unified_augmented`.
144
 
145
+ Results are post-filtered by a modality sanity check so that e.g.
146
+ *Image Generation* won't surface text-only LLMs. The status line below
147
+ the table shows which capability your task requires and how many
148
+ candidates passed the filter.
149
+
150
  > **BYO OpenAI key.** This Space embeds your dataset description with
151
  > `text-embedding-3-small`.
152
  """
 
204
  with gr.Column(scale=3):
205
  status = gr.Markdown("")
206
  table = gr.Dataframe(
207
+ headers=_TABLE_COLS,
208
  interactive=False,
209
  wrap=True,
210
+ datatype=["number", "str", "str", "number", "str", "number", "markdown"],
211
  )
212
 
213
  run_btn.click(
recommend.py CHANGED
@@ -400,6 +400,21 @@ def _task_required_caps_bits(task: str) -> int:
400
  return _DEFAULT_TASK_CAPS
401
 
402
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  def _slug(s: str) -> str:
404
  return re.sub(r"[^a-z0-9]+", "", str(s).strip().lower())
405
 
@@ -428,6 +443,7 @@ class Recommendation:
428
  size_bucket: int
429
  size_b: float # raw size in billions of params; NaN if unknown
430
  family_id: int
 
431
  popularity: int
432
  hf_url: str
433
 
@@ -731,6 +747,7 @@ class Recommender:
731
  size_bucket=int(self.size_ids[i]),
732
  size_b=float(self.sizes_b[i]),
733
  family_id=int(self.family_ids[i]),
 
734
  popularity=int(self.popularities[i]),
735
  hf_url=self.urls[i],
736
  )
 
400
  return _DEFAULT_TASK_CAPS
401
 
402
 
403
+ def caps_bits_to_labels(bits: int) -> list[str]:
404
+ """Human-readable capability labels (e.g., 'vision-generation') from a bitmask."""
405
+ pretty = {
406
+ "text": "text",
407
+ "text_embedding": "text-embedding",
408
+ "vision": "vision",
409
+ "vision_generate": "vision-generation",
410
+ "vision_language": "vision-language",
411
+ "audio": "audio",
412
+ "video": "video",
413
+ "document": "document",
414
+ }
415
+ return [pretty[c] for c in _ALL_CAPS if bits & _CAP_BIT[c]]
416
+
417
+
418
  def _slug(s: str) -> str:
419
  return re.sub(r"[^a-z0-9]+", "", str(s).strip().lower())
420
 
 
443
  size_bucket: int
444
  size_b: float # raw size in billions of params; NaN if unknown
445
  family_id: int
446
+ family: str
447
  popularity: int
448
  hf_url: str
449
 
 
747
  size_bucket=int(self.size_ids[i]),
748
  size_b=float(self.sizes_b[i]),
749
  family_id=int(self.family_ids[i]),
750
+ family=self._id2family.get(int(self.family_ids[i]), ""),
751
  popularity=int(self.popularities[i]),
752
  hf_url=self.urls[i],
753
  )