Text Generation
Transformers
Safetensors
Uzbek
English
qwen3_5_text
qwen3.5
uzbek
conversational
translation
text-generation-inference
Instructions to use NeuronUz/NeuronAI-2B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use NeuronUz/NeuronAI-2B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="NeuronUz/NeuronAI-2B") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("NeuronUz/NeuronAI-2B") model = AutoModelForCausalLM.from_pretrained("NeuronUz/NeuronAI-2B", 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 NeuronUz/NeuronAI-2B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "NeuronUz/NeuronAI-2B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "NeuronUz/NeuronAI-2B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/NeuronUz/NeuronAI-2B
- SGLang
How to use NeuronUz/NeuronAI-2B 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 "NeuronUz/NeuronAI-2B" \ --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": "NeuronUz/NeuronAI-2B", "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 "NeuronUz/NeuronAI-2B" \ --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": "NeuronUz/NeuronAI-2B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use NeuronUz/NeuronAI-2B with Docker Model Runner:
docker model run hf.co/NeuronUz/NeuronAI-2B
Replace with full-FT v3 checkpoint (weighted 0.4388, was 0.4190); update card with benchmarks + clean usage
Browse files- README.md +129 -105
- model.safetensors +1 -1
- tokenizer_config.json +1 -1
README.md
CHANGED
|
@@ -12,93 +12,98 @@ tags:
|
|
| 12 |
- text-generation
|
| 13 |
- conversational
|
| 14 |
- axolotl
|
| 15 |
-
- lora
|
| 16 |
---
|
| 17 |
|
| 18 |
-
# Qwen3.5 2B Uzbek Fine-Tuned
|
| 19 |
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
## Model lineage
|
| 26 |
|
| 27 |
1. `Qwen/Qwen3.5-2B-Base`
|
| 28 |
-
2.
|
| 29 |
-
3.
|
| 30 |
-
4.
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
## Training summary
|
| 35 |
|
| 36 |
- Framework: Axolotl / Transformers
|
| 37 |
-
-
|
| 38 |
-
-
|
| 39 |
-
|
| 40 |
-
-
|
| 41 |
-
-
|
| 42 |
-
-
|
| 43 |
-
-
|
| 44 |
-
-
|
| 45 |
-
-
|
| 46 |
-
-
|
| 47 |
-
|
| 48 |
-
The training
|
| 49 |
-
examples, and Uzbek knowledge/language material. The underlying dataset is not
|
| 50 |
-
included in this repository.
|
| 51 |
|
| 52 |
## Usage
|
| 53 |
|
| 54 |
```python
|
| 55 |
-
import re
|
| 56 |
import torch
|
| 57 |
-
from transformers import
|
| 58 |
-
AutoModelForCausalLM,
|
| 59 |
-
AutoTokenizer,
|
| 60 |
-
StoppingCriteria,
|
| 61 |
-
StoppingCriteriaList,
|
| 62 |
-
)
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
class SentenceLimitCriteria(StoppingCriteria):
|
| 66 |
-
"""Stop after a fixed number of complete generated sentences."""
|
| 67 |
-
|
| 68 |
-
def __init__(self, tokenizer, prompt_length, max_sentences=4):
|
| 69 |
-
self.tokenizer = tokenizer
|
| 70 |
-
self.prompt_length = prompt_length
|
| 71 |
-
self.max_sentences = max_sentences
|
| 72 |
-
|
| 73 |
-
def __call__(self, input_ids, scores, **kwargs):
|
| 74 |
-
generated = self.tokenizer.decode(
|
| 75 |
-
input_ids[0, self.prompt_length:], skip_special_tokens=True
|
| 76 |
-
)
|
| 77 |
-
endings = re.findall(r'[.!?](?:["\'’”)]*)?\s+', generated)
|
| 78 |
-
return len(endings) >= self.max_sentences
|
| 79 |
-
|
| 80 |
|
| 81 |
model_id = "NeuronUz/qwen3.5-2b-fine-tuned"
|
| 82 |
-
device = "cuda:0" if torch.cuda.is_available() else "cpu"
|
| 83 |
-
max_sentences = 4
|
| 84 |
|
| 85 |
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 86 |
model = AutoModelForCausalLM.from_pretrained(
|
| 87 |
model_id,
|
| 88 |
-
|
| 89 |
-
#
|
| 90 |
-
device_map=device,
|
| 91 |
)
|
| 92 |
|
| 93 |
messages = [
|
| 94 |
-
{
|
| 95 |
-
"role": "system",
|
| 96 |
-
"content": (
|
| 97 |
-
"Siz foydali AI yordamchisiz. Javoblarni qisqa va aniq yozing. "
|
| 98 |
-
"Agar foydalanuvchi batafsil javob so'ramasa, odatda 2-4 ta "
|
| 99 |
-
"to'liq gap bilan javob bering."
|
| 100 |
-
),
|
| 101 |
-
},
|
| 102 |
{"role": "user", "content": "O'zbekiston haqida qisqacha ma'lumot bering."},
|
| 103 |
]
|
| 104 |
|
|
@@ -109,58 +114,77 @@ inputs = tokenizer.apply_chat_template(
|
|
| 109 |
return_dict=True,
|
| 110 |
).to(model.device)
|
| 111 |
|
| 112 |
-
im_end_id = tokenizer.convert_tokens_to_ids("<|im_end|>")
|
| 113 |
-
eos_ids = [tokenizer.eos_token_id, im_end_id]
|
| 114 |
-
stopping_criteria = StoppingCriteriaList(
|
| 115 |
-
[
|
| 116 |
-
SentenceLimitCriteria(
|
| 117 |
-
tokenizer,
|
| 118 |
-
prompt_length=inputs["input_ids"].shape[-1],
|
| 119 |
-
max_sentences=max_sentences,
|
| 120 |
-
)
|
| 121 |
-
]
|
| 122 |
-
)
|
| 123 |
-
|
| 124 |
with torch.inference_mode():
|
| 125 |
-
output = model.generate(
|
| 126 |
-
|
| 127 |
-
max_new_tokens=256,
|
| 128 |
-
do_sample=False,
|
| 129 |
-
repetition_penalty=1.15,
|
| 130 |
-
no_repeat_ngram_size=3,
|
| 131 |
-
eos_token_id=eos_ids,
|
| 132 |
-
pad_token_id=tokenizer.eos_token_id,
|
| 133 |
-
stopping_criteria=stopping_criteria,
|
| 134 |
-
)
|
| 135 |
-
|
| 136 |
-
prompt_length = inputs["input_ids"].shape[-1]
|
| 137 |
reply = tokenizer.decode(
|
| 138 |
-
output[0][
|
| 139 |
).strip()
|
|
|
|
|
|
|
| 140 |
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
sentence_endings = list(sentence_end_re.finditer(reply))
|
| 145 |
-
if len(sentence_endings) >= max_sentences:
|
| 146 |
-
reply = reply[:sentence_endings[max_sentences - 1].end()].strip()
|
| 147 |
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
```
|
| 150 |
|
| 151 |
-
|
| 152 |
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
|
| 161 |
## Limitations
|
| 162 |
|
| 163 |
-
The model may produce inaccurate, biased, or fabricated information.
|
| 164 |
-
|
| 165 |
-
|
|
|
|
|
|
|
| 166 |
consequential settings.
|
|
|
|
| 12 |
- text-generation
|
| 13 |
- conversational
|
| 14 |
- axolotl
|
|
|
|
| 15 |
---
|
| 16 |
|
| 17 |
+
# Qwen3.5 2B Uzbek Fine-Tuned
|
| 18 |
|
| 19 |
+
A text-only Qwen3.5 2B checkpoint for Uzbek instruction following and
|
| 20 |
+
conversation, with English retained. Uzbek continued pretraining and annealing,
|
| 21 |
+
then a full-parameter supervised fine-tune.
|
| 22 |
+
|
| 23 |
+
This release replaces the earlier LoRA-broad checkpoint. It scores higher on
|
| 24 |
+
every benchmark below and, unlike its predecessor, **stops generating on its
|
| 25 |
+
own** — the previous checkpoints never learned to emit the turn terminator and
|
| 26 |
+
needed sentence counters and repetition penalties to produce usable output. The
|
| 27 |
+
usage example below is correspondingly plain.
|
| 28 |
|
| 29 |
## Model lineage
|
| 30 |
|
| 31 |
1. `Qwen/Qwen3.5-2B-Base`
|
| 32 |
+
2. Uzbek tokenizer extension (vocabulary 248,320) and embedding initialization
|
| 33 |
+
3. Uzbek continued pretraining
|
| 34 |
+
4. Annealing
|
| 35 |
+
5. Full-parameter supervised fine-tuning (no LoRA — these are the trained weights)
|
| 36 |
+
|
| 37 |
+
## Benchmarks
|
| 38 |
+
|
| 39 |
+
Public Uzbek evaluation suite, vLLM backend, full test splits, greedy decoding.
|
| 40 |
+
Identical harness and settings for all three models. Translation is FLORES+ with
|
| 41 |
+
sacreBLEU and COMET (`Unbabel/wmt22-comet-da`).
|
| 42 |
+
|
| 43 |
+
| Benchmark | Metric | **This model** | Previous release (LoRA broad) | Qwen3.5-2B-Instruct (stock) |
|
| 44 |
+
| --- | --- | ---: | ---: | ---: |
|
| 45 |
+
| UzLiB | accuracy | **0.4863** | 0.4782 | 0.2880 |
|
| 46 |
+
| TUMLU-Uzbek | accuracy | **0.3214** | 0.3686 | 0.3129 |
|
| 47 |
+
| News classification | accuracy | **0.7948** | 0.7355 | 0.3675 |
|
| 48 |
+
| Sentiment (binary) | accuracy | **0.9626** | 0.9348 | 0.7676 |
|
| 49 |
+
| MMLU (English) | accuracy | **0.5422** | 0.5300 | 0.5241 |
|
| 50 |
+
| MMLU (Uzbek) | accuracy | **0.4707** | 0.4640 | 0.3711 |
|
| 51 |
+
| FLORES+ en→uz | BLEU | **9.90** | 4.05 | 4.16 |
|
| 52 |
+
| FLORES+ en→uz | COMET | **0.8496** | 0.7413 | 0.6790 |
|
| 53 |
+
| FLORES+ uz→en | BLEU | **23.07** | 5.93 | 17.13 |
|
| 54 |
+
| FLORES+ uz→en | COMET | **0.8314** | 0.6056 | 0.8091 |
|
| 55 |
+
| **Weighted score** | | **0.4388** | 0.4190 | 0.3154 |
|
| 56 |
+
|
| 57 |
+
The weighted score combines all eight tasks (UzLiB 0.20, TUMLU 0.20, en→uz 0.15,
|
| 58 |
+
news 0.10, MMLU-en 0.10, MMLU-uz 0.10, uz→en 0.05, sentiment 0.05), with BLEU
|
| 59 |
+
scaled to a 0–1 range.
|
| 60 |
+
|
| 61 |
+
Notes on reading these numbers honestly:
|
| 62 |
+
|
| 63 |
+
- **Translation is where the gain is largest** (en→uz BLEU 4.05 → 9.90, uz→en
|
| 64 |
+
5.93 → 23.07). Much of that is the terminator fix: the previous checkpoint ran
|
| 65 |
+
past the end of its answer, which BLEU punishes severely.
|
| 66 |
+
- **TUMLU-Uzbek regressed** (0.3686 → 0.3214) and is this model's weakest task.
|
| 67 |
+
It is also near the 0.25 random baseline for 4-choice questions, so treat
|
| 68 |
+
Uzbek multi-subject knowledge as unreliable.
|
| 69 |
+
- Invalid-output rate was 0.0000 on all format-scored tasks.
|
| 70 |
+
- The checkpoint published here is the one that scored best on this suite
|
| 71 |
+
(1.5 epochs), selected across all 12 training checkpoints. It is not the final
|
| 72 |
+
epoch-3 weights, which scored 0.4310.
|
| 73 |
|
| 74 |
## Training summary
|
| 75 |
|
| 76 |
- Framework: Axolotl / Transformers
|
| 77 |
+
- Method: full-parameter supervised fine-tuning
|
| 78 |
+
- Data: 169,919 conversational examples (Uzbek-first, with task-format and
|
| 79 |
+
English retention data)
|
| 80 |
+
- Sequence length: 2,048, one sample per sequence (no packing)
|
| 81 |
+
- Epochs: 3, best checkpoint by benchmark score taken at 1.5 epochs
|
| 82 |
+
- Effective batch size: 32
|
| 83 |
+
- Learning rate: 1e-5, cosine schedule, 3% warmup
|
| 84 |
+
- Optimizer: AdamW, β₂ = 0.95, gradient clipping 1.0
|
| 85 |
+
- Precision: bf16
|
| 86 |
+
- Loss on assistant turns only; `<|im_end|>` trained as the turn terminator
|
| 87 |
+
|
| 88 |
+
The training data is not included in this repository.
|
|
|
|
|
|
|
| 89 |
|
| 90 |
## Usage
|
| 91 |
|
| 92 |
```python
|
|
|
|
| 93 |
import torch
|
| 94 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
model_id = "NeuronUz/qwen3.5-2b-fine-tuned"
|
|
|
|
|
|
|
| 97 |
|
| 98 |
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 99 |
model = AutoModelForCausalLM.from_pretrained(
|
| 100 |
model_id,
|
| 101 |
+
dtype=torch.bfloat16,
|
| 102 |
+
device_map="cuda:0", # keep this hybrid model on a single device
|
|
|
|
| 103 |
)
|
| 104 |
|
| 105 |
messages = [
|
| 106 |
+
{"role": "system", "content": "Siz foydali AI yordamchisiz."},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
{"role": "user", "content": "O'zbekiston haqida qisqacha ma'lumot bering."},
|
| 108 |
]
|
| 109 |
|
|
|
|
| 114 |
return_dict=True,
|
| 115 |
).to(model.device)
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
with torch.inference_mode():
|
| 118 |
+
output = model.generate(**inputs, max_new_tokens=512, do_sample=False)
|
| 119 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
reply = tokenizer.decode(
|
| 121 |
+
output[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True
|
| 122 |
).strip()
|
| 123 |
+
print(reply)
|
| 124 |
+
```
|
| 125 |
|
| 126 |
+
No stopping criteria, repetition penalty, or `no_repeat_ngram_size` are needed —
|
| 127 |
+
the model emits `<|im_end|>`, and `generation_config.json` already registers it
|
| 128 |
+
as an end-of-sequence token.
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
+
### Multi-turn chat
|
| 131 |
+
|
| 132 |
+
```python
|
| 133 |
+
messages = [{"role": "system", "content": "Siz foydali AI yordamchisiz."}]
|
| 134 |
+
|
| 135 |
+
while True:
|
| 136 |
+
user = input("> ").strip()
|
| 137 |
+
if user in {"", "exit", "quit"}:
|
| 138 |
+
break
|
| 139 |
+
messages.append({"role": "user", "content": user})
|
| 140 |
+
|
| 141 |
+
inputs = tokenizer.apply_chat_template(
|
| 142 |
+
messages,
|
| 143 |
+
add_generation_prompt=True,
|
| 144 |
+
return_tensors="pt",
|
| 145 |
+
return_dict=True,
|
| 146 |
+
).to(model.device)
|
| 147 |
+
|
| 148 |
+
with torch.inference_mode():
|
| 149 |
+
output = model.generate(**inputs, max_new_tokens=512, do_sample=False)
|
| 150 |
+
|
| 151 |
+
reply = tokenizer.decode(
|
| 152 |
+
output[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True
|
| 153 |
+
).strip()
|
| 154 |
+
print(reply)
|
| 155 |
+
messages.append({"role": "assistant", "content": reply})
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
### vLLM
|
| 159 |
+
|
| 160 |
+
```python
|
| 161 |
+
from vllm import LLM, SamplingParams
|
| 162 |
+
|
| 163 |
+
llm = LLM(model="NeuronUz/qwen3.5-2b-fine-tuned", max_model_len=4096)
|
| 164 |
+
params = SamplingParams(temperature=0.0, max_tokens=512)
|
| 165 |
+
|
| 166 |
+
messages = [
|
| 167 |
+
{"role": "system", "content": "Siz foydali AI yordamchisiz."},
|
| 168 |
+
{"role": "user", "content": "Bugungi ob-havo haqida nima deya olasiz?"},
|
| 169 |
+
]
|
| 170 |
+
print(llm.chat(messages, params)[0].outputs[0].text)
|
| 171 |
```
|
| 172 |
|
| 173 |
+
### Notes
|
| 174 |
|
| 175 |
+
- Requires a Transformers release with Qwen3.5 support.
|
| 176 |
+
- Greedy decoding (`do_sample=False`) was used for all benchmark numbers above.
|
| 177 |
+
For sampling, a reasonable starting point is `temperature=0.7`, `top_p=0.8`,
|
| 178 |
+
`top_k=20`.
|
| 179 |
+
- Avoid `device_map="auto"` when several GPUs are visible: current
|
| 180 |
+
Accelerate/Transformers releases may split the Qwen3.5 hybrid layers across
|
| 181 |
+
devices and produce invalid text. Pin the model to one device as shown.
|
| 182 |
|
| 183 |
## Limitations
|
| 184 |
|
| 185 |
+
The model may produce inaccurate, biased, or fabricated information. Uzbek
|
| 186 |
+
multi-subject knowledge (TUMLU) is close to the random baseline, so factual
|
| 187 |
+
answers in specialist domains should not be trusted. It has not been
|
| 188 |
+
comprehensively evaluated for safety or high-stakes use. Verify outputs
|
| 189 |
+
independently before relying on them in medical, legal, financial, or other
|
| 190 |
consequential settings.
|
model.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 4781022144
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d39d981c03f63bb711d44ab9a7fb963dc118f57eef0cc00bff9d39543e086f03
|
| 3 |
size 4781022144
|
tokenizer_config.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
| 10 |
"errors": "replace",
|
| 11 |
"image_token": "<|image_pad|>",
|
| 12 |
"is_local": true,
|
| 13 |
-
"local_files_only":
|
| 14 |
"model_max_length": 262144,
|
| 15 |
"model_specific_special_tokens": {
|
| 16 |
"audio_bos_token": "<|audio_start|>",
|
|
|
|
| 10 |
"errors": "replace",
|
| 11 |
"image_token": "<|image_pad|>",
|
| 12 |
"is_local": true,
|
| 13 |
+
"local_files_only": true,
|
| 14 |
"model_max_length": 262144,
|
| 15 |
"model_specific_special_tokens": {
|
| 16 |
"audio_bos_token": "<|audio_start|>",
|