Tristan
HF staff
commited on
Commit
80f2297
1 Parent(s): 4dd611a

fixed cuttoff issue for wide leaderboards, made leaderboard data updating asynchronous, made streamlit set the url to match the selected dataset

Browse files
Files changed (2) hide show
  1. app.py +57 -52
  2. requirements.txt +2 -1
app.py CHANGED
@@ -1,4 +1,3 @@
1
- import requests
2
  import pandas as pd
3
  from tqdm.auto import tqdm
4
  import streamlit as st
@@ -6,17 +5,9 @@ from huggingface_hub import HfApi, hf_hub_download
6
  from huggingface_hub.repocard import metadata_load
7
  from ascending_metrics import ascending_metrics
8
  import numpy as np
9
-
10
-
11
- def make_clickable(model_name):
12
- link = "https://huggingface.co/" + model_name
13
- return f'<a target="_blank" href="{link}">{model_name}</a>'
14
-
15
- def make_bold(value):
16
- return f'<b>{value}</b>'
17
-
18
- def make_string(value):
19
- return str(value)
20
 
21
 
22
  def get_model_ids():
@@ -71,24 +62,42 @@ def parse_metrics_rows(meta):
71
  row[type] = value
72
  yield row
73
 
 
 
74
 
75
- @st.cache(ttl=86400)
76
- def get_data():
77
- data = []
78
- model_ids = get_model_ids()
79
- for model_id in tqdm(model_ids):
80
- meta = get_metadata(model_id)
81
- if meta is None:
82
- continue
83
- for row in parse_metrics_rows(meta):
84
- if row is None:
85
  continue
86
- row["model_id"] = model_id
87
- data.append(row)
88
- return pd.DataFrame.from_records(data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
-
91
- dataframe = get_data()
92
  selectable_datasets = list(set(dataframe.dataset.tolist()))
93
 
94
  st.markdown("# 🤗 Leaderboards")
@@ -104,19 +113,20 @@ dataset = st.sidebar.selectbox(
104
  selectable_datasets,
105
  index=selectable_datasets.index(default_dataset),
106
  )
 
107
 
108
  dataset_df = dataframe[dataframe.dataset == dataset]
109
  dataset_df = dataset_df.dropna(axis="columns", how="all")
110
 
111
  selectable_metrics = list(filter(lambda column: column not in ("model_id", "dataset"), dataset_df.columns))
112
- metric = st.sidebar.radio(
113
- "Sorting Metric",
114
  selectable_metrics,
115
  )
116
 
117
  dataset_df = dataset_df.filter(["model_id"] + selectable_metrics)
118
  dataset_df = dataset_df.dropna(thresh=2) # Want at least two non-na values (one for model_id and one for a metric).
119
- dataset_df = dataset_df.sort_values(by=metric, ascending=metric in ascending_metrics)
120
  dataset_df = dataset_df.replace(np.nan, '-')
121
 
122
  st.markdown(
@@ -127,30 +137,25 @@ st.markdown(
127
  "Want to beat the leaderboard? Don't see your model here? Simply request an automatic evaluation [here](https://huggingface.co/spaces/autoevaluate/autoevaluate)."
128
  )
129
 
130
- # display the model ranks
131
- dataset_df = dataset_df.reset_index(drop=True)
132
- dataset_df.index += 1
133
-
134
- # turn the model ids into clickable links
135
- dataset_df["model_id"] = dataset_df["model_id"].apply(make_clickable)
136
- dataset_df[metric] = dataset_df[metric].apply(make_bold)
137
- for other_metric in selectable_metrics:
138
- dataset_df[other_metric] = dataset_df[other_metric].apply(make_string)
139
-
140
- # Make the selected metric appear right after model names
141
  cols = dataset_df.columns.tolist()
142
- cols.remove(metric)
143
- cols = cols[:1] + [metric] + cols[1:]
144
  dataset_df = dataset_df[cols]
145
 
146
- # Highlight selected metric
147
- def highlight_cols(s):
148
- huggingface_yellow = "#FFD21E"
149
- return "background-color: %s" % huggingface_yellow
 
 
 
 
150
 
151
- dataset_df = dataset_df.style.applymap(highlight_cols, subset=pd.IndexSlice[metric])
 
 
 
152
 
153
- # Turn table into html
154
- table_html = dataset_df.to_html(escape=False)
155
- table_html = table_html.replace("<th>", '<th align="left">') # left-align the headers
156
- st.write(table_html, unsafe_allow_html=True)
 
1
  import pandas as pd
2
  from tqdm.auto import tqdm
3
  import streamlit as st
5
  from huggingface_hub.repocard import metadata_load
6
  from ascending_metrics import ascending_metrics
7
  import numpy as np
8
+ from st_aggrid import AgGrid, GridOptionsBuilder, JsCode
9
+ from os.path import exists
10
+ import threading
 
 
 
 
 
 
 
 
11
 
12
 
13
  def get_model_ids():
62
  row[type] = value
63
  yield row
64
 
65
+ @st.cache(ttl=3600)
66
+ def get_data_wrapper():
67
 
68
+ def get_data():
69
+ data = []
70
+ model_ids = get_model_ids()
71
+ for model_id in tqdm(model_ids):
72
+ meta = get_metadata(model_id)
73
+ if meta is None:
 
 
 
 
74
  continue
75
+ for row in parse_metrics_rows(meta):
76
+ if row is None:
77
+ continue
78
+ row["model_id"] = model_id
79
+ data.append(row)
80
+ dataframe = pd.DataFrame.from_records(data)
81
+ dataframe.to_pickle("cache.pkl")
82
+
83
+ if exists("cache.pkl"):
84
+ # If we have saved the results previously, call an asynchronous process
85
+ # to fetch the results and update the saved file. Don't make users wait
86
+ # while we fetch the new results. Instead, display the old results for
87
+ # now. The new results should be loaded when this method
88
+ # is called again.
89
+ dataframe = pd.read_pickle("cache.pkl")
90
+ t = threading.Thread(name='get_data procs', target=get_data)
91
+ t.start()
92
+ else:
93
+ # We have to make the users wait during the first startup of this app.
94
+ get_data()
95
+ dataframe = pd.read_pickle("cache.pkl")
96
+
97
+ return dataframe
98
+
99
+ dataframe = get_data_wrapper()
100
 
 
 
101
  selectable_datasets = list(set(dataframe.dataset.tolist()))
102
 
103
  st.markdown("# 🤗 Leaderboards")
113
  selectable_datasets,
114
  index=selectable_datasets.index(default_dataset),
115
  )
116
+ st.experimental_set_query_params(**{"dataset": [dataset]})
117
 
118
  dataset_df = dataframe[dataframe.dataset == dataset]
119
  dataset_df = dataset_df.dropna(axis="columns", how="all")
120
 
121
  selectable_metrics = list(filter(lambda column: column not in ("model_id", "dataset"), dataset_df.columns))
122
+ default_metric = st.sidebar.radio(
123
+ "Default Metric",
124
  selectable_metrics,
125
  )
126
 
127
  dataset_df = dataset_df.filter(["model_id"] + selectable_metrics)
128
  dataset_df = dataset_df.dropna(thresh=2) # Want at least two non-na values (one for model_id and one for a metric).
129
+ dataset_df = dataset_df.sort_values(by=default_metric, ascending=default_metric in ascending_metrics)
130
  dataset_df = dataset_df.replace(np.nan, '-')
131
 
132
  st.markdown(
137
  "Want to beat the leaderboard? Don't see your model here? Simply request an automatic evaluation [here](https://huggingface.co/spaces/autoevaluate/autoevaluate)."
138
  )
139
 
140
+ # Make the default metric appear right after model names
 
 
 
 
 
 
 
 
 
 
141
  cols = dataset_df.columns.tolist()
142
+ cols.remove(default_metric)
143
+ cols = cols[:1] + [default_metric] + cols[1:]
144
  dataset_df = dataset_df[cols]
145
 
146
+ # Make the leaderboard
147
+ gb = GridOptionsBuilder.from_dataframe(dataset_df)
148
+ gb.configure_column(
149
+ "model_id",
150
+ cellRenderer=JsCode('''function(params) {return '<a target="_blank" href="https://huggingface.co/'+params.value+'">'+params.value+'</a>'}'''),
151
+ )
152
+ for name in selectable_metrics:
153
+ gb.configure_column(name, type=["numericColumn","numberColumnFilter","customNumericFormat"], precision=2, aggFunc='sum')
154
 
155
+ gb.configure_column(
156
+ default_metric,
157
+ cellStyle=JsCode('''function(params) { return {'backgroundColor': '#FFD21E'}}''')
158
+ )
159
 
160
+ go = gb.build()
161
+ AgGrid(dataset_df, gridOptions=go, allow_unsafe_jscode=True, fit_columns_on_grid_load=True)
 
 
requirements.txt CHANGED
@@ -2,4 +2,5 @@ pandas
2
  tqdm
3
  streamlit
4
  huggingface_hub
5
- numpy
 
2
  tqdm
3
  streamlit
4
  huggingface_hub
5
+ numpy
6
+ streamlit-aggrid