Instructions to use HaoranLiu/SFT-4B-ScaleCUA-MixedOpen with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use HaoranLiu/SFT-4B-ScaleCUA-MixedOpen with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="HaoranLiu/SFT-4B-ScaleCUA-MixedOpen") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("HaoranLiu/SFT-4B-ScaleCUA-MixedOpen") model = AutoModelForMultimodalLM.from_pretrained("HaoranLiu/SFT-4B-ScaleCUA-MixedOpen", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use HaoranLiu/SFT-4B-ScaleCUA-MixedOpen with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "HaoranLiu/SFT-4B-ScaleCUA-MixedOpen" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "HaoranLiu/SFT-4B-ScaleCUA-MixedOpen", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/HaoranLiu/SFT-4B-ScaleCUA-MixedOpen
- SGLang
How to use HaoranLiu/SFT-4B-ScaleCUA-MixedOpen 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 "HaoranLiu/SFT-4B-ScaleCUA-MixedOpen" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "HaoranLiu/SFT-4B-ScaleCUA-MixedOpen", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'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 "HaoranLiu/SFT-4B-ScaleCUA-MixedOpen" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "HaoranLiu/SFT-4B-ScaleCUA-MixedOpen", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use HaoranLiu/SFT-4B-ScaleCUA-MixedOpen with Docker Model Runner:
docker model run hf.co/HaoranLiu/SFT-4B-ScaleCUA-MixedOpen
SFT-4B-ScaleCUA-MixedOpen
Qwen3-VL-4B-Instruct supervised-finetuned on 1430 Lite.ScaleCUA trajectories
from three open-source teachers in equal proportion, trained with
cua-lite + slime.
This is the epoch-3 checkpoint (iter_1070) — the best of the ScaleCUA SFT
arms measured here.
Results — Lite.OSWorld eval split
332 tasks, greedy (temperature=0), max_steps: 30, concurrency 12, group_size=1,
mean over all 332 with invalid tasks scored 0. Every row below reached
Valid 332/332 on one host under one protocol, so the rows are comparable to
each other.
All rows are epoch-3 (final) checkpoints.
| model | teachers | trajs | mean episode_return | success |
|---|---|---|---|---|
SFT-4B-ScaleCUA-MixedOpen (this) |
3 open-source, 1/task | 1430 | 0.3927 | 125/332 |
-MixedOpen-cap2 |
same 3, up to 2/task | 2520 | 0.3802 | 120/332 |
-Qwen35-27B |
Qwen3.5-27B only | — | 0.3682 | 117/332 |
-Qwen38 |
Qwen3.8-27B only | 1224 | 0.3623 | 115/332 |
| gpt-5.5 arm | gpt-5.5 only | 1254 | 0.3241 | 103/332 |
-EvoCUA |
EvoCUA-8B only | 865 | 0.3215 | 101/332 |
The gpt-5.5 row uses the unmodified gpt-5.5 cohort. An earlier gpt-5.5 collection reached 0.3753 with prompt engineering applied to the teacher, which is not comparable to the other rows here — every other teacher was collected without it, so that number is excluded rather than listed.
Three things the table settles:
Mixing beats every single teacher. Against the strongest single-teacher arm
(Qwen3.5-27B) the mix is +0.0245 / +8 tasks, and against Qwen38 — the
closest match in pipeline and trajectory count — +0.0304 / +10. Both clear
the threshold used here for a real effect (>0.02 mean and ≥7 tasks). Caveat
below: teacher identity and task coverage move together, so this is not a clean
single-variable ablation.
A second trajectory per task does not help. cap2 doubles the data (2520 vs
1430) at matched epochs and lands −0.0125 / −5 tasks below this model. Ten of
its per-domain cells move, five down and two up; the direction is consistently
mildly negative. More solutions for a task the model already has an example of is
not where the headroom is.
Two of the three teachers carry the mix. Qwen3.5-27B and Qwen38 land
within 0.006 of each other; EvoCUA-8B alone is 0.0408 / 14 tasks below
Qwen38 on only 865 trajectories. A two-teacher mix that drops EvoCUA is the
obvious next arm.
Per-domain (this checkpoint)
| domain | n | mean | pass |
|---|---|---|---|
vs_code |
18 | 0.722 | 13 |
thunderbird |
14 | 0.643 | 9 |
libreoffice_writer |
22 | 0.591 | 12 |
vlc |
15 | 0.587 | 7 |
os |
19 | 0.526 | 10 |
gimp |
16 | 0.500 | 8 |
chrome |
43 | 0.487 | 20 |
libreoffice_impress |
47 | 0.448 | 21 |
libreoffice_calc |
46 | 0.261 | 12 |
multi_apps |
92 | 0.159 | 13 |
multi_apps is 92 of 332 tasks (28%) and by far the weakest — the same shape the
single-teacher arms show. Multi-application coordination is the open problem in
this task pool, and no teacher mix measured here moves it.
Data
Equal-proportion mix over lite.scalecua rl tasks, one trajectory per task:
| teacher | trajectories | share |
|---|---|---|
Qwen/Qwen3.8-27B |
478 | 33.4% |
Qwen/Qwen3.5-27B |
477 | 33.4% |
meituan/EvoCUA-8B-20260105 |
475 | 33.2% |
1430 unique tasks (one trajectory each, no task appears twice). 1390/1430 are
full successes (episode_return == 1.0); the rest score 0.6–0.67 partial credit.
All rows come from the rl_tasks split.
The premise of the mix is that different agents specialize in different domains, so pooling open-source teachers widens task coverage. Note this means the mixed arm sees more tasks, not merely more trajectories — coverage and teacher diversity move together here and are not separated by this experiment.
Training
base Qwen/Qwen3-VL-4B-Instruct
export config scripts/configs/qwen3_vl/default/lite.osworld.yaml (full_history_size=4)
objective token-level SFT on assistant-action tokens; screenshots are
context only (masked out of the loss)
lr 5e-6 cosine -> min_lr 1e-6, warmup_fraction 0.1
batch global_batch_size 4 trajectories/step, micro_batch_size 1
epochs 3 (1070 steps, save_interval 358)
parallelism TP=2, 2x 80GB H100 -> DP=1
trained 2026-09-10 05:04 -> 20:52 UTC (15h47m)
code cua-lite-preference @ 6fbb2c9b, slime v0.3.0
ray_job raysubmit_TxuEdEMpVAAwC22Y
wandb liu-hr22-tsinghua-university/cua-lite-dev/runs/8mpvuigx
Sibling checkpoints kept locally: iter_356/iter_357 (ep1), iter_713/iter_715 (ep2).
Usage
uv run python scripts/rollout.py \
--model-id Qwen/Qwen3-VL-4B-Instruct \
--model-path <path to this checkpoint> \
--env-id lite.osworld --splits eval \
--filter "lambda m: not m.others.get('exclude_reason')" \
--concurrency 12 \
--config-path scripts/configs/qwen3_vl/default/lite.osworld.yaml
The qwen3_vl adapter/config is required: the model was trained on that
history protocol's rendering (full_history_size=4). Serving it under a different
window silently changes the prompt the model was fit to.
Caveats
- Only compare numbers produced on one host in one protocol. The same checkpoint has shifted by up to 0.018 / 7 tasks between VMs here — enough to flip a "real effect" verdict. The table above is one host, one protocol.
- Not a single-variable ablation. Mixed vs single teacher differs in teacher identity, trajectory count, and task coverage simultaneously.
num_validfirst.summary.json'smean_episode_returnaverages over valid tasks only, and a run may write an interim summary before its retry round finishes. CheckValid N/332before reading any mean.- Trained on
rltasks oflite.scalecua; evaluated onlite.osworldeval. These are separate task pools on a shared desktop substrate.
- Downloads last month
- 29
Model tree for HaoranLiu/SFT-4B-ScaleCUA-MixedOpen
Base model
Qwen/Qwen3-VL-4B-Instruct