Text Generation
Transformers
Safetensors
GGUF
Russian
English
Chinese
qwen3
russian
on-device
edge
mnn
keyboard
work-in-progress
conversational
text-generation-inference
Instructions to use Rahspide/MNN-Pocket-0.3B-RU with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Rahspide/MNN-Pocket-0.3B-RU with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Rahspide/MNN-Pocket-0.3B-RU") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("Rahspide/MNN-Pocket-0.3B-RU") model = AutoModelForCausalLM.from_pretrained("Rahspide/MNN-Pocket-0.3B-RU", 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=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use Rahspide/MNN-Pocket-0.3B-RU with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M # Run inference directly in the terminal: llama cli -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M # Run inference directly in the terminal: llama cli -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama cli -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Use Docker
docker model run hf.co/Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
- Llama new
- LM Studio
- Jan
- vLLM
How to use Rahspide/MNN-Pocket-0.3B-RU with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Rahspide/MNN-Pocket-0.3B-RU" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Rahspide/MNN-Pocket-0.3B-RU", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
- SGLang
How to use Rahspide/MNN-Pocket-0.3B-RU 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 "Rahspide/MNN-Pocket-0.3B-RU" \ --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": "Rahspide/MNN-Pocket-0.3B-RU", "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 "Rahspide/MNN-Pocket-0.3B-RU" \ --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": "Rahspide/MNN-Pocket-0.3B-RU", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use Rahspide/MNN-Pocket-0.3B-RU with Ollama:
ollama run hf.co/Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
- Unsloth Desktop
- Pi
How to use Rahspide/MNN-Pocket-0.3B-RU with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use Rahspide/MNN-Pocket-0.3B-RU with Docker Model Runner:
docker model run hf.co/Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
- Lemonade
How to use Rahspide/MNN-Pocket-0.3B-RU with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Run and chat with the model
lemonade run user.MNN-Pocket-0.3B-RU-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use Rahspide/MNN-Pocket-0.3B-RU with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use Rahspide/MNN-Pocket-0.3B-RU with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
File size: 13,221 Bytes
b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 609c481 b8f7f82 b63bfc8 b8f7f82 609c481 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 609c481 b8f7f82 609c481 b63bfc8 609c481 b63bfc8 b8f7f82 b63bfc8 b8f7f82 f3cb38c b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 b8f7f82 b63bfc8 609c481 52a9acb 609c481 b63bfc8 b8f7f82 5290680 b8f7f82 b63bfc8 b8f7f82 962b367 52a9acb 609c481 962b367 b8f7f82 962b367 b8f7f82 962b367 609c481 dca989a b8f7f82 994fe90 dca989a b8f7f82 dca989a b8f7f82 dca989a b63bfc8 b8f7f82 609c481 b8f7f82 fd05227 b8f7f82 b63bfc8 b8f7f82 6722589 b8f7f82 609c481 b8f7f82 609c481 b8f7f82 609c481 b8f7f82 6722589 b8f7f82 52a9acb b8f7f82 b63bfc8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | ---
language:
- ru
- en
- zh
license: apache-2.0
base_model: taobao-mnn/MNN-Pocket-0.3B-Base
library_name: transformers
pipeline_tag: text-generation
datasets:
- HuggingFaceFW/fineweb-2
- HuggingFaceFW/fineweb
tags:
- russian
- on-device
- edge
- mnn
- qwen3
- gguf
- keyboard
- work-in-progress
---



-6FA8FF?style=flat-square)



> **Status: v1 released.** 1.2 B tokens, one epoch, weights in this repository, GGUF in `gguf/`.
> Training log, checkpoints and the evaluation script live in the private repo
> [`Rahspide/mnn-pocket-ru-run`](https://huggingface.co/Rahspide/mnn-pocket-ru-run).
A continued-pretraining run of [`taobao-mnn/MNN-Pocket-0.3B-Base`](https://huggingface.co/taobao-mnn/MNN-Pocket-0.3B-Base)
that teaches it Russian while keeping English and Chinese readable. The keyboard is the use case that set the
size and latency budget.
It is trained as a plain causal LM on raw text, so it **continues** a typed prefix instead of answering it.
For dialogue there is a separate checkpoint — [`Rahspide/MNN-Pocket-0.3B-RU-Chat`](https://huggingface.co/Rahspide/MNN-Pocket-0.3B-RU-Chat).
## Two models, two jobs

| | This model — `MNN-Pocket-0.3B-RU` | Sister — `MNN-Pocket-0.3B-RU-Chat` |
|---|---|---|
| Job | continue text | follow instructions |
| Input | a prefix, often mid-sentence | a system + user message |
| Output | the plausible continuation | an answer |
| Trained with | continued pretraining, 1.2 B tokens of raw text | SFT on top of this model, 50 M tokens |
| Choose it for | keyboard suggestions, autocomplete, prefix completion | chat, Q&A, short rewrites |
| Do not choose it for | assistant behaviour: it continues your question instead of answering | autocomplete: it answers instead of continuing |
The two tasks reward opposite behaviour. Trained on both jobs, one checkpoint does each badly: it answers when
it should continue, and continues when it should answer.
## Specs
| | |
|---|---|
| Base | `taobao-mnn/MNN-Pocket-0.3B-Base` (Qwen3 architecture, 303 M non-embedding / 361 M total) |
| Tokenizer | 65,536 tokens, byte-level BPE, `<|endoftext|>` = 65510 |
| Training tokens | 1.2 B — 0.9 B ru + 0.204 B en + 0.096 B zh |
| Method | full fine-tune, 1 epoch, no LoRA |
| Steps | 36,621 × 32,768 tokens |
| Hardware | one Colab T4 16 GB, 4.8 k tok/s, ~69 h |
| Precision | fp32 master weights, fp16 autocast (T4 has no usable bf16) |
## Results

100 k held-out tokens per language, identical settings for both checkpoints:
| Lang | ppl base → v1 | bits/char base → v1 | top-1 base → v1 | top-5 base → v1 |
|---|---|---|---|---|
| **ru** | 10.42 → **5.05** | 1.625 → **1.123** (−31%) | 46.2% → **61.0%** | 69.3% → **80.6%** |
| en | 21.85 → 41.16 | 1.016 → 1.225 (+21%) | 39.9% → 35.5% | 64.1% → 58.7% |
| zh | 23.95 → 51.86 | 3.274 → 4.071 (+24%) | 41.9% → 37.7% | 62.0% → 55.6% |
The published weights were re-downloaded and re-evaluated independently (CPU, fp32, 20 k tokens per language)
and reproduce the same ordering: ru 1.022 against base 1.519, en 1.337 against 1.124, zh 4.053 against 3.393.
Russian landed past the target (1.123 against a 1.40 gate). English and Chinese regressed 21–24% instead of
the ≤10% the recipe aimed for. a 25% replay mix is too
thin at 0.36 B when the target language is tokenised this badly. A second pass with a 50/25/25 mix at lr 5e-5
was started, got through ~50 M of a planned 200 M tokens, and changed nothing measurable on English
(1.337 → 1.337 on the same eval), so it is **not** published. Treat v1 as Russian-first, with working but
measurably weaker English and Chinese.
## Why the tokenizer shapes the recipe

The base vocabulary is a distilled 65 k set with almost no Cyrillic merges, and it is byte-level: the
vocabulary stores UTF-8 bytes remapped to latin-1, so `convert_ids_to_tokens` prints `С` where the text says
`С`. That is a display artifact; `decode` returns the word. The count is what matters:
| Word | Characters | Tokens | Pieces |
|---|---|---|---|
| `Спасибо` | 7 | 6 | `С · п · ас · и · б · о` |
| `привет` | 6 | 3 | `пр · ив · ет` |
| `покупать` | 8 | 4 | `п · ок · уп · ать` |
| `Ёжик` | 4 | 4 | `Ё` lands in two separate byte tokens |
Because the vocabulary is byte-level, a token can end in the middle of a character: in `Ёжик` and `ЩУКА` the
uppercase letters are cut into single bytes. Decoding the whole sequence is still exact, but a streaming client
must hold an incomplete UTF-8 sequence back instead of printing it. `llama.cpp` and `transformers` buffer it for
you; a hand-rolled decoder has to do the same or the output shows replacement characters.
| Tokenizer | RU chars/token | RU tokens per word | EN chars/token |
|---|---|---|---|
| MNN-Pocket / Qwen3-distilled (65,536) | **1.75–1.85** (2.08 on dialogue text) | **≈3.3** | 3.78 |
| +8,192 Cyrillic merges (73,728) | **3.10** | ≈1.8 | — |
| +16,384 Cyrillic merges (81,920) | **3.39** | ≈1.6 | — |
| ruGPT3-small (50 k, Russian BPE) | 4.2 | ≈1.3 | — |
Consequences that shaped the plan:
- the same 1.2 B-token budget buys ~2.2 B Russian characters (~340 M words), roughly 2.2× less text than a
Russian-native tokenizer would fit;
- on a phone one suggested Russian word costs ~3 decode steps instead of ~1, which matters for a keyboard
latency budget;
- vocabulary surgery was measured but kept out of v1, so v1 stays tokenizer-compatible with the base and drops
into the existing MNN / GGUF toolchain. An extended-vocabulary artefact (`model_ext`, 73,728 rows, embeddings
initialised as the mean of their child tokens) exists in the private run repo but is not part of this release.
## Recipe
- Full fine-tune from `MNN-Pocket-0.3B-Base`, fp32 master weights with fp16 autocast.
- Sequence length 1024, random windows over a packed `uint16` token stream, `<|endoftext|>` between documents.
- 32,768 tokens per optimizer step (micro-batch 4 × 1024, gradient accumulation 8).
- AdamW, β = (0.9, 0.95), weight decay 0.1, gradient clip 1.0, lr 2e-4 with 1% linear warmup and cosine decay.
- One epoch over 1.2 B tokens = 36,621 steps.
- Checkpoint every 500 steps to a private HF repo; training auto-resumes from the last checkpoint after a
session restart.
## Data
All sources are public Hugging Face datasets. `*` marks the validation split: the first 100 k tokens of each
stream are held out before training starts, so validation text is never seen.
| Language | Dataset | Config | Tokens | Share |
|---|---|---|---|---|
| ru | [`HuggingFaceFW/fineweb-2`](https://huggingface.co/datasets/HuggingFaceFW/fineweb-2) | `rus_Cyrl` | 0.90 B (100 k held out*) | 75% |
| en | [`HuggingFaceFW/fineweb`](https://huggingface.co/datasets/HuggingFaceFW/fineweb) | `sample-100BT` | 0.204 B (100 k held out*) | 17% |
| zh | [`HuggingFaceFW/fineweb-2`](https://huggingface.co/datasets/HuggingFaceFW/fineweb-2) | `cmn_Hani` | 0.096 B (100 k held out*) | 8% |
Licences: FineWeb / FineWeb-2 are ODC-BY 1.0. No scraped Telegram dumps or other unlicensed chat corpora were
used, so the resulting weights stay publishable.
## Builds

| Build | Size | Download | Note |
|---|---|---|---|
| Q8_0 | 310 MB | [`MNN-Pocket-0.3B-RU-Q8_0.gguf`](https://huggingface.co/Rahspide/MNN-Pocket-0.3B-RU/blob/main/gguf/MNN-Pocket-0.3B-RU-Q8_0.gguf) | near-lossless, for desktop |
| Q4_K_M | 223 MB | [`MNN-Pocket-0.3B-RU-Q4_K_M.gguf`](https://huggingface.co/Rahspide/MNN-Pocket-0.3B-RU/blob/main/gguf/MNN-Pocket-0.3B-RU-Q4_K_M.gguf) | the size to ship on a phone |
| MNN INT4 | 165 MB | [mnn/MNN-Pocket-0.3B-RU-INT4](https://huggingface.co/Rahspide/MNN-Pocket-0.3B-RU/tree/main/mnn/MNN-Pocket-0.3B-RU-INT4) | MNN runtime, Android |
Both files sit under `gguf/` with the quant tag in the name, which is what llama.cpp matches on:
```bash
llama-cli -hf Rahspide/MNN-Pocket-0.3B-RU:Q4_K_M -p "Сегодня я" -n 40
```
Converted with llama.cpp `convert_hf_to_gguf.py` (f16) and quantised with `llama-quantize`. Measured on a
16-thread x86 CPU, no GPU involved:
| Build | Prompt processing | Generation |
|---|---|---|
| Q4_K_M | ~410 tok/s | **~130 tok/s** |
| Q8_0 | ~525 tok/s | ~99 tok/s |
Phone figures will be several times lower; these are desktop-CPU numbers.
The MNN build runs through MNN's own runtime. Build `llm_demo` from the MNN repository with
`-DMNN_BUILD_LLM=ON`, then point it at the folder:
```bash
cd mnn/MNN-Pocket-0.3B-RU-INT4 && llm_demo config.json prompt.txt
```
165 MB on disk, ~354 tok/s prefill and ~77 tok/s decode on 12 CPU threads here. `llm_config.json` carries no
chat template on purpose: this checkpoint continues the prompt, so the runtime should not wrap it in a dialogue
format.
Two conversion quirks, both already fixed in this repository's `tokenizer_config.json`.
- the base pre-tokenizer does not hash-match in current llama.cpp, so the Qwen pre-tokenizer has to be pinned
by hand (`qwen2`);
- `extra_special_tokens` must not be a list, or transformers v4 refuses to load the tokenizer.
## Reproduce
Everything below runs on CPU. The numbers in this card came from these paths.
```bash
# bits/char, ppl and top-k against the base, 20k tokens per language
python bench/eval_bpc.py --model Rahspide/MNN-Pocket-0.3B-RU --base taobao-mnn/MNN-Pocket-0.3B-Base \
--dataset HuggingFaceFW/fineweb-2 --config rus_Cyrl --tokens 20000
# throughput and a smoke generation on the quantised build
LLAMA_CLI=/path/to/llama-cli bash bench/bench_cpu.sh gguf/MNN-Pocket-0.3B-RU-Q4_K_M.gguf
```
`bench/eval_bpc.py` reports the same three metrics as the tables above (ppl, bits/char, top-1/top-5) and exits
non-zero when the model loses more than a given `--max-bpc-regression` against the base, so it can run as a
regression gate in CI. `bench/bench_cpu.sh` prints prompt and generation tok/s and checks that generation stops
at `<|endoftext|>`.
## Intended use
- On-device next-word and short-phrase suggestion in a keyboard or IME, Russian first, English and Chinese from
the same checkpoint (a keyboard can pick the language from the current word or the layout).
- Text completion, prefix continuation and autocomplete for Russian anywhere a ~220 MB quantised model has to
run locally: chat composers, note apps, search fields, terminal prompts.
- Any pipeline that needs a small causal LM fluent in Russian that can still read English and Chinese, for
example tagging, short rewriting suggestions, or generating Russian seed text.
Not intended for: instruction following, factual question answering, code, long-form reasoning, or translation.
This is a 0.36 B model trained for 1.2 B tokens; its knowledge is narrow by construction. The language mix is a
deliberate trade: Russian is the target, English and Chinese are kept from degrading, neither is improved.
## Limitations
- Russian is tokenised near character level (see above): slower decoding and a larger effective cost per Russian
word than the same model pays for English.
- Token boundaries do not follow character boundaries. Rare and uppercase Cyrillic letters are split into
single bytes, so a streaming decoder must buffer partial UTF-8 sequences; `llama.cpp` and `transformers`
already do this.
- Web text only. Register is mostly written/informal blog Russian; no dialogue corpora, no post-training.
- Capacity is 0.36 B. Expect weak facts, weak arithmetic, and drift on long generations.
- English and Chinese regressed 21–24% against the base. The 25% replay mix limits the damage; it does not
remove it.
- The ChatML template from the base is inherited but untrained here. Do not use this checkpoint in chat mode.
## Releases
| Date | Version | What changed |
|---|---|---|
| 2026-11-10 | **v1.0** | 1.2 B-token continued pretraining released: bf16 weights, GGUF Q8_0 and Q4_K_M, measured ru/en/zh bits-per-char |
| 2026-11-11 | v1.1 | MNN INT4 build for the MNN runtime: 165 MB, ~77 tok/s decode on 12 CPU threads |
| 2026-11-10 | v2.0 (sister) | Assistant checkpoint released: 50 M-token SFT on top of v1, weights and GGUF |
## Licence and attribution
Weights: Apache-2.0, inherited from the base model. Data: ODC-BY 1.0 (FineWeb, FineWeb-2).
If you use this model, credit the base release:
```bibtex
@misc{mnn_pocket_03b,
title = {MNN-Pocket-0.3B},
author = {Taobao MNN team},
year = {2026},
url = {https://huggingface.co/taobao-mnn/MNN-Pocket-0.3B}
}
```
|