---
license: apache-2.0
base_model: Nanbeige/Nanbeige4.1-3B
tags:
- litert
- litert-lm
- litertlm
- on-device
- edge
- reasoning
pipeline_tag: text-generation
library_name: litert-lm
---
# Nanbeige4.1-3B — LiteRT-LM (blockwise int4)
[Nanbeige/Nanbeige4.1-3B](https://huggingface.co/Nanbeige/Nanbeige4.1-3B) converted to the
**LiteRT-LM** (`.litertlm`) format for on-device inference with Google's
[LiteRT-LM](https://github.com/google-ai-edge/litert-lm) runtime (the engine behind the
official `litert-community/*` models).
Nanbeige4.1-3B is a fresh (Dec 2025) **phone-size reasoning** model on a plain dense
Llama architecture (Apache-2.0), reported to be competitive with much larger models. It
works the problem inside a `…` block before giving the final answer.
| | |
|---|---|
| **File** | `model.litertlm` (~2.2 GB; embedding externalized so every section is <2 GiB → loads on iOS) |
| **Quantization** | int4 weights — **blockwise (block 32) + OCTAV** optimal-clipping, symmetric; embedding INT8 |
| **Compute** | integer |
| **Context (KV cache)** | 4096 |
| **Base model** | Nanbeige/Nanbeige4.1-3B (Apache-2.0) |
| **Decode speed** | ~89 tok/s (Mac M4 Max, Metal GPU, greedy) |
## Usage
```bash
# build litert-lm from https://github.com/google-ai-edge/litert-lm, then:
litert_lm_main \
--model_path model.litertlm \
--backend gpu \
--input_prompt "A robe takes 2 bolts of blue fiber and half that much white fiber. How many bolts total?"
```
The `.litertlm` bundle carries the tokenizer and the prompt template (ChatML —
`<|im_start|>role\n … <|im_end|>`), so no separate tokenizer files are needed. This is a
**reasoning** model: it emits a `…` chain then the final answer (best
evaluated with a generous token budget), and stops cleanly at `<|im_end|>`.
## Run on Android
Install a recent [Google AI Edge Gallery](https://github.com/google-ai-edge/gallery)
(1.0.16+ can import `.litertlm` directly from Hugging Face), download `model.litertlm`
(or import this repo in-app), pick the **GPU** backend (CPU also works), and chat. Give it
a high max-tokens — it's a reasoning model with long chains of thought.
## Quality — GSM8K
Measured on GSM8K (n=50, greedy, 0-shot chain-of-thought, **max-tokens 2048** — a
reasoning model needs the budget to finish; scoring it at 512 tokens falsely penalises it):
| Configuration | GSM8K |
|---|---|
| **This model — LiteRT int4 (block32 + OCTAV)** | **84.0%** |
84% is a strong on-device GSM8K for a 3B, non-degenerate; the model also passes the local
quality gate **8/8** with a clean stop at `<|im_end|>`. Blockwise-32 + OCTAV optimal-clipping
(data-free) preserves the accuracy versus a naive min-max int4.
## Conversion
Converted with [`litert-torch`](https://github.com/google-ai-edge/litert) using a
**blockwise int4** recipe (INT4 weights, block size 32, symmetric, OCTAV optimal-clipping)
with the embedding at INT8, KV cache 4096, and a ChatML prompt template. Nanbeige4.1 is a
standard dense `LlamaForCausalLM`, so it rides the existing converter and runtime with no
custom graph code.
**`externalize_embedder=True` (required for iPhone).** The large 166k-token vocab makes the
weights a >2 GiB single TFLite section, which exceeds the ~2 GiB single-section `mmap` limit
on iOS. Externalizing the embedding drops the main section under 2 GiB so the model loads on
**iPhone (Metal GPU)** as well as Android/desktop. Same weights, so GSM8K is unchanged.
**Added-tokens tokenizer fix.** Nanbeige's 10 special tokens (`<|im_start|>`, `<|im_end|>`,
``, ``, ``, …) live at vocab ids 166100–166109, above the base
SentencePiece vocab (166100). The base SP conversion drops them, so the reasoning model would
generate `` (id 166103) and the runtime would crash with *"Token id out of range."* The
converted tokenizer here appends those added tokens as USER_DEFINED SentencePiece pieces at
their exact ids (padded to the model vocab), so `` and friends decode correctly.
## License
Apache-2.0, inherited from the base model
[Nanbeige/Nanbeige4.1-3B](https://huggingface.co/Nanbeige/Nanbeige4.1-3B).