lvkaokao's picture
disable auto-retry, gguf, set <32B for evaluation
cbcbfc6
Raw History Blame Contribute Delete
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="*",
)