Text Generation
Transformers
GGUF
English
llama
llama.cpp
unsloth
lora
reasoning
chain-of-thought
think-tags
smollm2
conversational
Instructions to use sbussiso/SmolThinker with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use sbussiso/SmolThinker with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="sbussiso/SmolThinker") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("sbussiso/SmolThinker") model = AutoModelForCausalLM.from_pretrained("sbussiso/SmolThinker", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use sbussiso/SmolThinker 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 sbussiso/SmolThinker:Q4_K_M # Run inference directly in the terminal: llama cli -hf sbussiso/SmolThinker:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf sbussiso/SmolThinker:Q4_K_M # Run inference directly in the terminal: llama cli -hf sbussiso/SmolThinker:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf sbussiso/SmolThinker:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf sbussiso/SmolThinker:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf sbussiso/SmolThinker:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf sbussiso/SmolThinker:Q4_K_M
Use Docker
docker model run hf.co/sbussiso/SmolThinker:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use sbussiso/SmolThinker with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "sbussiso/SmolThinker" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "sbussiso/SmolThinker", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/sbussiso/SmolThinker:Q4_K_M
- SGLang
How to use sbussiso/SmolThinker 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 "sbussiso/SmolThinker" \ --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": "sbussiso/SmolThinker", "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 "sbussiso/SmolThinker" \ --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": "sbussiso/SmolThinker", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use sbussiso/SmolThinker with Ollama:
ollama run hf.co/sbussiso/SmolThinker:Q4_K_M
- Unsloth Studio
How to use sbussiso/SmolThinker with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for sbussiso/SmolThinker to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for sbussiso/SmolThinker to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for sbussiso/SmolThinker to start chatting
- Docker Model Runner
How to use sbussiso/SmolThinker with Docker Model Runner:
docker model run hf.co/sbussiso/SmolThinker:Q4_K_M
- Lemonade
How to use sbussiso/SmolThinker with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull sbussiso/SmolThinker:Q4_K_M
Run and chat with the model
lemonade run user.SmolThinker-Q4_K_M
List all available models
lemonade list
- Atomic Chat
File size: 10,780 Bytes
02a58db d39ac56 02a58db d39ac56 ea5cc28 6405831 d39ac56 f51d4fd c56a0ed f51d4fd c56a0ed f51d4fd d39ac56 f51d4fd d39ac56 02a58db f51d4fd 02a58db d39ac56 02a58db d39ac56 | 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 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | ---
base_model: HuggingFaceTB/SmolLM2-1.7B-Instruct
datasets:
- sbussiso/SmolThinker-Synthetic-Low-Reasoning
library_name: transformers
license: apache-2.0
language:
- en
pipeline_tag: text-generation
tags:
- gguf
- llama.cpp
- unsloth
- lora
- reasoning
- chain-of-thought
- think-tags
- smollm2
---
# SmolThinker
`SmolLM2-1.7B-Instruct` fine-tuned to emit its reasoning inside literal
`<think>` ... `</think>` blocks, so chat UIs that render collapsible reasoning
(Open WebUI, Ollama, LM Studio) display it as a proper thinking section rather
than dumping it into the answer.
Reasoning is deliberately brief, around three short lines. The goal is reliable
tag emission and visible working, not long deliberation.
## Output format
```
<think>
I need to subtract 305 from 701.
Break 305 into 300 and 5.
701 - 300 = 401.
401 - 5 = 396.
</think>
701 - 305 = 396.
```
## Usage
```bash
llama-cli -hf sbussiso/SmolThinker --jinja
```
The `--jinja` flag matters. It uses the embedded ChatML template, which is what
the model was trained against.
For Ollama, ChatML turn format with both markers as stops:
```
PARAMETER stop "<|im_start|>"
PARAMETER stop "<|im_end|>"
```
## Prompt format
ChatML, inherited from SmolLM2:
```
<|im_start|>system
You are a helpful AI assistant.<|im_end|>
<|im_start|>user
What is 47 + 68?<|im_end|>
<|im_start|>assistant
```
Works with or without a system prompt. Roughly 40% of training rows carried no
system turn, so the template's injected default is in distribution; the rest
used generic prompts naming no model.
Multi-turn works too. About 11% of training rows are 2 to 3 turn conversations
where each follow-up depends on an earlier turn, so the model reads prior
context rather than treating every message as fresh.
## Training data
[sbussiso/SmolThinker-Synthetic-Low-Reasoning](https://huggingface.co/datasets/sbussiso/SmolThinker-Synthetic-Low-Reasoning),
2,593 rows.
| Source | Rows |
| --- | ---: |
| Templated single-turn, 26 task families | 1,800 |
| Templated multi-turn | 200 |
| Hand-written single-turn | 514 |
| Hand-written multi-turn | 79 |
593 rows are authored individually rather than generated. 100% of assistant
turns carry a think block, including greetings, so there is no example anywhere
of answering without one.
## Training configuration
LoRA adapter on a 16-bit base, trained with
[Unsloth](https://github.com/unslothai/unsloth) Studio on a single NVIDIA L4.
```yaml
method: LoRA (16-bit base)
num_epochs: 2
max_seq_length: 2048
learning_rate: 2e-4
lr_scheduler: linear
warmup_steps: 50
batch_size: 2
grad_accumulation: 4 # effective batch 8
optimizer: adamw_8bit
weight_decay: 0.001
packing: false
train_on_completions: true # loss on assistant turns only
random_seed: 3407
lora_r: 16
lora_alpha: 16
lora_dropout: 0
target_modules: q_proj k_proj v_proj o_proj gate_proj up_proj down_proj
```
614 steps, 762,325 tokens, 11m45s. Final training loss 0.639, final evaluation
loss approximately 0.600, final gradient norm 0.414.
### Why two epochs
Three runs were compared. At three epochs the model overfits: evaluation loss
bottoms around step 591 and then climbs while training loss keeps falling.
| Run | Config | Final train loss | Final eval loss | Overfit |
| --- | --- | ---: | ---: | --- |
| 1 | 3 epochs, rank 32 | 0.452 | ~0.645 | yes, 0.050 |
| 2 | 3 epochs, rank 16 | 0.517 | ~0.621 | yes, 0.030 |
| 3 | **2 epochs, rank 16** | **0.639** | **~0.600** | **none** |
Both three-epoch runs turned upward at the same step regardless of rank, so the
cause was epoch count against a 2,453-row training split rather than adapter
capacity. Run 3 is this release: higher training loss with the lowest
evaluation loss, and a gradient norm that stays flat instead of climbing, which
is what generalisation rather than memorisation looks like.
## Design notes
The tags are **ordinary text tokens**, not special tokens. On the SmolLM2
tokenizer `<think>` is `['<', 'think', '>']` and `</think>` is
`['</', 'think', '>']`, tokenizing identically in every training row. This is
deliberate: registering them via `add_special_tokens()` would give them
untrained embeddings and, more importantly, `skip_special_tokens=True` on
decode would strip them from the output, which is the usual reason a reasoning
fine-tune produces correct reasoning with no visible tags. Qwen3 makes the same
choice, adding them to the vocab but marking them `special=False`.
`embedding_learning_rate` was left unset for the same reason: the tags are
ordinary tokens and the embedding layer does not need to move.
## Evaluation
Measured on GSM8K (OpenAI grade-school math), a 300-problem subset of the
1,319-problem test set. Zero-shot: the raw question is sent through each model's
chat template with no few-shot examples. All four models are evaluated via
Ollama at Q4_K_M, so the only variable between SmolThinker and its base is the
fine-tune. SmolThinker emits its `<think>` block then a final answer; the
final number is parsed out and graded against the GSM8K answer key.
### GSM8K accuracy and format compliance
| Model | GSM8K acc | Well-formed | n |
| --- | ---: | ---: | ---: |
| **SmolThinker (this model, Q4_K_M)** | 27.7% | **94.3%** | 300 |
| SmolLM2-1.7B-Instruct (base, Q4_K_M) | 32.7% | 0.0% | 300 |
| Qwen2.5-1.5B-Instruct (Q4_K_M) | 64.3% | 0.0% | 300 |
| Llama-3.2-1B-Instruct (Q4_K_M) | 46.7% | 0.0% | 300 |
Well-formed means a single closed `<think>` block followed by a non-empty
answer. Only SmolThinker emits these tags, so the column is meaningful only for
it.

### Format compliance
Measured on 40 open-ended prompts written to be unlike anything in the training
data (why is the sky blue, write a two-line poem, how do I decline a meeting).
None of them appear anywhere in the dataset. The v1 column is the previous
release, trained on v1 of the dataset.
| Metric | v1 | This release |
| --- | ---: | ---: |
| Well-formed think block | 70.0% | **97.5%** |
| Usable (block plus an answer) | 90.0% | **97.5%** |
| Produced an answer | 100% | 100% |
| No ChatML leakage | 100% | 100% |
v1 emitted a spurious trailing `</think>` on 8 of 40 responses and an extra
opening tag on 2 more. This release does neither: the only remaining failure is
one creative-writing prompt where it answers without a think block.
The cause of the v1 defect was answer length. Every answer in v1 was a single
short clause of about 17 characters, so on open-ended prompts the model ran past
the answer-length distribution it had learned and reached for the closing tag it
associated with finishing. v2 added hand-written long-form and medium-form
answers to fill that gap, and the defect disappeared.
### Held-out accuracy
On the dataset's own 140-row validation split: **59.3% accuracy, 98.6%
well-formed**. This is **not comparable** to the previous release's 88.3%, because
the validation split changed between versions in both size and content. v2's
split contains the hand-written long-form and multi-turn rows that v1's did not,
and those are substantially harder to grade than a templated arithmetic answer.
Treat it as a v2 baseline for future runs rather than as a regression.
### What the fine-tune does and does not do
The fine-tune reliably produces clean, leak-free structured reasoning. On the
300 held-out GSM8K problems SmolThinker emitted a well-formed `<think>` block
94.3% of the time, always produced a parseable final answer (100%), and never
leaked ChatML markers (`<|im_start|>` / `<|im_end|>`) into its output. Median
reasoning length is 158 characters, around three short lines, which is the
intended behavior.
It does **not** improve GSM8K accuracy over its base. SmolThinker scores 27.7%
against the base's 32.7%, about 5 points lower, and that gap is **not
statistically significant at this sample size**. The 95% confidence interval on
the difference is [-2.3, +12.3] points, and McNemar's test on the discordant
pairs gives chi-squared 2.42 against the 3.84 needed for p < 0.05. So the
honest reading is "no measurable difference in either direction", not a
regression and not parity. The head-to-head on the same 300 problems shows the
shape of it:
| Outcome | Count |
| --- | ---: |
| Both correct | 50 |
| Both wrong | 169 |
| SmolThinker correct, base wrong | 33 |
| Base correct, SmolThinker wrong | 48 |
| Net | -15 |
The reasoning helps on 33 problems the base missed and hurts on 48 problems the
base got right, netting -15, which is the accuracy gap. Two failure patterns
account for most of the losses. When the think block breaks (17 of 300 rows) the
final-number parser pulls a nonsense value, and when the model skips reasoning
it answers like a weaker SmolLM2. The concise reasoning this fine-tune produces
is sometimes insufficient for multi-step arithmetic.
### Context
The base this model is built on, SmolLM2-1.7B-Instruct, is itself a weak math
model at roughly 33% on this subset, well behind same-class peers: Qwen2.5-1.5B
scores 64.3% and Llama-3.2-1B scores 46.7%. SmolThinker did not start from a
strong base and the fine-tune did not change that.
**In short: SmolThinker is a formatting fine-tune. It teaches reliable, visible,
structured chain-of-thought emission. It does not improve, and may slightly
reduce, raw math accuracy versus the base.**
These are 300-problem subset numbers. A full 1,319-problem run would tighten
the accuracy estimate. Broader benchmarks (ARC, HellaSwag, MMLU) have not yet
been run, so general-knowledge retention versus the base is not yet measured.
Methodology and raw per-problem results live in the `bench/` directory of the
source repository.
## Limitations
Training data is largely templated and synthetic, so phrasing diversity in that
portion is bounded and the task set is deliberately narrow. This teaches the
shape of reasoning and reliable tag emission, not general reasoning ability.
Expect arithmetic to degrade outside the ranges seen in training, and expect
confident-looking traces on problems the model gets wrong.
The 593 hand-written rows are a finite set, so some memorisation of them is
possible.
Evaluated on GSM8K only (see above). The fine-tune does not improve raw math
accuracy over the base and trends slightly lower, so this is a formatting
fine-tune rather than a capability upgrade. Broader benchmarks (ARC, HellaSwag,
MMLU) have not been run, so general-knowledge retention versus the base is not
measured.
If you consume the output programmatically, strip any stray `</think>` after
the first closing tag rather than assuming exactly one.
Built with [Unsloth](https://github.com/unslothai/unsloth).
|