Results (held-out physical-free test split, 3,966 rows; positive class = valid)
Table with columns: split, accuracy, balanced acc, macro-F1, MCC, AUROC| split | accuracy | balanced acc | macro-F1 | MCC | AUROC |
|---|
| synthetic test | 0.905 | 0.869 | 0.880 | 0.750 | 0.960 |
| human-drawn sketches (280, manual labels) | 0.629 | – | – | 0.276 | 0.721 |
Recall on invalid prompts 0.939, on valid prompts 0.799. A geometry-only classifier on the same test split reaches 0.932
accuracy, so the synthetic benchmark is largely separable from sketch coordinates; treat the human-sketch numbers as the deployment estimate.
Usage
The adapter must be scored the way it was trained: the user turn is the image plus
"<VERDICT_INSTRUCTION>\n\nCaption: <caption>", and the verdict is chosen by the label-span log-likelihood of
verdict: right vs verdict: wrong (see training/vlm_training.py and training/train_local.py --evaluate-adapter
in the DrawVLA repository). Prompting it differently (e.g. a system prompt + bare next-token scoring) roughly halves the margins.
from transformers import AutoModelForImageTextToText, AutoProcessor
from peft import PeftModel
base = "Qwen/Qwen3-VL-2B-Instruct"
model = PeftModel.from_pretrained(AutoModelForImageTextToText.from_pretrained(base, dtype="bfloat16"), "shibuina/drawvla-verify-qwen3vl-2b-lora")
processor = AutoProcessor.from_pretrained(base)
Files: adapter_config.json, adapter_model.safetensors, chat_template.jinja, processor_config.json, run_config.json, test_generation_metrics.json, tokenizer.json, tokenizer_config.json, train_metrics.json, validation_generation_metrics.json.