-
Notifications
You must be signed in to change notification settings - Fork 655
Refactor split create_tables into static Benchmark methods #3126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
098f616
a7ff0da
0b59f5d
bf930f3
130bec1
3fa7ac4
a4e74b8
444cdf4
d6d9070
97f9650
5787990
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,3 +72,19 @@ def load_results( | |
| results = base_results.select_tasks(self.tasks) | ||
| self.results_cache[base_results] = results | ||
| return results | ||
|
|
||
| @staticmethod | ||
| def create_summary_table(scores_long: list[dict], search_query: str | None = None): | ||
| """create_summary_table""" | ||
| # Avoid circular references | ||
| from mteb.leaderboard.table import create_summary_table | ||
|
|
||
| return create_summary_table(scores_long, search_query) | ||
|
|
||
| @staticmethod | ||
| def create_per_task_table(scores_long: list[dict], search_query: str | None = None): | ||
| """create_per_task_table""" | ||
| # Avoid circular references | ||
| from mteb.leaderboard.table import create_per_task_table | ||
|
|
||
| return create_per_task_table(scores_long, search_query) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, the circular import here is a bit odd. I would just move the code here (note that gradio isn't a required dependency in mteb)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would also make both of these private
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would also be great if this just returns a dataframe, and styling is applied in the leaderboard. That way, certain columns are always consistently styled, and user can get a daframe in a working format from this. |
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you are missing the clean-up of this script - plenty of functions are no longer used. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -344,3 +344,239 @@ def create_tables( | |
| joint_table, per_task, score_columns, column_types | ||
| ) | ||
| return summary_table, per_task_table | ||
|
|
||
|
|
||
| def _prepare_data( | ||
| scores_long: list[dict], search_query: str | None = None | ||
| ) -> tuple[pd.DataFrame, list[str]] | None: | ||
| """Prepare raw dataframe and filter invalid models. | ||
|
q275343119 marked this conversation as resolved.
Outdated
|
||
|
|
||
| Returns: | ||
| per_task dataframe, models_to_remove | ||
| """ | ||
| if not scores_long: | ||
| return None | ||
|
|
||
| data = pd.DataFrame.from_records(scores_long) | ||
| per_task = data.pivot(index="model_name", columns="task_name", values="score") | ||
|
|
||
| to_remove = per_task.isna().all(axis="columns") | ||
| if search_query: | ||
| names = per_task.index.get_level_values("model_name") | ||
| names = pd.Series(names, index=per_task.index) | ||
| to_remove |= ~names.str.contains(search_query, regex=True) | ||
|
|
||
| if to_remove.all(): | ||
| return None | ||
|
|
||
| models_to_remove = list(per_task[to_remove].index) | ||
| per_task = per_task.drop(models_to_remove, axis=0) | ||
|
|
||
| return per_task, models_to_remove | ||
|
|
||
|
|
||
| def apply_summary_styling( | ||
| joint_table: pd.DataFrame, score_columns: list[str], column_types: list[str] | ||
| ) -> gr.DataFrame: | ||
| """Apply styling for summary (joint) table.""" | ||
| excluded_columns = [ | ||
| "Rank (Borda)", | ||
| "Model", | ||
| "Number of Parameters", | ||
| "Embedding Dimensions", | ||
| "Max Tokens", | ||
| "Memory Usage (MB)", | ||
| ] | ||
| gradient_columns = [ | ||
| col for col in joint_table.columns if col not in excluded_columns | ||
| ] | ||
| light_green_cmap = create_light_green_cmap() | ||
|
|
||
| numeric_data = joint_table.copy() | ||
| joint_table["Zero-shot"] = joint_table["Zero-shot"].apply(format_zero_shot) | ||
| joint_table[score_columns] = joint_table[score_columns].map(format_scores) | ||
|
|
||
| joint_table_style = joint_table.style.format( | ||
| {**dict.fromkeys(score_columns, "{:.2f}"), "Rank (Borda)": "{:.0f}"}, | ||
| na_rep="", | ||
| ) | ||
| joint_table_style = joint_table_style.highlight_min( | ||
| "Rank (Borda)", props="font-weight: bold" | ||
| ).highlight_max(subset=score_columns, props="font-weight: bold") | ||
|
|
||
| # background gradient for each column | ||
| for col in gradient_columns: | ||
| if col in joint_table.columns: | ||
| mask = numeric_data[col].notna() | ||
| if col != "Zero-shot": | ||
| gmap_values = numeric_data[col] * 100 | ||
| cmap = light_green_cmap | ||
| joint_table_style = joint_table_style.background_gradient( | ||
| cmap=cmap, | ||
| subset=pd.IndexSlice[mask, col], | ||
| gmap=gmap_values.loc[mask], | ||
| ) | ||
| else: | ||
| gmap_values = numeric_data[col] | ||
| cmap = "RdYlGn" | ||
| joint_table_style = joint_table_style.background_gradient( | ||
| cmap=cmap, | ||
| subset=pd.IndexSlice[mask, col], | ||
| vmin=50, | ||
| vmax=100, | ||
| gmap=gmap_values.loc[mask], | ||
| ) | ||
|
|
||
| column_widths = get_column_widths(joint_table_style.data) | ||
| column_widths[0] = "100px" | ||
| column_widths[1] = "250px" | ||
|
|
||
| return gr.DataFrame( | ||
| joint_table_style, | ||
| datatype=column_types, | ||
| interactive=False, | ||
| pinned_columns=3, | ||
| column_widths=column_widths, | ||
| wrap=True, | ||
| show_fullscreen_button=True, | ||
| show_copy_button=True, | ||
| show_search="filter", | ||
| ) | ||
|
|
||
|
|
||
| def apply_per_task_styling(per_task: pd.DataFrame) -> gr.DataFrame: | ||
| """Apply styling for per-task table.""" | ||
| task_score_columns = per_task.select_dtypes("number").columns | ||
| per_task[task_score_columns] *= 100 | ||
|
|
||
| per_task_style = per_task.style.format( | ||
| "{:.2f}", subset=task_score_columns, na_rep="" | ||
| ).highlight_max(subset=task_score_columns, props="font-weight: bold") | ||
|
|
||
| return gr.DataFrame( | ||
| per_task_style, | ||
| interactive=False, | ||
| pinned_columns=1, | ||
| show_fullscreen_button=True, | ||
| show_copy_button=True, | ||
| show_search="filter", | ||
| ) | ||
|
|
||
|
|
||
| def create_summary_table( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would probably just take BenchmarkResults as the input here. I think you can even use the |
||
| scores_long: list[dict], search_query: str | None = None | ||
| ) -> gr.DataFrame: | ||
| """create_summary_table""" | ||
| prepared = _prepare_data(scores_long, search_query) | ||
| if prepared is None: | ||
| no_results_frame = pd.DataFrame( | ||
| {"No results": ["You can try relaxing your criteria"]} | ||
| ) | ||
| return gr.DataFrame(no_results_frame) | ||
|
|
||
| per_task, models_to_remove = prepared | ||
| data = pd.DataFrame.from_records(scores_long) | ||
|
|
||
| mean_per_type = get_means_per_types(per_task) | ||
| mean_per_type = mean_per_type.pivot( | ||
| index="model_name", columns="task_type", values="score" | ||
| ) | ||
| mean_per_type.columns = [ | ||
| split_on_capital(column) for column in mean_per_type.columns | ||
| ] | ||
| typed_mean = mean_per_type.mean(skipna=False, axis=1) | ||
| overall_mean = per_task.mean(skipna=False, axis=1) | ||
| joint_table = mean_per_type.copy() | ||
| joint_table = joint_table.drop(models_to_remove, axis=0) | ||
| joint_table.insert(0, "mean", overall_mean) | ||
| joint_table.insert(1, "mean_by_task_type", typed_mean) | ||
| joint_table["borda_rank"] = get_borda_rank(per_task) | ||
| joint_table = joint_table.sort_values("borda_rank", ascending=True) | ||
| joint_table = joint_table.reset_index() | ||
| model_metas = joint_table["model_name"].map(failsafe_get_model_meta) | ||
| joint_table = joint_table[model_metas.notna()] | ||
| joint_table["model_link"] = model_metas.map(lambda m: m.reference) | ||
| joint_table.insert( | ||
| 1, | ||
| "Max Tokens", | ||
| model_metas.map(lambda m: format_max_tokens(m.max_tokens)), | ||
| ) | ||
| joint_table.insert( | ||
| 1, | ||
| "Embedding Dimensions", | ||
| model_metas.map(lambda m: str(int(m.embed_dim)) if m.embed_dim else "Unknown"), | ||
| ) | ||
| joint_table.insert( | ||
| 1, | ||
| "Number of Parameters", | ||
| model_metas.map(lambda m: format_n_parameters(m.n_parameters)), | ||
| ) | ||
| joint_table.insert( | ||
| 1, | ||
| "Memory Usage (MB)", | ||
| model_metas.map( | ||
| lambda m: str(int(m.memory_usage_mb)) if m.memory_usage_mb else "Unknown" | ||
| ), | ||
| ) | ||
| tasks = get_tasks(tasks=list(data["task_name"].unique())) | ||
| joint_table.insert( | ||
| 1, "Zero-shot", model_metas.map(lambda m: m.zero_shot_percentage(tasks)) | ||
| ) | ||
| joint_table["Zero-shot"] = joint_table["Zero-shot"].fillna(-1) | ||
| # joint_table = joint_table[joint_table["Zero-shot"].notna()] | ||
| # Removing HF organization from model | ||
| joint_table["model_name"] = joint_table["model_name"].map( | ||
| lambda name: name.split("/")[-1] | ||
| ) | ||
| # Adding markdown link to model names | ||
| name_w_link = ( | ||
| "[" + joint_table["model_name"] + "](" + joint_table["model_link"] + ")" | ||
| ) | ||
| joint_table["model_name"] = joint_table["model_name"].mask( | ||
| joint_table["model_link"].notna(), name_w_link | ||
| ) | ||
| joint_table = joint_table.drop(columns=["model_link"]) | ||
| joint_table = joint_table.rename( | ||
| columns={ | ||
| "model_name": "Model", | ||
| "mean_by_task_type": "Mean (TaskType)", | ||
| "mean": "Mean (Task)", | ||
| } | ||
| ) | ||
|
|
||
| joint_table.insert(0, "Rank (Borda)", joint_table.pop("borda_rank")) | ||
| column_types = get_column_types(joint_table) | ||
| # setting model name column to markdown | ||
| column_types[1] = "markdown" | ||
| score_columns = ["Mean (Task)", "Mean (TaskType)", *mean_per_type.columns] | ||
|
|
||
| return apply_summary_styling(joint_table, score_columns, column_types) | ||
|
|
||
|
|
||
| def create_per_task_table( | ||
| scores_long: list[dict], search_query: str | None = None | ||
| ) -> gr.DataFrame: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't believe the search query was used, which I believe simplified things quite a bit
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can probably remove _prepare_data |
||
| """create_per_task_table""" | ||
| prepared = _prepare_data(scores_long, search_query) | ||
| if prepared is None: | ||
| no_results_frame = pd.DataFrame( | ||
| {"No results": ["You can try relaxing your criteria"]} | ||
| ) | ||
| return gr.DataFrame(no_results_frame) | ||
|
|
||
| per_task, _ = prepared | ||
|
|
||
| per_task["borda_rank"] = get_borda_rank(per_task) | ||
| per_task = per_task.sort_values("borda_rank", ascending=True) | ||
| per_task = per_task.drop(columns=["borda_rank"]) | ||
| per_task = per_task.reset_index() | ||
| per_task["model_name"] = per_task["model_name"].map( | ||
| lambda name: name.split("/")[-1] | ||
| ) | ||
| per_task = per_task.rename( | ||
| columns={ | ||
| "model_name": "Model", | ||
| } | ||
| ) | ||
|
|
||
| return apply_per_task_styling(per_task) | ||
Uh oh!
There was an error while loading. Please reload this page.