← Back to Labs / Unsloth

Self-Hosted LLM Fine-Tuning Pipeline: Unsloth, LLoRA, and Docker Compose

OpsNexusAI Engineering •
12 min read

Overview

Fine-tuning open-weight models (like Llama 3, Mistral, or Qwen) on proprietary domain datasets is essential for enterprise AI. However, standard Hugging Face TRL fine-tuning pipelines consume vast amounts of VRAM and memory. Unsloth accelerates fine-tuning speeds by 2-5x while cutting VRAM requirements by 80% using custom Triton kernels.

This guide provides a production Docker Compose setup for fine-tuning LLMs with Unsloth and exporting GGUF/AWQ weights.


Docker Compose Fine-Tuning Environment

Create /opt/unsloth-pipeline/docker-compose.yml:

version: "3.8"

services:
  unsloth_trainer:
    image: unsloth/unsloth-notebook:latest
    container_name: unsloth_trainer
    restart: "no"
    ipc: host
    environment:
      - HUGGING_FACE_HUB_TOKEN=${HF_TOKEN}
    volumes:
      - ./data:/workspace/data:rw
      - ./output:/workspace/output:rw
    ports:
      - "8888:8888"
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Python QLoRA Fine-Tuning Script

Create /opt/unsloth-pipeline/data/train.py:

from unsloth import FastLanguageModel
import torch

max_seq_length = 2048
dtype = None # Auto detect

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/llama-3-8b-Instruct-bnb-4bit",
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = True,
)

model = FastLanguageModel.get_peft_model(
    model,
    r = 16,
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj"],
    lora_alpha = 16,
    lora_dropout = 0,
    bias = "none",
)

# Export Merged 16bit / GGUF model
model.save_pretrained_merged("output/llama-3-8b-custom", tokenizer, save_method = "merged_16bit")

Summary Checklist

  • Provisioned Docker container with Unsloth Triton kernels.
  • Configured 4-bit QLoRA training parameters.
  • Exported merged model weights for vLLM / Ollama serving.

Fine-Tuning Optimization Architecture

Fine-tuning large language models (LLMs) like Llama 3.3 70B or Qwen 2.5 on custom enterprise data traditionally requires massive VRAM overhead.

Unsloth optimizes Low-Rank Adaptation (LoRA) and QLoRA kernel operations by rewriting PyTorch compute graphs directly into optimized Triton C-code. This reduces VRAM requirements by up to 80% while accelerating training speeds by 2x-5x compared to Hugging Face peft and TRL baselines.

+-------------------------------------------------------------------------+
|                  Unsloth QLoRA Docker Environment                       |
|  +-------------------------------------------------------------------+  |
|  | Custom Dataset (JSONL) -> Tokenizer -> Unsloth Triton Kernels     |  |
|  +-------------------------------------------------------------------+  |
|                                   | 4-bit / 8-bit Quantized Base Model  |
|                                   \/                                    |
|  +-------------------------------------------------------------------+  |
|  | NVIDIA GPU Memory (VRAM)                                          |  |
|  | [ Base Model Weights (Frozen) ] + [ Trainable LoRA Adapters ]     |  |
|  +-------------------------------------------------------------------+  |
+-------------------------------------------------------------------------+

Step 1: Docker Container Deployment (docker-compose.yml)

version: "3.8"

services:
  unsloth-trainer:
    image: unsloth/unsloth:latest
    container_name: unsloth-pipeline
    restart: "no"
    runtime: nvidia
    environment:
      - CUDA_VISIBLE_DEVICES=0
      - WANDB_DISABLED=true
    ipc: host
    volumes:
      - ./data:/workspace/data
      - ./output:/workspace/output
      - ./scripts:/workspace/scripts
    command: python3 /workspace/scripts/train.py

Step 2: Unsloth Fine-Tuning Execution Script (scripts/train.py)

from unsloth import FastLanguageModel
import torch
from datasets import load_dataset
from trl import SFTTrainer
from transformers import TrainingArguments

# 1. Load Model & Tokenizer with 4-bit Quantization
max_seq_length = 4096
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Llama-3.2-3B-Instruct",
    max_seq_length = max_seq_length,
    load_in_4bit = True,
)

# 2. Add Target LoRA Adapters
model = FastLanguageModel.get_peft_model(
    model,
    r = 16,
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],
    lora_alpha = 16,
    lora_dropout = 0,
    bias = "none",
)

# 3. Load & Format Dataset
dataset = load_dataset("json", data_files={"train": "/workspace/data/dataset.jsonl"})

# 4. Configure SFTTrainer
trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = dataset["train"],
    dataset_text_field = "text",
    max_seq_length = max_seq_length,
    args = TrainingArguments(
        per_device_train_batch_size = 2,
        gradient_accumulation_steps = 4,
        warmup_steps = 10,
        max_steps = 100,
        learning_rate = 2e-4,
        fp16 = not torch.cuda.is_bf16_supported(),
        bf16 = torch.cuda.is_bf16_supported(),
        logging_steps = 1,
        output_dir = "/workspace/output",
    ),
)

# 5. Execute Training & Export GGUF / LoRA
trainer.train()
model.save_pretrained_merged("/workspace/output/final_model", tokenizer, save_method="merged_16bit")
print("[+] Model fine-tuning and export completed successfully.")

OpsNexusAI Engineering

Verified Lab Publication

OpsNexusAI is a technical laboratory dedicated to sovereign AI infrastructure. Every implementation guide and architectural blueprint published here is tested on physical hardware and isolated networks. Our team specializes in the deployment of private LLMs, network hardening with OPNsense, and enterprise-grade automation patterns.


Join the OpsNexus Brief

Get technical teardowns on sovereign AI architectures delivered to your inbox.