CoolFace
Modelpublic

Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie-scoring-64k-balanced

sourceHugging Faceapache-2.0updated 1mo agoView on Hugging Face
0likes34downloads
Model Card

Qwen3-VL-8B-Instruct-UI-Genie-scoring-64k-balanced

A Bradley-Terry reward model fine-tuned from Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie (itself SFT'd from Qwen/Qwen3-VL-8B-Instruct) on a class-balanced 64k subset of UI-Genie-RM-517k.

This is the balanced-split counterpart to Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie-scoring. Same architecture, same objective, different training subset.

Merged sequence-classification checkpoint (task_type="seq_cls", num_labels=1, problem_type="regression") trained with the Bradley-Terry pairwise loss. A learned score.weight linear head projects the last non-padding token's hidden state to a scalar reward.

Score = `score_head(last non-padding token hidden state)` — a single float per input trajectory. Higher score = higher quality action.

Provenance of the head is recorded in score_head_source.txt: consolidated from the deepspeed shards of bt_qwen3vl_8b_64k_balanced/checkpoint-1000/global_step*/ via zero_to_fp32. The swift trainer keeps the score head out of the LoRA adapter and writes it only to deepspeed checkpoint shards, so a naive merge/export silently drops it — this checkpoint carries the actual trained head.

Intended Use

Scalar reward signal for GUI agent training (PPO/GRPO, RLHF) or best-of-N selection. Unlike the discrete <|+|> / <|-|> classifier, this model outputs a continuous unbounded reward directly usable as a value signal.

Evaluation

Pairwise accuracy on android_flux_recovery_action_preference from Gyubeum/AndroidFlux_RM_Eval — 94 pairs, each two candidate t+1 recovery actions from the same checkpoint, labelled by success under a 12-model continuation panel:

ModelPairwise accuracyTiesMean margin
`-scoring` (unbalanced 64k)0.6064 (57/94)0+1.381
this model (balanced 64k)0.4894 (46/94)1+0.471
`UI-Genie` (discrete SFT)0.0106 (1/94)90−0.021

This checkpoint performs at chance on that benchmark. Breaking it out by subset shows no split above chance:

SplitPairsAccuracy
clean_path560.4821
error_path380.5000
success_rate650.4615
combined_success_length290.5517

For comparison, the unbalanced -scoring model separates the same pairs with visible structure (0.658 on error_path vs 0.571 on clean_path). The head here does produce well-separated scores — only 1 tie, margins spanning [−17.75, +18.38] — but that separation does not correlate with which action succeeds.

With n=94 the 95% CI is roughly ±10 points, so treat the gap as indicative rather than tight. Evaluated 2026-08-27 with rm_eval --mode bt.

Inference

vLLM's Qwen3VLForConditionalGeneration loader does not support the extra score.weight tensor — use HuggingFace transformers directly.

python
import json, torch
from safetensors import safe_open
from huggingface_hub import hf_hub_download
from transformers import AutoProcessor, Qwen3VLForConditionalGeneration

MODEL_PATH = "Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie-scoring-64k-balanced"
DEVICE = "cuda"

model = Qwen3VLForConditionalGeneration.from_pretrained(
    MODEL_PATH, torch_dtype=torch.bfloat16, low_cpu_mem_usage=True,
).to(DEVICE).eval()
processor = AutoProcessor.from_pretrained(MODEL_PATH, max_pixels=1_048_576)

# `score.weight` is not wired into the base CausalLM class — load it separately.
index = json.load(open(hf_hub_download(MODEL_PATH, "model.safetensors.index.json")))
shard = hf_hub_download(MODEL_PATH, index["weight_map"]["score.weight"])
with safe_open(shard, framework="pt") as f:
    w = f.get_tensor("score.weight")
score_head = torch.nn.Linear(w.shape[1], w.shape[0], bias=False)
with torch.no_grad():
    score_head.weight.copy_(w)
score_head = score_head.to(DEVICE, dtype=torch.bfloat16)

# score = score_head(hidden_states[:, last_non_pad_index, :])

Training Details

FieldValue
Base modelGyubeum/Qwen3-VL-8B-Instruct-UI-Genie
Training methodBradley-Terry pairwise loss (LoRA, merged)
Training dataUI-Genie-RM-517k, class-balanced 64k subset
ArchitectureQwen3VLForConditionalGeneration + score.weight linear head
Task typeseq_cls (regression, num_labels=1)
ScoreLast non-padding token hidden state → linear head → scalar
dtypebfloat16

Related Models

  • —[Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie-scoring](https://huggingface.co/Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie-scoring) — same objective on the unbalanced 64k split; higher accuracy on the recovery benchmark.
  • —[Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie](https://huggingface.co/Gyubeum/Qwen3-VL-8B-Instruct-UI-Genie) — the SFT discrete preference classifier this model's score.weight was fine-tuned on top of.

Citation

bibtex
@misc{qwen3technicalreport,
      title={Qwen3 Technical Report},
      author={Qwen Team},
      year={2025},
      eprint={2505.09388},
      archivePrefix={arXiv},
      primaryClass={cs.CL},
}