Qwen3-32B's BPE tokenizer over-segments common Korean endings and particles (어미/조사) into 2-4 sub-tokens. This model adds them as single tokens, trained via QLoRA to be natively used during generation.
The 3,682 tokens were extracted from HyperCLOVA's Korean-optimized vocabulary — specifically endings (어미) and particles (조사) that Qwen's BPE consistently fragments.
1from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
2import torch
3
4model_id = "2264K/Qwen3-32B-KoTokenizer"
5
6# NF4 quantization (fits in 24GB VRAM)
7bnb_config = BitsAndBytesConfig(
8 load_in_4bit=True,
9 bnb_4bit_quant_type="nf4",
10 bnb_4bit_compute_dtype=torch.bfloat16,
11 bnb_4bit_use_double_quant=True,
12)
13
14tokenizer = AutoTokenizer.from_pretrained(model_id)
15model = AutoModelForCausalLM.from_pretrained(
16 model_id,
17 quantization_config=bnb_config,
18 device_map="auto",
19 torch_dtype=torch.bfloat16,
20)
21
22# Verify new tokens work
23print(tokenizer.encode("했잖아", add_special_tokens=False))
24# [155305] ← single token (was 3 tokens before)
25
26# Generate
27messages = [{"role": "user", "content": "어제 친구를 만났는데 걔가 갑자기 이상한 얘기를 하더라고."}]
28text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True, enable_thinking=False)
29inputs = tokenizer(text, return_tensors="pt").to(model.device)
30
31with torch.no_grad():
32 outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9)
33
34print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))