Skip to main content
skill CX Codex

llm-fine-tuning — Claude Code skill: what it does, how to install

Configures infrastructure for fine-tuning open LLMs with QLoRA, LoRA, and DeepSpeed. Useful when training models on proprietary domain datasets.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill llm-fine-tuning -a claude-code
Open on GitHub

What llm-fine-tuning does

This skill provides training configurations and code templates for fine-tuning open-source language models. It covers Hugging Face TRL (SFTTrainer and DPOTrainer), production configs for Axolotl, ZeRO Stage 3 DeepSpeed setups, and a Kubernetes Job template for A100 clusters. It also includes Python snippets to merge LoRA adapters into base model weights before serving with vLLM or exporting to Hugging Face Hub.

Running these pipelines requires an NVIDIA GPU with at least 24GB of VRAM (such as an RTX 4090, A100, or H100), CUDA 12.1+, Python 3.10+, and 500GB+ of free disk space. Without a 24GB+ GPU, local training will fail on out-of-memory errors. Access to gated checkpoints also requires setting HF_TOKEN.

What it helps with

  • set up QLoRA training runs with Hugging Face TRL and PEFT
  • create Axolotl configuration files with sample packing and Flash Attention
  • configure multi-GPU distributed training using DeepSpeed ZeRO-3
  • merge trained LoRA weights with base models for vLLM deployment

Example prompts for the agent

  • Create a QLoRA fine-tuning script for Llama 3.1 8B using TRL SFTTrainer on a single RTX 4090.
  • Configure Axolotl and DeepSpeed ZeRO-3 for training a 70B model across 4 GPUs.
  • Write a script to merge PEFT adapters into base weights and save them for vLLM.

How to install llm-fine-tuning

1Skills CLI (Vercel)

npx skills add BagelHole/DevOps-Security-Agent-Skills --skill llm-fine-tuning -a claude-code

2Manually: put the files in place

~/.claude/skills/llm-fine-tuning/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/llm-fine-tuning/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about llm-fine-tuning

How do I install llm-fine-tuning in Claude Code?

Run npx skills add BagelHole/DevOps-Security-Agent-Skills --skill llm-fine-tuning -a claude-code.

What does the llm-fine-tuning skill do?

It gives your AI agent production-ready templates for QLoRA, Axolotl, DPO alignment, DeepSpeed distribution, and model weight merging.

What hardware is required to run these training runs?

You need an NVIDIA GPU with at least 24GB VRAM, CUDA 12.1+, Python 3.10+, and 500GB+ of local disk space for model checkpoints.

Source text

SKILL.md · MIT
---
name: llm-fine-tuning
description: Set up infrastructure for fine-tuning LLMs with QLoRA, LoRA, and full fine-tuning using Hugging Face TRL, Axolotl, and distributed training with DeepSpeed or FSDP. Covers dataset prep, training runs, and model export.
license: MIT
metadata:
  author: devops-skills
  version: "1.0"
---

# LLM Fine-Tuning Infrastructure

Train and fine-tune open-source LLMs efficiently — from LoRA on a single GPU to distributed full fine-tuning across multi-node clusters.

## When to Use This Skill

Use this skill when:
- Fine-tuning an LLM on domain-specific data (legal, medical, code, support)
- Running QLoRA to fine-tune 70B models on consumer GPUs
- Setting up distributed training with DeepSpeed or FSDP
- Exporting fine-tuned adapters for production serving
- Implementing RLHF, DPO, or instruction tuning pipelines

## Prerequisites

- NVIDIA GPU(s) with 24GB+ VRAM (RTX 4090 / A100 / H100)
- CUDA 12.1+ and `nvidia-smi` working
- Python 3.10+ with `pip`
- Hugging Face account and `HF_TOKEN` for gated models
- 500GB+ disk for model weights and training data

## Quick Start: QLoRA Fine-Tuning

```bash
pip install transformers datasets trl peft bitsandbytes accelerate

python - <<'EOF'
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
from trl import SFTTrainer, SFTConfig
import torch

model_id = "meta-llama/Llama-3.1-8B-Instruct"

# 4-bit quantization (QLoRA)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

model = AutoModelForCausalLM.from_pretrained(
    model_id, quantization_config=bnb_config, device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_id)

# LoRA configuration
peft_config = LoraConfig(
    r=16,                    # rank
    lora_alpha=32,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

dataset = load_dataset("your-org/your-dataset", split="train")

trainer = SFTTrainer(
    model=model,
    args=SFTConfig(
        output_dir="./output",
        num_train_epochs=3,
        per_device_train_batch_size=2,
        gradient_accumulation_steps=8,
        learning_rate=2e-4,
        bf16=True,
        logging_steps=10,
        save_strategy="epoch",
        report_to="wandb",
    ),
    train_dataset=dataset,
    peft_config=peft_config,
    processing_class=tokenizer,
)
trainer.train()
trainer.save_model("./fine-tuned-model")
EOF
```

## Axolotl (Production Fine-Tuning Framework)

```yaml
# config.yaml — Axolotl QLoRA config for Llama 3.1
base_model: meta-llama/Llama-3.1-8B-Instruct
model_type: LlamaForCausalLM
tokenizer_type: PreTrainedTokenizerFast

load_in_4bit: true
adapter: qlora
lora_r: 32
lora_alpha: 64
lora_dropout: 0.05
lora_target_modules:
  - q_proj
  - k_proj
  - v_proj
  - o_proj
  - gate_proj
  - up_proj
  - down_proj

datasets:
  - path: your-org/your-dataset
    type: alpaca              # or sharegpt, chat_template, etc.

dataset_prepared_path: ./prepared-data
val_set_size: 0.05
output_dir: ./output

sequence_len: 4096
sample_packing: true         # pack multiple short samples for efficiency

micro_batch_size: 2
gradient_accumulation_steps: 8
num_epochs: 3
learning_rate: 2e-4
optimizer: adamw_bnb_8bit
lr_scheduler: cosine
warmup_ratio: 0.05

bf16: true
flash_attention: true

logging_steps: 10
eval_steps: 100
save_steps: 200
wandb_project: my-fine-tune
```

```bash
# Run with Axolotl
pip install axolotl[flash-attn,deepspeed]
accelerate launch -m axolotl.cli.train config.yaml
```

## Distributed Training with DeepSpeed

```json
// deepspeed_zero3.json — ZeRO Stage 3 (split optimizer + gradients + params)
{
  "zero_optimization": {
    "stage": 3,
    "offload_optimizer": {"device": "cpu", "pin_memory": true},
    "offload_param": {"device": "cpu", "pin_memory": true},
    "overlap_comm": true,
    "contiguous_gradients": true,
    "sub_group_size": 1e9,
    "reduce_bucket_size": "auto",
    "stage3_prefetch_bucket_size": "auto",
    "stage3_param_persistence_threshold": "auto",
    "stage3_max_live_parameters": 1e9,
    "stage3_max_reuse_distance": 1e9,
    "gather_16bit_weights_on_model_save": true
  },
  "bf16": {"enabled": true},
  "gradient_clipping": 1.0,
  "train_batch_size": "auto",
  "train_micro_batch_size_per_gpu": "auto"
}
```

```bash
# Launch 4-GPU DeepSpeed training
deepspeed --num_gpus=4 train.py \
  --deepspeed deepspeed_zero3.json \
  --model_name meta-llama/Llama-3.1-70B-Instruct \
  --output_dir ./output
```

## DPO / RLHF Alignment

```python
from trl import DPOTrainer, DPOConfig
from datasets import load_dataset

# Dataset format: {"prompt": ..., "chosen": ..., "rejected": ...}
dataset = load_dataset("your-org/preference-data")

trainer = DPOTrainer(
    model=model,
    ref_model=None,           # None = implicit reference with peft
    args=DPOConfig(
        output_dir="./dpo-output",
        beta=0.1,             # KL divergence weight
        num_train_epochs=1,
        per_device_train_batch_size=1,
        gradient_accumulation_steps=16,
        learning_rate=5e-7,
        bf16=True,
    ),
    train_dataset=dataset["train"],
    peft_config=peft_config,
    processing_class=tokenizer,
)
trainer.train()
```

## Merging LoRA Adapters for Deployment

```python
from peft import PeftModel
from transformers import AutoModelForCausalLM

# Load base model in full precision
base_model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.1-8B-Instruct",
    torch_dtype=torch.bfloat16,
    device_map="cpu",
)

# Load and merge LoRA adapter
model = PeftModel.from_pretrained(base_model, "./fine-tuned-model")
merged_model = model.merge_and_unload()

# Save merged model (ready for vLLM serving)
merged_model.save_pretrained("./merged-model", safe_serialization=True)
tokenizer.save_pretrained("./merged-model")

# Push to Hugging Face Hub
merged_model.push_to_hub("your-org/your-fine-tuned-model")
```

## Kubernetes Training Job

```yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: llm-fine-tune
spec:
  template:
    spec:
      restartPolicy: OnFailure
      nodeSelector:
        nvidia.com/gpu.product: A100-SXM4-80GB
      containers:
      - name: trainer
        image: nvcr.io/nvidia/pytorch:24.05-py3
        command: ["accelerate", "launch", "-m", "axolotl.cli.train", "/config/config.yaml"]
        resources:
          limits:
            nvidia.com/gpu: "4"
            memory: "320Gi"
          requests:
            nvidia.com/gpu: "4"
        volumeMounts:
        - name: config
          mountPath: /config
        - name: model-cache
          mountPath: /root/.cache/huggingface
        - name: output
          mountPath: /output
        env:
        - name: HUGGING_FACE_HUB_TOKEN
          valueFrom:
            secretKeyRef:
              name: hf-token
              key: token
        - name: WANDB_API_KEY
          valueFrom:
            secretKeyRef:
              name: wandb-token
              key: key
      volumes:
      - name: config
        configMap:
          name: axolotl-config
      - name: model-cache
        persistentVolumeClaim:
          claimName: model-cache-pvc
      - name: output
        persistentVolumeClaim:
          claimName: training-output-pvc
```

## Common Issues

| Issue | Cause | Fix |
|-------|-------|-----|
| `CUDA out of memory` | Batch too large | Reduce `micro_batch_size`; increase `gradient_accumulation_steps` |
| Training loss NaN | Learning rate too high | Lower LR to `1e-4` or `5e-5`; add warmup |
| Slow training | No Flash Attention | Install `flash-attn`; enable `flash_attention: true` |
| Poor fine-tune quality | Bad data formatting | Validate dataset format; check `sample_packing` compatibility |
| Adapter merge errors | Mixed quantization | Merge in bf16 on CPU, not in 4-bit |

## Best Practices

- Use Flash Attention 2 — it's 2–4× faster and uses less memory.
- Monitor training loss/eval loss via W&B or MLflow; overfit = more dropout or less data.
- Validate with a held-out eval set (5–10%); MMLU or custom evals for quality gates.
- Start with LoRA r=16 before increasing — higher rank = more parameters, diminishing returns.
- Use `sample_packing` in Axolotl to maximize GPU utilization on short sequences.

## Related Skills

- [vllm-server](../vllm-server/) - Serve fine-tuned models
- [gpu-server-management](../../servers/gpu-server-management/) - GPU setup
- [llm-inference-scaling](../llm-inference-scaling/) - Deploy at scale
- [ai-pipeline-orchestration](../../../devops/ai/ai-pipeline-orchestration/) - Training pipelines

© devops-skills · MIT · BagelHole/DevOps-Security-Agent-Skills

Similar skills

Everything for AI and ML →

From the same set129

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor