3morixd's picture
Upload app.py with huggingface_hub
704c39c verified
Raw
History Blame Contribute Delete
11.3 kB
"""
Dispatch AI — AI Cost Calculator
Input: cloud API usage (tokens/month) → Output: cost savings by switching to on-device.
Shows breakeven point, 1-year savings, CO2 reduction.
"""
import gradio as gr
# ---------------------------------------------------------------------------
# Pricing assumptions (USD per 1M tokens) — approximate 2026 rates
# ---------------------------------------------------------------------------
CLOUD_PRICING = {
"GPT-4o (input)": 2.50,
"GPT-4o (output)": 10.00,
"GPT-4o-mini (input)": 0.15,
"GPT-4o-mini (output)": 0.60,
"Claude 3.5 Sonnet (input)": 3.00,
"Claude 3.5 Sonnet (output)": 15.00,
"Claude 3.5 Haiku (input)": 0.25,
"Claude 3.5 Haiku (output)": 1.25,
"Llama 3.1 70B (Together AI)": 0.88,
"Llama 3.1 8B (Together AI)": 0.18,
"Mistral Large (input)": 2.00,
"Mistral Large (output)": 6.00,
"Gemini 1.5 Pro (input)": 1.25,
"Gemini 1.5 Pro (output)": 5.00,
"Gemini 1.5 Flash (input)": 0.075,
"Gemini 1.5 Flash (output)": 0.30,
}
# On-device cost: amortized phone hardware + electricity
# Phone cost ~$400 amortized over 2 years = $0.0167/day
# Power: ~4W * 8h = 0.032 kWh/day * $0.12/kWh = $0.00384/day
# On-device cost per 1M tokens: effectively $0 (amortized) but we show the hardware cost
PHONE_COST = 400 # USD, one-time
PHONE_LIFETIME_MONTHS = 24
ELECTRICITY_PER_MONTH = 2.50 # USD, charging phones
INFERENCE_SPEED_TPS = 16 # tokens/sec on S20 FE Q4_K_M
# CO2: 1 kWh = ~0.4 kg CO2 (US grid average)
# Cloud data center: ~0.5 kg CO2 / kWh (including cooling overhead)
# On-device: 4W * 8h * 30 days = 0.96 kWh/month → 0.384 kg CO2/month per phone
# Cloud: roughly 0.0004 kg CO2 per 1000 tokens generated
CLOUD_CO2_PER_1M_TOKENS = 0.4 # kg CO2 per 1M tokens (server-side)
ONDEVICE_CO2_PER_MONTH = 0.384 # kg CO2 per phone per month
def calculate_savings(
input_tokens_m, output_tokens_m, cloud_provider, num_phones, months
):
"""
Calculate cost savings of switching from cloud API to on-device inference.
Args:
input_tokens_m: Input tokens per month in millions
output_tokens_m: Output tokens per month in millions
cloud_provider: Key into CLOUD_PRICING
num_phones: Number of phones to deploy
months: Number of months to project
"""
try:
inp = float(input_tokens_m) if input_tokens_m else 0
outp = float(output_tokens_m) if output_tokens_m else 0
phones = int(num_phones) if num_phones else 1
mos = int(months) if months else 12
except (ValueError, TypeError):
return "❌ Invalid input. Please enter numeric values.", "", "", ""
# Cloud cost
# We pair input/output pricing: find the matching output key
base = cloud_provider.replace(" (input)", "").replace(" (output)", "")
in_key = f"{base} (input)"
out_key = f"{base} (output)"
in_price = CLOUD_PRICING.get(in_key, CLOUD_PRICING.get(cloud_provider, 1.0))
out_price = CLOUD_PRICING.get(out_key, in_price)
cloud_monthly = (inp * in_price) + (outp * out_price)
cloud_total = cloud_monthly * mos
# On-device cost
# Hardware amortized
hardware_monthly_per_phone = PHONE_COST / PHONE_LIFETIME_MONTHS
hardware_total = hardware_monthly_per_phone * phones * mos
electricity_total = ELECTRICITY_PER_MONTH * phones * mos
ondevice_total = hardware_total + electricity_total
ondevice_monthly = hardware_monthly_per_phone * phones + ELECTRICITY_PER_MONTH * phones
# Savings
savings = cloud_total - ondevice_total
savings_pct = (savings / cloud_total * 100) if cloud_total > 0 else 0
# Breakeven: how many months until on-device cost < cumulative cloud cost
if cloud_monthly > 0 and ondevice_monthly < cloud_monthly:
# Month 0: on-device = hardware_monthly * phones, cloud = cloud_monthly
# After M months: on-device = (hardware_monthly + elec_monthly) * phones * M
# Cloud = cloud_monthly * M
# Breakeven: (hardware_monthly + elec_monthly) * phones * M = cloud_monthly * M
# Actually hardware is amortized so: on-device cumulative = hardware_monthly*phones*M + elec*phones*M
# Cloud cumulative = cloud_monthly * M
# Breakeven when cloud > on-device: from month 1 if cloud_monthly > ondevice_monthly
ondevice_monthly_total = (hardware_monthly_per_phone + ELECTRICITY_PER_MONTH) * phones
if ondevice_monthly_total < cloud_monthly:
breakeven = 1 # immediate
else:
breakeven = float('inf')
else:
breakeven = float('inf')
breakeven_str = f"Month {breakeven}" if breakeven != float('inf') else "Never (cloud is cheaper)"
# CO2
cloud_co2 = (inp + outp) * mos * CLOUD_CO2_PER_1M_TOKENS # kg
ondevice_co2 = ONDEVICE_CO2_PER_MONTH * phones * mos
co2_saved = cloud_co2 - ondevice_co2
co2_saved_pct = (co2_saved / cloud_co2 * 100) if cloud_co2 > 0 else 0
# Throughput check: can the phones handle the load?
phone_capacity_monthly = (INFERENCE_SPEED_TPS * 3600 * 8 * 30) / 1_000_000 # 1M tokens/month per phone (8h/day)
total_capacity = phone_capacity_monthly * phones
capacity_note = (
f"✅ Your {phones} phone(s) can generate ~{total_capacity:.1f}M tokens/month "
f"(8h/day at {INFERENCE_SPEED_TPS} t/s)"
if total_capacity >= (inp + outp)
else f"⚠️ Your {phones} phone(s) can only generate ~{total_capacity:.1f}M tokens/month. "
f"You need {(inp + outp) / phone_capacity_monthly:.0f} phones for {inp + outp}M tokens/month."
)
summary = f"""
## 💰 Cost Comparison — {mos} months
| Metric | Cloud API | On-Device |
|--------|-----------|-----------|
| Monthly Cost | ${cloud_monthly:,.2f} | ${ondevice_monthly:,.2f} |
| {mos}-Month Total | ${cloud_total:,.2f} | ${ondevice_total:,.2f} |
| CO2 Emissions | {cloud_co2:,.1f} kg | {ondevice_co2:,.1f} kg |
---
### 📊 Key Results
- **Total Savings: ${savings:,.2f}** ({savings_pct:.1f}% reduction)
- **Breakeven Point:** {breakeven_str}
- **Monthly Savings:** ${cloud_monthly - ondevice_monthly:,.2f}/month
- **CO2 Reduction:** {co2_saved:,.1f} kg ({co2_saved_pct:.1f}% less)
- **Equivalent to:** {co2_saved / 120:,.1f} trees planted* 🌳
---
### {capacity_note}
---
### 📋 Assumptions
- Cloud provider: **{base}** ($ {in_price}/1M input, ${out_price}/1M output)
- Phone: Samsung S20 FE ($400, 24-month lifespan)
- Inference: {INFERENCE_SPEED_TPS} t/s (Qwen2.5-1.5B Q4_K_M on SD865)
- Electricity: ${ELECTRICITY_PER_MONTH}/month/phone
- CO2: 0.4 kg/1M tokens (cloud) vs 0.384 kg/month (phone)
- *1 tree absorbs ~120 kg CO2/year
---
### 🌍 Environmental Impact
Switching to on-device AI reduces your carbon footprint by **{co2_saved:,.1f} kg of CO2** over {mos} months.
That's equivalent to driving **{co2_saved / 0.4:,.0f} km** less in a petrol car.
"""
return summary, f"${savings:,.2f}", f"{co2_saved:,.1f} kg", f"{breakeven_str}"
# --- UI -----------------------------------------------------------------------
CSS = """
#dispatch-header h1 {
color: #FFFFFF; font-size: 2.2rem; margin: 0;
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; }
.dispatch-footer { text-align: center; color: #8A8F9C; font-size: 0.9rem; padding-top: 8px; }
"""
with gr.Blocks(
title="Dispatch AI — AI Cost Calculator",
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",
),
css=CSS,
) as demo:
with gr.Column(elem_id="dispatch-header"):
gr.Markdown(
"""
# Dispatch AI — AI Cost Calculator
Calculate savings by switching from cloud APIs to on-device inference · Dispatch AI (FZE) · UAE
"""
)
gr.Markdown(
"""
Enter your current cloud API usage to see how much you'd save by running AI models on phones.
Includes cost, breakeven point, and CO2 reduction.
"""
)
with gr.Row():
with gr.Column(scale=1):
input_tokens = gr.Number(
label="Input Tokens / Month (millions)", value=10,
info="e.g. 10 = 10 million input tokens/month",
)
output_tokens = gr.Number(
label="Output Tokens / Month (millions)", value=5,
info="e.g. 5 = 5 million output tokens/month",
)
cloud_provider = gr.Dropdown(
list(dict.fromkeys(
k.replace(" (input)", "").replace(" (output)", "") for k in CLOUD_PRICING
)),
label="Cloud Provider / Model",
value="GPT-4o",
info="Which cloud API are you currently using?",
)
num_phones = gr.Number(
label="Number of Phones to Deploy", value=1, minimum=1,
)
months = gr.Slider(
minimum=1, maximum=36, value=12, step=1,
label="Projection Period (months)",
)
calc_btn = gr.Button("💰 Calculate Savings", variant="primary")
with gr.Column(scale=2):
savings_big = gr.Textbox(label="💵 Total Savings", interactive=False, scale=1)
co2_big = gr.Textbox(label="🌍 CO2 Reduction", interactive=False, scale=1)
breakeven_big = gr.Textbox(label="⏱️ Breakeven Point", interactive=False, scale=1)
summary_md = gr.Markdown()
# Examples
gr.Examples(
examples=[
[10, 5, "GPT-4o", 1, 12],
[50, 25, "Claude 3.5 Sonnet", 5, 12],
[100, 50, "GPT-4o", 10, 24],
[5, 2, "GPT-4o-mini", 1, 12],
[200, 100, "Claude 3.5 Sonnet", 20, 36],
],
inputs=[input_tokens, output_tokens, cloud_provider, num_phones, months],
label="Quick Scenarios — click to load",
)
# Events
calc_btn.click(
calculate_savings,
inputs=[input_tokens, output_tokens, cloud_provider, num_phones, months],
outputs=[summary_md, savings_big, co2_big, breakeven_big],
)
gr.Markdown(
"""
<div class="dispatch-footer">
© 2026 Dispatch AI (FZE) · Sharjah, UAE · License 10818 ·
On-device inference via llama.cpp Q4_K_M on Snapdragon 865
</div>
"""
)
if __name__ == "__main__":
demo.queue()
demo.launch()