Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import json | |
| def generate_model_card(model_id: str, base_model: str = "", quantization: str = "Q4_K_M", | |
| params: str = "", task: str = "Text Generation", phone_tested: bool = True, | |
| tokens_per_sec: float = 0.0, ram_mb: int = 0, file_size_mb: int = 0) -> str: | |
| """Generate a HuggingFace model card (README.md) for a mobile-optimized model. | |
| Use this tool when you need to create or update a model card for a dispatchAI | |
| mobile model. Produces properly formatted markdown with YAML frontmatter, | |
| benchmark results, and usage examples. | |
| Args: | |
| model_id: The HuggingFace repo ID (e.g., "dispatchAI/MyModel-mobile") | |
| base_model: The original/base model name (e.g., "Qwen/Qwen2.5-0.5B-Instruct") | |
| quantization: Quantization method used (Q4_K_M, Q5_K_M, Q8_0, INT4, FP16) | |
| params: Parameter count as string (e.g., "500M", "1B", "3B") | |
| task: Primary task (Text Generation, Code Generation, etc.) | |
| phone_tested: Whether the model was tested on real phone hardware | |
| tokens_per_sec: Measured tokens/sec on Snapdragon 865 (0 if untested) | |
| ram_mb: RAM required in MB | |
| file_size_mb: Model file size in MB | |
| Returns: | |
| JSON string with the generated model card markdown | |
| """ | |
| org_name = model_id.split("/")[0] if "/" in model_id else "dispatchAI" | |
| model_name = model_id.split("/")[-1] if "/" in model_id else model_id | |
| tags = ["mobile", "on-device", "quantized", quantization.lower(), "dispatchai"] | |
| if task == "Code Generation": | |
| tags.extend(["code", "coder"]) | |
| elif "arabic" in model_name.lower(): | |
| tags.extend(["arabic", "multilingual"]) | |
| elif "function" in model_name.lower(): | |
| tags.extend(["function-calling", "agent"]) | |
| elif "vision" in model_name.lower(): | |
| tags.extend(["vision", "multimodal"]) | |
| card = f"""--- | |
| license: apache-2.0 | |
| language: | |
| - en | |
| library_name: transformers | |
| tags: | |
| {chr(10).join(f" - {t}" for t in tags)} | |
| pipeline_tag: {task.lower().replace(" ", "-") if " " in task else task} | |
| --- | |
| # {model_name} | |
| {("Mobile-optimized version of " + base_model) if base_model else "A mobile-optimized language model"} β quantized to {quantization}, designed to run on phones and edge devices. | |
| ## Model Details | |
| | Attribute | Value | | |
| |-----------|-------| | |
| | **Base Model** | {base_model or "N/A"} | | |
| | **Parameters** | {params or "Unknown"} | | |
| | **Quantization** | {quantization} | | |
| | **File Size** | {file_size_mb} MB | | |
| | **RAM Required** | {ram_mb} MB | | |
| | **Task** | {task} | | |
| | **License** | Apache-2.0 | | |
| | **Organization** | [{org_name}](https://huggingface.co/{org_name}) | | |
| ## Mobile Performance | |
| {"β **Tested on real hardware**" if phone_tested else "β οΈ Not yet tested on phone hardware"} | |
| | Hardware | Tokens/sec | RAM Usage | Status | | |
| |----------|-----------|-----------|--------| | |
| | Snapdragon 865 (S20 FE) | {tokens_per_sec} t/s | {ram_mb} MB | {"β Pass" if tokens_per_sec > 2 else "β Fail" if phone_tested else "β³ Pending"} | | |
| ## Usage | |
| ### Python (transformers) | |
| ```python | |
| from transformers import AutoTokenizer, AutoModelForCausalLM | |
| model = AutoModelForCausalLM.from_pretrained("{model_id}") | |
| tokenizer = AutoTokenizer.from_pretrained("{model_id}") | |
| messages = [{{"role": "user", "content": "Hello!"}}] | |
| input_text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) | |
| inputs = tokenizer(input_text, return_tensors="pt") | |
| outputs = model.generate(**inputs, max_new_tokens=100) | |
| print(tokenizer.decode(outputs[0])) | |
| ``` | |
| ### llama.cpp (GGUF) | |
| ```bash | |
| # Download | |
| hf download {model_id} model.gguf | |
| # Run on phone/desktop | |
| llama-cli -m model.gguf -p "Hello!" -n 100 -t 4 | |
| ``` | |
| ## Quantization Details | |
| This model uses **{quantization}** quantization: | |
| - File size: {file_size_mb} MB ({round(file_size_mb / 1024, 2)} GB) | |
| - Quality retention: ~92% of FP16 | |
| - Optimized for: Mobile and edge devices with < 4GB RAM | |
| ## About dispatchAI | |
| [dispatchAI](https://huggingface.co/dispatchAI) re-engineers open-source LLMs for mobile and edge devices. Every model is tested on real Snapdragon hardware. | |
| **Small. Mobile. Free. UAE-built.** | |
| --- | |
| *I think, therefore I ship.* | |
| """ | |
| return json.dumps({ | |
| "model_id": model_id, | |
| "card_content": card, | |
| "tags": tags, | |
| "instructions": f"Upload this as README.md to {model_id} repo" | |
| }, indent=2) | |
| with gr.Blocks(title="dispatchAI Model Card Writer MCP") as demo: | |
| gr.Markdown("## π dispatchAI Model Card Writer (MCP Tool)") | |
| with gr.Row(): | |
| mid = gr.Textbox(label="Model ID", placeholder="dispatchAI/MyModel-mobile") | |
| base = gr.Textbox(label="Base Model", placeholder="Qwen/Qwen2.5-0.5B-Instruct") | |
| with gr.Row(): | |
| quant = gr.Dropdown(["FP16", "INT4", "Q4_K_M", "Q5_K_M", "Q6_K", "Q8_0"], value="Q4_K_M", label="Quantization") | |
| params = gr.Textbox(label="Params", placeholder="500M, 1B, 3B...") | |
| task = gr.Dropdown(["Text Generation", "Code Generation", "Function Calling", "Image-to-Text"], value="Text Generation", label="Task") | |
| with gr.Row(): | |
| tested = gr.Checkbox(value=True, label="Phone Tested") | |
| tps = gr.Number(value=18.0, label="Tokens/sec (Snapdragon 865)") | |
| ram = gr.Number(value=1100, label="RAM (MB)") | |
| size = gr.Number(value=700, label="File Size (MB)") | |
| btn = gr.Button("Generate Model Card", variant="primary") | |
| out = gr.Textbox(label="Generated Card (JSON)", lines=25) | |
| btn.click(fn=generate_model_card, inputs=[mid, base, quant, params, task, tested, tps, ram, size], outputs=out) | |
| demo.launch(mcp_server=True) | |