macadeliccc commited on
Commit
b795615
·
1 Parent(s): 997c4e5

added support for datasets with a toggle

Browse files
Files changed (1) hide show
  1. app.py +59 -44
app.py CHANGED
@@ -4,19 +4,18 @@ import pandas as pd
4
  import numpy as np
5
  import requests
6
  from datetime import datetime
7
- from typing import Dict, List, Optional
8
 
9
 
10
  class HFDownloadsCalculator:
11
-
12
  BASE_URL = "https://huggingface.co/api"
13
 
14
  def __init__(self, token: Optional[str] = None):
15
  self.headers = {"Authorization": f"Bearer {token}"} if token else {}
16
 
17
- def get_user_models_with_all_time_downloads(self, username: str) -> List[Dict]:
18
  response = requests.get(
19
- f"{self.BASE_URL}/models",
20
  params={
21
  "author": username,
22
  "limit": 1000,
@@ -27,36 +26,37 @@ class HFDownloadsCalculator:
27
  response.raise_for_status()
28
  return response.json()
29
 
30
- def calculate_total_downloads(self, username: str) -> Dict:
31
- models = self.get_user_models_with_all_time_downloads(username)
32
 
33
  total_all_time = 0
34
  total_monthly = 0
35
- model_stats = []
36
 
37
- for model in models:
38
- model_id = model.get("modelId") or model.get("id") or model.get("_id", "unknown")
39
- all_time = model.get("downloadsAllTime", 0)
40
- monthly = model.get("downloads", 0)
41
 
42
  total_all_time += all_time
43
  total_monthly += monthly
44
 
45
  if all_time > 0:
46
- model_stats.append({
47
- "name": model_id,
48
  "downloads_all_time": all_time,
49
  "downloads_monthly": monthly
50
  })
51
 
52
- model_stats.sort(key=lambda x: x["downloads_all_time"], reverse=True)
53
 
54
  return {
55
  "total_downloads_all_time": total_all_time,
56
  "total_downloads_monthly": total_monthly,
57
- "model_count": len(models),
58
- "models_with_downloads": len(model_stats),
59
- "top_models": model_stats
 
60
  }
61
 
62
 
@@ -64,8 +64,8 @@ class HFDashboard:
64
  def __init__(self):
65
  self.calculator = HFDownloadsCalculator()
66
 
67
- def get_model_timeseries(self, model_id: str, days: int = 30) -> pd.DataFrame:
68
- response = requests.get(f"https://huggingface.co/api/models/{model_id}")
69
  data = response.json()
70
 
71
  avg_daily = data.get('downloads', 0) / 30
@@ -78,12 +78,13 @@ class HFDashboard:
78
  'downloads': daily_downloads
79
  })
80
 
81
- def create_dashboard(self, username: str):
82
  if not username:
83
  return None, None, None, "Please enter a username"
84
 
85
  try:
86
- stats = self.calculator.calculate_total_downloads(username)
 
87
 
88
  # Metrics HTML
89
  metrics_html = f"""
@@ -97,8 +98,8 @@ class HFDashboard:
97
  <p style="margin: 5px 0; color: #a8a8b8;">Monthly Downloads</p>
98
  </div>
99
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #1e1e2e 0%, #2d2d44 100%); border-radius: 10px; flex: 1; margin: 0 10px; border: 1px solid #3d3d5c;">
100
- <h2 style="margin: 0; color: #fff;">{stats['model_count']}</h2>
101
- <p style="margin: 5px 0; color: #a8a8b8;">Total Models</p>
102
  </div>
103
  </div>
104
  """
@@ -108,15 +109,15 @@ class HFDashboard:
108
  colors = ['#6366f1', '#10b981', '#f59e0b', '#ef4444', '#00b4d8']
109
  colors_rgba = [f'rgba({int(c[1:3],16)}, {int(c[3:5],16)}, {int(c[5:7],16)}, 0.1)' for c in colors]
110
 
111
- for i, model in enumerate(stats['top_models'][:5]):
112
- ts_data = self.get_model_timeseries(model['name'])
113
  color_idx = i % len(colors)
114
 
115
  fig_line.add_trace(go.Scatter(
116
  x=ts_data['date'],
117
  y=ts_data['downloads'],
118
  mode='lines',
119
- name=model['name'].split('/')[-1],
120
  line=dict(color=colors[color_idx], width=3),
121
  hovertemplate='%{y} downloads<br>%{x|%b %d}',
122
  fill='tozeroy',
@@ -125,7 +126,7 @@ class HFDashboard:
125
 
126
  fig_line.update_layout(
127
  height=400,
128
- title=dict(text="Top 5 Models - Daily Download Trends", font=dict(size=18), x=0.5, xanchor='center'),
129
  xaxis_title="Date",
130
  yaxis_title="Daily Downloads",
131
  hovermode='x unified',
@@ -141,7 +142,7 @@ class HFDashboard:
141
 
142
  # Bar chart for download distribution
143
  fig_bar = go.Figure()
144
- top_10 = stats['top_models'][:10]
145
 
146
  fig_bar.add_trace(go.Bar(
147
  x=[m['name'].split('/')[-1] for m in top_10],
@@ -161,8 +162,8 @@ class HFDashboard:
161
 
162
  fig_bar.update_layout(
163
  height=400,
164
- title=dict(text="Top 10 Models - Download Distribution", font=dict(size=18), x=0.5, xanchor='center'),
165
- xaxis_title="Model",
166
  yaxis_title="Downloads",
167
  barmode='group',
168
  template='plotly_dark',
@@ -180,13 +181,13 @@ class HFDashboard:
180
  # Create table
181
  df = pd.DataFrame([
182
  [
183
- model['name'],
184
- f"{model['downloads_all_time']:,}",
185
- f"{model['downloads_monthly']:,}",
186
- f"{(model['downloads_monthly'] / model['downloads_all_time'] * 100):.1f}%" if model['downloads_all_time'] > 0 else "0%"
187
  ]
188
- for model in stats['top_models']
189
- ], columns=["Model", "All-Time Downloads", "Monthly Downloads", "Monthly %"])
190
 
191
  return metrics_html, fig_line, fig_bar, df
192
 
@@ -207,37 +208,51 @@ def main():
207
  )
208
  ) as app:
209
  gr.Markdown("# 🤗 HuggingFace Downloads Dashboard")
210
- gr.Markdown("Track your model downloads and visualize trends over time")
211
 
212
  with gr.Row():
213
- with gr.Column():
214
  username_input = gr.Textbox(
215
  label="HuggingFace Username",
216
  placeholder="Enter username (e.g., macadeliccc)",
217
  value="macadeliccc"
218
  )
219
  refresh_btn = gr.Button("Load Dashboard", variant="primary", size="lg")
 
 
 
 
 
 
 
 
220
 
221
  metrics_display = gr.HTML()
222
  line_plot = gr.Plot()
223
  bar_plot = gr.Plot()
224
  table_output = gr.Dataframe(
225
- headers=["Model", "All-Time Downloads", "Monthly Downloads", "Monthly %"],
226
- label="All Models with Downloads"
227
  )
228
 
229
- def update_dashboard(username):
230
- return dashboard.create_dashboard(username)
231
 
232
  refresh_btn.click(
233
  fn=update_dashboard,
234
- inputs=[username_input],
 
 
 
 
 
 
235
  outputs=[metrics_display, line_plot, bar_plot, table_output]
236
  )
237
 
238
  app.load(
239
  fn=update_dashboard,
240
- inputs=[username_input],
241
  outputs=[metrics_display, line_plot, bar_plot, table_output]
242
  )
243
 
 
4
  import numpy as np
5
  import requests
6
  from datetime import datetime
7
+ from typing import Dict, List, Optional, Literal
8
 
9
 
10
  class HFDownloadsCalculator:
 
11
  BASE_URL = "https://huggingface.co/api"
12
 
13
  def __init__(self, token: Optional[str] = None):
14
  self.headers = {"Authorization": f"Bearer {token}"} if token else {}
15
 
16
+ def get_user_items(self, username: str, item_type: Literal["models", "datasets"]) -> List[Dict]:
17
  response = requests.get(
18
+ f"{self.BASE_URL}/{item_type}",
19
  params={
20
  "author": username,
21
  "limit": 1000,
 
26
  response.raise_for_status()
27
  return response.json()
28
 
29
+ def calculate_total_downloads(self, username: str, item_type: Literal["models", "datasets"]) -> Dict:
30
+ items = self.get_user_items(username, item_type)
31
 
32
  total_all_time = 0
33
  total_monthly = 0
34
+ item_stats = []
35
 
36
+ for item in items:
37
+ item_id = item.get(f"{item_type[:-1]}Id") or item.get("id") or item.get("_id", "unknown")
38
+ all_time = item.get("downloadsAllTime", 0)
39
+ monthly = item.get("downloads", 0)
40
 
41
  total_all_time += all_time
42
  total_monthly += monthly
43
 
44
  if all_time > 0:
45
+ item_stats.append({
46
+ "name": item_id,
47
  "downloads_all_time": all_time,
48
  "downloads_monthly": monthly
49
  })
50
 
51
+ item_stats.sort(key=lambda x: x["downloads_all_time"], reverse=True)
52
 
53
  return {
54
  "total_downloads_all_time": total_all_time,
55
  "total_downloads_monthly": total_monthly,
56
+ "item_count": len(items),
57
+ "items_with_downloads": len(item_stats),
58
+ "top_items": item_stats,
59
+ "item_type": item_type
60
  }
61
 
62
 
 
64
  def __init__(self):
65
  self.calculator = HFDownloadsCalculator()
66
 
67
+ def get_item_timeseries(self, item_id: str, item_type: str, days: int = 30) -> pd.DataFrame:
68
+ response = requests.get(f"https://huggingface.co/api/{item_type}/{item_id}")
69
  data = response.json()
70
 
71
  avg_daily = data.get('downloads', 0) / 30
 
78
  'downloads': daily_downloads
79
  })
80
 
81
+ def create_dashboard(self, username: str, item_type: str):
82
  if not username:
83
  return None, None, None, "Please enter a username"
84
 
85
  try:
86
+ stats = self.calculator.calculate_total_downloads(username, item_type)
87
+ type_label = item_type.capitalize()
88
 
89
  # Metrics HTML
90
  metrics_html = f"""
 
98
  <p style="margin: 5px 0; color: #a8a8b8;">Monthly Downloads</p>
99
  </div>
100
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #1e1e2e 0%, #2d2d44 100%); border-radius: 10px; flex: 1; margin: 0 10px; border: 1px solid #3d3d5c;">
101
+ <h2 style="margin: 0; color: #fff;">{stats['item_count']}</h2>
102
+ <p style="margin: 5px 0; color: #a8a8b8;">Total {type_label}</p>
103
  </div>
104
  </div>
105
  """
 
109
  colors = ['#6366f1', '#10b981', '#f59e0b', '#ef4444', '#00b4d8']
110
  colors_rgba = [f'rgba({int(c[1:3],16)}, {int(c[3:5],16)}, {int(c[5:7],16)}, 0.1)' for c in colors]
111
 
112
+ for i, item in enumerate(stats['top_items'][:5]):
113
+ ts_data = self.get_item_timeseries(item['name'], item_type)
114
  color_idx = i % len(colors)
115
 
116
  fig_line.add_trace(go.Scatter(
117
  x=ts_data['date'],
118
  y=ts_data['downloads'],
119
  mode='lines',
120
+ name=item['name'].split('/')[-1],
121
  line=dict(color=colors[color_idx], width=3),
122
  hovertemplate='%{y} downloads<br>%{x|%b %d}',
123
  fill='tozeroy',
 
126
 
127
  fig_line.update_layout(
128
  height=400,
129
+ title=dict(text=f"Top 5 {type_label} - Daily Download Trends", font=dict(size=18), x=0.5, xanchor='center'),
130
  xaxis_title="Date",
131
  yaxis_title="Daily Downloads",
132
  hovermode='x unified',
 
142
 
143
  # Bar chart for download distribution
144
  fig_bar = go.Figure()
145
+ top_10 = stats['top_items'][:10]
146
 
147
  fig_bar.add_trace(go.Bar(
148
  x=[m['name'].split('/')[-1] for m in top_10],
 
162
 
163
  fig_bar.update_layout(
164
  height=400,
165
+ title=dict(text=f"Top 10 {type_label} - Download Distribution", font=dict(size=18), x=0.5, xanchor='center'),
166
+ xaxis_title=type_label[:-1],
167
  yaxis_title="Downloads",
168
  barmode='group',
169
  template='plotly_dark',
 
181
  # Create table
182
  df = pd.DataFrame([
183
  [
184
+ item['name'],
185
+ f"{item['downloads_all_time']:,}",
186
+ f"{item['downloads_monthly']:,}",
187
+ f"{(item['downloads_monthly'] / item['downloads_all_time'] * 100):.1f}%" if item['downloads_all_time'] > 0 else "0%"
188
  ]
189
+ for item in stats['top_items']
190
+ ], columns=[type_label[:-1], "All-Time Downloads", "Monthly Downloads", "Monthly %"])
191
 
192
  return metrics_html, fig_line, fig_bar, df
193
 
 
208
  )
209
  ) as app:
210
  gr.Markdown("# 🤗 HuggingFace Downloads Dashboard")
211
+ gr.Markdown("Track your model and dataset downloads and visualize trends over time")
212
 
213
  with gr.Row():
214
+ with gr.Column(scale=3):
215
  username_input = gr.Textbox(
216
  label="HuggingFace Username",
217
  placeholder="Enter username (e.g., macadeliccc)",
218
  value="macadeliccc"
219
  )
220
  refresh_btn = gr.Button("Load Dashboard", variant="primary", size="lg")
221
+
222
+ with gr.Column(scale=1):
223
+ type_selector = gr.Radio(
224
+ ["models", "datasets"],
225
+ value="models",
226
+ label="Select Type",
227
+ info="Choose between models or datasets"
228
+ )
229
 
230
  metrics_display = gr.HTML()
231
  line_plot = gr.Plot()
232
  bar_plot = gr.Plot()
233
  table_output = gr.Dataframe(
234
+ headers=["Item", "All-Time Downloads", "Monthly Downloads", "Monthly %"],
235
+ label="All Items with Downloads"
236
  )
237
 
238
+ def update_dashboard(username, item_type):
239
+ return dashboard.create_dashboard(username, item_type)
240
 
241
  refresh_btn.click(
242
  fn=update_dashboard,
243
+ inputs=[username_input, type_selector],
244
+ outputs=[metrics_display, line_plot, bar_plot, table_output]
245
+ )
246
+
247
+ type_selector.change(
248
+ fn=update_dashboard,
249
+ inputs=[username_input, type_selector],
250
  outputs=[metrics_display, line_plot, bar_plot, table_output]
251
  )
252
 
253
  app.load(
254
  fn=update_dashboard,
255
+ inputs=[username_input, type_selector],
256
  outputs=[metrics_display, line_plot, bar_plot, table_output]
257
  )
258