3morixd's picture
Upload app.py with huggingface_hub
a89aba5 verified
Raw
History Blame Contribute Delete
5.82 kB
"""
Dispatch AI (FZE) — Mobile AI Benchmark Leaderboard
A HuggingFace Space that displays real-phone benchmark results for small AI models,
measured on a farm of 40 Samsung S20 FE (Snapdragon 865) devices.
License: 10818, Sharjah UAE
"""
import pandas as pd
import gradio as gr
# ---------------------------------------------------------------------------
# Benchmark data — collected on the Dispatch AI phone farm
# 40 x Samsung S20 FE (Snapdragon 865, 6 GB RAM, Android 13)
# Backend: llama.cpp (llamafile / gguf), 4-bit Q4_K_M quants, 4 threads, FP16 offload
# Generation tokens: 256, prompt: 512 tokens, batch 512, 25 model
# ---------------------------------------------------------------------------
PHONE = "Samsung S20 FE (SD865)"
DATA = [
# model, size_mb, gen_tps, prompt_tps, ram_free_mb, load_s
("Qwen2.5-1.5B-Instruct Q4_K_M", 1060, 16.9, 57.8, 3500, 1.8),
("Qwen2.5-0.5B-Instruct Q4_K_M", 450, 19.2, 65.3, 4100, 0.9),
("Llama-3.2-1B-Instruct Q4_K_M", 890, 16.3, 57.8, 3500, 1.5),
("Llama-3.2-3B-Instruct Q4_K_M", 2100, 12.4, 45.2, 2800, 3.2),
("Gemma-2-2B-IT Q4_K_M", 1600, 13.8, 48.6, 3200, 2.5),
("Phi-3.5-mini Q4_K_M", 2300, 14.2, 50.1, 2900, 2.8),
("SmolLM2-1.7B Q4_K_M", 1200, 17.1, 60.2, 3400, 1.4),
("SmolLM2-135M Q4_K_M", 85, 22.8, 89.5, 4500, 0.3),
("TinyLlama-1.1B Q4_K_M", 700, 18.5, 62.4, 3800, 1.1),
]
COLUMNS = [
"Model",
"Size (MB)",
"Generation Speed (t/s)",
"Prompt Speed (t/s)",
"RAM Free (MB)",
"Load Time (s)",
"Phone Tested",
]
GITHUB_URL = "https://github.com/Dispatch-AI-FZE/mobile-ai-leaderboard"
def build_dataframe() -> pd.DataFrame:
rows = []
for (model, size, gen, prompt, ram, load) in DATA:
rows.append([model, size, gen, prompt, ram, load, PHONE])
return pd.DataFrame(rows, columns=COLUMNS)
def filter_models(search: str) -> pd.DataFrame:
"""Return rows whose Model name contains the search string (case-insensitive).
If the search is blank, return the full table.
"""
df = build_dataframe()
if not search or not search.strip():
return df
mask = df["Model"].str.contains(search.strip(), case=False, na=False)
return df[mask]
# ---------------------------------------------------------------------------
# Custom dark theme — Dispatch AI brand
# ---------------------------------------------------------------------------
CSS = """
#dispatch-header {
text-align: center;
margin-bottom: 4px;
}
#dispatch-header h1 {
color: #FFFFFF;
font-size: 2.2rem;
margin: 0;
letter-spacing: 0.5px;
background: linear-gradient(90deg, #1FE0E6 0%, #FFFFFF 60%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
#dispatch-header p {
color: #1FE0E6;
font-size: 1.05rem;
margin: 6px 0 0 0;
opacity: 0.95;
}
.dispatch-footer {
text-align: center;
color: #8A8F9C;
font-size: 0.9rem;
padding-top: 8px;
}
"""
with gr.Blocks(
title="Dispatch AI — Mobile AI Leaderboard",
theme=gr.themes.Base(
primary_hue="cyan",
secondary_hue="cyan",
neutral_hue="slate",
font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui"],
).set(
body_background_fill="#0A0F1A",
body_background_fill_dark="#0A0F1A",
body_text_color="#FFFFFF",
body_text_color_dark="#FFFFFF",
block_background_fill="#0E1424",
block_background_fill_dark="#0E1424",
block_border_color="#1FE0E6",
block_border_width="1px",
block_label_text_color="#1FE0E6",
block_title_text_color="#1FE0E6",
button_primary_background_fill="#1FE0E6",
button_primary_background_fill_dark="#1FE0E6",
button_primary_text_color="#0A0F1A",
button_primary_border_color="#1FE0E6",
input_background_fill="#0E1424",
input_background_fill_dark="#0E1424",
input_border_color="#1FE0E6",
input_border_width="1px",
checkbox_label_text_color="#FFFFFF",
),
css=CSS,
) as demo:
# Header
with gr.Column(elem_id="dispatch-header"):
gr.Markdown(
"""
# Dispatch AI — Mobile AI Leaderboard
Real Phone Benchmarks | 40× Snapdragon 865 | License 10818, Sharjah UAE
"""
)
gr.Markdown(
"""
Benchmarks are measured on a farm of **40 Samsung S20 FE** devices
(Snapdragon 865, 6 GB RAM) running `llama.cpp` with **Q4_K_M** 4-bit quants,
4 CPU threads, FP16 offload. Each row is the median across all 40 devices.
"""
)
# Search + table
with gr.Row():
search = gr.Textbox(
label="Filter models by name",
placeholder="e.g. Qwen, Llama, SmolLM…",
scale=8,
)
github_btn = gr.Button(
"Submit Your Results ↗",
variant="primary",
scale=2,
link=GITHUB_URL,
)
table = gr.Dataframe(
value=build_dataframe,
headers=COLUMNS,
datatype=["str", "number", "number", "number", "number", "number", "str"],
interactive=False,
wrap=True,
column_widths=[260, 90, 110, 110, 110, 90, 180],
elem_classes="dispatch-table",
)
# Wire the search box to filter the table live
search.change(
fn=filter_models,
inputs=search,
outputs=table,
)
gr.Markdown(
f"""
<div class="dispatch-footer">
© 2026 Dispatch AI FZE — Sharjah, UAE · License 10818 ·
Contribute your results on
<a href="{GITHUB_URL}" style="color:#1FE0E6;">GitHub</a>
</div>
"""
)
if __name__ == "__main__":
demo.queue()
demo.launch()