Download app.py from wenjiao/low_bit_open_llm_leaderboard_5_26: direct link, hf CLI and curl.
- Browser
- Download file 57.2 kB
-
https://huggingface.co/spaces/wenjiao/low_bit_open_llm_leaderboard_5_26/resolve/main/app.py
- Command line
-
hf download hf://spaces/wenjiao/low_bit_open_llm_leaderboard_5_26/app.py
-
curl -L -o app.py https://huggingface.co/spaces/wenjiao/low_bit_open_llm_leaderboard_5_26/resolve/main/app.py
57.2 kB
| """Low-Bit Quantized Open LLM Leaderboard β Gradio app entry point. | |
| This module wires together the leaderboard UI, the submission queue tabs, | |
| the Metrics dashboard, and the About / FAQ pages, then mounts the resulting | |
| Gradio Blocks app under a FastAPI root so we can serve the | |
| ``/api/hf-model-zip`` streaming download route alongside it. | |
| Most reusable logic has been split into ``src/app_helpers/*``; this file | |
| only contains the UI layout (the ``with demo:`` block), the ``init_space`` | |
| data loader, and the FastAPI / uvicorn bootstrap. | |
| """ | |
| import logging | |
| import os | |
| import re | |
| import time | |
| # ββ Logging configuration (must precede library imports that use logging) ββ | |
| logging.basicConfig( | |
| level=os.environ.get("LOG_LEVEL", "INFO").upper(), | |
| format="%(asctime)s %(name)s [%(levelname)s] %(message)s", | |
| datefmt="%Y-%m-%d %H:%M:%S", | |
| ) | |
| logger = logging.getLogger(__name__) | |
| import gradio as gr | |
| import pandas as pd | |
| from apscheduler.schedulers.background import BackgroundScheduler | |
| from fastapi import FastAPI | |
| from huggingface_hub import snapshot_download | |
| from src.ci_dispatcher import CIDispatcher | |
| from src.display.about import ( | |
| AUTO_EVAL_TEXT, | |
| AUTO_PIPELINE_RESULTS_TEXT, | |
| AUTO_QUANT_TEXT, | |
| CITATION_BUTTON_LABEL, | |
| CITATION_BUTTON_TEXT, | |
| ETHICAL_CONSIDERATIONS_TEXT, | |
| EVALUATION_QUEUE_TEXT, | |
| FAQ_TEXT, | |
| INTRODUCTION_TEXT, | |
| LLM_BENCHMARKS_TEXT, | |
| TITLE, | |
| ) | |
| from src.display.css_html_js import custom_css | |
| from src.display.utils import ( | |
| auto_eval_cols, | |
| EVAL_COLS, | |
| EVAL_DISPLAY_COLS, | |
| EVAL_DISPLAY_HEADERS, | |
| EVAL_DISPLAY_TYPES, | |
| NUMERIC_INTERVALS, | |
| NUMERIC_MODELSIZE, | |
| QUANT_COLS, | |
| QUANT_DISPLAY_COLS, | |
| QUANT_DISPLAY_HEADERS, | |
| QUANT_DISPLAY_TYPES, | |
| ComputeDtype, | |
| Precision, | |
| QuantType, | |
| WeightDtype, | |
| fields, | |
| ) | |
| from src.envs import ( | |
| API, | |
| AZP_DEVOPS_PAT, | |
| DYNAMIC_INFO_PATH, | |
| DYNAMIC_INFO_REPO, | |
| ENABLE_RETRY, | |
| GIT_REQUESTS_PATH, | |
| GIT_RESULTS_PATH, | |
| GIT_STATUS_PATH, | |
| GLOBAL_COND, | |
| H4_TOKEN, | |
| IS_PUBLIC, | |
| REPO, | |
| REPO_ID, | |
| ) | |
| from src.leaderboard.read_auto_pipeline_results import ( | |
| AUTO_PIPELINE_ALL_COLUMNS, | |
| AUTO_PIPELINE_ALWAYS_VISIBLE_COLUMNS, | |
| AUTO_PIPELINE_DEFAULT_COLUMNS, | |
| AUTO_PIPELINE_HIDDEN_FROM_SELECTOR, | |
| AUTO_PIPELINE_SORT_COL, | |
| ) | |
| from src.populate import get_auto_pipeline_results_df, get_evaluation_queue_df | |
| from src.scripts.update_all_request_files import update_dynamic_files | |
| from src.submission.check_validity import GPU_COUNT_CHOICES, GPU_HARDWARE_CHOICES | |
| from src.tools.plots import ( | |
| compute_metrics_summary, | |
| create_method_comparison_chart, | |
| create_scheme_accuracy_chart, | |
| create_score_distribution_chart, | |
| create_submission_timeline_chart, | |
| create_top10_benchmark_lines, | |
| ) | |
| # Helper modules | |
| from src.app_helpers import oauth_patch # noqa: F401 (import side-effect: applies patch) | |
| from src.app_helpers.assets import FORCE_LIGHT_JS, SIDEBAR_HEAD | |
| from src.app_helpers.auth import ( | |
| check_auth_for_submit, | |
| is_allowed_to_resubmit_failed, | |
| is_whitelisted, | |
| process_user_on_load, | |
| sync_username, | |
| ) | |
| from src.app_helpers.duplicates import ( | |
| inline_dup_check_eval, | |
| inline_dup_check_quant, | |
| inline_license_check, | |
| ) | |
| from src.app_helpers.pipeline_table import ( | |
| ROW_NUMBER_COL, | |
| add_row_numbers, | |
| auto_pipeline_datatypes, | |
| filter_auto_pipeline_table, | |
| on_pipeline_dl_click, | |
| prepare_auto_pipeline_display_df, | |
| ) | |
| from src.app_helpers.queues import refresh_pipeline_leaderboard, refresh_queue_tables | |
| from src.app_helpers.sidebar import render_sidebar_menu | |
| from src.app_helpers.submissions import submit_model, submit_quant | |
| from src.app_helpers.zip_stream import register_routes as register_zip_route | |
| def restart_space(): | |
| """Restart the HuggingFace Space (called periodically by the scheduler).""" | |
| API.restart_space(repo_id=REPO_ID, token=H4_TOKEN) | |
| def init_space(full_init: bool = True): | |
| """Pull latest data from git + HF, then load the queue / pipeline DataFrames. | |
| Returns a tuple of: | |
| (auto_pipeline_results_df, | |
| finished_eval, running_eval, pending_eval, failed_eval, | |
| finished_quant, running_quant, pending_quant, failed_quant) | |
| """ | |
| max_retries = 3 | |
| if full_init: | |
| for attempt in range(1, max_retries + 1): | |
| try: | |
| branch = REPO.active_branch.name | |
| REPO.remotes.origin.pull(branch) | |
| break | |
| except Exception as e: | |
| logger.warning("Git pull attempt %d/%d failed: %s", attempt, max_retries, e) | |
| if attempt == max_retries: | |
| logger.error("All git pull attempts exhausted, restarting space") | |
| restart_space() | |
| time.sleep(2 ** attempt) | |
| for attempt in range(1, max_retries + 1): | |
| try: | |
| snapshot_download( | |
| repo_id=DYNAMIC_INFO_REPO, | |
| local_dir=DYNAMIC_INFO_PATH, | |
| repo_type="dataset", | |
| tqdm_class=None, | |
| etag_timeout=30, | |
| ) | |
| break | |
| except Exception as e: | |
| logger.warning("Snapshot download attempt %d/%d failed: %s", attempt, max_retries, e) | |
| if attempt == max_retries: | |
| logger.error("All snapshot download attempts exhausted, restarting space") | |
| restart_space() | |
| time.sleep(2 ** attempt) | |
| auto_pipeline_results_df = get_auto_pipeline_results_df(GIT_RESULTS_PATH) | |
| ( | |
| finished_eval_queue_df, | |
| running_eval_queue_df, | |
| pending_eval_queue_df, | |
| failed_eval_queue_df, | |
| ) = get_evaluation_queue_df( | |
| GIT_STATUS_PATH, EVAL_COLS, request_type="eval", results_path=GIT_RESULTS_PATH, | |
| ) | |
| ( | |
| finished_quant_queue_df, | |
| running_quant_queue_df, | |
| pending_quant_queue_df, | |
| failed_quant_queue_df, | |
| ) = get_evaluation_queue_df( | |
| GIT_STATUS_PATH, QUANT_COLS, request_type="quant", results_path=GIT_RESULTS_PATH, | |
| ) | |
| return ( | |
| auto_pipeline_results_df, | |
| finished_eval_queue_df, running_eval_queue_df, pending_eval_queue_df, failed_eval_queue_df, | |
| finished_quant_queue_df, running_quant_queue_df, pending_quant_queue_df, failed_quant_queue_df, | |
| ) | |
| ( | |
| auto_pipeline_results_df, | |
| finished_eval_queue_df, running_eval_queue_df, pending_eval_queue_df, failed_eval_queue_df, | |
| finished_quant_queue_df, running_quant_queue_df, pending_quant_queue_df, failed_quant_queue_df, | |
| ) = init_space() | |
| demo = gr.Blocks(fill_width=True, js=FORCE_LIGHT_JS) | |
| with demo: | |
| # Hidden login button (CSS hidden, triggered by JS when auth needed) | |
| login_btn = gr.LoginButton(elem_id="real_login_btn") | |
| # Hidden signal box for auth check communication | |
| signal_box = gr.Textbox(visible=False, elem_id="auth-signal-box") | |
| # Per-user session state (replaces global mutable variables) | |
| username_state = gr.State(value="") | |
| # Hidden trigger: set to artifact repo by table.select(), read by JS to open download modal | |
| pipeline_dl_trigger = gr.Textbox(visible=False, elem_id="pipeline-dl-trigger", value="") | |
| gr.HTML(TITLE) | |
| gr.Markdown(INTRODUCTION_TEXT, elem_classes="markdown-text") | |
| # ββ Sidebar menu (uses gradio_sidebar_menu component) ββββββββββββ | |
| _menu_data = [ | |
| {"type": "item", "id": "pipeline-results", "label": "Leaderboard", "icon": "trophy", "color": "#0f766e"}, | |
| {"type": "item", "id": "quant", "label": "Quantization", "icon": "rocket", "color": "#3b82f6"}, | |
| {"type": "item", "id": "eval", "label": "Evaluation", "icon": "flask-conical", "color": "#8b5cf6"}, | |
| {"type": "item", "id": "metrics", "label": "Metrics", "icon": "bar-chart-3", "color": "#10b981"}, | |
| {"type": "item", "id": "about", "label": "About", "icon": "file-text", "color": "#f43f5e"}, | |
| {"type": "item", "id": "faq", "label": "FAQ", "icon": "help-circle", "color": "#f59e0b"}, | |
| ] | |
| menu = render_sidebar_menu( | |
| menu_data=_menu_data, | |
| value="pipeline-results", | |
| open=True, | |
| position="left", | |
| width=220, | |
| elem_id="app-sidebar", | |
| ) | |
| with gr.Column(elem_classes="main-content"): | |
| # ββ Page: Auto Pipeline Results βββββββββββββββββββββββββββββββ | |
| with gr.Column(visible=True, elem_id="page-pipeline-results") as page_pipeline_results: | |
| auto_pipeline_all_df = auto_pipeline_results_df.copy() | |
| auto_pipeline_visible_choices = [ | |
| col for col in AUTO_PIPELINE_ALL_COLUMNS | |
| if col not in AUTO_PIPELINE_ALWAYS_VISIBLE_COLUMNS | |
| and col not in AUTO_PIPELINE_HIDDEN_FROM_SELECTOR | |
| ] | |
| auto_pipeline_default_visible = [ | |
| col for col in AUTO_PIPELINE_DEFAULT_COLUMNS | |
| if col not in AUTO_PIPELINE_ALWAYS_VISIBLE_COLUMNS | |
| and col not in AUTO_PIPELINE_HIDDEN_FROM_SELECTOR | |
| ] | |
| auto_pipeline_pipeline_choices = ( | |
| sorted(auto_pipeline_all_df["Pipeline"].dropna().astype(str).unique().tolist()) | |
| if "Pipeline" in auto_pipeline_all_df.columns | |
| else [] | |
| ) | |
| auto_pipeline_scheme_choices = ( | |
| sorted(auto_pipeline_all_df["Scheme"].dropna().astype(str).unique().tolist()) | |
| if "Scheme" in auto_pipeline_all_df.columns and not auto_pipeline_all_df["Scheme"].dropna().empty | |
| else ["W4A16", "MXFP4", "NVFP4"] | |
| ) | |
| with gr.Row(elem_id="pipeline-search-row"): | |
| auto_pipeline_search_bar = gr.Textbox( | |
| placeholder="Search by model name, scheme, or method β¦ ", | |
| show_label=False, | |
| elem_id="pipeline-search-bar", | |
| scale=5, | |
| ) | |
| auto_pipeline_search_button = gr.Button("Search", variant="primary", scale=1, min_width=120, elem_id="pipeline-search-button") | |
| with gr.Accordion("Filters & Columns", open=False, elem_id="accordion-filters-pipeline-results"): | |
| with gr.Group(elem_id="filter-panel"): | |
| with gr.Row(equal_height=True): | |
| auto_pipeline_filter = gr.CheckboxGroup( | |
| label="Pipelines", | |
| choices=auto_pipeline_pipeline_choices, | |
| value=auto_pipeline_pipeline_choices, | |
| interactive=True, | |
| ) | |
| auto_pipeline_scheme_filter = gr.CheckboxGroup( | |
| label="Scheme", | |
| choices=auto_pipeline_scheme_choices, | |
| value=auto_pipeline_scheme_choices, | |
| interactive=True, | |
| ) | |
| _size_vals = pd.to_numeric(auto_pipeline_all_df.get("Params (B)", pd.Series(dtype=float)), errors="coerce").dropna() | |
| _size_min = float(_size_vals.min()) if not _size_vals.empty else 0.0 | |
| _size_max = float(_size_vals.max()) if not _size_vals.empty else 100.0 | |
| # Custom two-thumb range slider with number inputs (full-width, independent row) | |
| with gr.Row(elem_id="size-range-row"): | |
| gr.HTML( | |
| f"""<div class="custom-range-slider-container" id="pipeline-size-range-ui"> | |
| <div class="custom-range-label">Model Params (B)</div> | |
| <div class="custom-range-row"> | |
| <input type="number" id="pipeline-size-num-min" class="custom-range-num-input" | |
| value="{_size_min:.1f}" min="{_size_min:.4f}" max="{_size_max:.4f}" step="0.1" title="Min params (B)"> | |
| <div class="custom-range-wrapper"> | |
| <div class="custom-range-track"> | |
| <div class="custom-range-selected" id="pipeline-size-range-fill"></div> | |
| </div> | |
| <input type="range" class="custom-range-thumb custom-range-thumb-min" | |
| id="pipeline-size-range-min" | |
| min="{_size_min:.4f}" max="{_size_max:.4f}" | |
| value="{_size_min:.4f}" step="0.1"> | |
| <input type="range" class="custom-range-thumb custom-range-thumb-max" | |
| id="pipeline-size-range-max" | |
| min="{_size_min:.4f}" max="{_size_max:.4f}" | |
| value="{_size_max:.4f}" step="0.1"> | |
| </div> | |
| <input type="number" id="pipeline-size-num-max" class="custom-range-num-input" | |
| value="{_size_max:.1f}" min="{_size_min:.4f}" max="{_size_max:.4f}" step="0.1" title="Max params (B)"> | |
| </div> | |
| </div>""" | |
| ) | |
| # Hidden Gradio sliders β values are driven by the custom HTML range slider above. | |
| # Must be visible=True so Gradio renders the input into the DOM; CSS hides them visually. | |
| with gr.Row(elem_id="size-range-hidden-row"): | |
| auto_pipeline_min_size_slider = gr.Slider( | |
| minimum=_size_min, | |
| maximum=_size_max, | |
| value=_size_min, | |
| step=0.1, | |
| label="Min Model Params (B)", | |
| interactive=True, | |
| visible=True, | |
| elem_id="min-size-slider-pipeline", | |
| elem_classes=["hidden-internal-slider"], | |
| ) | |
| auto_pipeline_size_slider = gr.Slider( | |
| minimum=_size_min, | |
| maximum=_size_max, | |
| value=_size_max, | |
| step=0.1, | |
| label="Max Model Params (B)", | |
| interactive=True, | |
| visible=True, | |
| elem_id="size-slider-pipeline", | |
| elem_classes=["hidden-internal-slider"], | |
| ) | |
| with gr.Row(): | |
| auto_pipeline_shown_columns = gr.CheckboxGroup( | |
| label="Visible columns", | |
| choices=auto_pipeline_visible_choices, | |
| value=auto_pipeline_default_visible, | |
| interactive=True, | |
| elem_id="column-select", | |
| ) | |
| auto_pipeline_initial_cols = [] | |
| for col in AUTO_PIPELINE_ALWAYS_VISIBLE_COLUMNS + AUTO_PIPELINE_DEFAULT_COLUMNS: | |
| if col in auto_pipeline_all_df.columns and col not in auto_pipeline_initial_cols and col not in AUTO_PIPELINE_HIDDEN_FROM_SELECTOR: | |
| auto_pipeline_initial_cols.append(col) | |
| _avg_sort_col = "Average" | |
| _sorted_pipeline_df = ( | |
| auto_pipeline_all_df.sort_values(by=_avg_sort_col, ascending=False, na_position="last") | |
| if _avg_sort_col in auto_pipeline_all_df.columns | |
| else auto_pipeline_all_df.sort_values(by=AUTO_PIPELINE_SORT_COL, ascending=False, na_position="last") | |
| ) | |
| auto_pipeline_display_df = prepare_auto_pipeline_display_df(_sorted_pipeline_df) | |
| _initial_display_cols = [ROW_NUMBER_COL] + auto_pipeline_initial_cols | |
| auto_pipeline_table = gr.components.Dataframe( | |
| value=add_row_numbers(auto_pipeline_display_df[auto_pipeline_initial_cols]), | |
| headers=_initial_display_cols, | |
| datatype=auto_pipeline_datatypes(_initial_display_cols), | |
| interactive=False, | |
| visible=True, | |
| elem_id="pipeline-leaderboard-table", | |
| ) | |
| # Keep the full unfiltered DataFrame in a server-side gr.State so it round-trips | |
| # through Gradio without being serialized to a string table (which previously | |
| # corrupted NaN handling and HTML cell values, breaking the Pipelines/Scheme | |
| # filters). | |
| hidden_auto_pipeline_table = gr.State(value=auto_pipeline_all_df) | |
| auto_pipeline_search_inputs = [ | |
| hidden_auto_pipeline_table, | |
| auto_pipeline_shown_columns, | |
| auto_pipeline_filter, | |
| auto_pipeline_scheme_filter, | |
| auto_pipeline_search_bar, | |
| auto_pipeline_min_size_slider, | |
| auto_pipeline_size_slider, | |
| ] | |
| auto_pipeline_search_bar.submit( | |
| filter_auto_pipeline_table, | |
| auto_pipeline_search_inputs, | |
| auto_pipeline_table, | |
| trigger_mode="always_last", | |
| concurrency_id="pipeline-filter", | |
| concurrency_limit=1, | |
| show_progress="hidden", | |
| ) | |
| auto_pipeline_search_bar.input( | |
| filter_auto_pipeline_table, | |
| auto_pipeline_search_inputs, | |
| auto_pipeline_table, | |
| queue=True, | |
| trigger_mode="always_last", | |
| concurrency_id="pipeline-filter", | |
| concurrency_limit=1, | |
| show_progress="hidden", | |
| ) | |
| auto_pipeline_search_button.click( | |
| filter_auto_pipeline_table, | |
| auto_pipeline_search_inputs, | |
| auto_pipeline_table, | |
| queue=True, | |
| trigger_mode="always_last", | |
| concurrency_id="pipeline-filter", | |
| concurrency_limit=1, | |
| show_progress="hidden", | |
| ) | |
| for selector in [ | |
| auto_pipeline_shown_columns, | |
| auto_pipeline_filter, | |
| auto_pipeline_scheme_filter, | |
| auto_pipeline_min_size_slider, | |
| auto_pipeline_size_slider, | |
| ]: | |
| selector.change( | |
| filter_auto_pipeline_table, | |
| [ | |
| hidden_auto_pipeline_table, | |
| auto_pipeline_shown_columns, | |
| auto_pipeline_filter, | |
| auto_pipeline_scheme_filter, | |
| auto_pipeline_search_bar, | |
| auto_pipeline_min_size_slider, | |
| auto_pipeline_size_slider, | |
| ], | |
| auto_pipeline_table, | |
| queue=True, | |
| trigger_mode="always_last", | |
| concurrency_id="pipeline-filter", | |
| concurrency_limit=1, | |
| show_progress="hidden", | |
| ) | |
| # ββ Download-modal trigger (Python β JS bridge) ββββββββββββββββββ | |
| auto_pipeline_table.select( | |
| on_pipeline_dl_click, | |
| inputs=[hidden_auto_pipeline_table], | |
| outputs=[pipeline_dl_trigger], | |
| queue=True, | |
| ) | |
| pipeline_dl_trigger.change( | |
| fn=None, | |
| inputs=[pipeline_dl_trigger], | |
| outputs=[], | |
| queue=False, | |
| js="""(repo) => { | |
| if (repo && repo.indexOf('/') !== -1 && window._dlOpenModal) { | |
| window._dlOpenModal(repo); | |
| } | |
| return []; | |
| }""", | |
| ) | |
| with gr.Accordion("About This Benchmark", open=False, elem_classes=["submission-info-accordion"], elem_id="accordion-info-pipeline-results"): | |
| gr.Markdown(AUTO_PIPELINE_RESULTS_TEXT, elem_classes="markdown-text") | |
| # ββ Page: Auto Quant βββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Column(visible=True, elem_id="page-quant", elem_classes=["page-hidden"]) as page_quant: | |
| with gr.Accordion("Submission Information", open=False, elem_classes=["submission-info-accordion"], elem_id="accordion-info-quant"): | |
| gr.Markdown(EVALUATION_QUEUE_TEXT, elem_classes="markdown-text") | |
| gr.Markdown(AUTO_QUANT_TEXT, elem_classes="markdown-text") | |
| gr.Markdown( | |
| "β οΈ **Note:** Currently only models **under 70B** parameters are supported. " | |
| "Not all models can be supported on day one β this depends on upstream community software " | |
| "(e.g. [Transformers](https://github.com/huggingface/transformers), [vLLM](https://github.com/vllm-project/vllm)). " | |
| "If you find that your submitted model is not yet supported, please " | |
| "[open an issue on AutoRound](https://github.com/intel/auto-round/issues).\n\n" | |
| "For popular community models **over 70B**, please " | |
| "[open a request on the Leaderboard](https://huggingface.co/spaces/Intel/low-bit-leaderboard/discussions) " | |
| "and we will evaluate how to support them.", | |
| elem_classes=["disclaimer-note"], | |
| ) | |
| queue_search_quant = gr.Textbox( | |
| placeholder="Search queue by model name β¦ ", | |
| show_label=False, | |
| elem_id="queue-search-quant", | |
| ) | |
| with gr.Group(elem_id="submit-panel"): | |
| revision_name_textbox = gr.Textbox(value="main", visible=False) | |
| private = gr.Checkbox(False, label="Private", visible=not IS_PUBLIC) | |
| base_model_name_textbox = gr.Textbox( | |
| label="Base model (for delta or adapter weights)", | |
| visible=not IS_PUBLIC, | |
| ) | |
| model_size_input = gr.Textbox( | |
| value="", visible=False, container=False, | |
| ) | |
| gr.Markdown( | |
| "<small>βΉοΈ Submits for **AutoRound quantization + evaluation** on HellaSwag, MMLU & PIQA. See **Submission Information** above for details.</small>", | |
| elem_classes=["submit-hint"], | |
| ) | |
| with gr.Row(equal_height=True): | |
| with gr.Column(scale=4): | |
| model_name_textbox = gr.Textbox(label="Model name", placeholder="org/model-name", elem_id="model-input-quant") | |
| with gr.Column(scale=2): | |
| compute_type = gr.Dropdown( | |
| choices=["MXFP4", "NVFP4", "INT4 (W4A16)"], | |
| label="Quantization Scheme", | |
| info='Follows the AutoRound approach. <a href="https://github.com/intel/auto-round" target="_blank" rel="noopener">See AutoRound for details β</a>', | |
| multiselect=False, | |
| value="INT4 (W4A16)", | |
| interactive=True, | |
| ) | |
| with gr.Column(scale=2, visible=False) as hw_col_quant: | |
| hw_dropdown_quant = gr.Dropdown( | |
| choices=GPU_HARDWARE_CHOICES, | |
| label="Hardware", | |
| value="Auto (recommended)", | |
| interactive=True, | |
| elem_id="hw-select-quant", | |
| ) | |
| gpu_count_quant = gr.Dropdown( | |
| choices=GPU_COUNT_CHOICES, | |
| label="GPU Count", | |
| value="Auto", | |
| interactive=True, | |
| elem_id="gpu-count-quant", | |
| ) | |
| with gr.Column(scale=1, min_width=160, elem_classes=["submit-col"]): | |
| submit_button = gr.Button( | |
| "Submit", | |
| variant="primary", | |
| interactive=False, | |
| elem_id="submit-button-quant", | |
| elem_classes=["submit-action-btn"], | |
| ) | |
| submission_result = gr.Markdown(visible=False) | |
| dup_inline_quant = gr.Markdown( | |
| visible=False, | |
| elem_id="dup-inline-quant", | |
| elem_classes=["dup-inline-warning"], | |
| ) | |
| license_warning_quant = gr.Markdown( | |
| visible=False, | |
| elem_id="license-warning-quant", | |
| elem_classes=["license-inline-warning"], | |
| ) | |
| _quant_submit_evt = submit_button.click( | |
| fn=lambda: None, | |
| inputs=[], | |
| outputs=[], | |
| js="""() => { | |
| var modelInput = document.querySelector('#model-input-quant input, #model-input-quant textarea'); | |
| var modelVal = modelInput ? modelInput.value.trim() : ''; | |
| sessionStorage.setItem('pending_submit', JSON.stringify({ | |
| tab: 'quant', | |
| model: modelVal | |
| })); | |
| return []; | |
| }""", | |
| ).then( | |
| check_auth_for_submit, | |
| inputs=[], | |
| outputs=signal_box, | |
| ).then( | |
| sync_username, | |
| inputs=[], | |
| outputs=[username_state], | |
| ).then( | |
| # Disable the submit button immediately so the user cannot | |
| # double-click while auth + queue checks are running. We | |
| # intentionally do NOT clear `submission_result` / | |
| # `dup_inline_quant` / `license_warning_quant` here: the | |
| # streaming `submit_quant` generator below overwrites them | |
| # on its first yield, and an extra clear-then-show cycle in | |
| # the same click event chain can race in Gradio 6.5.1 and | |
| # leave the result panel hidden on subsequent submissions. | |
| fn=lambda: gr.update(interactive=False), | |
| inputs=[], | |
| outputs=[submit_button], | |
| ).then( | |
| submit_quant, | |
| [ | |
| signal_box, | |
| model_name_textbox, | |
| revision_name_textbox, | |
| private, | |
| compute_type, | |
| model_size_input, | |
| hw_dropdown_quant, | |
| gpu_count_quant, | |
| ], | |
| [submission_result, model_name_textbox, submit_button, dup_inline_quant, license_warning_quant], | |
| js="""(signal, model, revision, priv, scheme, size, hw, cnt) => { | |
| // Only clear pending_submit when NOT redirecting to OAuth | |
| if (signal !== 'TRIGGER') sessionStorage.removeItem('pending_submit'); | |
| // Fallback: read model from DOM if Gradio internal state is empty | |
| // (happens after OAuth return where JS filled the value) | |
| if (!model || model.trim() === '') { | |
| var input = document.querySelector('#model-input-quant input, #model-input-quant textarea'); | |
| if (input && input.value.trim()) model = input.value.trim(); | |
| } | |
| return [signal, model, revision, priv, scheme, size, hw, cnt]; | |
| }""", | |
| ) # revision_name_textbox is hidden, always "main" | |
| with gr.Column(): | |
| with gr.Row(elem_classes=["filter-row"]): | |
| my_submissions_quant_cb = gr.Checkbox( | |
| label="Only show my submissions", | |
| value=False, | |
| interactive=True, | |
| elem_id="my-submissions-quant", | |
| ) | |
| current_user_quant = gr.HTML( | |
| value='<span style="color:#9ca3af;font-size:0.85rem;margin-left:4px;">' | |
| 'Unauthorized β <a href="#" class="auth-trigger-link" data-tab="quant" ' | |
| 'style="color:#3b82f6;cursor:pointer;text-decoration:underline;">' | |
| 'Click to authorize</a></span>', | |
| elem_id="current-user-quant", | |
| ) | |
| with gr.Accordion( | |
| f"Finished Quantizations ({len(finished_quant_queue_df)})", | |
| open=False, elem_id="accordion-finished-quant", | |
| ) as accordion_finished_quant: | |
| finished_quant_table = gr.components.Dataframe( | |
| value=finished_quant_queue_df[QUANT_DISPLAY_COLS] if not finished_quant_queue_df.empty else finished_quant_queue_df, | |
| headers=QUANT_DISPLAY_HEADERS, | |
| datatype=QUANT_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(QUANT_DISPLAY_COLS) - 2), | |
| ) | |
| with gr.Accordion( | |
| f"Running Quantization Queue ({len(running_quant_queue_df)})", | |
| open=False, elem_id="accordion-running-quant", | |
| ) as accordion_running_quant: | |
| running_quant_table = gr.components.Dataframe( | |
| value=running_quant_queue_df[QUANT_DISPLAY_COLS] if not running_quant_queue_df.empty else running_quant_queue_df, | |
| headers=QUANT_DISPLAY_HEADERS, | |
| datatype=QUANT_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(QUANT_DISPLAY_COLS) - 2), | |
| ) | |
| with gr.Accordion( | |
| f"Pending Quantization Queue ({len(pending_quant_queue_df)})", | |
| open=False, elem_id="accordion-pending-quant", | |
| ) as accordion_pending_quant: | |
| pending_quant_table = gr.components.Dataframe( | |
| value=pending_quant_queue_df[QUANT_DISPLAY_COLS] if not pending_quant_queue_df.empty else pending_quant_queue_df, | |
| headers=QUANT_DISPLAY_HEADERS, | |
| datatype=QUANT_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(QUANT_DISPLAY_COLS) - 2), | |
| ) | |
| with gr.Accordion( | |
| f"Failed Quantizations ({len(failed_quant_queue_df)})", | |
| open=False, elem_id="accordion-failed-quant", | |
| ) as accordion_failed_quant: | |
| failed_quant_table = gr.components.Dataframe( | |
| value=failed_quant_queue_df[QUANT_DISPLAY_COLS] if not failed_quant_queue_df.empty else failed_quant_queue_df, | |
| headers=QUANT_DISPLAY_HEADERS, | |
| datatype=QUANT_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(QUANT_DISPLAY_COLS) - 2), | |
| ) | |
| # ββ Page: Auto Eval ββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Column(visible=True, elem_id="page-eval", elem_classes=["page-hidden"]) as page_eval: | |
| with gr.Accordion("Submission Information", open=False, elem_classes=["submission-info-accordion"], elem_id="accordion-info-eval"): | |
| gr.Markdown(EVALUATION_QUEUE_TEXT, elem_classes="markdown-text") | |
| gr.Markdown(AUTO_EVAL_TEXT, elem_classes="markdown-text") | |
| gr.Markdown( | |
| "β οΈ **Note:** Currently only models **under 70B** parameters are supported. " | |
| "Not all models can be supported on day one β this depends on upstream community software " | |
| "(e.g. [Transformers](https://github.com/huggingface/transformers), [vLLM](https://github.com/vllm-project/vllm)). " | |
| "If you find that your submitted model is not yet supported, please " | |
| "[open an issue on AutoRound](https://github.com/intel/auto-round/issues).\n\n" | |
| "For popular community models **over 70B**, please " | |
| "[open a request on the Leaderboard](https://huggingface.co/spaces/Intel/low-bit-leaderboard/discussions) " | |
| "and we will evaluate how to support them.", | |
| elem_classes=["disclaimer-note"], | |
| ) | |
| queue_search_eval = gr.Textbox( | |
| placeholder="Search queue by model name β¦ ", | |
| show_label=False, | |
| elem_id="queue-search-eval", | |
| ) | |
| with gr.Group(elem_id="submit-panel"): | |
| revision_name_textbox_auto_eval = gr.Textbox(value="main", visible=False) | |
| private_auto_eval = gr.Checkbox(False, label="Private", visible=not IS_PUBLIC) | |
| base_model_name_textbox_auto_eval = gr.Textbox( | |
| label="Base model (for delta or adapter weights)", | |
| visible=not IS_PUBLIC, | |
| ) | |
| model_size_input_auto_eval = gr.Textbox( | |
| value="", visible=False, container=False, | |
| ) | |
| with gr.Row(equal_height=True): | |
| with gr.Column(scale=4): | |
| model_name_textbox_auto_eval = gr.Textbox(label="Model name", placeholder="org/model-name", elem_id="model-input-eval") | |
| with gr.Column(scale=2): | |
| compute_type_auto_eval = gr.Dropdown( | |
| choices=["INT4 (W4A16)"], | |
| label="Quantization Scheme", | |
| info='Follows the vLLM approach. <a href="https://github.com/vllm-project/vllm" target="_blank" rel="noopener">See vLLM for details β</a>', | |
| multiselect=False, | |
| value="INT4 (W4A16)", | |
| interactive=True, | |
| ) | |
| with gr.Column(scale=2, visible=False) as hw_col_eval: | |
| hw_dropdown_eval = gr.Dropdown( | |
| choices=GPU_HARDWARE_CHOICES, | |
| label="Hardware", | |
| value="Auto (recommended)", | |
| interactive=True, | |
| elem_id="hw-select-eval", | |
| ) | |
| gpu_count_eval = gr.Dropdown( | |
| choices=GPU_COUNT_CHOICES, | |
| label="GPU Count", | |
| value="Auto", | |
| interactive=True, | |
| elem_id="gpu-count-eval", | |
| ) | |
| with gr.Column(scale=1, min_width=160, elem_classes=["submit-col"]): | |
| submit_button_auto_eval = gr.Button( | |
| "Submit", | |
| variant="primary", | |
| interactive=False, | |
| elem_id="submit-button-eval", | |
| elem_classes=["submit-action-btn"], | |
| ) | |
| submission_result_auto_eval = gr.Markdown(visible=False) | |
| dup_inline_eval = gr.Markdown( | |
| visible=False, | |
| elem_id="dup-inline-eval", | |
| elem_classes=["dup-inline-warning"], | |
| ) | |
| license_warning_eval = gr.Markdown( | |
| visible=False, | |
| elem_id="license-warning-eval", | |
| elem_classes=["license-inline-warning"], | |
| ) | |
| _eval_submit_evt = submit_button_auto_eval.click( | |
| fn=lambda: None, | |
| inputs=[], | |
| outputs=[], | |
| js="""() => { | |
| var modelInput = document.querySelector('#model-input-eval input, #model-input-eval textarea'); | |
| var modelVal = modelInput ? modelInput.value.trim() : ''; | |
| sessionStorage.setItem('pending_submit', JSON.stringify({ | |
| tab: 'eval', | |
| model: modelVal | |
| })); | |
| return []; | |
| }""", | |
| ).then( | |
| check_auth_for_submit, | |
| inputs=[], | |
| outputs=signal_box, | |
| ).then( | |
| sync_username, | |
| inputs=[], | |
| outputs=[username_state], | |
| ).then( | |
| # See the quant submit chain above for the rationale: only | |
| # disable the submit button here. Clearing the result / | |
| # warning Markdowns is handled by the streaming generator's | |
| # first yield, which avoids a visibility-toggle race in | |
| # Gradio 6.5.1 that hid the result panel on re-submission. | |
| fn=lambda: gr.update(interactive=False), | |
| inputs=[], | |
| outputs=[submit_button_auto_eval], | |
| ).then( | |
| submit_model, | |
| [ | |
| signal_box, | |
| model_name_textbox_auto_eval, | |
| revision_name_textbox_auto_eval, | |
| private_auto_eval, | |
| compute_type_auto_eval, | |
| model_size_input_auto_eval, | |
| hw_dropdown_eval, | |
| gpu_count_eval, | |
| ], | |
| [submission_result_auto_eval, model_name_textbox_auto_eval, submit_button_auto_eval, dup_inline_eval, license_warning_eval], | |
| js="""(signal, model, revision, priv, compute, size, hw, cnt) => { | |
| // Only clear pending_submit when NOT redirecting to OAuth | |
| if (signal !== 'TRIGGER') sessionStorage.removeItem('pending_submit'); | |
| // Fallback: read model from DOM if Gradio internal state is empty | |
| // (happens after OAuth return where JS filled the value) | |
| if (!model || model.trim() === '') { | |
| var input = document.querySelector('#model-input-eval input, #model-input-eval textarea'); | |
| if (input && input.value.trim()) model = input.value.trim(); | |
| } | |
| return [signal, model, revision, priv, compute, size, hw, cnt]; | |
| }""", | |
| ) | |
| with gr.Column(): | |
| with gr.Row(elem_classes=["filter-row"]): | |
| my_submissions_eval_cb = gr.Checkbox( | |
| label="Only show my submissions", | |
| value=False, | |
| interactive=True, | |
| elem_id="my-submissions-eval", | |
| ) | |
| current_user_eval = gr.HTML( | |
| value='<span style="color:#9ca3af;font-size:0.85rem;margin-left:4px;">' | |
| 'Unauthorized β <a href="#" class="auth-trigger-link" data-tab="eval" ' | |
| 'style="color:#3b82f6;cursor:pointer;text-decoration:underline;">' | |
| 'Click to authorize</a></span>', | |
| elem_id="current-user-eval", | |
| ) | |
| with gr.Accordion( | |
| f"Finished Evaluations ({len(finished_eval_queue_df)})", | |
| open=False, elem_id="accordion-finished-eval", | |
| ) as accordion_finished_eval: | |
| finished_eval_table_auto_eval = gr.components.Dataframe( | |
| value=finished_eval_queue_df[EVAL_DISPLAY_COLS] if not finished_eval_queue_df.empty else finished_eval_queue_df, | |
| headers=EVAL_DISPLAY_HEADERS, | |
| datatype=EVAL_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(EVAL_DISPLAY_COLS) - 2), | |
| ) | |
| with gr.Accordion( | |
| f"Running Evaluation Queue ({len(running_eval_queue_df)})", | |
| open=False, elem_id="accordion-running-eval", | |
| ) as accordion_running_eval: | |
| running_eval_table_auto_eval = gr.components.Dataframe( | |
| value=running_eval_queue_df[EVAL_DISPLAY_COLS] if not running_eval_queue_df.empty else running_eval_queue_df, | |
| headers=EVAL_DISPLAY_HEADERS, | |
| datatype=EVAL_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(EVAL_DISPLAY_COLS) - 2), | |
| ) | |
| with gr.Accordion( | |
| f"Pending Evaluation Queue ({len(pending_eval_queue_df)})", | |
| open=False, elem_id="accordion-pending-eval", | |
| ) as accordion_pending_eval: | |
| pending_eval_table_auto_eval = gr.components.Dataframe( | |
| value=pending_eval_queue_df[EVAL_DISPLAY_COLS] if not pending_eval_queue_df.empty else pending_eval_queue_df, | |
| headers=EVAL_DISPLAY_HEADERS, | |
| datatype=EVAL_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(EVAL_DISPLAY_COLS) - 2), | |
| ) | |
| with gr.Accordion( | |
| f"Failed Evaluations ({len(failed_eval_queue_df)})", | |
| open=False, elem_id="accordion-failed-eval", | |
| ) as accordion_failed_eval: | |
| failed_eval_table_auto_eval = gr.components.Dataframe( | |
| value=failed_eval_queue_df[EVAL_DISPLAY_COLS] if not failed_eval_queue_df.empty else failed_eval_queue_df, | |
| headers=EVAL_DISPLAY_HEADERS, | |
| datatype=EVAL_DISPLAY_TYPES, | |
| row_count=5, | |
| column_widths=["40%", "20%"] + ["auto"] * (len(EVAL_DISPLAY_COLS) - 2), | |
| ) | |
| # ββ Page: Metrics ββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Column(visible=True, elem_id="page-metrics", elem_classes=["page-hidden"]) as page_metrics: | |
| with gr.Column(elem_id="metrics-layout"): | |
| # ββ KPI summary cards ββββββββββββββββββββββββββββββββββββββββββ | |
| _ms = compute_metrics_summary(auto_pipeline_results_df) | |
| _kpi_html = f""" | |
| <div style="display:flex;flex-wrap:wrap;gap:12px;margin-bottom:20px;"> | |
| <div class="metrics-kpi-card"> | |
| <div class="metrics-kpi-value">{_ms['total_models']}</div> | |
| <div class="metrics-kpi-label">Models Evaluated</div> | |
| </div> | |
| <div class="metrics-kpi-card"> | |
| <div class="metrics-kpi-value">{_ms['best_score'] if _ms['best_score'] is not None else 'β'}</div> | |
| <div class="metrics-kpi-label">Best Average Score (%)</div> | |
| <div class="metrics-kpi-sub" title="{_ms['best_model']}">{(_ms['best_model'][:30] + 'β¦') if len(_ms['best_model']) > 30 else _ms['best_model']}</div> | |
| </div> | |
| <div class="metrics-kpi-card"> | |
| <div class="metrics-kpi-value">{_ms['unique_schemes']}</div> | |
| <div class="metrics-kpi-label">Quant Schemes</div> | |
| </div> | |
| <div class="metrics-kpi-card"> | |
| <div class="metrics-kpi-value">{_ms['unique_methods']}</div> | |
| <div class="metrics-kpi-label">Quant Methods</div> | |
| </div> | |
| <div class="metrics-kpi-card"> | |
| <div class="metrics-kpi-value">{_ms['auto_quant_count']}</div> | |
| <div class="metrics-kpi-label">Quantization Runs</div> | |
| </div> | |
| <div class="metrics-kpi-card"> | |
| <div class="metrics-kpi-value">{_ms['auto_eval_count']}</div> | |
| <div class="metrics-kpi-label">Evaluation Runs</div> | |
| </div> | |
| <div class="metrics-kpi-card"> | |
| <div class="metrics-kpi-value" style="font-size:1.1rem;">{_ms['latest_date']}</div> | |
| <div class="metrics-kpi-label">Latest Evaluation</div> | |
| </div> | |
| </div> | |
| """ | |
| gr.HTML(_kpi_html) | |
| # ββ Row 1: Scheme accuracy + Score distribution ββββββββββββββββ | |
| with gr.Row(equal_height=False): | |
| with gr.Column(scale=3, min_width=300): | |
| gr.HTML("<h3 style='margin:0 0 4px 0;font-size:1rem;font-weight:700;color:#1e3a8a;'>Average Score by Quantization Scheme</h3>") | |
| gr.Plot(value=create_scheme_accuracy_chart(auto_pipeline_results_df), min_width=300) | |
| with gr.Column(scale=2, min_width=260): | |
| gr.HTML("<h3 style='margin:0 0 4px 0;font-size:1rem;font-weight:700;color:#1e3a8a;'>Score Distribution</h3>") | |
| gr.Plot(value=create_score_distribution_chart(auto_pipeline_results_df), min_width=260) | |
| # ββ Row 2: Submission timeline + Method comparison βββββββββββββ | |
| with gr.Row(equal_height=False): | |
| with gr.Column(scale=2, min_width=260): | |
| gr.HTML("<h3 style='margin:0 0 4px 0;font-size:1rem;font-weight:700;color:#1e3a8a;'>Submissions per Month</h3>") | |
| gr.Plot(value=create_submission_timeline_chart(auto_pipeline_results_df), min_width=260) | |
| with gr.Column(scale=3, min_width=300): | |
| gr.HTML("<h3 style='margin:0 0 4px 0;font-size:1rem;font-weight:700;color:#1e3a8a;'>Best Score by Quantization Method</h3>") | |
| gr.Plot(value=create_method_comparison_chart(auto_pipeline_results_df), min_width=300) | |
| # ββ Benchmark profile lines for top-10 ββββββββββββββββββββββββ | |
| _chart_df = auto_pipeline_results_df.copy() | |
| _chart_df[auto_eval_cols.dummy.name] = _chart_df["Model"].apply( | |
| lambda x: re.sub(r'<[^>]+>', '', str(x)).strip() if pd.notna(x) else "" | |
| ) | |
| gr.HTML("<h3 style='margin:20px 0 4px 0;font-size:1rem;font-weight:700;color:#1e3a8a;'>Top 10 Models β Score Profile Across Benchmarks</h3>") | |
| gr.Plot(value=create_top10_benchmark_lines(_chart_df), min_width=400, elem_id="metrics-bench-lines") | |
| gr.HTML(""" | |
| <script> | |
| (function () { | |
| "use strict"; | |
| function syncImages(plotDiv) { | |
| var meta = (plotDiv.layout || {}).meta || {}; | |
| var groups = meta.image_groups || {}; | |
| var update = {}; | |
| (plotDiv.data || []).forEach(function (trace) { | |
| var visible = trace.visible !== false && trace.visible !== "legendonly"; | |
| (groups[trace.name] || []).forEach(function (idx) { | |
| update["images[" + idx + "].visible"] = visible; | |
| }); | |
| }); | |
| if (Object.keys(update).length) Plotly.relayout(plotDiv, update); | |
| } | |
| function attachSync(plotDiv) { | |
| ["plotly_legendclick", "plotly_legenddoubleclick"].forEach(function (evt) { | |
| plotDiv.on(evt, function () { setTimeout(function () { syncImages(plotDiv); }, 80); }); | |
| }); | |
| } | |
| function tryAttach() { | |
| var el = document.querySelector("#metrics-bench-lines .js-plotly-plot"); | |
| if (el) { attachSync(el); return; } | |
| var obs = new MutationObserver(function (_, o) { | |
| var el2 = document.querySelector("#metrics-bench-lines .js-plotly-plot"); | |
| if (el2) { o.disconnect(); attachSync(el2); } | |
| }); | |
| obs.observe(document.body, { childList: true, subtree: true }); | |
| } | |
| if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", tryAttach); } else { tryAttach(); } | |
| }()); | |
| </script>""") | |
| # ββ Page: About ββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Column(visible=True, elem_id="page-about", elem_classes=["page-hidden"]) as page_about: | |
| gr.Markdown(LLM_BENCHMARKS_TEXT, elem_classes="markdown-text") | |
| gr.Markdown(ETHICAL_CONSIDERATIONS_TEXT, elem_classes="markdown-text") | |
| with gr.Accordion("Citation", open=False, elem_id="accordion-citation"): | |
| citation_button = gr.Textbox( | |
| value=CITATION_BUTTON_TEXT, | |
| label=CITATION_BUTTON_LABEL, | |
| lines=20, | |
| elem_id="citation-button", | |
| buttons=["copy"], | |
| ) | |
| # ββ Page: FAQ ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Column(visible=True, elem_id="page-faq", elem_classes=["page-hidden"]) as page_faq: | |
| gr.Markdown(FAQ_TEXT, elem_classes="markdown-text") | |
| # ββ Sidebar β page switching (handled entirely in client-side JS) ββ | |
| # Log user info on page load; show hardware dropdown for whitelisted users | |
| _USER_OUTPUTS = [hw_col_quant, hw_col_eval, username_state, current_user_quant, current_user_eval] | |
| demo.load( | |
| fn=process_user_on_load, | |
| inputs=None, | |
| outputs=_USER_OUTPUTS, | |
| ) | |
| # ββ Refresh queues immediately after a successful submission ββββ | |
| _REFRESH_OUTPUTS = [ | |
| finished_quant_table, running_quant_table, pending_quant_table, failed_quant_table, | |
| finished_eval_table_auto_eval, running_eval_table_auto_eval, | |
| pending_eval_table_auto_eval, failed_eval_table_auto_eval, | |
| accordion_finished_quant, accordion_running_quant, | |
| accordion_pending_quant, accordion_failed_quant, | |
| accordion_finished_eval, accordion_running_eval, | |
| accordion_pending_eval, accordion_failed_eval, | |
| ] | |
| _REFRESH_INPUTS = [my_submissions_quant_cb, my_submissions_eval_cb, username_state, | |
| queue_search_quant, queue_search_eval] | |
| _quant_submit_evt.then(fn=refresh_queue_tables, inputs=_REFRESH_INPUTS, outputs=_REFRESH_OUTPUTS) | |
| _eval_submit_evt.then(fn=refresh_queue_tables, inputs=_REFRESH_INPUTS, outputs=_REFRESH_OUTPUTS) | |
| # Checkbox filters β instantly re-filter the queue tables | |
| my_submissions_quant_cb.change( | |
| fn=refresh_queue_tables, | |
| inputs=_REFRESH_INPUTS, | |
| outputs=_REFRESH_OUTPUTS, | |
| ) | |
| my_submissions_eval_cb.change( | |
| fn=refresh_queue_tables, | |
| inputs=_REFRESH_INPUTS, | |
| outputs=_REFRESH_OUTPUTS, | |
| ) | |
| # ββ Disable submit immediately while user is typing βββββββββββββββββ | |
| model_name_textbox.input( | |
| fn=lambda _: gr.update(interactive=False), | |
| inputs=[model_name_textbox], | |
| outputs=[submit_button], | |
| ) | |
| model_name_textbox_auto_eval.input( | |
| fn=lambda _: gr.update(interactive=False), | |
| inputs=[model_name_textbox_auto_eval], | |
| outputs=[submit_button_auto_eval], | |
| ) | |
| # ββ Inline real-time checks (quant): dup β license, chained βββββββββ | |
| model_name_textbox.change( | |
| fn=inline_dup_check_quant, | |
| inputs=[model_name_textbox, compute_type, username_state], | |
| outputs=[dup_inline_quant, submit_button], | |
| ).then( | |
| fn=inline_license_check, | |
| inputs=[model_name_textbox, dup_inline_quant], | |
| outputs=[license_warning_quant, submit_button], | |
| queue=True, | |
| ) | |
| # ββ Inline real-time checks (eval): dup β license, chained ββββββββββ | |
| model_name_textbox_auto_eval.change( | |
| fn=inline_dup_check_eval, | |
| inputs=[model_name_textbox_auto_eval, compute_type_auto_eval, username_state], | |
| outputs=[dup_inline_eval, submit_button_auto_eval], | |
| ).then( | |
| fn=inline_license_check, | |
| inputs=[model_name_textbox_auto_eval, dup_inline_eval], | |
| outputs=[license_warning_eval, submit_button_auto_eval], | |
| queue=True, | |
| ) | |
| # scheme change also re-triggers the inline duplicate check | |
| compute_type.change( | |
| fn=lambda: gr.update(interactive=False), | |
| inputs=[], | |
| outputs=[submit_button], | |
| ).then( | |
| fn=inline_dup_check_quant, | |
| inputs=[model_name_textbox, compute_type, username_state], | |
| outputs=[dup_inline_quant, submit_button], | |
| ).then( | |
| fn=inline_license_check, | |
| inputs=[model_name_textbox, dup_inline_quant], | |
| outputs=[license_warning_quant, submit_button], | |
| queue=True, | |
| ) | |
| compute_type_auto_eval.change( | |
| fn=lambda: gr.update(interactive=False), | |
| inputs=[], | |
| outputs=[submit_button_auto_eval], | |
| ).then( | |
| fn=inline_dup_check_eval, | |
| inputs=[model_name_textbox_auto_eval, compute_type_auto_eval, username_state], | |
| outputs=[dup_inline_eval, submit_button_auto_eval], | |
| ).then( | |
| fn=inline_license_check, | |
| inputs=[model_name_textbox_auto_eval, dup_inline_eval], | |
| outputs=[license_warning_eval, submit_button_auto_eval], | |
| queue=True, | |
| ) | |
| # ββ Queue search textbox events βββββββββββββββββββββββββββββββββββ | |
| for _search_box in [queue_search_quant, queue_search_eval]: | |
| _search_box.submit(fn=refresh_queue_tables, inputs=_REFRESH_INPUTS, outputs=_REFRESH_OUTPUTS) | |
| _search_box.input(fn=refresh_queue_tables, inputs=_REFRESH_INPUTS, outputs=_REFRESH_OUTPUTS, queue=True) | |
| # When signal_box changes to "TRIGGER", redirect to OAuth login | |
| signal_box.change( | |
| fn=None, | |
| inputs=[signal_box], | |
| outputs=[], | |
| queue=False, | |
| js="""(sig) => { | |
| console.log('[signal_box.change] value:', sig); | |
| if (sig === "TRIGGER") { | |
| const el = document.getElementById("real_login_btn"); | |
| if (el) { | |
| // Try every clickable descendant in order of specificity | |
| const btn = el.querySelector('a[href]') | |
| || el.querySelector('button') | |
| || el.querySelector('a') | |
| || el; | |
| console.log('[signal_box.change] Clicking login button', btn.tagName); | |
| // Remove visual hiding temporarily so the click registers | |
| const prev = el.style.cssText; | |
| el.style.cssText = 'position:absolute;opacity:0;height:1px;width:1px;overflow:hidden;'; | |
| btn.click(); | |
| el.style.cssText = prev; | |
| } | |
| } | |
| }""", | |
| ) | |
| # ββ Live queue refresh (every 60 s, transparent to the user) βββββββββ | |
| _queue_timer = gr.Timer(value=60) | |
| _queue_timer.tick( | |
| fn=refresh_queue_tables, | |
| inputs=_REFRESH_INPUTS, | |
| outputs=_REFRESH_OUTPUTS, | |
| ) | |
| # ββ Live pipeline leaderboard refresh (every 60 s) ββββββββββββββββββββ | |
| _pipeline_refresh_inputs = [ | |
| auto_pipeline_shown_columns, | |
| auto_pipeline_filter, | |
| auto_pipeline_scheme_filter, | |
| auto_pipeline_search_bar, | |
| auto_pipeline_min_size_slider, | |
| auto_pipeline_size_slider, | |
| ] | |
| _pipeline_refresh_outputs = [hidden_auto_pipeline_table, auto_pipeline_table] | |
| _queue_timer.tick( | |
| fn=refresh_pipeline_leaderboard, | |
| inputs=_pipeline_refresh_inputs, | |
| outputs=_pipeline_refresh_outputs, | |
| trigger_mode="always_last", | |
| concurrency_id="pipeline-filter", | |
| concurrency_limit=1, | |
| show_progress="hidden", | |
| ) | |
| demo.queue(default_concurrency_limit=40) | |
| # Mount Gradio under a FastAPI root so we can serve /api/hf-model-zip alongside it. | |
| _api_app = FastAPI() | |
| register_zip_route(_api_app) | |
| app = gr.mount_gradio_app( | |
| _api_app, | |
| demo, | |
| path="/", | |
| ssr_mode=False, | |
| css=custom_css, | |
| head=SIDEBAR_HEAD, | |
| ) | |
| if __name__ == "__main__": | |
| import uvicorn | |
| scheduler = BackgroundScheduler() | |
| scheduler.add_job(restart_space, "interval", hours=3, id="restart_space") | |
| scheduler.add_job(update_dynamic_files, "interval", hours=12, id="update_dynamic_files") | |
| _ci_dispatcher = CIDispatcher( | |
| repo=REPO, | |
| git_lock=GLOBAL_COND, | |
| status_path=GIT_STATUS_PATH, | |
| requests_path=GIT_REQUESTS_PATH, | |
| azure_pat=AZP_DEVOPS_PAT, | |
| max_concurrent=2, | |
| enable_retry=ENABLE_RETRY, | |
| ) | |
| scheduler.add_job( | |
| _ci_dispatcher.scan_and_dispatch, | |
| "interval", | |
| seconds=60, | |
| max_instances=1, | |
| coalesce=True, | |
| id="ci_dispatcher", | |
| ) | |
| scheduler.start() | |
| port = int( | |
| os.environ.get("PORT") | |
| or os.environ.get("GRADIO_SERVER_PORT") | |
| or "7860" | |
| ) | |
| uvicorn.run( | |
| "__main__:app", | |
| host="0.0.0.0", | |
| port=port, | |
| proxy_headers=True, | |
| forwarded_allow_ips="*", | |
| ) | |