mcpField
L
llm-fine-tuning

llm-fine-tuning

github.com/bagelholeデータ・データベース1.2k320 回インストール23 週間前に更新
リポジトリ

llm-fine-tuning について

llm-fine-tuningは、ドメインデータに合わせてオープンソースLLMを調整するチーム向けのスキルです。LoRAやQLoRA、分散トレーニング、アライメント手法、サービング用アダプターの出力を扱います。

主な機能

  1. 01LoRAとQLoRAによるファインチューニング
  2. 02Axolotlのトレーニング設定
  3. 03DeepSpeedによる分散トレーニング
  4. 04DPOとRLHFのアライメントワークフロー
  5. 05デプロイ向けLoRAアダプターのマージ

活用シーン

  1. 01法律やサポートのデータに合わせたLLM調整
  2. 02GPUメモリが限られた環境でのモデル微調整
  3. 03複数GPUでの分散トレーニング実行
  4. 04本番サービング用アダプターの準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill llm-fine-tuning

インストール後、Claude Code で/llm-fine-tuningを入力して読み込まれたか確認します。

詳細

LLM ファインチューニングインフラストラクチャ

オープンソース LLM を効率的にトレーニング、ファインチューニングします。単一 GPU での LoRA から、マルチノードクラスターにまたがる分散フルファインチューニングまで対応します。

このスキルを使用する場面

次の場合にこのスキルを使用します。

  • ドメイン固有のデータ(法律、医療、コード、サポート)で LLM をファインチューニングする場合
  • コンシューマー向け GPU で 70B モデルをファインチューニングするために QLoRA を実行する場合
  • DeepSpeed または FSDP を使用した分散トレーニングを設定する場合
  • ファインチューニング済みアダプターを本番環境でのサービング用にエクスポートする場合
  • RLHF、DPO、またはインストラクションチューニングのパイプラインを実装する場合

前提条件

  • 24GB 以上の VRAM を搭載した NVIDIA GPU(RTX 4090 / A100 / H100)
  • CUDA 12.1 以降と、正常に動作する nvidia-smi
  • pip を備えた Python 3.10 以降
  • Hugging Face アカウント、およびゲート付きモデル用の HF_TOKEN
  • モデルの重みとトレーニングデータ用に 500GB 以上のディスク容量

クイックスタート:QLoRA ファインチューニング

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(本番向けファインチューニングフレームワーク)

# 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
# Run with Axolotl
pip install axolotl[flash-attn,deepspeed]
accelerate launch -m axolotl.cli.train config.yaml

DeepSpeed による分散トレーニング

// 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"
}
# 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 によるアライメント

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()

デプロイ用の LoRA アダプターのマージ

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 トレーニングジョブ

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

よくある問題

問題原因対処方法
CUDA out of memoryバッチサイズが大きすぎますmicro_batch_size を減らし、gradient_accumulation_steps を増やします
トレーニング損失が NaN になる学習率が高すぎますLR を 1e-4 または 5e-5 に下げ、ウォームアップを追加します
トレーニングが遅いFlash Attention がありませんflash-attn をインストールし、flash_attention: true を有効にします
ファインチューニングの品質が低いデータの形式が不適切ですデータセットの形式を検証し、sample_packing との互換性を確認します
アダプターのマージエラー量子化が混在しています4-bit ではなく、CPU 上で bf16 を使用してマージします

ベストプラクティス

  • Flash Attention 2 を使用します。2~4 倍高速で、メモリ使用量も少なくなります。
  • W&B または MLflow でトレーニング損失/評価損失を監視します。過学習している場合は、ドロップアウトを増やすか、データ量を減らします。
  • 保留評価セット(5~10%)を使って検証します。品質基準には MMLU またはカスタム評価を使用します。
  • 最初は LoRA r=16 から始めてから増やします。ランクを上げるとパラメーター数が増え、効果は次第に小さくなります。
  • 短いシーケンスで GPU 使用率を最大化するため、Axolotl では sample_packing を使用します。

関連スキル

コメント