Kanitakorn-Qwen3-8B-SFT-v3 (research-driven recipe)
A LoRA adapter on top of Qwen/Qwen3-8B, third iteration with research-driven recipe fixes.
Differences from v1
| change | v1 | v3 | why |
|---|---|---|---|
| Loss masking | text-mode loss-on-all (TRL default) | assistant_only_loss=True | TRL's text-mode trains the model to reproduce user turns โ addresses MT-Bench regression |
| Input format | text field |
messages field |
required for assistant-only loss |
| LoRA rank | r=64, alpha=128 | r=16, alpha=32, use_rslora=True | Biderman 2024: lower rank preserves base chat fluency |
| Learning rate | 1e-4 | 5e-5 | lower for stability with smaller rank |
| Dataset | 4,147 Kanitakorn (gap-weighted Thai benchmark) | 14,215 records: 4,215 Kanitakorn + 4,000 WangchanThaiInstruct + 3,000 WildChat + 1,500 OASST + 1,500 No Robots | added chat-balanced data per Tulu-3 mixture proportions |
| Training | 2 epochs, ~1,652 steps | 1 epoch, 1,500 max steps | one pass over the larger corpus |
| Contamination check | n/a | iapp/openthaieval test-only confirmed, NO OTE+CoT data added | avoids inflating our OTE scores |
Results
WARNING โ incomplete evaluation. Full benchmark eval was interrupted to free GPU for Round 4 (which uses Unsloth acceleration). Only partial data:
| benchmark | v3 | v1 (for ref) | sample |
|---|---|---|---|
| AIME24 | 0.154 | 0.033 | n=13 (partial, larger sample needed) |
| (all other benchmarks) | TODO โ eval was killed at step 13 of 285 | โ | โ |
Use with caution: the AIME24 partial number is encouraging (4.7x vs v1) but n=13 has very wide CI. Reproduce in your own pipeline before using v3 over v1 for any decision.
Training recipe
LoraConfig(
r=16, lora_alpha=32, target_modules='all-linear',
lora_dropout=0.05, bias='none', task_type='CAUSAL_LM',
use_rslora=True,
)
SFTConfig(
num_train_epochs=1, max_steps=1500,
per_device_train_batch_size=2, gradient_accumulation_steps=8,
learning_rate=5e-5, bf16=True,
warmup_ratio=0.05, weight_decay=0.01,
lr_scheduler_type='cosine',
neftune_noise_alpha=5.0,
assistant_only_loss=True, # KEY DIFFERENCE
gradient_checkpointing=True,
)
Usage
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base = "Qwen/Qwen3-8B"
adapter = "Jnx03/kanitakorn-qwen3-8b-sft-v3"
tok = AutoTokenizer.from_pretrained(base, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(base, torch_dtype="bfloat16", device_map="auto")
model = PeftModel.from_pretrained(model, adapter).merge_and_unload()
Honest disclosure
v3 is an experimental iteration testing the assistant_only_loss + rsLoRA + chat-balanced corpus hypotheses from our research. We released the checkpoint for transparency, but did not finish evaluating it before pivoting to v4 (Unsloth-accelerated, larger corpus). v1 remains the recommended production model until v3/v4 are fully benchmarked.
See https://huggingface.co/datasets/Jnx03/kanitakorn-th-sft for the full development log.