""" 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( """ """ ) if __name__ == "__main__": demo.queue() demo.launch()