from html import escape from math import ceil, floor, log10 from pathlib import Path import base64 import random import gradio as gr import pandas as pd import plotly.graph_objects as go from model_display import display_model_name _LOGO_PATH = Path(__file__).resolve().parent / "pruna-logo.png" _LOGO_DATA_URI = ( "data:image/png;base64," + base64.b64encode(_LOGO_PATH.read_bytes()).decode("ascii") if _LOGO_PATH.exists() else "https://playground.pruna.ai/logo.svg" ) MAX_COMPARE_MODELS = 4 DEFAULT_COMPARE_PROMPTS = 3 MAX_COMPARE_PROMPTS = 8 MAX_PARETO_METRICS = 8 _PARETO_SLOT_COUNT = 1 + MAX_PARETO_METRICS * 8 _PARETO_PRICE_COLUMN = "Price / Image (USD)" _PARETO_TIME_COLUMN = "Min Generation Time (s)" _PARETO_SCALE_CHOICES = [ ("Linear", "Linear"), ("Log", "Logarithmic"), ] _PARETO_SCALE_VALUES = {value for _, value in _PARETO_SCALE_CHOICES} _PARETO_SCALE_DEFAULT = "Linear" TAB_LEADERBOARDS = "leaderboards" TAB_PARETO = "pareto" TAB_SAMPLES = "samples" TAB_ABOUT = "about" _MODEL_CHOICES_CACHE = {} _VIEW_EVENTS = { "show_progress": "hidden", "trigger_mode": "always_last", "concurrency_id": "workspace-views", "concurrency_limit": 1, } ABOUT_OVERVIEW_CONTENT = """ # About P-Bench P-Bench compares **text-to-image models**, including optimized or accelerated endpoints, on **quality, speed, and price**. Each view is a **dataset** scored with a **metric**, written as `Dataset | Metric`. There is no single score across P-Bench. ## How to read it 1. Pick a **dataset** and a **metric**. 2. **Leaderboards**: ranked by that metric. Price and generation time sit in the same table when the source publishes them. 3. **Pareto plots**: mark models that are not beaten on both higher score and lower price (or time). Only datasets with price or generation time can open this tab (not Arena AI). 4. **Samples**: the same prompts, side by side. Only for datasets we generated (Qwen Image Dataset and OneIG Alignment Dataset). ## How a score is made On **Qwen Image Dataset** and **OneIG Alignment Dataset**: 1. Each endpoint is given the same prompt suite. 2. It generates one image per prompt when the run succeeds. Not every model has every prompt or every metric. 3. Quality is scored automatically (OneIG alignment, P-Judger) and, where available, by human preference (Datapoint Elo, Rapidata Elo). 4. Price per image and generation time are joined from the evaluation table. **Artificial Analysis** and **Arena AI** are external leaderboards. We import their published Elos (and Artificial Analysis price). We do not run their prompt suites, so samples are not shown. ## Current datasets ### Qwen Image Dataset 100 prompts from the 1,000-prompt Qwen Image Bench set, sampled for coverage across its fine-grained (L3) categories. Metrics include Datapoint Elo, Rapidata Elo, and P-Judger. Samples are available. ### OneIG Alignment Dataset Prompt-image **alignment** on anime / stylization (100), human / portrait (100), and general object prompts (99). This is the alignment slice of OneIG, not the full suite. Alignment Overall is the mean of the category scores that exist for that row. Also includes Datapoint category Elo, Rapidata Elo, and P-Judger. Samples are available. ### Artificial Analysis Dataset External text-to-image Elo and price per image from Artificial Analysis. Their prompt set is private, so samples are not shown. Pareto plots use price vs score only. ### Arena AI Dataset External text-to-image Elo (overall and category) from Arena AI. Their prompt set is private, so samples are not shown. Price and generation time are not in this export, so Pareto plots are unavailable. """ ABOUT_DETAILS_CONTENT = """ # Metrics & limits ## Metrics - **Alignment**: how well the image matches the prompt (OneIG category scores). - **P-Judger**: Pruna's automatic judger. A private scoring model that rates each (prompt, image) pair in one pass and returns an absolute quality score, not a pairwise Elo. It is not a text-to-image model on the leaderboard. Use it alongside Datapoint and Rapidata Elo, not instead of them. - **Datapoint Elo**: human-preference Elo from Datapoint pairwise comparisons. - **Rapidata Elo**: human-preference Elo from Rapidata pairwise comparisons. Rapidata rejects prompts over 400 characters, so this Elo is on a subset of each suite (see Setup). Rapidata is not a dataset. - **Artificial Analysis Elo**: Elo published by Artificial Analysis on their own dataset. - **Arena Elo**: Elo published by Arena AI on their own dataset, plus category Elos (branding, 3D, cartoon/anime, photorealistic, art, portraits, text rendering). - **Generation time**: median and minimum generation time in seconds, as reported in the evaluation table. This is not a p95, and we do not state warm vs cold or concurrent load. Not available for Arena AI. - **Price**: USD per image in the evaluation table. We do not state list price vs amount paid, or whether failed generations are included. Not available for Arena AI. Scores from different datasets or metrics are **not interchangeable**. A high OneIG alignment score is not the same quantity as a Datapoint Elo. Compare models *within* a Dataset | Metric view. ## Setup - **Evaluation window:** July–August 2026. - **Update policy:** numbers come from evaluation snapshots in the tables, not a live API poll. - **Prompt counts:** OneIG Alignment uses 100 anime, 100 human, and 99 object prompts (299 total). Qwen Image Dataset uses 100 prompts sampled from the 1,000-prompt pool for roughly even coverage of its fine-grained (L3) categories. Artificial Analysis and Arena AI use their own private prompt sets. - **Generation (Qwen and OneIG):** one image per prompt per endpoint when the run exists. Default resolution is 1024×1024. Exceptions: FLUX 1.1 Pro Ultra at 2K, FLUX 2 Flex at 1008×1008, and any endpoint labeled 2K. The seed is derived from the prompt, so every model gets the same seed for the same prompt. Steps, CFG, prompt rewrite, and safety filters follow each endpoint's default. This does not describe Artificial Analysis or Arena AI. - **Datapoint (Qwen and OneIG):** every model pair is compared on every prompt, with 10 votes per battle. - **Rapidata (Qwen and OneIG):** prompts longer than 400 characters are dropped, leaving 212 OneIG prompts and 85 Qwen Image Dataset prompts. 4 votes per pair; about 26,000 votes on OneIG and 35,000 on Qwen Image Dataset. ## Limits - Empty cells mean that track was not run or not reported for that model. - Artificial Analysis and Arena AI samples, prompts, and (for Arena) price or latency are not available to P-Bench. - Rapidata Elo is not on the full prompt suite, so it is not directly comparable to Datapoint Elo even on the same dataset. - Elo ratings can shift when the comparison pool changes: treat them as relative rankings for the snapshot, not absolute constants. - Close scores can be a tie in practice; the table does not show confidence intervals. - Optimized or accelerated endpoints (when labeled) may differ from the base model publisher's default serving stack. - APIs and prices drift; a rank is for the snapshot, not a guarantee. Built by [Pruna AI](https://www.pruna.ai/). If you have questions, reach out to us on [Discord](https://discord.gg/JFQmtFKCjd). """ FOOTER_CONTENT = """
""" CITATION_CONTENT = """ ```bibtex @misc{P-Bench, title={P-Bench: A Leaderboard for Text-to-Image Models}, author={PrunaAI}, year={2026}, howpublished={\\url{https://huggingface.co/spaces/PrunaAI/P-Bench}} } ``` """ def render_header(): gr.HTML( f"""Compare text-to-image models on quality, speed, and price
" f"{escape(message)}" "
" ) def _pareto_note_update(message): if message: return gr.update( value=_pareto_unavailable_html(message), visible=True, ) return gr.update(value="", visible=False) def _pareto_plot_update(fig): if fig is not None: return gr.update(value=fig, visible=True) return gr.update(value=None, visible=False) def _skip_all(count): return tuple(gr.skip() for _ in range(count)) def _pareto_skip_updates(): return _skip_all(_PARETO_SLOT_COUNT) def _selection_key(dataset_id, metric_id, models): return ( dataset_id, tuple(_normalize_metric_ids(metric_id)), tuple(models or ()), ) def _applied_key(view_state): view_state = view_state or {} return _selection_key( view_state.get("dataset_id"), view_state.get("metric_id"), view_state.get("models"), ) def _build_pareto_figure( data, score_column, x_column, x_title, x_hover_prefix="", x_hover_suffix="", x_axis_type="linear", ): scatter = ( data[["Model", score_column, x_column]] .dropna() .copy() .reset_index(drop=True) ) if scatter.empty: return None x_values = scatter[x_column].astype(float).tolist() scores = scatter[score_column].astype(float).tolist() on_frontier = _pareto_frontier_mask(x_values, scores) dominated = scatter.loc[[not flag for flag in on_frontier]].copy() frontier = scatter.loc[on_frontier].sort_values(x_column).copy() if not dominated.empty: dominated["Model"] = dominated["Model"].map(display_model_name) if not frontier.empty: frontier["Model"] = frontier["Model"].map(display_model_name) hover = ( "%{text}{prompt_text}
" + " ".join(parts) + "
" def _filter_row(datasets, metrics, default_dataset_id, default_metric_id=None): metric_id = _coerce_metric( datasets, metrics, default_dataset_id, default_metric_id ) with gr.Row(elem_classes="view-filters"): dataset_dd = gr.Dropdown( choices=_dataset_choices(datasets), value=default_dataset_id, label="Dataset", type="value", filterable=False, scale=2, min_width=160, ) metric_dd = gr.Dropdown( choices=_metric_dropdown_choices(datasets, metrics, default_dataset_id), value=_metric_dropdown_value(metric_id), label="Metric", type="value", multiselect=True, allow_custom_value=False, filterable=True, scale=2, min_width=180, elem_classes="filter-chips", ) models_dd = gr.Dropdown( choices=_model_choices(datasets, default_dataset_id), value=[], multiselect=True, label="Models", type="value", allow_custom_value=False, filterable=True, scale=2, min_width=180, elem_classes="filter-chips", ) return dataset_dd, metric_dd, models_dd def render_image_workspace(datasets, metrics, default_dataset_id, default_metric_id): default_metric_id = _coerce_metric( datasets, metrics, default_dataset_id, default_metric_id ) initial = resolve_view(datasets, metrics, default_dataset_id, default_metric_id) initial_data = initial["data"] initial_columns = initial["columns"] initial_samples = initial.get("samples") with gr.Column(elem_classes="workspace-shell"): with gr.Column(elem_classes="workspace-filters") as filters_host: gr.Markdown( "" "These filters apply to Leaderboards, Pareto plots, and Samples. " "On Samples, only datasets we have generations for are listed. " "On Pareto plots, only datasets with price or generation time " "are listed. Search in Models, or leave it empty to include " "every model." "
", elem_classes="filter-help-host", ) dataset_dd, metric_dd, models_dd = _filter_row( datasets, metrics, default_dataset_id, None ) with gr.Tabs(elem_classes="main-tabs") as main_tabs: with gr.TabItem("Leaderboards", id=TAB_LEADERBOARDS) as lb_tab: lb_note = gr.Markdown( _leaderboard_intro_markdown(initial.get("note")), elem_classes="view-help-host", ) platform_choices = _filter_choices(initial_data, "Platform") owner_choices = _filter_choices(initial_data, "Endpoint Owner") optimized_choices = _filter_choices(initial_data, "Optimized") with gr.Row( elem_classes="leaderboard-controls", visible=bool( platform_choices or owner_choices or optimized_choices ), ) as lb_controls: platform = gr.Dropdown( choices=platform_choices, value=[], label="Providers", multiselect=True, allow_custom_value=False, filterable=False, scale=1, visible=bool(platform_choices), ) owner = gr.Dropdown( choices=owner_choices, value=[], label="Endpoint owners", multiselect=True, allow_custom_value=False, filterable=False, scale=1, visible=bool(owner_choices), ) optimized = gr.Dropdown( choices=optimized_choices, value=[], label="Optimized", multiselect=True, allow_custom_value=False, filterable=False, scale=1, visible=bool(optimized_choices), ) ranking = gr.HTML( _leaderboard_html( _assign_leaderboard_ranks( initial_data, initial.get("score_column") ), initial_columns, ), padding=False, elem_classes="ranking-table-host", ) with gr.TabItem( "Pareto Plots", id=TAB_PARETO, interactive=_dataset_has_pareto(datasets, default_dataset_id), ) as pp_tab: gr.Markdown( "" "Score against price and generation time. Green points are on " "the frontier; lavender points sit below it. Hover a point to " "see which model it is." "
" "" "You can switch between linear and logarithmic scale for all " "the plots, or individually for each plots." "
", elem_classes="view-help-host", ) with gr.Row( equal_height=False, elem_classes="pareto-scale-all-row", ): gr.HTML( "All plots", padding=False, ) pareto_all_scale = _pareto_scale_radio( "pareto-scale-toggle-all", ) pareto_dataset_note = gr.HTML( "", padding=False, visible=False, elem_classes="pareto-note", ) pareto_slots = [] for slot_index in range(MAX_PARETO_METRICS): with gr.Column( visible=False, elem_classes="pareto-metric-block", ) as slot_group: slot_title = gr.Markdown( "", elem_classes="pareto-metric-title", ) with gr.Row( equal_height=True, elem_classes="pareto-layout", ) as slot_layout: with gr.Column( scale=1, min_width=320, elem_classes="pareto-col", ) as slot_price_col: slot_price_scale = _pareto_plot_heading( "Price vs score" ) slot_price = gr.Plot( value=None, show_label=False, elem_classes="pareto-plot", ) with gr.Column( scale=1, min_width=320, elem_classes="pareto-col", ) as slot_time_col: slot_time_scale = _pareto_plot_heading( "Min generation time vs score" ) slot_time = gr.Plot( value=None, show_label=False, elem_classes="pareto-plot", ) slot_note = gr.HTML( "", padding=False, visible=False, elem_classes="pareto-note", ) pareto_slots.append( ( slot_group, slot_title, slot_note, slot_layout, slot_price_col, slot_price, slot_price_scale, slot_time_col, slot_time, slot_time_scale, ) ) with gr.TabItem( "Samples", id=TAB_SAMPLES, interactive=_dataset_has_samples(datasets, default_dataset_id), ) as sm_tab: with gr.Column(visible=bool(initial_samples)) as samples_panel: gr.Markdown( f"" f"The same prompts, side by side. Select up to " f"{MAX_COMPARE_MODELS} models above, or leave " f"Models empty for two defaults." f"
", elem_classes="view-help-host", ) with gr.Row(equal_height=False, elem_classes="compare-controls"): prompt_count = gr.Slider( minimum=1, maximum=MAX_COMPARE_PROMPTS, value=DEFAULT_COMPARE_PROMPTS, step=1, label="Prompts to show", container=False, show_reset_button=False, scale=1, min_width=180, elem_classes="compare-prompt-count", ) shuffle_button = gr.Button( "Shuffle prompts", variant="primary", scale=0, min_width=140, elem_classes="compare-shuffle", ) gallery = gr.HTML( value=_samples_html( initial_samples, [], DEFAULT_COMPARE_PROMPTS, seed=0 ), elem_classes="compare-gallery", ) seed_state = gr.State(0) with gr.TabItem("About", id=TAB_ABOUT) as about_tab: render_about() def _synced_filters(dataset_id, metric_id, models, *, clear_metric=False): if clear_metric: metric_id = [] else: metric_id = _coerce_metric(datasets, metrics, dataset_id, metric_id) model_choices = _model_choices(datasets, dataset_id) model_values = set(_model_choice_values(model_choices)) models = [model for model in (models or []) if model in model_values] metric_choices = _metric_dropdown_choices(datasets, metrics, dataset_id) return ( dataset_id, metric_id, models, gr.update( choices=metric_choices, value=_metric_dropdown_value(metric_id), ), gr.update(choices=model_choices, value=models), ) def _leaderboard_extras(data, platform_value, owner_value, optimized_value): platform_choices = _filter_choices(data, "Platform") owner_choices = _filter_choices(data, "Endpoint Owner") optimized_choices = _filter_choices(data, "Optimized") platform_value = [ value for value in (platform_value or []) if value in platform_choices ] owner_value = [ value for value in (owner_value or []) if value in owner_choices ] optimized_value = [ value for value in (optimized_value or []) if value in optimized_choices ] return ( gr.update( choices=platform_choices, value=platform_value, visible=bool(platform_choices), ), gr.update( choices=owner_choices, value=owner_value, visible=bool(owner_choices), ), gr.update( choices=optimized_choices, value=optimized_value, visible=bool(optimized_choices), ), platform_value, owner_value, optimized_value, gr.update( visible=bool( platform_choices or owner_choices or optimized_choices ) ), ) def _content_flags(tab): return { "include_leaderboard": tab == TAB_LEADERBOARDS, "include_pareto": tab == TAB_PARETO, "include_samples": tab == TAB_SAMPLES, } def _commit_state( view_state, dataset_id, metric_id, models, tab, flags, extras=None, ): prev = dict(view_state or {}) extras = extras or {} return { "dataset_id": dataset_id, "metric_id": metric_id, "models": list(models or []), "current_tab": tab, "platform": list( extras.get("platform", prev.get("platform") or []) ), "owner": list(extras.get("owner", prev.get("owner") or [])), "optimized": list( extras.get("optimized", prev.get("optimized") or []) ), "price_scales": _normalize_pareto_scales(prev.get("price_scales")), "time_scales": _normalize_pareto_scales(prev.get("time_scales")), "stale": { TAB_LEADERBOARDS: not flags["include_leaderboard"], TAB_PARETO: not flags["include_pareto"], TAB_SAMPLES: not flags["include_samples"], }, } def _save_leaderboard_filters( view_state, platform_value, owner_value, optimized_value ): view_state["platform"] = list(platform_value or []) view_state["owner"] = list(owner_value or []) view_state["optimized"] = list(optimized_value or []) return view_state def _restore_leaderboard_filters( view_state, platform_value, owner_value, optimized_value ): stored_platform = (view_state or {}).get("platform") or [] stored_owner = (view_state or {}).get("owner") or [] stored_optimized = (view_state or {}).get("optimized") or [] view = resolve_view( datasets, metrics, (view_state or {}).get("dataset_id"), (view_state or {}).get("metric_id"), ) extras = _leaderboard_extras( view["data"] if view else None, stored_platform, stored_owner, stored_optimized, ) platform_update = extras[0] if list(platform_value or []) != extras[3] else gr.skip() owner_update = extras[1] if list(owner_value or []) != extras[4] else gr.skip() optimized_update = extras[2] if list(optimized_value or []) != extras[5] else gr.skip() return ( extras[6], platform_update, owner_update, optimized_update, extras[3], extras[4], extras[5], ) def _views( dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, *, include_leaderboard=True, include_pareto=False, include_samples=False, price_scales=None, time_scales=None, ): view = resolve_view(datasets, metrics, dataset_id, metric_id) data = view["data"] if include_leaderboard: note = _leaderboard_intro_markdown(view.get("note")) ranking_html = _leaderboard_html( _filter_leaderboard( _assign_leaderboard_ranks(data, view["score_column"]), platform_value or [], owner_value or [], optimized_value or [], models=models, ), view["columns"], ) else: note = gr.skip() ranking_html = gr.skip() if include_pareto: pareto_data = _filter_leaderboard(data, [], [], [], models=models) pareto_updates = _pareto_slot_updates( pareto_data, view["score_columns"], price_scales=price_scales, time_scales=time_scales, ) else: pareto_updates = _pareto_skip_updates() if include_samples: samples = view.get("samples") samples_html = _samples_html( samples, models, int(num_prompts or DEFAULT_COMPARE_PROMPTS), int(seed or 0), ) samples_visible = gr.update(visible=bool(samples)) else: samples_html = gr.skip() samples_visible = gr.skip() return ( note, ranking_html, *pareto_updates, samples_html, samples_visible, ) def _apply_filter_change( source, dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ): view_state = dict(view_state or {}) tab = view_state.get("current_tab") or TAB_LEADERBOARDS selected_raw = _normalize_metric_ids(metric_id) incoming_models = list(models or []) dataset_changed = source == "dataset" and dataset_id != view_state.get( "dataset_id" ) if source == "dataset": synced = _synced_filters( dataset_id, metric_id, models, clear_metric=dataset_changed ) dataset_id, metric_id, models = synced[:3] metric_update, models_update = synced[3], synced[4] else: metric_id = _coerce_metric(datasets, metrics, dataset_id, metric_id) if source == "models": allowed = set( _model_choice_values(_model_choices(datasets, dataset_id)) ) models = [model for model in incoming_models if model in allowed] models_update = ( gr.update(value=models) if models != incoming_models else gr.skip() ) else: models = incoming_models models_update = gr.skip() metric_update = ( gr.update( choices=_metric_dropdown_choices(datasets, metrics, dataset_id), value=_metric_dropdown_value(metric_id), ) if source == "metric" and ALL_METRICS_ID in selected_raw else gr.skip() ) unchanged = _applied_key(view_state) == _selection_key( dataset_id, metric_id, models ) if ( not dataset_changed and not (source == "metric" and ALL_METRICS_ID in selected_raw) and unchanged ): return None selected_tab = tab extras = ( list(platform_value or []), list(owner_value or []), list(optimized_value or []), ) extra_updates = None can_pareto = _dataset_has_pareto(datasets, dataset_id) can_samples = _dataset_has_samples(datasets, dataset_id) if source == "dataset": if tab == TAB_SAMPLES and not can_samples: selected_tab = TAB_LEADERBOARDS elif tab == TAB_PARETO and not can_pareto: selected_tab = TAB_LEADERBOARDS view = resolve_view(datasets, metrics, dataset_id, metric_id) extra_updates = _leaderboard_extras( view["data"] if view else None, platform_value, owner_value, optimized_value, ) extras = extra_updates[3:6] flags = _content_flags(selected_tab) extras_payload = ( { "platform": extras[0], "owner": extras[1], "optimized": extras[2], } if selected_tab == TAB_LEADERBOARDS else {} ) return { "dataset_id": dataset_id, "metric_update": metric_update, "models_update": models_update, "selected_tab": selected_tab, "tab": tab, "extra_updates": extra_updates, "can_pareto": can_pareto, "can_samples": can_samples, "views": _views( dataset_id, metric_id, models, extras[0], extras[1], extras[2], num_prompts, seed, price_scales=view_state.get("price_scales"), time_scales=view_state.get("time_scales"), **flags, ), "state": _commit_state( view_state, dataset_id, metric_id, models, selected_tab, flags, extras=extras_payload, ), } def on_dataset( dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ): result = _apply_filter_change( "dataset", dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ) if result is None: return _skip_all(len(dataset_outputs)) extras = result["extra_updates"] return ( _dataset_dropdown_update( datasets, result["selected_tab"], result["dataset_id"] ), result["metric_update"], result["models_update"], extras[6], extras[0], extras[1], extras[2], *result["views"], gr.update(interactive=result["can_pareto"]), gr.update(interactive=result["can_samples"]), gr.update(selected=result["selected_tab"]) if result["selected_tab"] != result["tab"] else gr.skip(), result["state"], ) def on_metric( dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ): result = _apply_filter_change( "metric", dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ) if result is None: return _skip_all(len(metric_outputs)) return (result["metric_update"], *result["views"], result["state"]) def on_models( dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ): result = _apply_filter_change( "models", dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ) if result is None: return _skip_all(len(models_outputs)) return (result["models_update"], *result["views"], result["state"]) def on_tab_select( tab, dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ): view_state = dict(view_state or {}) prev_tab = view_state.get("current_tab") or TAB_LEADERBOARDS requested_tab = tab if tab == TAB_SAMPLES and not _dataset_has_samples(datasets, dataset_id): tab = TAB_LEADERBOARDS elif tab == TAB_PARETO and not _dataset_has_pareto(datasets, dataset_id): tab = TAB_LEADERBOARDS if prev_tab == TAB_LEADERBOARDS: _save_leaderboard_filters( view_state, platform_value, owner_value, optimized_value, ) dataset_update = _dataset_dropdown_update(datasets, tab, dataset_id) metric_id = _coerce_metric(datasets, metrics, dataset_id, metric_id) models = list(models or []) view_state["current_tab"] = tab view_state["dataset_id"] = dataset_id view_state["metric_id"] = metric_id view_state["models"] = models show_filters = tab != TAB_ABOUT show_metric = tab in (TAB_LEADERBOARDS, TAB_PARETO) was_filters = prev_tab != TAB_ABOUT was_metric = prev_tab in (TAB_LEADERBOARDS, TAB_PARETO) filters_vis = ( gr.update(visible=show_filters) if show_filters != was_filters else gr.skip() ) metric_vis = ( gr.update(visible=show_metric) if show_metric != was_metric else gr.skip() ) if tab == TAB_LEADERBOARDS: restored = _restore_leaderboard_filters( view_state, platform_value, owner_value, optimized_value, ) platform_value = restored[4] owner_value = restored[5] optimized_value = restored[6] lb_filters = restored[:4] else: lb_filters = _skip_all(4) stale = dict(view_state.get("stale") or {}) chrome = ( filters_vis, dataset_update, metric_vis, gr.skip(), *lb_filters, ) tab_select = ( gr.update(selected=tab) if tab != requested_tab else gr.skip() ) if tab == TAB_ABOUT or not stale.get(tab, True): return ( *chrome, *_skip_all(len(view_outputs)), tab_select, view_state, ) flags = _content_flags(tab) views = _views( dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, price_scales=view_state.get("price_scales"), time_scales=view_state.get("time_scales"), **flags, ) stale[tab] = False view_state["stale"] = stale return (*chrome, *views, tab_select, view_state) def on_leaderboard_filters( dataset_id, metric_id, models, platform_value, owner_value, optimized_value, view_state, ): view_state = dict(view_state or {}) _save_leaderboard_filters( view_state, platform_value, owner_value, optimized_value, ) view = resolve_view(datasets, metrics, dataset_id, metric_id) return ( _leaderboard_html( _filter_leaderboard( _assign_leaderboard_ranks(view["data"], view["score_column"]), platform_value or [], owner_value or [], optimized_value or [], models=models, ), view["columns"], ), view_state, ) def on_samples_controls(dataset_id, models, num_prompts, seed): view = resolve_view(datasets, metrics, dataset_id, None) return _samples_html( view.get("samples") if view else None, models, int(num_prompts or DEFAULT_COMPARE_PROMPTS), int(seed or 0), ) def on_shuffle(dataset_id, models, num_prompts, seed): next_seed = int(seed or 0) + 1 view = resolve_view(datasets, metrics, dataset_id, None) return next_seed, _samples_html( view.get("samples") if view else None, models, int(num_prompts or DEFAULT_COMPARE_PROMPTS), next_seed, ) def _on_pareto_plot_scale(slot_index, axis): def handler(dataset_id, metric_id, models, scale, view_state): view_state = dict(view_state or {}) price_scales = _normalize_pareto_scales( view_state.get("price_scales") ) time_scales = _normalize_pareto_scales( view_state.get("time_scales") ) if axis == "price": if price_scales[slot_index] == scale: return gr.skip(), gr.skip(), gr.skip() price_scales[slot_index] = scale else: if time_scales[slot_index] == scale: return gr.skip(), gr.skip(), gr.skip() time_scales[slot_index] = scale view_state["price_scales"] = price_scales view_state["time_scales"] = time_scales master_scale = _pareto_master_scale_update( price_scales, time_scales ) view = resolve_view(datasets, metrics, dataset_id, metric_id) score_columns = [ column for column in (view["score_columns"] or []) if column ] if slot_index >= len(score_columns): return gr.skip(), master_scale, view_state data = _filter_leaderboard( view["data"], [], [], [], models=list(models or []) ) price_fig, _, time_fig, _ = _pareto_pair( data, score_columns[slot_index], latency_scale=time_scales[slot_index], price_scale=price_scales[slot_index], ) fig = price_fig if axis == "price" else time_fig return _pareto_plot_update(fig), master_scale, view_state handler.__name__ = f"on_pareto_{axis}_scale_{slot_index}" return handler def on_pareto_all_scale(dataset_id, metric_id, models, scale, view_state): if scale not in _PARETO_SCALE_VALUES: return (*_skip_all(MAX_PARETO_METRICS * 4), gr.skip()) view_state = dict(view_state or {}) scales = _uniform_pareto_scales(scale) if ( _normalize_pareto_scales(view_state.get("price_scales")) == scales and _normalize_pareto_scales(view_state.get("time_scales")) == scales ): return (*_skip_all(MAX_PARETO_METRICS * 4), gr.skip()) view_state["price_scales"] = scales view_state["time_scales"] = scales view = resolve_view(datasets, metrics, dataset_id, metric_id) data = _filter_leaderboard( view["data"], [], [], [], models=list(models or []) ) return ( *_pareto_all_scale_updates(data, view["score_columns"], scale), view_state, ) def _on_tab(tab): def handler( dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ): return on_tab_select( tab, dataset_id, metric_id, models, platform_value, owner_value, optimized_value, num_prompts, seed, view_state, ) handler.__name__ = f"on_tab_{tab}" return handler view_state = gr.State( { "dataset_id": default_dataset_id, "metric_id": None, "models": [], "current_tab": TAB_LEADERBOARDS, "platform": [], "owner": [], "optimized": [], "price_scales": _default_pareto_scales(), "time_scales": _default_pareto_scales(), "stale": { TAB_LEADERBOARDS: False, TAB_PARETO: True, TAB_SAMPLES: False, }, } ) pareto_outputs = [ pareto_dataset_note, *[ component for slot_group, slot_title, slot_note, slot_layout, slot_price_col, slot_price, slot_price_scale, slot_time_col, slot_time, slot_time_scale in pareto_slots for component in ( slot_group, slot_title, slot_note, slot_layout, slot_price_col, slot_price, slot_time_col, slot_time, ) ], ] pareto_all_scale_outputs = [ *[ slot_price for _, _, _, _, _, slot_price, _, _, _, _ in pareto_slots ], *[ slot_time for _, _, _, _, _, _, _, _, slot_time, _ in pareto_slots ], *[ slot_price_scale for _, _, _, _, _, _, slot_price_scale, _, _, _ in pareto_slots ], *[ slot_time_scale for _, _, _, _, _, _, _, _, _, slot_time_scale in pareto_slots ], ] view_inputs = [ platform, owner, optimized, prompt_count, seed_state, view_state, ] view_outputs = [ lb_note, ranking, *pareto_outputs, gallery, samples_panel, ] filter_inputs = [dataset_dd, metric_dd, models_dd, *view_inputs] dataset_outputs = [ dataset_dd, metric_dd, models_dd, lb_controls, platform, owner, optimized, *view_outputs, pp_tab, sm_tab, main_tabs, view_state, ] dataset_dd.change( on_dataset, inputs=filter_inputs, outputs=dataset_outputs, **_VIEW_EVENTS, ) metric_outputs = [ metric_dd, *view_outputs, view_state, ] metric_dd.change( on_metric, inputs=filter_inputs, outputs=metric_outputs, **_VIEW_EVENTS, ) models_outputs = [ models_dd, *view_outputs, view_state, ] models_dd.change( on_models, inputs=filter_inputs, outputs=models_outputs, **_VIEW_EVENTS, ) tab_outputs = [ filters_host, dataset_dd, metric_dd, models_dd, lb_controls, platform, owner, optimized, *view_outputs, main_tabs, view_state, ] for tab, tab_item in ( (TAB_LEADERBOARDS, lb_tab), (TAB_PARETO, pp_tab), (TAB_SAMPLES, sm_tab), (TAB_ABOUT, about_tab), ): tab_item.select( _on_tab(tab), inputs=filter_inputs, outputs=tab_outputs, show_progress="hidden", ) for component in (platform, owner, optimized): component.change( on_leaderboard_filters, inputs=[ dataset_dd, metric_dd, models_dd, platform, owner, optimized, view_state, ], outputs=[ranking, view_state], show_progress="hidden", ) pareto_all_scale.change( on_pareto_all_scale, inputs=[ dataset_dd, metric_dd, models_dd, pareto_all_scale, view_state, ], outputs=[*pareto_all_scale_outputs, view_state], **_VIEW_EVENTS, ) for slot_index, ( _, _, _, _, _, slot_price, slot_price_scale, _, slot_time, slot_time_scale, ) in enumerate(pareto_slots): slot_price_scale.change( _on_pareto_plot_scale(slot_index, "price"), inputs=[ dataset_dd, metric_dd, models_dd, slot_price_scale, view_state, ], outputs=[slot_price, pareto_all_scale, view_state], **_VIEW_EVENTS, ) slot_time_scale.change( _on_pareto_plot_scale(slot_index, "time"), inputs=[ dataset_dd, metric_dd, models_dd, slot_time_scale, view_state, ], outputs=[slot_time, pareto_all_scale, view_state], **_VIEW_EVENTS, ) prompt_count.change( on_samples_controls, inputs=[dataset_dd, models_dd, prompt_count, seed_state], outputs=gallery, show_progress="hidden", ) shuffle_button.click( on_shuffle, inputs=[dataset_dd, models_dd, prompt_count, seed_state], outputs=[seed_state, gallery], show_progress="hidden", ) def render_about(): with gr.Row(elem_classes="about-layout", equal_height=False): with gr.Column(scale=1, min_width=340, elem_classes="about-col"): gr.Markdown(ABOUT_OVERVIEW_CONTENT, elem_classes="about-copy") with gr.Column(scale=1, min_width=340, elem_classes="about-col"): gr.Markdown(ABOUT_DETAILS_CONTENT, elem_classes="about-copy") def render_footer(): gr.HTML(FOOTER_CONTENT, padding=False, elem_classes="page-footer-host") with gr.Accordion( "Citation", open=False, elem_classes="citation-accordion", ): gr.Markdown(CITATION_CONTENT)