CoolFace
Apppublic

dispatchAI/mcp-hub

sourceHugging Faceapache-2.0updated 3mo agoView on Hugging Face
0likes
app.py145 linesDownload Raw Back to root
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