Tekko

Language

Get in Touch

Usually respond within 24 hours

Back to BlogAI & ML

Fine-Tuning Phi-3 with Unsloth: A Guide to Efficient SLM Automation

7 min read
Phi-3UnslothFine-TuningLLMOpsMachine Learning
Fine-Tuning Phi-3 with Unsloth: A Guide to Efficient SLM Automation

For the past few years, the prevailing wisdom in AI was 'bigger is better.' We watched as parameter counts ballooned from billions to trillions. However, for many engineering teams, deploying a 70B or 400B parameter model to handle a specific, repetitive task—like extracting structured data from invoices or triaging customer support tickets—is like using a sledgehammer to hang a picture frame. It is expensive, slow, and overkill.

Enter Small Language Models (SLMs). Microsoft’s Phi-3 is a standout in this category, punching significantly above its weight class. But to make an SLM truly effective for your specific business logic, you need to fine-tune it. This guide explores how to use Unsloth and QLoRA to fine-tune Phi-3 efficiently, turning a general-purpose model into a specialized automation engine.

Why Phi-3 and Why Now?

Phi-3-mini (3.8B parameters) is a powerhouse. Despite its size, it rivals models twice its size on benchmarks like MMLU and MT-Bench. Its architecture is optimized for high-quality data over sheer volume, making it an ideal candidate for fine-tuning.

From a technical perspective, SLMs offer three primary advantages:

  1. Latency: Faster token generation means snappier user experiences and higher throughput for batch processing.
  2. Cost: You can host Phi-3 on consumer-grade hardware or small cloud instances (like a single T4 or A10G), drastically reducing inference costs.
  3. Privacy: Because the model is small, it is feasible to run it entirely on-premises or within a VPC, keeping sensitive data out of third-party APIs.

The Toolkit: Unsloth and QLoRA

If you have ever tried to fine-tune a model using standard Hugging Face transformers and peft libraries, you know the pain of OOM (Out of Memory) errors and agonizingly slow training loops. This is where Unsloth changes the game.

Unsloth: Performance by Design

Unsloth is a lightweight library that wraps around the Hugging Face ecosystem to accelerate fine-tuning. It provides manually written Triton kernels for the backpropagation step, which can result in up to a 2x speedup and a 70% reduction in memory usage compared to standard implementations. For a senior engineer, this means you can fine-tune a 3.8B model on a free-tier Google Colab instance or a mid-range workstation in minutes rather than hours.

QLoRA: Quantized Low-Rank Adaptation

QLoRA is the mechanism that makes this efficiency possible. Instead of updating all 3.8 billion parameters (which would require massive VRAM), we freeze the base model in 4-bit quantization and inject small, trainable 'adapter' layers (Low-Rank Adapters). We only train these tiny adapters. When finished, we merge them back into the model or swap them out dynamically.

Real-World Use Case: Structured Medical Data Extraction

To ground this in reality, let's look at a common automation task: converting messy, unstructured clinical notes into valid JSON for an Electronic Health Record (EHR) system. A base Phi-3 model might struggle with the specific medical jargon or the exact JSON schema required. Fine-tuning allows us to bake those constraints directly into the model's weights.

Step 1: Environment Setup

First, we need to install the necessary dependencies. Unsloth simplifies this by handling the complex CUDA requirements.

# Install Unsloth and dependencies !pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git" !pip install --no-deps "xformers<0.0.27" "trl<0.9.0" peft accelerate bitsandbytes

Step 2: Loading Phi-3 with Unsloth

We use the FastLanguageModel class from Unsloth to load Phi-3-mini. We specify a 4-bit quantization to keep the memory footprint low.

from unsloth import FastLanguageModel import torch max_seq_length = 2048 # Supports RoPE Scaling internally dtype = None # None for auto detection load_in_4bit = True # Use 4bit quantization model, tokenizer = FastLanguageModel.from_pretrained( model_name = "unsloth/Phi-3-mini-4k-instruct", max_seq_length = max_seq_length, dtype = dtype, load_in_4bit = load_in_4bit, )

Step 3: Configuring LoRA Adapters

This is where we define the scope of our fine-tuning. We target specific modules like q_proj, k_proj, and v_proj (the attention heads) to maximize the impact of our training.

model = FastLanguageModel.get_peft_model( model, r = 16, # Rank: higher = more capacity but more memory target_modules = ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], lora_alpha = 16, lora_dropout = 0, # Optimized at 0 for Unsloth bias = "none", # Optimized at "none" for Unsloth use_gradient_checkpointing = "unsloth", # Saves 70% VRAM random_state = 3407, use_rslora = False, loftq_config = None, )

Step 4: Data Preparation

For domain-specific tasks, your dataset is your most valuable asset. For our medical extraction task, we need a dataset of (Instruction, Input, Output) triplets.

  • Instruction: "Extract patient vitals into JSON format."
  • Input: "Patient presents with BP 120/80 and heart rate of 72 bpm."
  • Output: {"bp": "120/80", "hr": 72}

You should aim for at least 500–1,000 high-quality examples. Quality trumps quantity every time in SLM fine-tuning.

Step 5: The Training Loop

We utilize the SFTTrainer (Supervised Fine-tuning Trainer) from the TRL library, which integrates seamlessly with Unsloth.

from trl import SFTTrainer from transformers import TrainingArguments trainer = SFTTrainer( model = model, tokenizer = tokenizer, train_dataset = dataset, dataset_text_field = "text", max_seq_length = max_seq_length, dataset_num_proc = 2, args = TrainingArguments( per_device_train_batch_size = 2, gradient_accumulation_steps = 4, warmup_steps = 5, max_steps = 60, # Small step count for demonstration learning_rate = 2e-4, fp16 = not torch.cuda.is_bf16_supported(), bf16 = torch.cuda.is_bf16_supported(), logging_steps = 1, optim = "adamw_8bit", weight_decay = 0.01, lr_scheduler_type = "linear", seed = 3407, output_dir = "outputs", ), ) trainer_stats = trainer.train()

Evaluation and "The Vibe Check"

Quantitative metrics like loss and perplexity are useful for monitoring convergence, but for domain-specific automation, you need a custom evaluation pipeline.

  1. Schema Validation: If your model outputs JSON, run it through a Pydantic validator. What percentage of outputs are valid JSON?
  2. LLM-as-a-Judge: Use a larger model (like GPT-4o) to grade the output of your fine-tuned Phi-3 against a ground-truth dataset. This provides a nuanced score for 'correctness' that simple string matching cannot provide.
  3. Regression Testing: Ensure that fine-tuning for structured extraction didn't break the model's ability to follow basic instructions (a phenomenon known as 'catastrophic forgetting').

Deploying the Specialized Model

Once satisfied, you have two main paths for deployment:

1. Merging to GGUF for Local Inference

If you want to run your model on-device (e.g., in a desktop app or on a Raspberry Pi), Unsloth allows you to export directly to GGUF format, which is compatible with llama.cpp and Ollama.

model.save_pretrained_gguf("model", tokenizer, quantization_method = "q4_k_m")

2. vLLM for Production APIs

For high-concurrency cloud deployments, export the LoRA adapters and use a library like vLLM. vLLM can load the base Phi-3 model and apply your custom LoRA adapter on the fly, allowing you to serve multiple specialized versions of the same base model from a single inference server.

Strategic Considerations for Technical Leaders

Fine-tuning is not a silver bullet. Before committing engineering resources, consider the following:

  • Data Scarcity: If you don't have 500+ examples of 'good' behavior, focus on Few-Shot Prompt Engineering first. Fine-tuning on bad data will only make your model confidently wrong.
  • Maintenance Overhead: Fine-tuned models are snapshots in time. If your domain's terminology or requirements change, you must re-train and re-deploy. This requires a robust CI/CD pipeline for your models (LLMOps).
  • Base Model Selection: While Phi-3 is excellent, always evaluate it against competitors like Mistral-7B-v0.3 or Gemma-2-9B. The 'best' model is often the smallest one that can reliably pass your evaluation suite.

Conclusion

The era of the monolithic LLM is giving way to a more modular, efficient approach. By fine-tuning Small Language Models like Phi-3 using Unsloth and QLoRA, engineering teams can build highly specialized, low-latency, and cost-effective automation tools that were previously impossible.

Actionable Next Steps:

  1. Identify a narrow, repetitive text-processing task in your current pipeline.
  2. Curate a dataset of 500 high-quality input-output pairs.
  3. Run a fine-tuning experiment using the Unsloth library on a single GPU.
  4. Compare the cost and latency of your specialized Phi-3 against your current general-purpose API provider.