evijit HF Staff commited on
Commit
59d14c6
·
verified ·
1 Parent(s): fb9f81e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -230
app.py CHANGED
@@ -1,21 +1,22 @@
1
- # --- START OF FIXED FILE app.py ---
2
-
3
  import gradio as gr
4
  import pandas as pd
5
  import plotly.express as px
6
  import time
7
- import json
8
  from datasets import load_dataset
 
 
9
 
10
  # --- Constants ---
11
  PARAM_CHOICES = ['< 1B', '1B', '5B', '12B', '32B', '64B', '128B', '256B', '> 500B']
12
- PARAM_CHOICES_DEFAULT_INDICES_JSON = json.dumps([0, len(PARAM_CHOICES) - 1])
 
13
 
14
  TOP_K_CHOICES = list(range(5, 51, 5))
15
  HF_DATASET_ID = "evijit/orgstats_daily_data"
16
  TAG_FILTER_CHOICES = [ "Audio & Speech", "Time series", "Robotics", "Music", "Video", "Images", "Text", "Biomedical", "Sciences" ]
17
  PIPELINE_TAGS = [ 'text-generation', 'text-to-image', 'text-classification', 'text2text-generation', 'audio-to-audio', 'feature-extraction', 'image-classification', 'translation', 'reinforcement-learning', 'fill-mask', 'text-to-speech', 'automatic-speech-recognition', 'image-text-to-text', 'token-classification', 'sentence-similarity', 'question-answering', 'image-feature-extraction', 'summarization', 'zero-shot-image-classification', 'object-detection', 'image-segmentation', 'image-to-image', 'image-to-text', 'audio-classification', 'visual-question-answering', 'text-to-video', 'zero-shot-classification', 'depth-estimation', 'text-ranking', 'image-to-video', 'multiple-choice', 'unconditional-image-generation', 'video-classification', 'text-to-audio', 'time-series-forecasting', 'any-to-any', 'video-text-to-text', 'table-question-answering' ]
18
 
 
19
  def load_models_data():
20
  overall_start_time = time.time()
21
  print(f"Attempting to load dataset from Hugging Face Hub: {HF_DATASET_ID}")
@@ -75,226 +76,49 @@ def create_treemap(treemap_data, count_by, title=None):
75
  fig.update_traces(textinfo="label+value+percent root", hovertemplate="<b>%{label}</b><br>%{value:,} " + count_by + "<br>%{percentRoot:.2%} of total<extra></extra>")
76
  return fig
77
 
78
- # Custom head with noUiSlider CSS and JS
79
- custom_head = """
80
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.css">
81
- <script src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.js"></script>
82
- """
83
-
84
- # JavaScript for creating the slider - this will be injected properly
85
- def create_slider_js():
86
- return f"""
87
- function initializeSlider() {{
88
- const paramChoices = {json.dumps(PARAM_CHOICES)};
89
- const sliderContainer = document.getElementById('param-slider');
90
- const hiddenInput = document.querySelector('#param-range-hidden input');
91
-
92
- if (!sliderContainer || !hiddenInput) {{
93
- console.log('Slider elements not found, retrying...');
94
- setTimeout(initializeSlider, 100);
95
- return;
96
- }}
97
-
98
- // Clear any existing slider
99
- if (sliderContainer.noUiSlider) {{
100
- sliderContainer.noUiSlider.destroy();
101
- }}
102
-
103
- // Create the slider
104
- noUiSlider.create(sliderContainer, {{
105
- start: [0, paramChoices.length - 1],
106
- connect: true,
107
- step: 1,
108
- range: {{
109
- 'min': 0,
110
- 'max': paramChoices.length - 1
111
- }},
112
- pips: {{
113
- mode: 'values',
114
- values: Array.from({{length: paramChoices.length}}, (_, i) => i),
115
- density: 100 / (paramChoices.length - 1),
116
- format: {{
117
- to: function(value) {{
118
- return paramChoices[Math.round(value)];
119
- }}
120
- }}
121
- }}
122
- }});
123
-
124
- // Update hidden input when slider changes
125
- sliderContainer.noUiSlider.on('update', function(values) {{
126
- const indices = values.map(v => Math.round(parseFloat(v)));
127
- hiddenInput.value = JSON.stringify(indices);
128
- hiddenInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
129
-
130
- // Highlight selected range
131
- document.querySelectorAll('.noUi-value').forEach((pip, index) => {{
132
- const isSelected = index >= indices[0] && index <= indices[1];
133
- pip.style.fontWeight = isSelected ? 'bold' : 'normal';
134
- pip.style.color = isSelected ? '#2563eb' : '#6b7280';
135
- }});
136
- }});
137
-
138
- // Initial highlight
139
- document.querySelectorAll('.noUi-value').forEach((pip, index) => {{
140
- const isSelected = index >= 0 && index <= paramChoices.length - 1;
141
- pip.style.fontWeight = isSelected ? 'bold' : 'normal';
142
- pip.style.color = isSelected ? '#2563eb' : '#6b7280';
143
- }});
144
-
145
- console.log('Slider initialized successfully');
146
- }}
147
-
148
- // Initialize when DOM is ready
149
- if (document.readyState === 'loading') {{
150
- document.addEventListener('DOMContentLoaded', initializeSlider);
151
- }} else {{
152
- initializeSlider();
153
- }}
154
- """
155
-
156
- with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True, head=custom_head) as demo:
157
  models_data_state = gr.State(pd.DataFrame())
158
  loading_complete_state = gr.State(False)
159
 
160
  with gr.Row():
161
  with gr.Column(scale=1):
162
- count_by_dropdown = gr.Dropdown(
163
- label="Metric",
164
- choices=[("Downloads (last 30 days)", "downloads"), ("Downloads (All Time)", "downloadsAllTime"), ("Likes", "likes")],
165
- value="downloads"
166
- )
167
-
168
- filter_choice_radio = gr.Radio(
169
- label="Filter Type",
170
- choices=["None", "Tag Filter", "Pipeline Filter"],
171
- value="None"
172
- )
173
 
174
- tag_filter_dropdown = gr.Dropdown(
175
- label="Select Tag",
176
- choices=TAG_FILTER_CHOICES,
177
- value=None,
178
- visible=False
179
- )
180
-
181
- pipeline_filter_dropdown = gr.Dropdown(
182
- label="Select Pipeline Tag",
183
- choices=PIPELINE_TAGS,
184
- value=None,
185
- visible=False
186
- )
187
-
188
- # Parameter range slider section
189
- with gr.Group():
190
- gr.Markdown("### Parameters")
191
-
192
- # Custom HTML for the slider
193
- gr.HTML(f"""
194
- <div id="param-slider" style="margin: 20px 10px 60px 10px; height: 20px;"></div>
195
- <style>
196
- #param-slider {{
197
- height: 20px;
198
- }}
199
- .noUi-target {{
200
- background: #f1f5f9;
201
- border-radius: 10px;
202
- border: 1px solid #e2e8f0;
203
- box-shadow: none;
204
- }}
205
- .noUi-connect {{
206
- background: #3b82f6;
207
- border-radius: 10px;
208
- }}
209
- .noUi-handle {{
210
- width: 20px;
211
- height: 20px;
212
- right: -10px;
213
- top: -5px;
214
- background: white;
215
- border: 2px solid #3b82f6;
216
- border-radius: 50%;
217
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
218
- cursor: pointer;
219
- }}
220
- .noUi-handle:before,
221
- .noUi-handle:after {{
222
- display: none;
223
- }}
224
- .noUi-handle:focus {{
225
- outline: none;
226
- }}
227
- .noUi-pips {{
228
- color: #6b7280;
229
- font-size: 12px;
230
- }}
231
- .noUi-pips-horizontal {{
232
- padding: 10px 0;
233
- height: 60px;
234
- }}
235
- .noUi-value {{
236
- font-size: 11px;
237
- padding-top: 5px;
238
- cursor: pointer;
239
- }}
240
- .noUi-marker-horizontal.noUi-marker {{
241
- background: #e2e8f0;
242
- height: 5px;
243
- width: 1px;
244
- }}
245
- </style>
246
- """)
247
-
248
- # Hidden input to store slider values
249
- param_range_hidden = gr.Textbox(
250
- value=PARAM_CHOICES_DEFAULT_INDICES_JSON,
251
- visible=False,
252
- elem_id="param-range-hidden"
253
- )
254
-
255
- top_k_dropdown = gr.Dropdown(
256
- label="Number of Top Organizations",
257
- choices=TOP_K_CHOICES,
258
- value=25
259
- )
260
-
261
- skip_orgs_textbox = gr.Textbox(
262
- label="Organizations to Skip (comma-separated)",
263
- value="TheBloke,MaziyarPanahi,unsloth,modularai,Gensyn,bartowski"
264
- )
265
-
266
- generate_plot_button = gr.Button(
267
- value="Generate Plot",
268
- variant="primary",
269
- interactive=False
270
  )
 
 
 
 
 
 
271
 
272
  with gr.Column(scale=3):
273
  plot_output = gr.Plot()
274
  status_message_md = gr.Markdown("Initializing...")
275
  data_info_md = gr.Markdown("")
276
-
277
- # Event handlers
278
- def _update_button_interactivity(is_loaded_flag):
279
- return gr.update(interactive=is_loaded_flag)
280
 
281
- loading_complete_state.change(
282
- fn=_update_button_interactivity,
283
- inputs=loading_complete_state,
284
- outputs=generate_plot_button
285
- )
286
-
287
- def _toggle_filters_visibility(choice):
288
- return (
289
- gr.update(visible=choice == "Tag Filter"),
290
- gr.update(visible=choice == "Pipeline Filter")
291
- )
292
 
293
- filter_choice_radio.change(
294
- fn=_toggle_filters_visibility,
295
- inputs=filter_choice_radio,
296
- outputs=[tag_filter_dropdown, pipeline_filter_dropdown]
297
- )
 
 
298
 
299
  def ui_load_data_controller(progress=gr.Progress()):
300
  progress(0, desc=f"Loading dataset '{HF_DATASET_ID}'...")
@@ -320,7 +144,7 @@ with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True, head=custom_he
320
  return current_df, load_success_flag, data_info_text, status_msg_ui
321
 
322
  def ui_generate_plot_controller(metric_choice, filter_type, tag_choice, pipeline_choice,
323
- param_range_json, k_orgs, skip_orgs_input, df_current_models, progress=gr.Progress()):
324
  if df_current_models is None or df_current_models.empty:
325
  return create_treemap(pd.DataFrame(), metric_choice, "Error: Model Data Not Loaded"), "Model data is not loaded."
326
 
@@ -329,11 +153,6 @@ with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True, head=custom_he
329
  pipeline_to_use = pipeline_choice if filter_type == "Pipeline Filter" else None
330
  orgs_to_skip = [org.strip() for org in skip_orgs_input.split(',') if org.strip()]
331
 
332
- try:
333
- param_range_indices = json.loads(param_range_json)
334
- except:
335
- param_range_indices = [0, len(PARAM_CHOICES) - 1]
336
-
337
  min_label = PARAM_CHOICES[int(param_range_indices[0])]
338
  max_label = PARAM_CHOICES[int(param_range_indices[1])]
339
  param_labels_for_filtering = [min_label, max_label]
@@ -349,35 +168,25 @@ with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True, head=custom_he
349
  plot_stats_md = "No data matches the selected filters. Please try different options."
350
  else:
351
  total_items_in_plot = len(treemap_df['id'].unique())
 
352
  total_value_in_plot = treemap_df[metric_choice].sum()
353
  plot_stats_md = f"## Plot Statistics\n- **Models shown**: {total_items_in_plot:,}\n- **Total {metric_choice}**: {int(total_value_in_plot):,}"
354
  return plotly_fig, plot_stats_md
355
 
356
- # Load data on startup and initialize slider
357
  demo.load(
358
  fn=ui_load_data_controller,
359
  inputs=[],
360
  outputs=[models_data_state, loading_complete_state, data_info_md, status_message_md]
361
  )
362
-
363
- # Initialize slider after page loads
364
- demo.load(
365
- fn=lambda: None,
366
- inputs=[],
367
- outputs=[],
368
- js=create_slider_js()
369
- )
370
 
371
- # Generate plot button click handler
372
  generate_plot_button.click(
373
  fn=ui_generate_plot_controller,
374
  inputs=[count_by_dropdown, filter_choice_radio, tag_filter_dropdown, pipeline_filter_dropdown,
375
- param_range_hidden, top_k_dropdown, skip_orgs_textbox, models_data_state],
376
  outputs=[plot_output, status_message_md]
377
  )
378
 
379
  if __name__ == "__main__":
380
  print(f"Application starting...")
381
- demo.queue().launch()
382
-
383
- # --- END OF FIXED FILE
 
 
 
1
  import gradio as gr
2
  import pandas as pd
3
  import plotly.express as px
4
  import time
 
5
  from datasets import load_dataset
6
+ # --- FIX 1: Import the new, stable RangeSlider component ---
7
+ from gradio_rangeslider import RangeSlider
8
 
9
  # --- Constants ---
10
  PARAM_CHOICES = ['< 1B', '1B', '5B', '12B', '32B', '64B', '128B', '256B', '> 500B']
11
+ # The new component uses a tuple for its default value
12
+ PARAM_CHOICES_DEFAULT_INDICES = (0, len(PARAM_CHOICES) - 1)
13
 
14
  TOP_K_CHOICES = list(range(5, 51, 5))
15
  HF_DATASET_ID = "evijit/orgstats_daily_data"
16
  TAG_FILTER_CHOICES = [ "Audio & Speech", "Time series", "Robotics", "Music", "Video", "Images", "Text", "Biomedical", "Sciences" ]
17
  PIPELINE_TAGS = [ 'text-generation', 'text-to-image', 'text-classification', 'text2text-generation', 'audio-to-audio', 'feature-extraction', 'image-classification', 'translation', 'reinforcement-learning', 'fill-mask', 'text-to-speech', 'automatic-speech-recognition', 'image-text-to-text', 'token-classification', 'sentence-similarity', 'question-answering', 'image-feature-extraction', 'summarization', 'zero-shot-image-classification', 'object-detection', 'image-segmentation', 'image-to-image', 'image-to-text', 'audio-classification', 'visual-question-answering', 'text-to-video', 'zero-shot-classification', 'depth-estimation', 'text-ranking', 'image-to-video', 'multiple-choice', 'unconditional-image-generation', 'video-classification', 'text-to-audio', 'time-series-forecasting', 'any-to-any', 'video-text-to-text', 'table-question-answering' ]
18
 
19
+
20
  def load_models_data():
21
  overall_start_time = time.time()
22
  print(f"Attempting to load dataset from Hugging Face Hub: {HF_DATASET_ID}")
 
76
  fig.update_traces(textinfo="label+value+percent root", hovertemplate="<b>%{label}</b><br>%{value:,} " + count_by + "<br>%{percentRoot:.2%} of total<extra></extra>")
77
  return fig
78
 
79
+ with gr.Blocks(title="🤗 ModelVerse Explorer", fill_width=True) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  models_data_state = gr.State(pd.DataFrame())
81
  loading_complete_state = gr.State(False)
82
 
83
  with gr.Row():
84
  with gr.Column(scale=1):
85
+ count_by_dropdown = gr.Dropdown(label="Metric", choices=[("Downloads (last 30 days)", "downloads"), ("Downloads (All Time)", "downloadsAllTime"), ("Likes", "likes")], value="downloads")
86
+ filter_choice_radio = gr.Radio(label="Filter Type", choices=["None", "Tag Filter", "Pipeline Filter"], value="None")
87
+ tag_filter_dropdown = gr.Dropdown(label="Select Tag", choices=TAG_FILTER_CHOICES, value=None, visible=False)
88
+ pipeline_filter_dropdown = gr.Dropdown(label="Select Pipeline Tag", choices=PIPELINE_TAGS, value=None, visible=False)
 
 
 
 
 
 
 
89
 
90
+ # --- FIX 2: Replace all previous slider attempts with the stable custom component ---
91
+ param_range_slider = RangeSlider(
92
+ minimum=0,
93
+ maximum=len(PARAM_CHOICES) - 1,
94
+ value=PARAM_CHOICES_DEFAULT_INDICES,
95
+ step=1,
96
+ label="Parameters"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  )
98
+ # This markdown will display the selected range labels
99
+ param_range_display = gr.Markdown(f"Range: `{PARAM_CHOICES[0]}` to `{PARAM_CHOICES[-1]}`")
100
+
101
+ top_k_dropdown = gr.Dropdown(label="Number of Top Organizations", choices=TOP_K_CHOICES, value=25)
102
+ skip_orgs_textbox = gr.Textbox(label="Organizations to Skip (comma-separated)", value="TheBloke,MaziyarPanahi,unsloth,modularai,Gensyn,bartowski")
103
+ generate_plot_button = gr.Button(value="Generate Plot", variant="primary", interactive=False)
104
 
105
  with gr.Column(scale=3):
106
  plot_output = gr.Plot()
107
  status_message_md = gr.Markdown("Initializing...")
108
  data_info_md = gr.Markdown("")
 
 
 
 
109
 
110
+ # Event handler to update the text display when the slider changes
111
+ def update_param_display(value: tuple):
112
+ min_idx, max_idx = int(value[0]), int(value[1])
113
+ return f"Range: `{PARAM_CHOICES[min_idx]}` to `{PARAM_CHOICES[max_idx]}`"
 
 
 
 
 
 
 
114
 
115
+ param_range_slider.change(update_param_display, param_range_slider, param_range_display)
116
+
117
+ def _update_button_interactivity(is_loaded_flag): return gr.update(interactive=is_loaded_flag)
118
+ loading_complete_state.change(fn=_update_button_interactivity, inputs=loading_complete_state, outputs=generate_plot_button)
119
+
120
+ def _toggle_filters_visibility(choice): return gr.update(visible=choice == "Tag Filter"), gr.update(visible=choice == "Pipeline Filter")
121
+ filter_choice_radio.change(fn=_toggle_filters_visibility, inputs=filter_choice_radio, outputs=[tag_filter_dropdown, pipeline_filter_dropdown])
122
 
123
  def ui_load_data_controller(progress=gr.Progress()):
124
  progress(0, desc=f"Loading dataset '{HF_DATASET_ID}'...")
 
144
  return current_df, load_success_flag, data_info_text, status_msg_ui
145
 
146
  def ui_generate_plot_controller(metric_choice, filter_type, tag_choice, pipeline_choice,
147
+ param_range_indices, k_orgs, skip_orgs_input, df_current_models, progress=gr.Progress()):
148
  if df_current_models is None or df_current_models.empty:
149
  return create_treemap(pd.DataFrame(), metric_choice, "Error: Model Data Not Loaded"), "Model data is not loaded."
150
 
 
153
  pipeline_to_use = pipeline_choice if filter_type == "Pipeline Filter" else None
154
  orgs_to_skip = [org.strip() for org in skip_orgs_input.split(',') if org.strip()]
155
 
 
 
 
 
 
156
  min_label = PARAM_CHOICES[int(param_range_indices[0])]
157
  max_label = PARAM_CHOICES[int(param_range_indices[1])]
158
  param_labels_for_filtering = [min_label, max_label]
 
168
  plot_stats_md = "No data matches the selected filters. Please try different options."
169
  else:
170
  total_items_in_plot = len(treemap_df['id'].unique())
171
+ # --- FIX 3: Corrected the NameError from the traceback ---
172
  total_value_in_plot = treemap_df[metric_choice].sum()
173
  plot_stats_md = f"## Plot Statistics\n- **Models shown**: {total_items_in_plot:,}\n- **Total {metric_choice}**: {int(total_value_in_plot):,}"
174
  return plotly_fig, plot_stats_md
175
 
176
+ # A standard load event, no JS needed anymore.
177
  demo.load(
178
  fn=ui_load_data_controller,
179
  inputs=[],
180
  outputs=[models_data_state, loading_complete_state, data_info_md, status_message_md]
181
  )
 
 
 
 
 
 
 
 
182
 
 
183
  generate_plot_button.click(
184
  fn=ui_generate_plot_controller,
185
  inputs=[count_by_dropdown, filter_choice_radio, tag_filter_dropdown, pipeline_filter_dropdown,
186
+ param_range_slider, top_k_dropdown, skip_orgs_textbox, models_data_state],
187
  outputs=[plot_output, status_message_md]
188
  )
189
 
190
  if __name__ == "__main__":
191
  print(f"Application starting...")
192
+ demo.queue().launch()