Instructions to use hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged") model = AutoModelForCausalLM.from_pretrained("hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged
- SGLang
How to use hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged with Docker Model Runner:
docker model run hf.co/hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged
CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged
This is an intermediate checkpoint, released as a baseline. It is a 30.5B-parameter mixture-of-experts model (3.3B activated) built from Qwen3-30B-A3B-Base by continual pre-training on 784M tokens of Cantonese and Hong Kong text, then adding the chat vector taken from Qwen3-30B-A3B-Thinking-2507.
It has Hong Kong knowledge and instruction following, acquired at zero training cost for the second of those. What it does not have is Cantonese reasoning: it thinks in Written Chinese. Installing that behaviour took three further stages, and the result is CantoneseLLM-v2.0-30B-A3B-Thinking.
Use this model if you want a Cantonese-knowledgeable instruct model and do not care what language the chain-of-thought is in, or you are reproducing the paper's ablations. Otherwise use the final model.
📄 Paper: CantoneseLLM v2: Reasoning in a Low-Resource Language (arXiv:2609.06970)
🧪 Evaluation Benchmark: hon9kon9ize/hkeval2025
What the chat vector does, and what it does not
The merge is one operation and requires no instruction data:
Δ_chat = θ_instruct − θ_base # Qwen3-30B-A3B-Thinking-2507 − Qwen3-30B-A3B-Base
θ_merged = θ_cpt + Δ_chat # added to the continually pre-trained checkpoint
It installs instruction following and alignment for free. It also carries over the donor's reasoning language, which continual pre-training does not override. On a translated GSM8K probe, under a system prompt that explicitly asks for Hong Kong Cantonese, this model opens its trace in Cantonese:
首先,用戶嘅問題係關於Janet嘅鴨蛋生意。我需要用香港廣東話回應,因為系統設定係CantoneseLLM。
(First, the user's question is about Janet's duck egg business. I need to respond in Hong Kong Cantonese, because the system is set to CantoneseLLM.)
…and then slides into Written Chinese later in the same span, ending up discussing the output language rather than thinking in it:
…現在,用香港廣東話回應。…在回應中,要用口語廣東話。
(…Now, respond in Hong Kong Cantonese. … In the response, colloquial Cantonese should be used.)
現在 jin6 zoi6 is the Written Chinese form where Cantonese uses 而家 ji4 gaa1, and 在⋯中 zoi6…zung1 is a Mandarin-shared construction. The final answer is correct and reads as Cantonese; the reasoning that produced it does not.
Trace length over eight fixed probes (mean tokens between the reasoning tags):
| Checkpoint | Mean CoT tokens | CoT-to-answer ratio |
|---|---|---|
| Qwen3-30B-A3B-Thinking-2507 (donor) | 1,042 | 6.25 |
| This model | 1,442 | 5.85 |
| CantoneseLLM-v2.0-30B-A3B-Thinking (final) | 155 | 1.43 |
This model reasons at length — longer than its own donor. That is worth knowing: the length was never the problem, the language was.
Benchmark results
HKCanto-Eval (Cheng et al., 2025), reasoning mode on:
| Model | MMLU | CantoMMLU | Cultural | Linguistic | Academic & Prof. | Avg. |
|---|---|---|---|---|---|---|
| Qwen3-30B-A3B-Thinking-2507 (donor) | 86.65 | 82.52 | 68.65 | 57.00 | 86.70 | 76.30 |
| This model | 80.71 | 80.26 | 70.24 | 55.00 | 85.59 | 74.36 |
| CantoneseLLM-v2.0-30B-A3B-Thinking (final) | 84.26 | 76.24 | 65.06 | 56.50 | 83.70 | 73.16 |
The merge costs 1.94 points against the donor (−2.55%), and the regression is concentrated in MMLU in English, which drops 5.94 points. Cultural is the one category that improves — 68.65 → 70.24 — which is the continual pre-training showing through, since that is the category most about Hong Kong.
This model scores 1.20 points above the final RLVR model. That is not a reason to prefer it. The benchmark is multiple-choice and does not measure the language of the chain-of-thought, which is the entire difference between the two checkpoints. Selecting on this average gets you a model that thinks in Written Chinese.
Artefacts released with this work
The CPT corpus itself is not released, but its two largest public constituents are.
| What it is | |
|---|---|
| 🌐 Traditional-Chinese-Common-Crawl-by-year | Traditional Chinese extracted from all 111 Common Crawl snapshots, released per snapshot across thirteen years |
| 🇭🇰 Cantonese-Web-Data | The Cantonese subset of the above, filtered with CantoneseDetect and globally deduplicated to 477,298 unique documents |
| 🏋️ cantonese-nemo-gym-environments | The six NeMo-Gym environments and the multiplicative language reward. Used by the final models, not by this checkpoint; MIT licensed |
| 📊 Nemotron-3-Nano-RL-Training-Blend-STEM-Yue-Translated | The RLVR prompt corpus, a three-way parallel en/ yue/ zh-hk/ translation of NVIDIA's Nemotron-3-Nano RL blend. Also used by the final models only |
Other models in this release
All four checkpoints are in the CantoneseLLM v2.0 collection.
| Model | What it is |
|---|---|
| CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged | this model — CPT + chat-vector merge, before SFT, DPO and RLVR |
| CantoneseLLM-v2.0-30B-A3B-Thinking | The flagship, built from this checkpoint through SFT, DPO and two-stage RLVR. Reasons in Cantonese. Prefer it unless you specifically need this baseline |
| CantoneseLLM-v2.0-8B-Thinking-Chat-Vector-Merged | The same intermediate stage at 8B, where the inherited reasoning language is Simplified Chinese rather than Written Chinese |
| CantoneseLLM-v2.0-8B-Thinking | The 8B dense model through the full five stages |
Usage
Transformers
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, dtype="auto", device_map="auto")
SYSTEM = "你係CantoneseLLM,一個由Hon9Kon9ize開發嘅語言模型,請使用香港嘅廣東話回答用家問題"
messages = [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": "小明有 5 個蘋果,佢俾咗 2 個朋友,每人 1 個,跟住又買多 3 個。佢而家有幾多個蘋果?"},
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer([text], return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=2048, temperature=0.6, top_p=0.95)
print(tokenizer.decode(out[0][len(inputs.input_ids[0]):], skip_special_tokens=True))
vLLM
The stock command works — no special flags are required:
vllm serve hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged
Add --tensor-parallel-size N to shard across N GPUs, and
--reasoning-parser qwen3 if you want the reasoning block returned separately
as reasoning_content rather than inline in content (parser names vary by
vLLM version).
OpenAI-compatible API
The served endpoint speaks the OpenAI protocol, so the official client works unchanged:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
SYSTEM = "你係CantoneseLLM,一個由Hon9Kon9ize開發嘅語言模型,請使用香港嘅廣東話回答用家問題"
resp = client.chat.completions.create(
model="hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged",
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": "小明有 5 個蘋果,佢俾咗 2 個朋友,每人 1 個,跟住又買多 3 個。佢而家有幾多個蘋果?"},
],
temperature=0.6,
top_p=0.95,
max_tokens=2048,
)
msg = resp.choices[0].message
print(getattr(msg, "reasoning_content", None) or "") # populated with --reasoning-parser
print(msg.content)
Or with curl:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "hon9kon9ize/CantoneseLLM-v2.0-30B-A3B-Thinking-Chat-Vector-Merged",
"messages": [
{"role": "system", "content": "你係CantoneseLLM,一個由Hon9Kon9ize開發嘅語言模型,請使用香港嘅廣東話回答用家問題"},
{"role": "user", "content": "點解香港嘅雨季集中喺五月到九月?"}
],
"temperature": 0.6, "top_p": 0.95, "max_tokens": 2048
}'
Sampling: temperature 0.6, top-p 0.95 — the settings used for every evaluation reported above and in the paper. Avoid greedy decoding.
System prompt: the Cantonese system prompt above was used throughout evaluation. Behaviour with other system prompts, or with none, is not characterised.
Chat template and thinking mode are inherited from the donor. The chat vector
came from Qwen3-30B-A3B-Thinking-2507, a reasoning-only model, so this checkpoint
always produces a reasoning block. Do not expect /no_think to work as it does
in the stock Qwen3 hybrid models.
Training pipeline
| Stage | What it installed | Compute |
|---|---|---|
| Continual pre-training | Hong Kong knowledge and Cantonese lexis. 784M tokens over 568K rows, 530 steps (2.19B tokens seen, 2.79 passes), LR 1.5×10⁻⁵, on 64 TPU v6e chips (Google TRC) via MaxText | 199 TPU chip-hours |
| Chat-vector merge | Instruction following and alignment. Δ = Qwen3-30B-A3B-Thinking-2507 − Qwen3-30B-A3B-Base, added to the CPT checkpoint | 0 |
That is the whole pipeline for this checkpoint — no SFT, no DPO, no RLVR. The corpus was 32.9% Common Crawl (5.4% of the total in Cantonese), 20.9% English replay from Nemotron pre-training data, and 17.1% web fiction, which is the only source where Cantonese is sustained over tens of thousands of tokens.
The CPT learning rate was selected across eight settings from 1.0×10⁻⁵ to 5.0×10⁻⁵ by benchmark average rather than by training loss — the paper reports that loss anti-correlates with the quantity of interest in this regime.
Risks & Limitations
- It does not reason in Cantonese. This is the defining limitation and the reason the rest of the pipeline exists. The trace opens in Cantonese and drifts into Written Chinese. If you need Cantonese chain-of-thought, use the final model.
- Instruction following is inherited, not trained. It arrives through weight arithmetic from the donor and was never fine-tuned on Cantonese instruction data. Behaviour outside the donor's own distribution is not characterised.
- MMLU regression. 5.94 points below the donor in English MMLU. The merge is not free in capability terms even though it is free in compute terms.
- No translation, data-curation or judging ability. Those were installed at SFT, which this checkpoint precedes.
- CPT was 784M tokens — small by continual-pre-training standards (Taiwan-LLM used 35.1B, Swallow and SEA-LION 200B each). Hong Kong knowledge is real but thin, and the corpus leans on web fiction for long-form Cantonese.
- Alignment is whatever the chat vector carried over. No additional safety tuning was performed at any stage.
- Long context is inherited and untested — the CPT sequence length was 4,096 packed. Behaviour beyond that is whatever the Qwen3 base provides.
- Standard LLM caveats apply: it will hallucinate.
Citation
@misc{cantonesellm_v2,
title={CantoneseLLM v2: Reasoning in a Low-Resource Language},
author={Tsz Chung Cheng and Chung Shing Cheng and Chaak Ming Lau and Cheuk Hei Chong},
year={2026},
eprint={2609.06970},
archivePrefix={arXiv},
primaryClass={cs.CL},
url={https://arxiv.org/abs/2609.06970},
}
The chat vector method is due to Huang et al., Chat Vector: A Simple Approach to Equip LLMs with Instruction Following and Model Alignment in New Languages, ACL 2024, pp. 10943–10959.
Acknowledgements
Continual pre-training (CPT) was carried out on Cloud TPUs (Tensor Processing Units) from Google's TPU Research Cloud with MaxText. Post-training was carried out on computer resources offered under the category of General Projects by Research Institute for Information Technology, Kyushu University. Usage fee and cost of data-curation costs with proprietary APIs were covered by Votee AI
The RLVR stage builds on NVIDIA's NeMo-RL and NeMo-Gym, and on the Nemotron post-training and RL datasets.
- Downloads last month
- 466