innocent-charles commited on
Commit
4cdf136
·
verified ·
1 Parent(s): e2a22a0

Create streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +345 -0
streamlit_app.py ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import re
3
+ from collections.abc import Iterable
4
+
5
+ import pandas as pd
6
+ import streamlit as st
7
+ from pandas.api.types import is_bool_dtype, is_datetime64_any_dtype, is_numeric_dtype
8
+
9
+ GITHUB_URL = "https://github.com/msamwelmollel/Swahili_LLM_Leaderboard"
10
+ NON_BENCHMARK_COLS = ["Open?", "Publisher"]
11
+
12
+
13
+ def extract_table_and_format_from_markdown_text(markdown_table: str) -> pd.DataFrame:
14
+ """Extracts a table from a markdown text and formats it as a pandas DataFrame.
15
+
16
+ Args:
17
+ text (str): Markdown text containing a table.
18
+
19
+ Returns:
20
+ pd.DataFrame: Table as pandas DataFrame.
21
+ """
22
+ df = (
23
+ pd.read_table(io.StringIO(markdown_table), sep="|", header=0, index_col=1)
24
+ .dropna(axis=1, how="all") # drop empty columns
25
+ .iloc[1:] # drop first row which is the "----" separator of the original markdown table
26
+ .sort_index(ascending=True)
27
+ .apply(lambda x: x.str.strip() if x.dtype == "object" else x)
28
+ .replace("", float("NaN"))
29
+ .astype(float, errors="ignore")
30
+ )
31
+
32
+ # remove whitespace from column names and index
33
+ df.columns = df.columns.str.strip()
34
+ df.index = df.index.str.strip()
35
+ df.index.name = df.index.name.strip()
36
+
37
+ return df
38
+
39
+
40
+ def extract_markdown_table_from_multiline(multiline: str, table_headline: str, next_headline_start: str = "#") -> str:
41
+ """Extracts the markdown table from a multiline string.
42
+
43
+ Args:
44
+ multiline (str): content of README.md file.
45
+ table_headline (str): Headline of the table in the README.md file.
46
+ next_headline_start (str, optional): Start of the next headline. Defaults to "#".
47
+
48
+ Returns:
49
+ str: Markdown table.
50
+
51
+ Raises:
52
+ ValueError: If the table could not be found.
53
+ """
54
+ # extract everything between the table headline and the next headline
55
+ table = []
56
+ start = False
57
+ for line in multiline.split("\n"):
58
+ if line.startswith(table_headline):
59
+ start = True
60
+ elif line.startswith(next_headline_start):
61
+ start = False
62
+ elif start:
63
+ table.append(line + "\n")
64
+
65
+ if len(table) == 0:
66
+ raise ValueError(f"Could not find table with headline '{table_headline}'")
67
+
68
+ return "".join(table)
69
+
70
+
71
+ def remove_markdown_links(text: str) -> str:
72
+ """Modifies a markdown text to remove all markdown links.
73
+ Example: [DISPLAY](LINK) to DISPLAY
74
+ First find all markdown links with regex.
75
+ Then replace them with: $1
76
+ Args:
77
+ text (str): Markdown text containing markdown links
78
+ Returns:
79
+ str: Markdown text without markdown links.
80
+ """
81
+
82
+ # find all markdown links
83
+ markdown_links = re.findall(r"\[([^\]]+)\]\(([^)]+)\)", text)
84
+
85
+ # remove link keep display text
86
+ for display, link in markdown_links:
87
+ text = text.replace(f"[{display}]({link})", display)
88
+
89
+ return text
90
+
91
+
92
+ def filter_dataframe_by_row_and_columns(df: pd.DataFrame, ignore_columns: list[str] | None = None) -> pd.DataFrame:
93
+ """
94
+ Filter dataframe by the rows and columns to display.
95
+
96
+ This does not select based on the values in the dataframe, but rather on the index and columns.
97
+ Modified from https://blog.streamlit.io/auto-generate-a-dataframe-filtering-ui-in-streamlit-with-filter_dataframe/
98
+
99
+ Args:
100
+ df (pd.DataFrame): Original dataframe
101
+ ignore_columns (list[str], optional): Columns to ignore. Defaults to None.
102
+
103
+ Returns:
104
+ pd.DataFrame: Filtered dataframe
105
+ """
106
+ df = df.copy()
107
+
108
+ if ignore_columns is None:
109
+ ignore_columns = []
110
+
111
+ modification_container = st.container()
112
+
113
+ with modification_container:
114
+ to_filter_index = st.multiselect("Filter by model:", sorted(df.index))
115
+ if to_filter_index:
116
+ df = pd.DataFrame(df.loc[to_filter_index])
117
+
118
+ to_filter_columns = st.multiselect(
119
+ "Filter by benchmark:", sorted([c for c in df.columns if c not in ignore_columns])
120
+ )
121
+ if to_filter_columns:
122
+ df = pd.DataFrame(df[ignore_columns + to_filter_columns])
123
+
124
+ return df
125
+
126
+
127
+ def filter_dataframe_by_column_values(df: pd.DataFrame) -> pd.DataFrame:
128
+ """
129
+ Filter dataframe by the values in the dataframe.
130
+
131
+ Modified from https://blog.streamlit.io/auto-generate-a-dataframe-filtering-ui-in-streamlit-with-filter_dataframe/
132
+
133
+ Args:
134
+ df (pd.DataFrame): Original dataframe
135
+
136
+ Returns:
137
+ pd.DataFrame: Filtered dataframe
138
+ """
139
+ df = df.copy()
140
+
141
+ modification_container = st.container()
142
+
143
+ with modification_container:
144
+ to_filter_columns = st.multiselect("Filter results on:", df.columns)
145
+ left, right = st.columns((1, 20))
146
+
147
+ for column in to_filter_columns:
148
+ if is_bool_dtype(df[column]):
149
+ user_bool_input = right.checkbox(f"{column}", value=True)
150
+ df = df[df[column] == user_bool_input]
151
+
152
+ elif is_numeric_dtype(df[column]):
153
+ _min = float(df[column].min())
154
+ _max = float(df[column].max())
155
+
156
+ if (_min != _max) and pd.notna(_min) and pd.notna(_max):
157
+ step = 0.01
158
+ user_num_input = right.slider(
159
+ f"Values for {column}:",
160
+ min_value=round(_min - step, 2),
161
+ max_value=round(_max + step, 2),
162
+ value=(_min, _max),
163
+ step=step,
164
+ )
165
+ df = df[df[column].between(*user_num_input)]
166
+
167
+ elif is_datetime64_any_dtype(df[column]):
168
+ user_date_input = right.date_input(
169
+ f"Values for {column}:",
170
+ value=(
171
+ df[column].min(),
172
+ df[column].max(),
173
+ ),
174
+ )
175
+ if isinstance(user_date_input, Iterable) and len(user_date_input) == 2:
176
+ user_date_input_datetime = tuple(map(pd.to_datetime, user_date_input))
177
+ start_date, end_date = user_date_input_datetime
178
+ df = df.loc[df[column].between(start_date, end_date)]
179
+
180
+ else:
181
+ selected_values = right.multiselect(
182
+ f"Values for {column}:",
183
+ sorted(df[column].unique()),
184
+ )
185
+
186
+ if selected_values:
187
+ df = df[df[column].isin(selected_values)]
188
+
189
+ return df
190
+
191
+
192
+ def setup_basic():
193
+ title = "🏆 Swahili-LLM-Leaderboard"
194
+
195
+ st.set_page_config(
196
+ page_title=title,
197
+ page_icon="🏆",
198
+ layout="wide",
199
+ )
200
+ st.title(title)
201
+
202
+ st.markdown(
203
+ "A joint community effort to create a Swahili central leaderboard for LLMs."
204
+ f" Visit [swahili-llm-leaderboard]({GITHUB_URL}) to contribute. \n"
205
+ # 'We refer to a model being "open" if it can be locally deployed and used for commercial purposes.'
206
+ )
207
+
208
+
209
+ def setup_leaderboard(readme: str):
210
+ leaderboard_table = extract_markdown_table_from_multiline(readme, table_headline="## Leaderboard")
211
+ leaderboard_table = remove_markdown_links(leaderboard_table)
212
+ df_leaderboard = extract_table_and_format_from_markdown_text(leaderboard_table)
213
+ df_leaderboard["Open?"] = df_leaderboard["Open?"].map({"yes": 1, "no": 0}).astype(bool)
214
+
215
+ st.markdown("## Leaderboard")
216
+ modify = st.checkbox("Add filters")
217
+ clear_empty_entries = st.checkbox("Clear empty entries", value=True)
218
+
219
+ if modify:
220
+ df_leaderboard = filter_dataframe_by_row_and_columns(df_leaderboard, ignore_columns=NON_BENCHMARK_COLS)
221
+ df_leaderboard = filter_dataframe_by_column_values(df_leaderboard)
222
+
223
+ if clear_empty_entries:
224
+ df_leaderboard = df_leaderboard.dropna(axis=1, how="all")
225
+ benchmark_columns = [c for c in df_leaderboard.columns if df_leaderboard[c].dtype == float]
226
+ rows_wo_any_benchmark = df_leaderboard[benchmark_columns].isna().all(axis=1)
227
+ df_leaderboard = df_leaderboard[~rows_wo_any_benchmark]
228
+
229
+ st.dataframe(df_leaderboard)
230
+
231
+ st.download_button(
232
+ "Download current selection as .html",
233
+ df_leaderboard.to_html().encode("utf-8"),
234
+ "leaderboard.html",
235
+ "text/html",
236
+ key="download-html",
237
+ )
238
+
239
+ st.download_button(
240
+ "Download current selection as .csv",
241
+ df_leaderboard.to_csv().encode("utf-8"),
242
+ "leaderboard.csv",
243
+ "text/csv",
244
+ key="download-csv",
245
+ )
246
+
247
+
248
+ def setup_benchmarks(readme: str):
249
+ benchmarks_table = extract_markdown_table_from_multiline(readme, table_headline="## Benchmarks")
250
+ df_benchmarks = extract_table_and_format_from_markdown_text(benchmarks_table)
251
+
252
+ st.markdown("## Covered Benchmarks")
253
+
254
+ selected_benchmark = st.selectbox("Select a benchmark to learn more:", df_benchmarks.index.unique())
255
+ df_selected = df_benchmarks.loc[selected_benchmark]
256
+ text = [
257
+ f"Name: {selected_benchmark}",
258
+ ]
259
+ for key in df_selected.keys():
260
+ text.append(f"{key}: {df_selected[key]} ")
261
+ st.markdown(" \n".join(text))
262
+
263
+
264
+ def setup_sources():
265
+ st.markdown("## Sources")
266
+ st.markdown(
267
+ "The results of this leaderboard are collected from the individual papers and published results of the model "
268
+ "authors. If you are interested in the sources of each individual reported model value, please visit the "
269
+ f"[llm-leaderboard]({GITHUB_URL}) repository."
270
+ )
271
+ st.markdown(
272
+ """
273
+ Special thanks to the following pages:
274
+ - [MosaicML - Model benchmarks](https://www.mosaicml.com/blog/mpt-7b)
275
+ - [lmsys.org - Chatbot Arena benchmarks](https://lmsys.org/blog/2023-05-03-arena/)
276
+ - [Papers With Code](https://paperswithcode.com/)
277
+ - [Stanford HELM](https://crfm.stanford.edu/helm/latest/)
278
+ - [Stanford HELM](https://crfm.stanford.edu/helm/latest/)
279
+ - [HF Open LLM Leaderboard](https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard)
280
+ """
281
+ )
282
+ def setup_Sponsorship():
283
+ st.markdown("## Sponsorship")
284
+ st.markdown(
285
+ # "The results of this leaderboard are collected from the individual papers and published results of the model "
286
+ # "authors. If you are interested in the sources of each individual reported model value, please visit the "
287
+ # f"[llm-leaderboard]({GITHUB_URL}) repository."
288
+ "The benchmark is English-based, and we need support translating it into Swahili."
289
+ "We welcome sponsorships to help advance this endeavor."
290
+ "Your sponsorship would facilitate this essential translation effort, bridging language barriers and making the benchmark "
291
+ "accessible to a broader audience. We're grateful for the dedication shown by our collaborators and aim to extend this impact "
292
+ "further with the support of sponsors committed to advancing language technologies."
293
+ "Any support please reach me: [email protected]"
294
+ )
295
+
296
+ def setup_Contribution():
297
+ st.markdown("## How to Contribute")
298
+
299
+ markdown_content = """
300
+ - Model name (don't forget the links):
301
+ - Filling in missing entries
302
+ - Adding a new model as a new row to the leaderboard. Please keep the descending order.
303
+ - Adding a new benchmark as a new column in the leaderboard and adding the benchmark to the benchmarks table. Please keep the descending order.
304
+ - Code work:
305
+ - Improving the existing code
306
+ - Requesting and implementing new features
307
+ """
308
+ st.markdown(markdown_content)
309
+
310
+
311
+
312
+ def setup_disclaimer():
313
+ st.markdown("## Disclaimer")
314
+ st.markdown(
315
+ "Above information may be wrong. If you want to use a published model for commercial use, please contact a "
316
+ "lawyer."
317
+ )
318
+
319
+
320
+ def setup_footer():
321
+ st.markdown(
322
+ """
323
+ ---
324
+ Made with ❤️ by the awesome open-source community from all over 🌍.
325
+ """
326
+ )
327
+
328
+
329
+ def main():
330
+ setup_basic()
331
+
332
+ with open("README.md", "r") as f:
333
+ readme = f.read()
334
+
335
+ setup_leaderboard(readme)
336
+ # setup_benchmarks(readme)
337
+ # setup_sources()
338
+ # setup_disclaimer()
339
+ # setup_footer()
340
+ setup_Contribution()
341
+ setup_Sponsorship()
342
+
343
+
344
+ if __name__ == "__main__":
345
+ main()