mcp-card-writer / app.py
3morixd's picture
Upload app.py with huggingface_hub
b043f30 verified
Raw
History Blame Contribute Delete
5.68 kB
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)