๐Ÿงญ Roadmap

status: not-started difficulty: โญโญโญโญ time_to_learn: 4-5 hours date_created: 2026-03-07 date_started: date_completed: tags:

๐Ÿ—บ๏ธ Concept Mind Map

            SMALL LANGUAGE MODELS (SLMs)
                        |
        +---------------+---------------+
        |               |               |
    MODELS          TECHNIQUES      ADVANTAGES
        |               |               |
        |               |               |
    Phi-3           Distillation     On-Device
    - 3.8B params   - Learn from     - Runs on phone
    - Microsoft       teacher        - No internet
    - 85% GPT-3.5   - Smaller model  - Private
    - Mobile-ready  - Same quality   - Fast (50ms)
        |               |               |
        |               |               |
    Gemma           Quantization     Cost Savings
    - 2B/7B         - Reduce         - $0 inference
    - Google          precision      - No API costs
    - Optimized     - 4-bit/8-bit    - One-time download
    - Pixel phones  - 4x smaller     - Scale for free
        |               |               |
        |               |               |
    Mistral-7B      Efficient        Low Latency
    - 7B params       Architecture   - 50-200ms
    - Outperforms   - Grouped Query  - 10x faster
      Llama-2-13B     Attention      - Real-time
    - Open-source   - Sliding Window - Responsive
        |               |               |
        |               |               |
    Llama-3-8B      Pruning          Edge Computing
    - 8B params     - Remove         - IoT devices
    - Meta            unimportant    - Embedded systems
    - Competitive     weights        - Offline apps
    - Free          - Sparse models  - Local AI

Size vs Performance:

MODEL         SIZE    QUALITY   SPEED    DEPLOYMENT
GPT-4         350GB   100%      2000ms   Cloud only
GPT-3.5       175GB   95%       500ms    Cloud only
Llama-2-70B   140GB   90%       800ms    Server
Llama-2-13B   26GB    80%       300ms    GPU
Mistral-7B    14GB    85%       200ms    GPU/Laptop
Phi-3         3.8GB   80%       50ms     Phone/Laptop
Gemma-2B      2GB     70%       30ms     Phone

Use Case Decision Tree:

Need highest quality? โ†’ GPT-4 (Cloud)
    โ†“ No
Need offline/private? โ†’ SLM (On-device)
    โ†“ No
High volume (1M+ requests)? โ†’ SLM (Cost savings)
    โ†“ No
Need fast response (<100ms)? โ†’ SLM (Low latency)
    โ†“ No
Use GPT-3.5 (Cloud) โ†’ Good balance

Economics:

CLOUD AI (GPT-3.5):
1M requests/day ร— $0.002 = $2,000/day = $60K/month

SMALL LLM (Phi-3):
One-time: $0 (open-source)
Hosting: $100/month (single server)
Total: $100/month
SAVINGS: $59,900/month (99.8%!)

Key Techniques:

  • Distillation: Learn from larger models
  • Quantization: Reduce precision (FP32โ†’INT8)
  • Pruning: Remove unnecessary weights
  • Efficient Architecture: Better design, fewer params

๐ŸŒŸ Start With a Real-World Scenario

You want to use AI on your phone:

Option 1: ChatGPT API

Requirements:
- Internet connection (always!)
- API costs: $0.002 per request
- Latency: 500-2000ms
- Privacy: Your data goes to OpenAI servers
- Cost at scale: $2,000/month for 1M requests

โŒ Expensive, slow, requires internet, privacy concerns!

Option 2: Phi-3 (Small Language Model)

Requirements:
- Runs on your phone! (3.8GB)
- No internet needed
- Latency: 50-200ms (10x faster!)
- Privacy: Everything stays on device
- Cost: $0 (one-time download)

โœ… Fast, private, free, works offline!


The Surprise:

Phi-3 (3.8B parameters):

  • Size: 3.8GB
  • Speed: 50ms per response
  • Quality: 85% of GPT-3.5 performance
  • Runs on: iPhone, Android, Laptop

GPT-3.5 (175B parameters):

  • Size: 350GB (46x larger!)
  • Speed: 500ms per response
  • Quality: 100% (baseline)
  • Runs on: Cloud servers only

Phi-3 is 46x smaller but 85% as good! ๐Ÿคฏ


Real-World Examples:

1. Microsoft Phi-3

  • 3.8B parameters
  • Beats GPT-3.5 on many tasks!
  • Runs on iPhone
  • Free and open-source

2. Google Gemma

  • 2B and 7B versions
  • Optimized for mobile
  • Runs on Pixel phones
  • Powers on-device features

3. Meta Llama-3-8B

  • 8B parameters
  • Competitive with GPT-3.5
  • Runs on laptops
  • Open-source

4. Mistral-7B

  • 7B parameters
  • Outperforms Llama-2-13B!
  • Efficient architecture
  • Commercial use allowed

The Economics:

Cloud AI (GPT-4):

  • Cost: $0.03 per 1K tokens
  • 1M users ร— 100 requests/day = $3M/month!
  • Requires internet
  • Latency: 500-2000ms

On-Device AI (Phi-3):

  • Cost: $0 (after download)
  • 1M users ร— 100 requests/day = $0/month!
  • Works offline
  • Latency: 50-200ms

Savings: $3M/month! ๐Ÿ’ฐ


Use Cases:

โœ… Perfect for:

  • Mobile apps (privacy + speed)
  • Offline applications
  • Edge devices (IoT, robots)
  • Cost-sensitive applications
  • Real-time responses
  • Privacy-critical apps (healthcare, finance)

โŒ Not ideal for:

  • Complex reasoning (use GPT-4/o1)
  • Specialized domains (use fine-tuned large models)
  • When accuracy is critical
  • When you need latest information

By the end of this guide, you'll understand:

  • How SLMs achieve 85% performance at 2% size
  • When to use SLMs vs. large models
  • How to run models on phones/laptops
  • Optimization techniques
  • Real-world deployment
  • Cost-benefit analysis

The revolution: AI in your pocket! No internet, no costs, full privacy! ๐Ÿ“ฑ

Let's dive in! ๐Ÿš€


๐Ÿ“ฑ Small Language Models

Efficient AI: Powerful Models That Fit on Your Phone

๐Ÿ› ๏ธ Local Setup (15 Minutes)

Set up small language models:

Step 1: Install Ollama (Easiest)

# macOS/Linux
curl -fsSL https://ollama.com/install.sh | sh

# Windows: Download from ollama.com

# Verify
ollama --version

Step 2: Download Models

# Phi-3 (3.8B) - Microsoft's SLM
ollama pull phi3

# Gemma (2B/7B) - Google's SLM
ollama pull gemma:2b

# Mistral (7B) - Mistral AI
ollama pull mistral

# Llama 3.2 (3B) - Meta
ollama pull llama3.2:3b

Step 3: Test Model

# Chat with model
ollama run phi3

# Or use Python

Step 4: Python Setup

pip install ollama transformers torch
import ollama

# Test
response = ollama.chat(
    model='phi3',
    messages=[{'role': 'user', 'content': 'Hello!'}]
)

print(response['message']['content'])
print("โœ… SLM working!")

๐Ÿง  Core Concept

The Problem: LLMs Are Too Big

Large models require massive resources:

# GPT-4: 1.76 trillion parameters
# Requires: 8x A100 GPUs, 350GB RAM
# Cost: $1000/month to run
# โŒ Can't run locally

The Solution: Small But Smart

Small models are efficient and capable:

# Phi-3: 3.8 billion parameters
# Requires: 1 GPU or even CPU, 4GB RAM
# Cost: $0 (run locally)
# โœ… Runs on laptop!

How SLMs Achieve Efficiency

1. High-Quality Training Data:

Fewer parameters + Better data = Great performance

2. Architectural Improvements:

Efficient attention + Optimized layers = Faster inference

3. Quantization:

16-bit โ†’ 8-bit โ†’ 4-bit = 4x smaller

SLM Comparison

Model Size Context Speed Use Case
Phi-3 3.8B 128K Fast General, coding
Gemma 2B 2B 8K Very Fast Chat, simple tasks
Mistral 7B 7B 32K Medium Complex reasoning
Llama 3.2 3B 128K Fast General purpose

๐Ÿ’ป Code Examples

Example 1: Running SLMs with Ollama

import ollama
from typing import List, Dict

class LocalLLM:
    """
    Run small language models locally with Ollama.
    """
    
    def __init__(self, model: str = "phi3"):
        self.model = model
        print(f"Using model: {model}")
    
    def chat(self, message: str, history: List[Dict] = None) -> str:
        """
        Chat with the model.
        """
        messages = history or []
        messages.append({'role': 'user', 'content': message})
        
        response = ollama.chat(
            model=self.model,
            messages=messages
        )
        
        return response['message']['content']
    
    def stream_chat(self, message: str):
        """
        Stream response token by token.
        """
        stream = ollama.chat(
            model=self.model,
            messages=[{'role': 'user', 'content': message}],
            stream=True
        )
        
        for chunk in stream:
            print(chunk['message']['content'], end='', flush=True)
        print()
    
    def generate(self, prompt: str, max_tokens: int = 500) -> str:
        """
        Generate completion.
        """
        response = ollama.generate(
            model=self.model,
            prompt=prompt,
            options={
                'num_predict': max_tokens,
                'temperature': 0.7
            }
        )
        
        return response['response']

# Example usage
llm = LocalLLM(model="phi3")

# Simple chat
response = llm.chat("Explain quantum computing in simple terms")
print(f"Response: {response}")

# Streaming
print("\nStreaming response:")
llm.stream_chat("Write a haiku about AI")

# Generation
code = llm.generate("Write a Python function to calculate fibonacci numbers")
print(f"\nGenerated code:\n{code}")

# Multi-turn conversation
history = []
history.append({'role': 'user', 'content': 'My name is Alice'})
history.append({'role': 'assistant', 'content': 'Nice to meet you, Alice!'})

response = llm.chat("What's my name?", history=history)
print(f"\nWith history: {response}")

Example 2: Comparing Multiple SLMs

import ollama
import time
from typing import List, Dict

class SLMBenchmark:
    """
    Compare different small language models.
    """
    
    def __init__(self, models: List[str]):
        self.models = models
    
    def benchmark_speed(self, prompt: str) -> Dict:
        """
        Measure inference speed.
        """
        results = {}
        
        for model in self.models:
            print(f"\nTesting {model}...")
            
            start = time.time()
            response = ollama.generate(model=model, prompt=prompt)
            end = time.time()
            
            duration = end - start
            tokens = len(response['response'].split())
            tokens_per_sec = tokens / duration
            
            results[model] = {
                'duration': duration,
                'tokens': tokens,
                'tokens_per_sec': tokens_per_sec,
                'response': response['response'][:100] + "..."
            }
        
        return results
    
    def benchmark_quality(self, questions: List[str]) -> Dict:
        """
        Compare answer quality.
        """
        results = {model: [] for model in self.models}
        
        for question in questions:
            print(f"\nQuestion: {question}")
            
            for model in self.models:
                response = ollama.generate(
                    model=model,
                    prompt=question,
                    options={'temperature': 0}
                )
                
                results[model].append({
                    'question': question,
                    'answer': response['response']
                })
                
                print(f"{model}: {response['response'][:80]}...")
        
        return results
    
    def print_speed_results(self, results: Dict):
        """
        Print speed benchmark results.
        """
        print("\n=== Speed Benchmark ===")
        print(f"{'Model':<15} {'Time (s)':<12} {'Tokens/sec':<12}")
        print("-" * 40)
        
        for model, data in sorted(results.items(), key=lambda x: x[1]['tokens_per_sec'], reverse=True):
            print(f"{model:<15} {data['duration']:<12.2f} {data['tokens_per_sec']:<12.1f}")

# Example usage
models = ['phi3', 'gemma:2b', 'llama3.2:3b']
benchmark = SLMBenchmark(models)

# Speed test
prompt = "Explain machine learning in one paragraph"
speed_results = benchmark.benchmark_speed(prompt)
benchmark.print_speed_results(speed_results)

# Quality test
questions = [
    "What is 25 * 47?",
    "Write a Python function to reverse a string",
    "Explain the water cycle"
]

quality_results = benchmark.benchmark_quality(questions)

Example 3: Quantized Model Loading

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

class QuantizedLLM:
    """
    Load and run quantized models.
    """
    
    def __init__(self, model_name: str, quantization: str = "4bit"):
        """
        Load model with quantization.
        quantization: "4bit", "8bit", or "none"
        """
        self.tokenizer = AutoTokenizer.from_pretrained(model_name)
        
        if quantization == "4bit":
            # 4-bit quantization (smallest)
            quantization_config = BitsAndBytesConfig(
                load_in_4bit=True,
                bnb_4bit_compute_dtype=torch.float16,
                bnb_4bit_use_double_quant=True,
                bnb_4bit_quant_type="nf4"
            )
            print("Loading in 4-bit...")
        
        elif quantization == "8bit":
            # 8-bit quantization (medium)
            quantization_config = BitsAndBytesConfig(
                load_in_8bit=True
            )
            print("Loading in 8-bit...")
        
        else:
            # No quantization (full precision)
            quantization_config = None
            print("Loading in full precision...")
        
        self.model = AutoModelForCausalLM.from_pretrained(
            model_name,
            quantization_config=quantization_config,
            device_map="auto",
            trust_remote_code=True
        )
        
        print(f"Model loaded: {model_name}")
        self.print_memory_usage()
    
    def print_memory_usage(self):
        """Print model memory usage."""
        if torch.cuda.is_available():
            memory_mb = torch.cuda.memory_allocated() / 1024 / 1024
            print(f"GPU Memory: {memory_mb:.2f} MB")
        else:
            print("Running on CPU")
    
    def generate(self, prompt: str, max_length: int = 200) -> str:
        """Generate text."""
        inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
        
        outputs = self.model.generate(
            **inputs,
            max_length=max_length,
            do_sample=True,
            temperature=0.7,
            top_p=0.9
        )
        
        return self.tokenizer.decode(outputs[0], skip_special_tokens=True)

# Example usage - Compare quantization levels
model_name = "microsoft/phi-2"

print("=== 4-bit Quantization ===")
model_4bit = QuantizedLLM(model_name, quantization="4bit")
response_4bit = model_4bit.generate("Explain AI in simple terms:")
print(f"Response: {response_4bit[:200]}...")

print("\n=== 8-bit Quantization ===")
model_8bit = QuantizedLLM(model_name, quantization="8bit")
response_8bit = model_8bit.generate("Explain AI in simple terms:")
print(f"Response: {response_8bit[:200]}...")

Example 4: Edge Deployment Simulator

import ollama
import time
from dataclasses import dataclass
from typing import List

@dataclass
class DeviceSpec:
    """Device specifications."""
    name: str
    ram_gb: int
    gpu: bool
    max_model_size_gb: float

class EdgeDeployment:
    """
    Simulate deploying SLMs to edge devices.
    """
    
    DEVICES = {
        "phone": DeviceSpec("iPhone 15", 8, True, 2.0),
        "laptop": DeviceSpec("MacBook Air", 16, True, 4.0),
        "raspberry_pi": DeviceSpec("Raspberry Pi 5", 8, False, 2.0),
        "server": DeviceSpec("Edge Server", 64, True, 16.0)
    }
    
    MODELS = {
        "gemma:2b": 1.4,  # GB
        "phi3": 2.3,
        "llama3.2:3b": 2.0,
        "mistral": 4.1
    }
    
    def check_compatibility(self, device: str, model: str) -> Dict:
        """
        Check if model can run on device.
        """
        device_spec = self.DEVICES[device]
        model_size = self.MODELS[model]
        
        can_run = model_size <= device_spec.max_model_size_gb
        
        # Estimate performance
        if can_run:
            if device_spec.gpu:
                tokens_per_sec = 30 * (device_spec.ram_gb / model_size)
            else:
                tokens_per_sec = 5 * (device_spec.ram_gb / model_size)
        else:
            tokens_per_sec = 0
        
        return {
            "compatible": can_run,
            "device": device_spec.name,
            "model_size_gb": model_size,
            "available_ram_gb": device_spec.max_model_size_gb,
            "estimated_tokens_per_sec": tokens_per_sec,
            "gpu_available": device_spec.gpu
        }
    
    def recommend_model(self, device: str) -> List[str]:
        """
        Recommend models for device.
        """
        device_spec = self.DEVICES[device]
        
        compatible = []
        for model, size in self.MODELS.items():
            if size <= device_spec.max_model_size_gb:
                compatible.append(model)
        
        return compatible
    
    def deployment_report(self):
        """
        Generate deployment compatibility report.
        """
        print("=== Edge Deployment Compatibility ===\n")
        
        for device in self.DEVICES:
            print(f"\n{self.DEVICES[device].name}:")
            print(f"  RAM: {self.DEVICES[device].ram_gb}GB")
            print(f"  GPU: {'Yes' if self.DEVICES[device].gpu else 'No'}")
            print(f"  Max Model: {self.DEVICES[device].max_model_size_gb}GB")
            
            compatible = self.recommend_model(device)
            print(f"  Compatible Models: {', '.join(compatible)}")

# Example usage
deployment = EdgeDeployment()

# Check specific combination
result = deployment.check_compatibility("phone", "gemma:2b")
print("Phone + Gemma 2B:")
print(f"  Compatible: {result['compatible']}")
print(f"  Speed: {result['estimated_tokens_per_sec']:.1f} tokens/sec")

# Full report
deployment.deployment_report()

Example 5: Hybrid LLM/SLM System

import ollama
from openai import OpenAI
from typing import Dict

class HybridAI:
    """
    Use SLM for simple queries, LLM for complex ones.
    """
    
    def __init__(self, slm_model: str = "phi3", llm_model: str = "gpt-4"):
        self.slm_model = slm_model
        self.llm_model = llm_model
        self.openai_client = OpenAI()
        
        self.stats = {
            "slm_calls": 0,
            "llm_calls": 0,
            "cost_saved": 0
        }
    
    def classify_complexity(self, query: str) -> str:
        """
        Classify query as simple or complex.
        """
        # Simple heuristics
        simple_keywords = ["what is", "define", "explain", "hello", "hi"]
        complex_keywords = ["analyze", "compare", "evaluate", "design", "create"]
        
        query_lower = query.lower()
        
        if any(kw in query_lower for kw in complex_keywords):
            return "complex"
        elif any(kw in query_lower for kw in simple_keywords):
            return "simple"
        elif len(query.split()) > 50:
            return "complex"
        else:
            return "simple"
    
    def query(self, question: str) -> Dict:
        """
        Route query to appropriate model.
        """
        complexity = self.classify_complexity(question)
        
        if complexity == "simple":
            # Use local SLM
            response = ollama.generate(
                model=self.slm_model,
                prompt=question
            )
            
            self.stats["slm_calls"] += 1
            self.stats["cost_saved"] += 0.03  # Saved ~$0.03
            
            return {
                "answer": response['response'],
                "model": self.slm_model,
                "cost": 0.00,
                "complexity": complexity
            }
        
        else:
            # Use cloud LLM
            response = self.openai_client.chat.completions.create(
                model=self.llm_model,
                messages=[{"role": "user", "content": question}]
            )
            
            self.stats["llm_calls"] += 1
            
            return {
                "answer": response.choices[0].message.content,
                "model": self.llm_model,
                "cost": 0.03,  # Approximate
                "complexity": complexity
            }
    
    def get_stats(self) -> Dict:
        """Get usage statistics."""
        total_calls = self.stats["slm_calls"] + self.stats["llm_calls"]
        slm_percentage = (self.stats["slm_calls"] / total_calls * 100) if total_calls > 0 else 0
        
        return {
            **self.stats,
            "total_calls": total_calls,
            "slm_percentage": slm_percentage
        }

# Example usage
hybrid = HybridAI()

# Simple queries (use SLM)
queries = [
    "What is machine learning?",
    "Define artificial intelligence",
    "Explain neural networks in simple terms",
    "Analyze the economic impact of AI on healthcare and provide a detailed report with citations"  # Complex
]

for query in queries:
    print(f"\nQuery: {query[:60]}...")
    result = hybrid.query(query)
    print(f"Model: {result['model']}")
    print(f"Complexity: {result['complexity']}")
    print(f"Cost: ${result['cost']:.2f}")
    print(f"Answer: {result['answer'][:100]}...")

# Statistics
print("\n=== Usage Statistics ===")
stats = hybrid.get_stats()
print(f"Total Calls: {stats['total_calls']}")
print(f"SLM Calls: {stats['slm_calls']} ({stats['slm_percentage']:.1f}%)")
print(f"LLM Calls: {stats['llm_calls']}")
print(f"Cost Saved: ${stats['cost_saved']:.2f}")

๐Ÿ“ Assignments & Practice Problems

Assignment 1: SLM Comparison โญโญ

Difficulty: Medium | Time: 60 minutes

Compare 3 small language models.

Requirements:

  • Test speed, quality, memory
  • Create comparison table
  • Recommend best for use cases

Assignment 2: Hybrid System โญโญโญ

Difficulty: Hard | Time: 120 minutes

Build hybrid SLM/LLM system.

Requirements:

  • Complexity classifier
  • Automatic routing
  • Cost tracking
  • Performance metrics

โŒ Bad: Model too large for device

7B model on 4GB RAM

โœ… Good: Match model to device

2B model on 4GB RAM


### Pitfall 2: No Quantization

```python
# โŒ Bad: Full precision (16GB)
model = load_model("mistral")

# โœ… Good: 4-bit quantization (4GB)
model = load_model("mistral", quantization="4bit")

๐Ÿ”— Related Concepts

๐Ÿ“š Resources

Models

  • ๐Ÿค– Phi-3 - Microsoft
  • ๐Ÿค– Gemma - Google
  • ๐Ÿค– Mistral - Mistral AI

Tools

<!--REF_CLOSE-->
# Ollama - Easiest way to run SLMs
curl -fsSL https://ollama.com/install.sh | sh

# LM Studio - GUI for local models
# Download from lmstudio.ai