Text Generation
Transformers
Safetensors
designcoder
ui-generation
front-end
html
css
javascript
code-generation
full-sft
Instructions to use xingxm/DesignCoder with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use xingxm/DesignCoder with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="xingxm/DesignCoder")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("xingxm/DesignCoder", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use xingxm/DesignCoder with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "xingxm/DesignCoder" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "xingxm/DesignCoder", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/xingxm/DesignCoder
- SGLang
How to use xingxm/DesignCoder with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "xingxm/DesignCoder" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "xingxm/DesignCoder", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "xingxm/DesignCoder" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "xingxm/DesignCoder", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use xingxm/DesignCoder with Docker Model Runner:
docker model run hf.co/xingxm/DesignCoder
Add designcoder_evaluator_qwen3.5_9b_adamw_bs256_data37847_step100/README.md
Browse files
designcoder_evaluator_qwen3.5_9b_adamw_bs256_data37847_step100/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: other
|
| 3 |
+
base_model: Qwen/Qwen3.5-9B
|
| 4 |
+
tags:
|
| 5 |
+
- designcoder
|
| 6 |
+
- evaluator
|
| 7 |
+
- reward-model
|
| 8 |
+
- ui-evaluation
|
| 9 |
+
- multimodal
|
| 10 |
+
- image-text-to-text
|
| 11 |
+
language:
|
| 12 |
+
- en
|
| 13 |
+
pipeline_tag: image-text-to-text
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
# DesignCoder Evaluator · Qwen3.5-9B · AdamW · bs256 · data37847 · step100
|
| 17 |
+
|
| 18 |
+
> **This is an evaluator, not a generation model.**
|
| 19 |
+
> Most checkpoints in this repository *write* HTML/CSS/JS. This one *scores* the
|
| 20 |
+
> rendered result: given a UI screenshot and a rubric it returns structured
|
| 21 |
+
> per-criterion verdicts, for use as a reward / judge model during rollout.
|
| 22 |
+
|
| 23 |
+
The lightweight companion to
|
| 24 |
+
[`designcoder_evaluator_qwen3.8_27b_adamw_bs256_data37847_step296`](../designcoder_evaluator_qwen3.8_27b_adamw_bs256_data37847_step296).
|
| 25 |
+
Roughly **1/3 the memory and 2× the speed** of the 27B, with equal or better
|
| 26 |
+
agreement — **provided the rubric has exactly 10 items** (see Limitations).
|
| 27 |
+
|
| 28 |
+
## Task
|
| 29 |
+
|
| 30 |
+
Input: one full-page UI screenshot + `<surface>` (landing | dashboard) +
|
| 31 |
+
`<generation_brief>` + `<frozen_rubric>`.
|
| 32 |
+
Output: `<think>` reasoning followed by strict JSON with `dynamic_scores` (5 × 0/1/2),
|
| 33 |
+
`static_scores` (34 dashboard / 35 landing), `interaction_rubrics` (free text) and
|
| 34 |
+
`frozen_dynamic_scores.verdicts` (binary per rubric item).
|
| 35 |
+
|
| 36 |
+
## Training
|
| 37 |
+
|
| 38 |
+
| | |
|
| 39 |
+
|---|---|
|
| 40 |
+
| Base model | Qwen3.5-9B (`Qwen3_5ForConditionalGeneration`) |
|
| 41 |
+
| Dataset | **DesignCoder-evaluate**, 37,847 filtered samples |
|
| 42 |
+
| Optimizer | AdamW, lr 1e-5, cosine, warmup 0.1, wd 0.0 |
|
| 43 |
+
| Precision / parallel | bf16 + DeepSpeed ZeRO-3, 8 nodes × 8 H20 = 64 GPUs |
|
| 44 |
+
| Global batch | 256 (per_device 2 × grad_accum 2 × 64) |
|
| 45 |
+
| **Exported step** | **100 / 296** (0.68 epoch), loss 0.4956 |
|
| 46 |
+
| Full-run final loss | 0.4358 @ step 296 |
|
| 47 |
+
| Frozen | vision tower (LM + projector fully tuned) |
|
| 48 |
+
|
| 49 |
+
> ⚠️ `data37847` is the **DesignCoder-evaluate** dataset (UI screenshot scoring).
|
| 50 |
+
> It is **not** the generation dataset behind the `data37865` / `data41287`
|
| 51 |
+
> checkpoints — the similar sample count is a coincidence.
|
| 52 |
+
|
| 53 |
+
### Why step 100 and not the final checkpoint
|
| 54 |
+
|
| 55 |
+
All six checkpoints (50/100/150/200/250/296) were evaluated on a purpose-built
|
| 56 |
+
**out-of-distribution suite** (576 prompts: rubric lengths 5/10/15/20/25 and three
|
| 57 |
+
dimension-grouping shapes). Step 100 wins on OOD agreement, and the final checkpoint
|
| 58 |
+
is measurably worse:
|
| 59 |
+
|
| 60 |
+
| Step | OOD κ | In-dist κ | Overfit gap | Train loss |
|
| 61 |
+
|---:|---:|---:|---:|---:|
|
| 62 |
+
| 50 | 0.6568 | 0.6610 | +0.004 | – |
|
| 63 |
+
| **100** | **0.6943** | 0.7010 | +0.007 | 0.4956 |
|
| 64 |
+
| 150 | 0.6730 | 0.6908 | +0.018 | – |
|
| 65 |
+
| 200 | 0.6649 | 0.6758 | +0.011 | – |
|
| 66 |
+
| 250 | 0.6765 | 0.6571 | −0.019 | – |
|
| 67 |
+
| 296 (final) | 0.6501 | 0.6772 | +0.027 | 0.4358 |
|
| 68 |
+
|
| 69 |
+
This mirrors the pattern documented for the generation runs in this repo — loss keeps
|
| 70 |
+
falling while held-out quality degrades — except the optimum arrives **earlier**
|
| 71 |
+
(~34% of training vs ~75% for generation).
|
| 72 |
+
|
| 73 |
+
### Optimizer ablation
|
| 74 |
+
|
| 75 |
+
A sibling 9B run using **Muon + `pure_bf16`** (otherwise identical data, batch, and
|
| 76 |
+
steps) failed badly, which is why this run uses AdamW:
|
| 77 |
+
|
| 78 |
+
| | Muon + pure_bf16 | **AdamW + ZeRO-3** |
|
| 79 |
+
|---|---:|---:|
|
| 80 |
+
| Final train loss | 0.7505 | **0.4358** |
|
| 81 |
+
| Truncated generations | 14 / 389 | **0 / 389** |
|
| 82 |
+
| Cohen's κ (25-item rubric) | 0.4831 | **0.6353** |
|
| 83 |
+
| Reproduces known quality ordering | ❌ inverted | ✅ correct |
|
| 84 |
+
|
| 85 |
+
The Muon arm stalled early (loss 1.376 → 1.138 over the first 50 steps) and degenerated
|
| 86 |
+
into repetition loops that ran into the 8192-token cap. Do not use Muon + `pure_bf16`
|
| 87 |
+
for this task.
|
| 88 |
+
|
| 89 |
+
## Evaluation
|
| 90 |
+
|
| 91 |
+
The dataset has no test split, so evaluation uses **held-out inputs**: 239 generated-page
|
| 92 |
+
screenshots already scored check-by-check by a stronger external vision judge
|
| 93 |
+
(md5 check: **0 overlap** with the 37,851 training images).
|
| 94 |
+
|
| 95 |
+
| Metric | 25-item rubric (OOD) | 10-item rubric (in-dist) |
|
| 96 |
+
|---|---:|---:|
|
| 97 |
+
| JSON parse rate | 1.0000 | 1.0000 |
|
| 98 |
+
| Verdict-count exact match | 0.6276 | **1.0000** |
|
| 99 |
+
| Per-check agreement | 0.9226 | 0.9343 |
|
| 100 |
+
| Cohen's κ | 0.6353 | 0.6560 |
|
| 101 |
+
| Defect recall | 0.6581 | 0.6730 |
|
| 102 |
+
| Defect precision | 0.7018 | 0.7137 |
|
| 103 |
+
| Case-level Pearson | 0.8417 | 0.7809 |
|
| 104 |
+
|
| 105 |
+
> Numbers above are for **step 296** (measured before checkpoint selection).
|
| 106 |
+
> Step 100 — the weights published here — scores **higher** on the OOD suite
|
| 107 |
+
> (κ 0.6943 vs 0.6501); the table is retained as a conservative reference.
|
| 108 |
+
|
| 109 |
+
### Reproducing the known quality ordering
|
| 110 |
+
|
| 111 |
+
External judge on three generation checkpoints: 4B `0.833` < 9B `0.884` < 27B `0.905`
|
| 112 |
+
|
| 113 |
+
| Scorer | 4B | 9B | 27B | Ordering |
|
| 114 |
+
|---|---:|---:|---:|---|
|
| 115 |
+
| This model (9B AdamW) | 0.855 | **0.886** | 0.910 | ✅ correct |
|
| 116 |
+
| 27B evaluator | 0.840 | 0.893 | 0.909 | ✅ correct |
|
| 117 |
+
| 9B Muon evaluator | 0.896 | 0.940 | 0.933 | ❌ inverted |
|
| 118 |
+
|
| 119 |
+
## Usage
|
| 120 |
+
|
| 121 |
+
```python
|
| 122 |
+
from transformers import AutoModelForImageTextToText, AutoProcessor, AutoTokenizer
|
| 123 |
+
from PIL import Image
|
| 124 |
+
import torch, math
|
| 125 |
+
|
| 126 |
+
MODEL = "xingxm/DesignCoder"
|
| 127 |
+
SUB = "designcoder_evaluator_qwen3.5_9b_adamw_bs256_data37847_step100"
|
| 128 |
+
|
| 129 |
+
tok = AutoTokenizer.from_pretrained(MODEL, subfolder=SUB, trust_remote_code=True)
|
| 130 |
+
proc = AutoProcessor.from_pretrained(MODEL, subfolder=SUB, trust_remote_code=True)
|
| 131 |
+
model = AutoModelForImageTextToText.from_pretrained(
|
| 132 |
+
MODEL, subfolder=SUB, dtype=torch.bfloat16, device_map="cuda", trust_remote_code=True
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
img = Image.open("screenshot.png").convert("RGB")
|
| 136 |
+
w, h = img.size # match training preprocessing
|
| 137 |
+
if w * h > 1048576:
|
| 138 |
+
s = math.sqrt(1048576 / (w * h))
|
| 139 |
+
img = img.resize((int(w * s), int(h * s)))
|
| 140 |
+
|
| 141 |
+
user = (
|
| 142 |
+
"<image>\n"
|
| 143 |
+
"Evaluate the attached UI screenshot using the selected visual criteria.\n\n"
|
| 144 |
+
"<surface>\nlanding\n</surface>\n\n"
|
| 145 |
+
"<generation_brief>\n...brief...\n</generation_brief>\n\n"
|
| 146 |
+
'<frozen_rubric>\n{"rubric":{"Alignment":["..."],"Layout":["..."]}}\n</frozen_rubric>'
|
| 147 |
+
)
|
| 148 |
+
text = tok.apply_chat_template(
|
| 149 |
+
[{"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user}],
|
| 150 |
+
tokenize=False, add_generation_prompt=True,
|
| 151 |
+
).replace("<image>", "<|vision_start|><|image_pad|><|vision_end|>")
|
| 152 |
+
|
| 153 |
+
inputs = proc(text=[text], images=[img], return_tensors="pt").to("cuda")
|
| 154 |
+
out = model.generate(**inputs, max_new_tokens=4096, do_sample=False)
|
| 155 |
+
print(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
`SYSTEM_PROMPT` must be the one shipped with the DesignCoder-evaluate dataset. The chat
|
| 159 |
+
template already ends with `<think>\n`, so generated text continues *inside* the reasoning
|
| 160 |
+
block and carries no opening `<think>` tag.
|
| 161 |
+
|
| 162 |
+
## Limitations
|
| 163 |
+
|
| 164 |
+
- **Feed it exactly 10 rubric items.** Every training rubric has exactly 10 (fixed shape
|
| 165 |
+
`Alignment:2, Layout:2, Typography:2, Components:2, Assets:1, Aesthetics:1`, 100% of
|
| 166 |
+
37,847 records). Off-length rubrics degrade verdict counting badly — the dimension names
|
| 167 |
+
stay correct but the per-dimension item count drifts, typically by ±1:
|
| 168 |
+
|
| 169 |
+
| Rubric length | 5 | 10 | 15 | 20 | 25 |
|
| 170 |
+
|---|---:|---:|---:|---:|---:|
|
| 171 |
+
| Count-match (this model) | 0.00 | **1.00** | 0.92 | 0.94 | 0.85 |
|
| 172 |
+
| Count-match (27B) | 1.00 | 1.00 | 0.99 | 1.00 | 1.00 |
|
| 173 |
+
|
| 174 |
+
**If your rubric length varies, use the 27B instead** — that is its main advantage,
|
| 175 |
+
not raw judgement quality (OOD κ is actually 0.694 here vs 0.664 for the 27B).
|
| 176 |
+
- **`summary` miscounts.** `frozen_dynamic_scores.summary` is rarely self-consistent
|
| 177 |
+
(e.g. `"24/24"` alongside 25 verdicts). Parse the `verdicts` array; ignore `summary`.
|
| 178 |
+
- **`static_scores` / `dynamic_scores` unvalidated on unseen data.** No ground truth exists
|
| 179 |
+
for those 40 items outside the training distribution; they were only checked on a
|
| 180 |
+
contaminated training sample (static exact-match 0.9135, dynamic 0.8400).
|
| 181 |
+
- Evidence is screenshot-only; the model cannot verify interaction behaviour, yet
|
| 182 |
+
`interaction_rubrics` asks it to describe interactions — treat that field as speculative.
|