dispatchAI/mcp-hub
0
1import gradio as gr2import json3 4# Import all tool functions5# (Inlined for Space simplicity)6 7MODELS = [8 {"Model": "SmolLM2-135M-Instruct-mobile", "Params": "135M", "Size_MB": 270, "RAM_MB": 400, "Task": "Chat", "Quant": "FP16", "Speed_tps": 25.5},9 {"Model": "SmolLM2-360M-Instruct-mobile", "Params": "360M", "Size_MB": 720, "RAM_MB": 700, "Task": "Chat", "Quant": "FP16", "Speed_tps": 21.0},10 {"Model": "Qwen2.5-0.5B-Instruct-mobile-int4", "Params": "500M", "Size_MB": 350, "RAM_MB": 550, "Task": "Chat", "Quant": "INT4", "Speed_tps": 20.0},11 {"Model": "Llama-3.2-1B-Instruct-Q4-mobile", "Params": "1B", "Size_MB": 700, "RAM_MB": 1100, "Task": "Chat", "Quant": "Q4", "Speed_tps": 18.2},12 {"Model": "Llama-3.2-3B-Instruct-Q5-mobile", "Params": "3B", "Size_MB": 2100, "RAM_MB": 2700, "Task": "Chat", "Quant": "Q5", "Speed_tps": 8.5},13 {"Model": "Gemma-2B-Arabic-mobile", "Params": "2B", "Size_MB": 5000, "RAM_MB": 5500, "Task": "Arabic", "Quant": "FP16", "Speed_tps": 8.0},14 {"Model": "Llama-3.2-1B-FunctionCall-mobile", "Params": "1B", "Size_MB": 2500, "RAM_MB": 3000, "Task": "Function Call", "Quant": "FP16", "Speed_tps": 12.0},15]16 17LATENCY_DB = {18 "135M": {"FP16": 25.5, "Q4_K_M": 32.0, "Q8_0": 28.2},19 "500M": {"FP16": 20.0, "Q4_K_M": 26.8, "INT4": 20.0},20 "1B": {"FP16": 12.0, "Q4_K_M": 18.2, "Q5_K_M": 17.5},21 "2B": {"FP16": 8.0, "Q5_K_M": 12.0, "Q4_K_M": 12.8},22 "3B": {"FP16": 5.5, "Q5_K_M": 8.5, "Q4_K_M": 9.0},23}24 25def recommend_model(ram_mb: int, task: str = "Any") -> str:26 """Recommend the best dispatchAI mobile model for a given RAM budget and task.27 28 Args:29 ram_mb: Available RAM in MB30 task: Task type (Chat, Code, Math, Arabic, Function Call, Vision, Embedding, Any)31 32 Returns:33 JSON with recommended model34 """35 filtered = [m for m in MODELS if m["RAM_MB"] <= ram_mb]36 if task != "Any":37 filtered = [m for m in filtered if m["Task"] == task]38 if not filtered:39 return json.dumps({"error": f"No models fit in {ram_mb}MB"})40 best = sorted(filtered, key=lambda x: x["Size_MB"])[0]41 return json.dumps({42 "recommended": best["Model"],43 "url": f"https://huggingface.co/dispatchAI/{best['Model']}",44 "size_mb": best["Size_MB"],45 "ram_mb": best["RAM_MB"],46 "speed_tps": best["Speed_tps"],47 }, indent=2)48 49def estimate_latency(params: str, quant: str = "Q4_K_M") -> str:50 """Estimate inference latency on Snapdragon 865.51 52 Args:53 params: Model size (e.g., "135M", "1B", "3B")54 quant: Quantization (FP16, Q4_K_M, Q5_K_M, Q8_0, INT4)55 56 Returns:57 JSON with speed and RAM estimates58 """59 params = params.upper()60 if params not in LATENCY_DB:61 return json.dumps({"error": f"Unknown: {params}. Valid: {list(LATENCY_DB.keys())}"})62 tps = LATENCY_DB[params].get(quant.upper(), 10.0)63 return json.dumps({64 "params": params,65 "quant": quant,66 "tokens_per_sec": tps,67 "ms_per_token": round(1000/tps, 0),68 "hardware": "Snapdragon 865",69 }, indent=2)70 71def calculate_savings(daily_queries: int, cloud_cost_per_1k: float) -> str:72 """Calculate savings from on-device vs cloud inference.73 74 Args:75 daily_queries: Queries per day76 cloud_cost_per_1k: Cloud cost per 1000 queries77 78 Returns:79 JSON with cost comparison80 """81 annual_cloud = daily_queries * 365 * cloud_cost_per_1k / 100082 annual_device = 0.583 return json.dumps({84 "cloud_annual": round(annual_cloud, 2),85 "device_annual": round(annual_device, 2),86 "savings": round(annual_cloud - annual_device, 2),87 "savings_pct": round((1 - annual_device/annual_cloud)*100, 1) if annual_cloud > 0 else 0,88 }, indent=2)89 90def search_models(query: str) -> str:91 """Search dispatchAI models by keyword.92 93 Args:94 query: Search term (e.g., "arabic", "coder", "1B", "quantized")95 96 Returns:97 JSON with matching models98 """99 q = query.lower()100 matches = [m for m in MODELS if q in m["Model"].lower() or q in m["Task"].lower() or q in m["Quant"].lower()]101 return json.dumps({"query": query, "matches": len(matches), "models": matches}, indent=2)102 103with gr.Blocks(title="dispatchAI MCP Hub") as demo:104 gr.Markdown("""105 # 🧰 dispatchAI MCP Tool Hub106 107 **One Space, four tools.** Add to Claude Desktop / Cursor / any MCP client.108 109 | Tool | Description |110 |------|-------------|111 | `recommend_model` | Find best model for your phone |112 | `estimate_latency` | Predict inference speed |113 | `calculate_savings` | Cloud vs on-device cost |114 | `search_models` | Search dispatchAI catalog |115 """)116 117 with gr.Tab("Recommend"):118 r_ram = gr.Slider(512, 8192, value=2048, label="RAM (MB)")119 r_task = gr.Dropdown(["Any", "Chat", "Arabic", "Function Call"], value="Any", label="Task")120 r_btn = gr.Button("Recommend")121 r_out = gr.Textbox(label="Result", lines=10)122 r_btn.click(fn=recommend_model, inputs=[r_ram, r_task], outputs=r_out)123 124 with gr.Tab("Latency"):125 l_p = gr.Dropdown(list(LATENCY_DB.keys()), value="1B", label="Params")126 l_q = gr.Dropdown(["FP16", "Q4_K_M", "Q5_K_M", "Q8_0", "INT4"], value="Q4_K_M", label="Quant")127 l_btn = gr.Button("Estimate")128 l_out = gr.Textbox(label="Result", lines=8)129 l_btn.click(fn=estimate_latency, inputs=[l_p, l_q], outputs=l_out)130 131 with gr.Tab("Cost"):132 c_dq = gr.Slider(100, 100000, value=10000, label="Daily Queries")133 c_cc = gr.Slider(0.1, 10, value=0.5, label="Cloud $/1K")134 c_btn = gr.Button("Calculate")135 c_out = gr.Textbox(label="Result", lines=8)136 c_btn.click(fn=calculate_savings, inputs=[c_dq, c_cc], outputs=c_out)137 138 with gr.Tab("Search"):139 s_q = gr.Textbox(label="Search Query", placeholder="arabic, coder, 1B...")140 s_btn = gr.Button("Search")141 s_out = gr.Textbox(label="Results", lines=10)142 s_btn.click(fn=search_models, inputs=s_q, outputs=s_out)143 144demo.launch(mcp_server=True)145 