qwen3.5-0.8b-open-jev-decision
Typed decision model fine-tuned from unsloth/Qwen3.5-0.8B on ZefanCai/Open-Jev (release-v2-redistributable)
with Unsloth FastDecisionModel / DecisionTrainer. For each record (a JSON state plus one
or more questions) it returns one probability per allowed option for every question:
noul → P(yes), choice → distribution over options, score → distribution over ordered levels.
Architecture
- Backbone:
unsloth/Qwen3.5-0.8B(revision23c69c53358a07516b5827588b3fdb12ae78fd65), loaded in 4-bit NF4 (bitsandbytes), LoRA on the language-model linear layers; vision tower frozen. - LoRA: r=16, alpha=16, dropout=0, target modules:
(?:.*?(?:language|text).*?(?:self_attn|attention|attn|mixer|mlp|feed_forward|ffn|dense|mixer).*?\.(?:qkv|proj|linear_fc1|linear_fc2|out_proj|in_proj_qkv|in_proj_z|in_proj_b|in_proj_a|gate_proj|up_proj|down_proj|q_proj|k_proj|v_proj|o_proj))|(?:\bmodel\.layers\.[\d]{1,}(?!.*\.experts\.\d)\..*?(?:self_attn|attention|attn|mixer|mlp|feed_forward|ffn|dense|mixer).*?\.(?:(?:qkv|proj|linear_fc1|linear_fc2|out_proj|in_proj_qkv|in_proj_z|in_proj_b|in_proj_a|gate_proj|up_proj|down_proj|q_proj|k_proj|v_proj|o_proj))). - Decision head: Clef joint schema head (fp32), config
{"hidden_size": 1024, "width": 512, "routing_layers": 2, "layers": 4, "heads": 8, "feedforward": 2048}. Questions of a record are scored jointly; options are read from the prompt (span pooling + lexical embedding prior), so the option set can differ per question. - Trainable parameters: 38,147,588 (LoRA 10,822,656, head 27,324,932).
- Max sequence length: 2048 tokens per record.
Training data
- Dataset:
ZefanCai/Open-Jev, configrelease-v2-redistributable, revisionc67699e13d0ae25e35b77165a4b6b079bedc8aba. - Model input:
state_json(decoded),question,kind,options.targetis the supervision only.id,group_id,split,source,metadata_json(incl. teacher/control labels),record_jsonandoriginal_line_numberare never part of the input. - Rows sharing
(group_id, state)are packed into records of ≤ 16 questions and ≤ 2048 tokens; option order is preserved.
| split | rows | questions used | skipped | records | mean tokens | truncated |
|---|---|---|---|---|---|---|
| train | 79,116 | 79,116 | 0 | 19,017 | 905 | 0 |
| calibration | 4,672 | 4,672 | 0 | 1,291 | 828 | 0 |
| validation | 3,723 | 3,723 | 0 | 1,091 | 738 | 0 |
| test | 10,356 | 10,356 | 0 | 2,532 | 904 | 0 |
| ood | 15,701 | 15,701 | 0 | 2,792 | 1121 | 0 |
Splits are the dataset's own; group_id sets are disjoint across splits. Train is used for training,
validation for checkpoint selection, calibration once for temperature fitting, test/OOD for reporting only.
Training procedure
- Loss: soft-target cross-entropy over each question's options (
noul= binary log loss on the [no, yes] target;choice/score= cross-entropy against the full target distribution), averaged over questions. label_smoothing=0.0, brier_weight=0.0, ordinal_weight=0.0. - Optimizer: AdamW, lr 0.0001 (LoRA) / 0.0001 (head), cosine schedule, warmup 50 steps, weight decay 0.01.
- Batch: 2 records × 4 accumulation = 8 records/step; bf16 autocast; Unsloth gradient checkpointing.
- Steps: 2378 (1.000 epochs of 2378 steps/epoch).
- Checkpoint selection: lowest validation
eval_loss(0.4202 atcheckpoint-2378). - Seed: 3407.
- Hardware: NVIDIA GeForce RTX 5060 Ti (15.9 GiB); train time 72.3 min; peak CUDA memory {'max_allocated_gib': 2.08, 'max_reserved_gib': 2.85}.
- Software: unsloth 2026.10.3, transformers 5.17.0, torch 2.11.0+cu128, peft 0.18.1, bitsandbytes 0.49.2.
Calibration
Per-kind temperatures fitted once on the calibration split (soft-target cross-entropy, range [0.5, 5]): {"noul": 1.1281152314853171, "choice": 1.0897223768764925, "score": 1.5317417263480422}. They are stored in unsloth_decision_config.json (temperature = [choice, score, noul]) and applied by FastDecisionModel.predict.
Evaluation
Metrics per decision kind (never averaged across kinds). top1_accuracy counts any option tied for the
highest target probability as correct; ece uses 15 bins; mae_expected_level is in level units.
validation (3,723 questions)
choice
| count | cross_entropy | kl_divergence | brier | top1_accuracy | ece | |
|---|---|---|---|---|---|---|
| model (calibrated) | 957 | 0.5858 | 0.3880 | 0.1928 | 0.8976 | 0.1546 |
| model (T=1) | 957 | 0.5899 | 0.3920 | 0.1927 | 0.8976 | 0.1440 |
| train-prior baseline | 957 | 1.1815 | 0.9836 | 0.5247 | 0.5308 | 0.1613 |
| uniform baseline | 957 | 1.3942 | 1.1964 | 0.5930 | 0.3647 | 0.0953 |
noul
| count | log_loss | brier | accuracy | f1_yes | roc_auc | ece | |
|---|---|---|---|---|---|---|---|
| model (calibrated) | 2285 | 0.1012 | 0.0299 | 0.9628 | 0.9302 | 0.9898 | 0.0122 |
| model (T=1) | 2285 | 0.1027 | 0.0302 | 0.9628 | 0.9302 | 0.9898 | 0.0153 |
| train-prior baseline | 2285 | 0.5248 | 0.1746 | 0.7177 | 0.1272 | 0.7196 | 0.0367 |
| uniform baseline | 2285 | 0.6931 | 0.2500 | 0.2801 | 0.4376 | 0.5000 | 0.2199 |
score
| count | cross_entropy | brier | top1_accuracy | mae_expected_level | ece | |
|---|---|---|---|---|---|---|
| model (calibrated) | 481 | 0.1484 | 0.0641 | 0.9439 | 0.0852 | 0.0245 |
| model (T=1) | 481 | 0.1526 | 0.0645 | 0.9439 | 0.0825 | 0.0245 |
| train-prior baseline | 481 | 1.2497 | 0.7195 | 0.3555 | 1.0217 | 0.1467 |
| uniform baseline | 481 | 1.3733 | 0.7256 | 0.2931 | 0.9854 | 0.2037 |
test (10,356 questions)
choice
| count | cross_entropy | kl_divergence | brier | top1_accuracy | ece | |
|---|---|---|---|---|---|---|
| model (calibrated) | 2408 | 0.3929 | 0.2724 | 0.1405 | 0.9124 | 0.0812 |
| model (T=1) | 2408 | 0.3952 | 0.2747 | 0.1408 | 0.9124 | 0.0732 |
| train-prior baseline | 2408 | 1.4070 | 1.2865 | 0.6279 | 0.3895 | 0.0819 |
| uniform baseline | 2408 | 1.6666 | 1.5461 | 0.6946 | 0.2919 | 0.0858 |
noul
| count | log_loss | brier | accuracy | f1_yes | roc_auc | ece | |
|---|---|---|---|---|---|---|---|
| model (calibrated) | 6364 | 0.0742 | 0.0224 | 0.9701 | 0.9401 | 0.9955 | 0.0099 |
| model (T=1) | 6364 | 0.0755 | 0.0226 | 0.9701 | 0.9401 | 0.9955 | 0.0115 |
| train-prior baseline | 6364 | 0.5137 | 0.1712 | 0.7423 | 0.1211 | 0.7084 | 0.0111 |
| uniform baseline | 6364 | 0.6931 | 0.2500 | 0.2575 | 0.4096 | 0.5000 | 0.2425 |
score
| count | cross_entropy | brier | top1_accuracy | mae_expected_level | ece | |
|---|---|---|---|---|---|---|
| model (calibrated) | 1584 | 0.1081 | 0.0486 | 0.9545 | 0.0665 | 0.0132 |
| model (T=1) | 1584 | 0.1094 | 0.0498 | 0.9545 | 0.0632 | 0.0110 |
| train-prior baseline | 1584 | 0.9735 | 0.5386 | 0.5795 | 0.8185 | 0.0509 |
| uniform baseline | 1584 | 1.3616 | 0.7285 | 0.2304 | 0.8425 | 0.0717 |
ood (15,701 questions)
choice
| count | cross_entropy | kl_divergence | brier | top1_accuracy | ece | |
|---|---|---|---|---|---|---|
| model (calibrated) | 3219 | 1.4359 | 1.3747 | 0.3860 | 0.7850 | 0.1811 |
| model (T=1) | 3219 | 1.5370 | 1.4758 | 0.3867 | 0.7850 | 0.1757 |
| train-prior baseline | 3219 | 1.6481 | 1.5869 | 0.7358 | 0.3020 | 0.0983 |
| uniform baseline | 3219 | 1.8714 | 1.8102 | 0.7621 | 0.3253 | 0.1355 |
noul
| count | log_loss | brier | accuracy | f1_yes | roc_auc | ece | |
|---|---|---|---|---|---|---|---|
| model (calibrated) | 9929 | 0.5547 | 0.0964 | 0.8849 | 0.7504 | 0.9068 | 0.0700 |
| model (T=1) | 9929 | 0.6121 | 0.0973 | 0.8849 | 0.7504 | 0.9068 | 0.0756 |
| train-prior baseline | 9929 | 0.5210 | 0.1727 | 0.7711 | 0.0977 | 0.6658 | 0.0740 |
| uniform baseline | 9929 | 0.6931 | 0.2500 | 0.2285 | 0.3720 | 0.5000 | 0.2715 |
score
| count | cross_entropy | brier | top1_accuracy | mae_expected_level | ece | |
|---|---|---|---|---|---|---|
| model (calibrated) | 2553 | 0.6442 | 0.2662 | 0.8394 | 0.3415 | 0.1022 |
| model (T=1) | 2553 | 0.9070 | 0.2790 | 0.8394 | 0.3337 | 0.1176 |
| train-prior baseline | 2553 | 0.9765 | 0.5673 | 0.5484 | 0.9007 | 0.0479 |
| uniform baseline | 2553 | 1.3676 | 0.7296 | 0.3098 | 0.8954 | 0.0592 |
Usage
from unsloth import FastDecisionModel
model, processor = FastDecisionModel.from_pretrained("thealper2/qwen3.5-0.8b-open-jev-decision", max_seq_length=2048, load_in_4bit=True)
answers = FastDecisionModel.predict(model, processor, state, {
"q1": {"type": "noul", "instructions": "Will moving up cause a collision?"},
"q2": {"type": "choice", "instructions": "Choose a direction.", "criteria": {"A": "up", "B": "right", "C": "down"}},
"q3": {"type": "score", "instructions": "Rate the risk.", "criteria": ["low", "medium", "high"]},
})
Choice criteria use ids A, B, … in the original option order (Clef sorts choice ids); noul options map
false/true to no/yes. src/inference.py in the training repository does this conversion.
Files
adapter_model.safetensors,adapter_config.json: LoRA weights for the backbone.joint_head.safetensors,joint_head_config.json: decision head.unsloth_decision_config.json: layout, max length, base model, calibrated temperatures.- tokenizer / processor files of the base model.
Limitations
- Trained and evaluated only on Open-Jev's controlled, mostly synthetic tasks; scores do not transfer to other decision problems. OOD here means the dataset's reserved wording/layout/family splits.
- Records longer than the max sequence length have the end of their state cut.
- Requires Unsloth's decision-model loader; the files are not a plain causal-LM adapter.