Introduction to Small Language Models (SLMs)
Large Language Models (LLMs) like GPT-4 and Claude have dominated the AI landscape, but they come with significant costs, latency, and infrastructure requirements. Small Language Models (SLMs) — typically ranging from 2B to 8B parameters — have emerged as powerful alternatives for developers who need capable AI without the overhead. In this tutorial, we'll compare three of the most popular SLMs available today: Qwen2, Mistral 7B, and Phi-3.
What Are SLMs and Why They Matter
Small Language Models are compact neural networks trained on high-quality data to perform language tasks at a fraction of the cost of their larger counterparts. They are designed to run on consumer hardware, edge devices, or cost-effective cloud instances while still delivering impressive performance on many tasks.
Why SLMs Matter for Developers
- Lower inference costs: SLMs require less compute, making them ideal for high-volume applications.
- Reduced latency: Smaller models generate tokens faster, improving user experience.
- Privacy and on-device deployment: SLMs can run locally, keeping sensitive data on-device.
- Easier fine-tuning: Training or fine-tuning an SLM is feasible on a single GPU.
- Open weights: Most popular SLMs are open-weight, giving developers full control.
Model Overview
Qwen2 (Alibaba)
Qwen2 is the second generation of Alibaba's Tongyi Qianwen model family. Released in multiple sizes (0.5B, 1.5B, 7B, and 72B), the 7B variant is the most comparable to its peers. Qwen2 supports a 128K context window in its extended version and was trained on a massive multilingual corpus covering 29+ languages. It excels in coding, mathematics, and multilingual tasks.
Key specs:
- Parameters: 7B (also available in 0.5B, 1.5B, 72B)
- Context window: 32K (standard), 128K (extended)
- License: Apache 2.0 (for most sizes)
- Strengths: Multilingual support, coding, long context
Mistral 7B (Mistral AI)
Mistral 7B was released by Mistral AI in late 2023 and quickly became a community favorite. It introduced Grouped-Query Attention (GQA) and Sliding Window Attention (SWA) for efficient inference. Mistral 7B outperformed Llama 2 13B on many benchmarks despite being nearly half the size, making it a landmark release for the SLM category.
Key specs:
- Parameters: 7B
- Context window: 8K (standard), extendable with RoPE scaling
- License: Apache 2.0
- Strengths: General reasoning, efficient architecture, strong community ecosystem
Phi-3 (Microsoft)
Phi-3 is Microsoft's family of small models, with the Phi-3 Mini (3.8B) being the flagship SLM. It was trained on "textbook quality" synthetic data, which allows it to punch well above its weight class. Despite being smaller than both Qwen2 7B and Mistral 7B, Phi-3 Mini competes with them on many reasoning and knowledge benchmarks.
Key specs:
- Parameters: 3.8B (Mini), also available in Small (7B) and Medium (14B)
- Context window: 4K (standard), 128K (mini-128K variant)
- License: MIT
- Strengths: Reasoning, compact size, high-quality training data
Head-to-Head Comparison
Let's compare these three models across key dimensions that matter to developers:
Performance on Common Benchmarks
- MMLU (general knowledge): Qwen2 7B (~84%), Mistral 7B (~62%), Phi-3 Mini (~69%)
- HumanEval (coding): Qwen2 7B (~79%), Mistral 7B (~30%), Phi-3 Mini (~62%)
- GSM8K (math reasoning): Qwen2 7B (~82%), Mistral 7B (~52%), Phi-3 Mini (~82%)
- MT-Bench (multi-turn conversation): All three perform competitively in the 6-8 range
Note: Benchmark numbers vary by quantization, prompt format, and evaluation methodology. Always run your own evaluation on your specific use case.
Resource Requirements
- Qwen2 7B: ~14GB VRAM (FP16), ~5GB (4-bit quantized)
- Mistral 7B: ~14GB VRAM (FP16), ~5GB (4-bit quantized)
- Phi-3 Mini: ~8GB VRAM (FP16), ~2.5GB (4-bit quantized)
Phi-3 Mini's smaller parameter count gives it a clear advantage in memory-constrained environments, while Qwen2 and Mistral require similar resources.
When to Choose Each Model
- Choose Qwen2 7B if you need multilingual support, long context windows, or strong coding capabilities.
- Choose Mistral 7B if you want a battle-tested general-purpose model with a mature ecosystem and tooling.
- Choose Phi-3 Mini if you have strict resource constraints or need on-device deployment with strong reasoning.
How to Use These Models
All three models are available through the Hugging Face Hub and can be loaded using the transformers library. Let's look at practical examples for each.
Prerequisites
First, install the required packages:
pip install transformers torch accelerate bitsandbytes
Loading and Running Qwen2 7B
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "Qwen/Qwen2-7B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
messages = [
{"role": "system", "content": "You are a helpful programming assistant."},
{"role": "user", "content": "Write a Python function to check if a string is a palindrome."}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
inputs = tokenizer([text], return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=512,
temperature=0.7,
do_sample=True
)
response = tokenizer.decode(
outputs[0][len(inputs.input_ids[0]):],
skip_special_tokens=True
)
print(response)
Loading and Running Mistral 7B
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "mistralai/Mistral-7B-Instruct-v0.3"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
messages = [
{"role": "user", "content": "Explain the difference between supervised and unsupervised learning in simple terms."}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
inputs = tokenizer([text], return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=400,
temperature=0.7,
do_sample=True
)
response = tokenizer.decode(
outputs[0][len(inputs.input_ids[0]):],
skip_special_tokens=True
)
print(response)
Loading and Running Phi-3 Mini with 4-bit Quantization
Phi-3 Mini is small enough to run on consumer GPUs. Here's how to load it with 4-bit quantization to save even more memory:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
model_name = "microsoft/Phi-3-mini-4k-instruct"
quantization_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=quantization_config,
device_map="auto"
)
messages = [
{"role": "system", "content": "You are a concise AI assistant."},
{"role": "user", "content": "What are three best practices for writing clean code?"}
]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
inputs = tokenizer([text], return_tensors="pt").to(model.device)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=300,
temperature=0.5,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
response = tokenizer.decode(
outputs[0][len(inputs.input_ids[0]):],
skip_special_tokens=True
)
print(response)
Using Ollama for Local Deployment
For the simplest local deployment experience, Ollama supports all three models. After installing Ollama, you can run any of them with a single command:
# Pull and run Qwen2 7B
ollama run qwen2:7b
# Pull and run Mistral 7B
ollama run mistral
# Pull and run Phi-3 Mini
ollama run phi3
You can then interact with the models via the Ollama Python SDK:
import requests
def query_ollama(model, prompt):
response = requests.post(
"http://localhost:11434/api/generate",
json={
"model": model,
"prompt": prompt,
"stream": False
}
)
return response.json()["response"]
# Example usage with all three models
models = ["qwen2:7b", "mistral", "phi3"]
prompt = "Summarize the concept of recursion in programming in two sentences."
for model in models:
print(f"\n=== {model} ===")
print(query_ollama(model, prompt))
Using vLLM for High-Throughput Inference
If you need to serve these models in production with high throughput, vLLM is an excellent choice:
# Install vLLM
pip install vllm
from vllm import LLM, SamplingParams
# Load any of the three models
llm = LLM(model="Qwen/Qwen2-7B-Instruct")
sampling_params = SamplingParams(
temperature=0.7,
max_tokens=512
)
prompts = [
"Write a haiku about debugging.",
"Explain what a REST API is.",
"List three Python best practices."
]
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f"Prompt: {prompt}")
print(f"Output: {generated_text}\n")
Fine-Tuning with LoRA
All three models can be fine-tuned efficiently using LoRA (Low-Rank Adaptation). Here's a minimal example using PEFT:
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from peft import LoraConfig, get_peft_model
from datasets import Dataset
from trl import SFTTrainer
model_name = "mistralai/Mistral-7B-Instruct-v0.3"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
# Apply LoRA
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Prepare a sample dataset
training_data = [
{"text": "### Human: What is Python?\n### Assistant: Python is a high-level programming language."},
{"text": "### Human: What is a variable?\n### Assistant: A variable is a named storage location in memory."}
]
dataset = Dataset.from_list(training_data)
training_args = TrainingArguments(
output_dir="./fine-tuned-mistral",
num_train_epochs=3,
per_device_train_batch_size=2,
save_steps=100,
logging_steps=10,
learning_rate=2e-4
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
args=training_args,
)
trainer.train()
# Save the fine-tuned adapter
model.save_pretrained("./fine-tuned-mistral-adapter")
Best Practices
Model Selection
- Benchmark on your own data: Public benchmarks are useful for initial filtering, but always evaluate on representative samples from your actual use case.
- Start small, scale up: Begin with Phi-3 Mini. If it doesn't meet your quality bar, move to Mistral 7B or Qwen2 7B.
- Consider quantization early: 4-bit quantization with bitsandbytes or AWQ can reduce memory by 75% with minimal quality loss.
Prompt Engineering
- Use the correct chat template: Each model has its own chat format. Always use
apply_chat_templaterather than manually formatting prompts. - Be explicit with system prompts: SLMs benefit more from clear instructions than larger models. Specify format, tone, and constraints explicitly.
- Keep prompts concise: Smaller models can lose focus with overly long or complex prompts. Break tasks into smaller steps.
Deployment
- Use vLLM or TGI for production: These serving frameworks provide batching, streaming, and optimized inference that raw
transformerscannot match. - Monitor for hallucinations: SLMs hallucinate more frequently than large models. Implement output validation and guardrails.
- Cache aggressively: Use semantic caching (e.g., with Redis or GPTCache) to avoid redundant inference calls.
- Consider a hybrid approach: Route simple queries to an SLM and complex queries to a larger model using a routing layer.
Fine-Tuning
- Use LoRA or QLoRA: Full fine-tuning of 7B models is expensive. LoRA adapters train in hours on a single GPU and can be swapped at runtime.
- Curate high-quality data: A few hundred high-quality examples often outperform thousands of mediocre ones, especially for SLMs.
- Evaluate after fine-tuning: Fine-tuning can cause catastrophic forgetting. Always evaluate on a held-out set that covers the model's original capabilities.
Conclusion
Qwen2, Mistral 7B, and Phi-3 represent the state of the art in small language models, each with distinct strengths. Qwen2 7B leads in multilingual tasks, coding, and long-context scenarios. Mistral 7B offers a mature, well-supported general-purpose model with an efficient architecture. Phi-3 Mini stands out for its remarkable reasoning ability in an ultra-compact footprint, making it ideal for edge deployment. The right choice depends on your specific constraints around latency, memory, language support, and task complexity. By starting with a clear evaluation strategy, leveraging quantization, and following deployment best practices, you can harness these SLMs to build cost-effective, performant AI applications that rival solutions built on much larger models.