Model description
- Base:
Qwen/Qwen3.5-2B (unified
VLM class, used text-only).
- Architecture:
Qwen3_5ForConditionalGeneration, Gated DeltaNet hybrid
attention, 24 layers, hidden 2048, vocab 248,320, tie_word_embeddings.
- Stage-1 adapter (now merged): LoRA
r=64, alpha=128, dropout 0.0,
bf16, targeting q/k/v/o_proj, gate/down/up_proj, and the Qwen3.5
linear-attention projections (linear_attn.in_proj_qkv, linear_attn.in_proj_z,
linear_attn.out_proj).
- What it knows: forward/reverse lookup, description, and child-enumeration
of UNSPSC / HS / NAICS / SOC / ISO-3166 codes, and their SERAX encodings.
Intended use
Use as the base model for SERAX task adapters (e.g. the v1.5 business-website
analyst). It can also be queried directly for code lookups (see below), but it is
a building block, not a finished product model.
How to use
Loads as an ordinary causal-LM. There is no system prompt for this stage —
training rows are direct user → assistant code queries.
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
m = "vantigeai/qwen35-2b-serax-codes-base"
tok = AutoTokenizer.from_pretrained(m)
model = AutoModelForCausalLM.from_pretrained(m, torch_dtype=torch.bfloat16, device_map="auto")
msgs = [{"role": "user",
"content": "What UNSPSC v26.0801 codes belong directly to 31163000 — Couplings?"}]
inputs = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device)
out = model.generate(inputs, max_new_tokens=256, do_sample=False)
print(tok.decode(out[0, inputs.shape[1]:], skip_special_tokens=True))
To load the stage-2 analyst adapter on top of this base:
from peft import PeftModel
model = PeftModel.from_pretrained(model, "vantigeai/serax_business_website_analyst_v1.5")
Training data
Stage-1 data is data/code_train.jsonl — 31,817 examples, each a direct
user → assistant turn (no system prompt), generated from the authoritative code
tables (prepare_code_data.py from data/code_fine_tuning.parquet). Only the
assistant turn is trained on (roles_to_train: ["assistant"]).
Coverage by code system (classified by the query text):
Table with columns: Code system, Examples| Code system | Examples |
|---|
| UNSPSC v26.0801 | 12,601 |
| HS 2022 | 5,326 |
| NAICS 2022 | 5,110 |
| SOC 2018 | 4,580 |
| Other (ISO-3166 geo, SERAX code records, etc.) | 4,200 |
| Total | 31,817 |
Task shapes (examples):
U: Give the description for SOC 2018 code 13-2030.
A: Budget Analysts
U: Find the SOC 2018 code for Physical Scientists, All Other.
A: 19-2099
U: What UNSPSC v26.0801 codes belong directly to 31163000 — Couplings?
A: 31163001 Elastomeric couplings
31163002 Gear couplings
31163003 Metallic couplings
...
U: Emit the SERAX record for ISO-3166 code KG-B.
A: ⨠ISO-3166-2⨡KG-B⨢Batken
U: Emit the SERAX record for Wood; assembled flooring panels … of bamboo in HS 2022.
A: ⨥441873⨦Wood; assembled flooring panels, of bamboo or with at least the top layer …
The tasks cover: code→description, description→code, enumerate children under a
parent code, and emit the SERAX encoding of a code. Assistant length: min 2 /
median 54 / max 12,438 characters.
Training configuration
Trained with Axolotl as stage 1
of 2. Key choices vs. stage 2: higher LR (2e-4) to drive rote memorization,
short sequence_len (3072 — the dataset max is 105 in + 2863 out tokens), and a
large micro_batch_size (32) since rows are short and pack efficiently.
base_model: Qwen/Qwen3.5-2B
plugins:
- axolotl.integrations.cut_cross_entropy.CutCrossEntropyPlugin
strict: false
chat_template: qwen3_5
datasets:
- path: ./data/code_train.jsonl
type: chat_template
field_messages: messages
message_property_mappings:
role: role
content: content
roles_to_train: ["assistant"]
dataset_prepared_path: last_run_prepared_codes
val_set_size: 0.02
output_dir: ./outputs/qwen35-2b-lora-codes
sequence_len: 3072
sample_packing: true
eval_sample_packing: true
pad_to_sequence_len: true
adapter: lora
lora_r: 64
lora_alpha: 128
lora_dropout: 0.0
lora_target_modules:
- q_proj
- k_proj
- v_proj
- o_proj
- gate_proj
- down_proj
- up_proj
- linear_attn.in_proj_qkv
- linear_attn.in_proj_z
- linear_attn.out_proj
attn_implementation: flash_attention_2
bf16: auto
tf32: true
optimizer: adamw_torch
lr_scheduler: cosine
learning_rate: 2.0e-4
weight_decay: 0.01
warmup_ratio: 0.03
num_epochs: 3
micro_batch_size: 32
gradient_accumulation_steps: 1
dataloader_num_workers: 8
dataloader_pin_memory: true
dataloader_prefetch_factor: 4
gradient_checkpointing: true
gradient_checkpointing_kwargs:
use_reentrant: false
logging_steps: 1
evals_per_epoch: 2
saves_per_epoch: 1
save_total_limit: 3
wandb_project: qwen35-2b-lora
wandb_entity:
wandb_name: qwen35-2b-lora-codes-4k-r64
wandb_watch:
wandb_log_model:
Key hyperparameters
Table | |
|---|
| adapter | LoRA r=64, alpha=128, dropout 0.0 (merged post-training) |
| learning_rate | 2e-4 (cosine, warmup_ratio 0.03) |
| epochs | 3 |
| micro_batch_size | 32 |
| gradient_accumulation_steps | 1 (effective batch 32) |
| optimizer | adamw_torch |
| weight_decay | 0.01 |
| sequence_len | 3,072 (sample packing) |
| precision | bf16, tf32 |
License
Apache-2.0, inheriting the Qwen3.5-2B license.
This repository redistributes Qwen3.5-2B weights with a merged fine-tuning delta.