Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import gradio as gr | |
| from collections import OrderedDict | |
| import logging | |
| import tempfile | |
| import os | |
| from huggingface_hub import ( | |
| HfApi, | |
| hf_hub_download, | |
| get_safetensors_metadata, | |
| metadata_load, | |
| ) | |
| from utils.misc import human_format, make_clickable_model | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| EXCLUDED_MODELS = [] # For models that misbehave :) | |
| K_EVALUATIONS = [1, 5, 10, 20, 50] | |
| DIST_EVALUATIONS = [1_000_000, 500_000, 100_000, 10_000] | |
| EXPECTED_KEY_TO_COLNAME = OrderedDict( | |
| [ | |
| ("rank", "Rank"), # Just for columns order | |
| ("model", "Model"), # Just for columns order | |
| ("model_size", "Model Size (Million)"), # Just for columns order | |
| ("conditioning", "Conditioning"), | |
| ("embedding_dim", "Embedding Dimension"), | |
| ] | |
| + [ | |
| (f"recall_at_{K}|{D}", f"R@{K} +{human_format(D)} Dist.") | |
| for D in DIST_EVALUATIONS | |
| for K in K_EVALUATIONS | |
| ] | |
| + [ | |
| ("n_dists", "Available Dists"), | |
| ], | |
| ) | |
| def get_safetensors_nparams(modelId): | |
| try: | |
| safetensors = get_safetensors_metadata(modelId) | |
| num_parameters = sum(safetensors.parameter_count.values()) | |
| return round(num_parameters / 1e6) | |
| except Exception: | |
| pass | |
| def parse_model(m): | |
| readme_path = hf_hub_download(m.modelId, filename="README.md") | |
| meta = metadata_load(readme_path) | |
| if "model-index" not in meta: | |
| raise ValueError("Missing `model-index` in metadata") | |
| for result in meta["model-index"][0]["results"]: | |
| if result["dataset"]["type"] == "Slep/LAION-RVS-Fashion": | |
| break # Found the right dataset | |
| # Get data from model-index / safetensors metadata | |
| d = { | |
| EXPECTED_KEY_TO_COLNAME["model"]: make_clickable_model(m.modelId), | |
| EXPECTED_KEY_TO_COLNAME["model_size"]: get_safetensors_nparams(m.modelId), | |
| } | |
| # Get data from exported results | |
| for metric in result["metrics"]: | |
| t = metric["type"] | |
| if t in EXPECTED_KEY_TO_COLNAME: | |
| d[EXPECTED_KEY_TO_COLNAME[t]] = metric["value"] | |
| return d | |
| def get_data_from_hub(): | |
| api = HfApi() | |
| models = api.list_models(filter="lrvsf-benchmark") | |
| df_list = [] | |
| for m in models: | |
| if m.modelId in EXCLUDED_MODELS: | |
| continue | |
| try: | |
| parsed = parse_model(m) | |
| if parsed: | |
| df_list.append(parsed) | |
| except Exception as e: | |
| logging.warning(f"Failed to parse model {m.modelId} : {e}") | |
| return pd.DataFrame(df_list, columns=EXPECTED_KEY_TO_COLNAME.values()) | |
| def filter_dataframe(df, k_filter, d_filter, c_filter): | |
| # ===== FILTER COLUMNS | |
| # Fixed column positions | |
| selected_columns = [ | |
| EXPECTED_KEY_TO_COLNAME["rank"], | |
| EXPECTED_KEY_TO_COLNAME["model"], | |
| EXPECTED_KEY_TO_COLNAME["conditioning"], | |
| EXPECTED_KEY_TO_COLNAME["model_size"], | |
| EXPECTED_KEY_TO_COLNAME["embedding_dim"], | |
| ] | |
| datatypes = ["number", "markdown", "number", "number"] | |
| for key, name in EXPECTED_KEY_TO_COLNAME.items(): | |
| if name in selected_columns: | |
| # Already added, probably part of the initial columns | |
| continue | |
| if key.startswith("recall_at_"): | |
| # Process : recall_at_K|D -> recall_at_K , D -> K , D | |
| # Could be a regex... but simple enough | |
| recall_at_K, D = key.split("|") | |
| K = recall_at_K.split("_")[-1] | |
| if int(K) in k_filter and int(D) in d_filter: | |
| selected_columns.append(name) | |
| datatypes.append("str") # Because of the ± std | |
| selected_columns.append(EXPECTED_KEY_TO_COLNAME["n_dists"]) | |
| datatypes.append("number") | |
| df = df[selected_columns] | |
| # ===== FILTER ROWS | |
| if c_filter != "all": | |
| df = df[df[EXPECTED_KEY_TO_COLNAME["conditioning"]] == c_filter] | |
| return df[selected_columns], datatypes | |
| def add_rank(df): | |
| main_metrics = df["R@1 +1M Dist."].str.split("±").str[0].astype(float) | |
| # Argsort is from smallest to largest so we reverse it | |
| df["Rank"] = df.shape[0] - main_metrics.argsort() | |
| return df | |
| def save_current_leaderboard(df): | |
| filename = tempfile.NamedTemporaryFile( | |
| prefix="lrvsf_export_", suffix=".csv", delete=False | |
| ).name | |
| df.to_csv(filename, index=False) | |
| return filename | |
| def load_lrvsf_models(k_filter, d_filter, c_filter, csv_file): | |
| # Remove previous tmpfile | |
| if csv_file: | |
| os.remove(csv_file) | |
| df = get_data_from_hub() | |
| df = add_rank(df) | |
| df, datatypes = filter_dataframe(df, k_filter, d_filter, c_filter) | |
| df = df.sort_values(by="Rank") | |
| filename = save_current_leaderboard(df) | |
| outputs = [ | |
| gr.DataFrame(value=df, datatype=datatypes), | |
| gr.File(filename, label="CSV File"), | |
| ] | |
| return outputs | |
| if __name__ == "__main__": | |
| with gr.Blocks() as demo: | |
| gr.Markdown( | |
| """ | |
| # 👗 LAION - Referred Visual Search - Fashion : Leaderboard | |
| - To submit, refer to the [LAION-RVS-Fashion Benchmark repository](https://github.com/Simon-Lepage/LRVSF-Benchmark). | |
| - For details on the task and the dataset, refer to the [LRVSF paper](https://arxiv.org/abs/2306.02928). | |
| - To download the leaderboard as CSV, click on the file below the table. | |
| """ | |
| ) | |
| with gr.Row(): | |
| k_filter = gr.CheckboxGroup( | |
| choices=K_EVALUATIONS, value=K_EVALUATIONS, label="Recall at K" | |
| ) | |
| d_filter = gr.CheckboxGroup( | |
| choices=[(human_format(D), D) for D in DIST_EVALUATIONS], | |
| value=DIST_EVALUATIONS, | |
| label="Number of Distractors", | |
| ) | |
| c_filter = gr.Radio( | |
| choices=["all", "category", "text"], | |
| value="all", | |
| label="Conditioning", | |
| ) | |
| df_table = gr.Dataframe(type="pandas", interactive=False) | |
| csv_file = gr.File(interactive=False) | |
| refresh = gr.Button("Refresh") | |
| # Actions | |
| refresh.click( | |
| load_lrvsf_models, | |
| inputs=[k_filter, d_filter, c_filter, csv_file], | |
| outputs=[df_table, csv_file], | |
| ) | |
| demo.load( | |
| load_lrvsf_models, | |
| inputs=[k_filter, d_filter, c_filter, csv_file], | |
| outputs=[df_table, csv_file], | |
| ) | |
| demo.launch() | |