import pandas as pd import gradio as gr from gradio_leaderboard import Leaderboard from utils import fetch_hf_results, show_output_box from constants import ( ASSAY_LIST, ASSAY_RENAME, ASSAY_EMOJIS, ASSAY_DESCRIPTION, EXAMPLE_FILE_DICT, ANONYMOUS_SUBMISSION_USERNAME, ) from about import ABOUT_TEXT, FAQS from submit import make_submission def format_leaderboard_table(df_results: pd.DataFrame, assay: str | None = None): # Previous things that were nice in the constellaration leaderboard: # Having a submission time column, and a user column where the username is clickable (this is a pro for usability but con for anonymity) # full_df.rename(columns={'submission_time': 'submission time', 'problem_type': 'problem type'}, inplace=True) # to_show['user'] = to_show['user'].apply(lambda x: make_user_clickable(x)).astype(str) column_order = ["model", "property", "spearman", "spearman_cross_val"] df = df_results.query("assay.isin(@ASSAY_RENAME.keys())").copy() if assay is not None: df = df[df["assay"] == assay] df = df[column_order] return df.sort_values(by="spearman", ascending=False) # Cache the results to avoid multiple downloads _cached_results = None def get_cached_results(): global _cached_results if _cached_results is None: _cached_results = fetch_hf_results() return _cached_results def get_leaderboard_object(assay: str | None = None): filter_columns = ["model"] if assay is None: filter_columns.append("property") # TODO how to sort filter columns alphabetically? Leaderboard( # TODO(Lood) check that this actually refreshes using the function value=format_leaderboard_table(df_results=get_cached_results(), assay=assay), datatype=["str", "str", "str", "number"], select_columns=["model", "property", "spearman", "spearman_cross_val"], search_columns=["model"], filter_columns=filter_columns, every=60, render=True, ) with gr.Blocks() as demo: gr.Markdown(""" ## Welcome to the Ginkgo Antibody Developability Benchmark! **Beta version, not publicly launched yet** Participants can submit their model to the leaderboard by uploading a CSV file (see the "✉️ Submit" tab). See more details in the "❔About" tab. """) with gr.Tabs(elem_classes="tab-buttons"): with gr.TabItem("❔About", elem_id="abdev-benchmark-tab-table"): gr.Image( value="./assets/competition_logo.jpg", show_label=False, # elem_classes=["resized-image"], show_download_button=False, width="50vw", # 50% of the "viewport width" ) gr.Markdown(ABOUT_TEXT) for question, answer in FAQS.items(): with gr.Accordion(question): gr.Markdown(answer) # Procedurally make these 5 tabs for assay in ASSAY_LIST: with gr.TabItem( f"{ASSAY_EMOJIS[assay]} {ASSAY_RENAME[assay]}", elem_id="abdev-benchmark-tab-table", ): gr.Markdown(f"# {ASSAY_DESCRIPTION[assay]}") get_leaderboard_object(assay=assay) with gr.TabItem("🚀 Overall", elem_id="abdev-benchmark-tab-table"): gr.Markdown( "# Antibody Developability Benchmark Leaderboard over all properties" ) get_leaderboard_object() with gr.TabItem("✉️ Submit", elem_id="boundary-benchmark-tab-table"): gr.Markdown( """ # Antibody Developability Submission Upload a CSV to get a score! Please use your Hugging Face account name to submit your model - we use this to track separate submissions, but only Hugging Face/Ginkgo will see these usernames (unless you choose to make them public). Your submission will be evaluated and added to the leaderboard. """ ) filename = gr.State(value=None) eval_state = gr.State(value=None) user_state = gr.State(value=None) submission_type_state = gr.State(value="GDPa1") download_file_state = gr.State(value=EXAMPLE_FILE_DICT["GDPa1"]) with gr.Row(): with gr.Column(): username_input = gr.Textbox( label="Username", placeholder="Enter your Hugging Face username or leave blank for anonymous submissions", info="This will be used to track your submissions, and to update your results if you submit again.", ) model_name_input = gr.Textbox( label="Model Name", placeholder="Enter your model name (e.g., 'MyProteinLM-v1')", info="This will be displayed on the leaderboard.", ) model_description_input = gr.Textbox( label="Model Description", placeholder="Brief description of your model and approach", info="Describe your model, training data, or methodology.", lines=3, ) with gr.Column(): submission_type_dropdown = gr.Dropdown( choices=["GDPa1", "GDPa1_cross_validation"], value="GDPa1", label="Submission Type", ) download_button = gr.DownloadButton( label="📥 Download example submission CSV", value=EXAMPLE_FILE_DICT["GDPa1"], variant="secondary", ) submission_file = gr.File(label="Submission CSV") # If username is empty, set to anonymous submission username_input.change( fn=lambda x: x if x.strip() else ANONYMOUS_SUBMISSION_USERNAME, inputs=username_input, outputs=user_state, ) def update_submission_type_and_file(submission_type): """ Based on the submission type selected in the dropdown, Update the submission type state Dynamically update example file for download """ download_file = EXAMPLE_FILE_DICT.get( submission_type, EXAMPLE_FILE_DICT["GDPa1"] ) return ( submission_type, download_file, gr.DownloadButton( label="📥 Download example submission CSV", value=download_file, variant="secondary", ), ) # Update submission type state and download button when dropdown changes submission_type_dropdown.change( fn=update_submission_type_and_file, inputs=submission_type_dropdown, outputs=[submission_type_state, download_file_state, download_button], ) submit_btn = gr.Button("Evaluate") message = gr.Textbox(label="Status", lines=1, visible=False) # help message gr.Markdown( "If you have issues with submission or using the leaderboard, please start a discussion in the Community tab of this Space." ) submit_btn.click( make_submission, inputs=[ submission_file, user_state, submission_type_state, model_name_input, model_description_input, ], outputs=[message], ).then( fn=show_output_box, inputs=[message], outputs=[message], ) # Footnote gr.Markdown( """
📬 For questions or feedback, contact datapoints@ginkgobioworks.com or visit the Community tab at the top of this page.
""", elem_id="contact-footer", ) if __name__ == "__main__": demo.launch()