Lewati ke konten utama

Panduan Unsloth: Optimalkan dan Percepat Fine-Tuning LLM

Fine-tuning model Llama 3.1 untuk menyelesaikan soal aljabar khusus dengan akurasi tinggi dan hasil terperinci menggunakan Unsloth.
· 11 mnt Baca

Jelajahi bersama AI

Pernah mengalami masalah memori saat melakukan fine-tuning model atau merasa prosesnya memakan waktu sangat lama untuk selesai? Jika Anda mencari solusi yang lebih efisien dan cepat dibandingkan menggunakan pustaka Transformers untuk fine-tuning large language models (LLM), Anda berada di tempat yang tepat!

Dalam tutorial ini, kita akan mempelajari cara melakukan fine-tuning model Llama 3.1 3B hanya dengan 9GB VRAM, dengan kecepatan 2x lebih cepat dibandingkan metode Transformers tradisional. Kita juga akan membahas cara melakukan inferensi cepat, mengonversi model ke format file yang kompatibel dengan vLLM dan GGUF, serta mendorong model yang disimpan ke Hugging Face Hub hanya dengan beberapa baris kode.

Jika Anda baru mengenal konsep-konsep ini, pastikan untuk mengikuti Master Large Language Models (LLMs) Concepts untuk membangun fondasi yang kuat sebelum masuk ke fine-tuning.

Fast Fine-tuning LLMs with Unsloth Feature Image

Gambar oleh Penulis

Apa itu Unsloth?

Unsloth AI adalah kerangka kerja Python yang dirancang untuk fine-tuning cepat dan mengakses large language models. Framework ini menawarkan API sederhana dan kinerja 2x lebih cepat dibandingkan Transformers. 

Fitur utama

  • API sederhana: Salah satu keunggulan Unsloth adalah API-nya yang sederhana, sehingga secara signifikan mengurangi kompleksitas dalam fine-tuning LLM.
  • Integrasi Transformers: Unsloth dibangun di atas pustaka Transformers, yang populer untuk bekerja dengan LLM. Integrasi ini memungkinkan Unsloth memanfaatkan fitur ekosistem Hugging Face yang tangguh sambil menghadirkan peningkatan untuk menyederhanakan proses fine-tuning.
  • Memerlukan sumber daya terbatas: Anda dapat melakukan fine-tuning LLM menggunakan GPU Colab gratis atau bahkan laptop dengan GPU.
  • Menyimpan ke Format vLLM dan GGUF: Hanya dengan satu baris kode, Anda dapat menggabungkan, mengonversi, dan mendorong model terkuantisasi ke Hugging Face Hub. 
  • Penggunaan memori efisien: Anda dapat memuat model kuantisasi 4-bit, melakukan fine-tuning, dan menggabungkannya dengan model penuh tanpa melampaui 12 GB VRAM GPU.

Mengakses LLM menggunakan Unsloth

Mengakses model Llama-3.1 dengan Unsloth sangat mudah. Kita tidak akan memuat model 16-bit. Sebagai gantinya, kita akan memuat versi 4-bit yang tersedia di Hugging Face untuk menghemat memori GPU dan mempercepat inferensi.

  1. Instal paket Python Unsloth.
%%capture
%pip install unsloth
  1. Muat model dan tokenizer menggunakan fungsi FastLanguageModel. 
from transformers import TextStreamer
from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Meta-Llama-3.1-8B-bnb-4bit"
)

Loading the unsloth/Meta-Llama-3.1-8B-bnb-4bit

  1. Aktifkan inferensi cepat Unsloth.
FastLanguageModel.for_inference(model)
  1. Tulis gaya prompt menggunakan system prompt, instruction, input, dan response. 
  2. Buat contoh prompt menggunakan gaya prompt tersebut. 
  3. Konversi teks menjadi token lalu menjadi representasi numerik.
  4. Siapkan text streamer.
  5. Gunakan model untuk menghasilkan respons secara streaming.
prompt_style = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
{}

### Input:
{}

### Response:
{}"""


inputs = tokenizer(
    [
        prompt_style.format(
            "You are a professional machine learning engineer",  
            "How would you deal with NaN validation loss?",  
            "", 
        )
    ],
    return_tensors="pt",
).to("cuda")

text_streamer = TextStreamer(tokenizer)
_ = model.generate(**inputs, streamer=text_streamer, max_new_tokens=128)

Kita menerima respons yang baik mengenai cara menangani NaN validation loss.

Output generated using unsloth/Meta-Llama-3.1-8B-bnb-4bit

Jika Anda kesulitan menjalankan kode di atas di Kaggle, berikut Notebook contohnya: Mengakses LLM menggunakan Unsloth.

Dengan mengikuti kursus Introduction to LLMs in Python, Anda akan mempelajari dasar arsitektur Transformer, termasuk cara membangunnya, melakukan fine-tuning, dan mengevaluasinya. Ini adalah gerbang Anda ke dunia fine-tuning LLM menggunakan Python.

Fine-tuning model Llama 3.1 menggunakan Unsloth

Dalam panduan ini, kita akan mempelajari cara melakukan fine-tuning Llama 3.1 pada dataset lighteval/MATH menggunakan Unsloth. Dataset ini berisi soal-soal aljabar dengan solusi dalam format markdown. Seluruh dataset dibagi menjadi lima tingkat kesulitan.

Untuk memahami panduan ini dengan lebih baik, saya merekomendasikan Anda mempelajari teori di balik setiap langkah dalam fine-tuning LLM dengan membaca Panduan Pengantar Fine-Tuning LLM. Luangkan beberapa menit untuk meninjau panduannya, karena akan membantu Anda memahami proses ini.

1. Penyiapan

Kita menggunakan notebook Kaggle sebagai cloud IDE, dan kita perlu menyiapkan notebook sebelum bekerja dengan model atau data.

  1. Pertama, kita perlu menyiapkan variabel lingkungan untuk Hugging Face API dan Weights & Biases API menggunakan rahasia Kaggle.

Setting up Hugging Face and W&B API key as environment variable.

  1. Atur akselerator ke GPU P100.
  2. Muat variabel lingkungan dan masuk ke Hugging Face CLI menggunakan kunci API.
from huggingface_hub import login
from kaggle_secrets import UserSecretsClient
user_secrets = UserSecretsClient()

hf_token = user_secrets.get_secret("HUGGINGFACE_TOKEN")
login(hf_token)
  1. Masuk ke Weights & Biases menggunakan kunci API untuk memulai proyek. 
import wandb

wb_token = user_secrets.get_secret("wandb")

wandb.login(key=wb_token)
run = wandb.init(
    project='Fine-tune Llama-3.1-8B-bnb-4bit on Math Dataset', 
    job_type="training", 
    anonymous="allow"
)

2. Memuat model dan tokenizer

Sama seperti bagian inferensi model, kita akan memuat versi kuantisasi 4-bit dari model Llama 3.1 menggunakan panjang urutan maksimum 2048 dan tipe data None.

from unsloth import FastLanguageModel
import torch

max_seq_length = 2048 
dtype = None 

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Meta-Llama-3.1-8B-bnb-4bit",
    max_seq_length = max_seq_length,
    dtype = dtype
)

3. Memuat dan memroses dataset

Selanjutnya, kita akan memuat dataset dan memprosesnya. Untuk itu, pertama kita harus membuat gaya prompt yang akan membantu kita memperoleh hasil yang diinginkan. 

Gaya prompt mencakup system prompt, instruction, serta placeholder untuk input dan response. 

prompt_style = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
You are a math genius who can solve any level of algebraic problems. Please answer the following math question.

### Input:
{}

### Response:
{}"""

Setelah itu, buat fungsi yang akan menggunakan gaya prompt untuk memasukkan soal dan solusi matematika, lalu mengonversinya menjadi teks yang sesuai. Pastikan untuk menambahkan EOS_TOKEN agar tidak terjadi pengulangan.

EOS_TOKEN = tokenizer.eos_token # Must add EOS_TOKEN
def formatting_prompts_func(examples):
    inputs       = examples["problem"]
    outputs      = examples["solution"]
    texts = []
    for input, output in zip(inputs, outputs):
        text = prompt_style.format(input, output) + EOS_TOKEN
        texts.append(text)
    return { "text" : texts, }

Muat 500 sampel dari dataset, terapkan fungsi formatting_prompts_func ke dataset, dan lihat sampel pertama dari kolom text.

from datasets import load_dataset

dataset = load_dataset("lighteval/MATH", split="train[0:500]", trust_remote_code=True)
dataset = dataset.map(
    formatting_prompts_func,
    batched=True,
)
dataset["text"][0]

Teks berisi system prompt, instruction, pertanyaan soal aljabar, dan solusi untuk soal tersebut. 

Math Dataset from Hugging Face

4. Menyiapkan model

Kita menambahkan LoRA (Low-Rank Adapter) ke model menggunakan modul linear dari model dasar. 

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", 
   
    use_gradient_checkpointing="unsloth", 
    random_state=3407,
    use_rslora=False, 
    loftq_config=None,
)

Siapkan trainer dengan model, tokenizer, panjang urutan maksimum, dan argumen pelatihan. Ini cukup mirip dengan penyiapan trainer menggunakan pustaka Transformers dan TRL.

from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported

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,
        learning_rate = 2e-4,
        fp16 = not is_bfloat16_supported(),
        bf16 = is_bfloat16_supported(),
        logging_steps = 1,
        optim = "adamw_8bit",
        weight_decay = 0.01,
        lr_scheduler_type = "linear",
        seed = 3407,
        output_dir = "outputs",
    ),
)

5. Pelatihan model

Pelatihan model memakan waktu hampir 19 menit, yang cukup mengesankan. Training loss berkurang secara signifikan di setiap langkah. 

trainer_stats = trainer.train()

Model training loss

Anda dapat melihat metrik kinerja model dan perangkat keras secara rinci di dasbor Weights & Biases.

W&B dashboard. Detailed model evaluation.

Anda juga dapat menggunakan torch dan trainer_stats untuk membuat laporan Anda sendiri.  

used_memory = round(torch.cuda.max_memory_reserved() / 1024 / 1024 / 1024, 3)
used_memory_for_lora = round(used_memory - start_gpu_memory, 3)
used_percentage = round(used_memory         /max_memory*100, 3)
lora_percentage = round(used_memory_for_lora/max_memory*100, 3)
print(f"{trainer_stats.metrics['train_runtime']} seconds used for training.")
print(f"{round(trainer_stats.metrics['train_runtime']/60, 2)} minutes used for training.")
print(f"Peak reserved memory = {used_memory} GB.")
print(f"Peak reserved memory for training = {used_memory_for_lora} GB.")
print(f"Peak reserved memory % of max memory = {used_percentage} %.")
print(f"Peak reserved memory for training % of max memory = {lora_percentage} %.")

Model dilatih dalam 20 menit, dan puncak memori yang dipesan untuk pelatihan sekitar 3,7 GB. Ini relatif rendah dibandingkan metode tradisional, yang melibatkan memuat model penuh, mengkuantisasinya, lalu melakukan fine-tuning. Dalam kasus tersebut, setidaknya memerlukan 15 GB memori GPU.

1207.5478 seconds used for training.
20.13 minutes used for training.
Peak reserved memory = 9.73 GB.
Peak reserved memory for training = 3.746 GB.
Peak reserved memory % of max memory = 61.241 %.
Peak reserved memory for training % of max memory = 23.578 %.

6. Pengujian model setelah fine-tuning

Untuk menguji model setelah fine-tuning, kita perlu mengaktifkan inferensi cepat. Selanjutnya, kita akan memasukkan contoh soal aljabar dari dataset ke gaya prompt dan mengonversinya menjadi token. Lalu, kita akan menggunakan model untuk menghasilkan respons dan mendekode keluarannya agar teks dapat ditampilkan. 

Teks yang dihasilkan dalam format Markdown, tetapi kita telah mengonversinya agar menampilkan teks dengan persamaan matematika yang tepat.

from IPython.display import display, Markdown

FastLanguageModel.for_inference(model)
inputs = tokenizer(
    [
        prompt_style.format(
            "If the system of equations \begin{align*} 3x+y&=a,\\ 2x+5y&=2a, \end{align*} has a solution $(x,y)$ when $x=2$, compute $a$.", 
            "", 
        )
    ],
    return_tensors="pt",
).to("cuda")

outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=250,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs)
Markdown(response[0].split("\n\n### Response:")[1])

Seperti terlihat, respons yang dihasilkan selaras dengan dataset dan memberikan solusi untuk soal-soal aljabar.

Output of the fine-tuned model

7. Menyimpan model dan tokenizer

Mari simpan model yang telah di-fine-tune dan dorong ke Hugging Face Hub agar Anda dapat dengan mudah membagikan atau menerapkannya.

new_model_online = "kingabzpro/Llama-3.1-8B-MATH"
new_model_local = "Llama-3.1-8B-MATH"
model.save_pretrained(new_model_local) # Local saving
tokenizer.save_pretrained(new_model_local) # Local saving

Kode berikut akan membuat repositori baru di Hugging Face lalu mendorong LoRA dan tokenizer beserta metadata.

model.push_to_hub(new_model_online) # Online saving
tokenizer.push_to_hub(new_model_online) # Online saving

Fine-tuned model saved on Hugging Face

Sumber: kingabzpro/Llama-3.1-8B-MATH

Jika Anda mengalami kendala saat melakukan fine-tuning LLM menggunakan Unsloth, silakan merujuk ke Notebook Kaggle Fine-tuning LLMs using Unsloth. Di dalamnya terdapat kode stabil yang dapat Anda jalankan sendiri untuk mereproduksi hasilnya.

Langkah berikutnya dalam perjalanan AI Anda adalah menggunakan LLM untuk mengembangkan aplikasi AI yang efektif. Anda dapat mempelajari lebih lanjut melalui tutorial How to Build LLM Applications with LangChain.

Menggabungkan dan Mengekspor Model

Menggabungkan LoRa dengan model dasar memerlukan VRAM dan penyimpanan lokal tambahan. Untuk menghindari batasan, kita akan membuat notebook Kaggle baru dengan GPU P100 sebagai akselerator. Kita juga akan mengaktifkan Hugging Face API untuk mengakses kunci API.

  1. Instal paket Python Unsloth.
%%capture
%pip install unsloth
  1. Muat kunci API dari rahasia Kaggle dan masuk ke Hugging Face CLI. 
from huggingface_hub import login
from kaggle_secrets import UserSecretsClient
user_secrets = UserSecretsClient()

hf_token = user_secrets.get_secret("HUGGINGFACE_TOKEN")
login(hf_token)
  1. Muat LoRA dan tokenizer dengan menyediakan tautan repositori model di Hugging Face. 
  2. Aktifkan inferensi model cepat. 
from unsloth import FastLanguageModel

new_model_name = "kingabzpro/Llama-3.1-8B-MATH"
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = new_model_name, # YOUR MODEL YOU USED FOR TRAINING
    max_seq_length = 2048,
    dtype = None,
    load_in_4bit = True,
)
FastLanguageModel.for_inference(model); 

Loading the fine-tuned adopter

  1. Salin dan tempel gaya prompt dari bagian sebelumnya. 
prompt_style = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
You are a math genius who can solve any level of algebraic problem. Please answer the following math question.

### Input:
{}

### Response:
{}"""
  1. Uji model dengan contoh soal matematika dari dataset untuk memastikan masih berfungsi dengan baik.
from IPython.display import display, Markdown

inputs = tokenizer(
    [
        prompt_style.format(
            "Solve the equation $|y-6| + 2y = 9$ for $y$.",  # input
            "",  # output - leave this blank for generation!
        )
    ],
    return_tensors="pt",
).to("cuda")

outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=250,
    pad_token_id=tokenizer.eos_token_id,
)
response = tokenizer.batch_decode(outputs)
Markdown(response[0].split("\n\n### Response:")[1])

Model berfungsi dengan baik dan siap digabungkan dengan model dasar.

output of the fine-tuned model.

  1. Buat direktori sementara lalu ubah penunjuk direktori. Mengapa kita melakukan ini? Direktori working Kaggle hanya menyediakan 20 GB, yang tidak cukup untuk menggabungkan dan mendorong model penuh. Membuat folder lain di direktori root memungkinkan kita mengakses 60 GB penyimpanan sementara.
%mkdir ../temp
%cd /kaggle/temp
  1. Dengan mengetik perintah berikut, kita akan menggabungkan LoRA dengan model dasar dan mendorongnya ke Hugging Face Hub. Ini berguna saat Anda ingin menerapkan dan menyajikan model di cloud menggunakan paket Python vLLM.
model.push_to_hub_merged(new_model_name, tokenizer, save_method = "merged_16bit")

Merging and saving the 16bit model.

  1. Jika Anda ingin menggunakan model yang telah di-fine-tune secara lokal, Anda dapat dengan mudah mengonversinya ke format llama.cpp, kemudian mengkuantisasinya, dan mendorongnya ke Hugging Face Hub. 
model.push_to_hub_gguf(new_model_name, tokenizer, quantization_method = "q4_k_m")

saving the quantized model in GGUF model format

Model 16-bit penuh, adaptor, dan file GGUF terkuantisasi tersedia di repositori model Anda. Untuk menggunakan model yang telah di-fine-tune secara lokal, cukup unduh file GGUF terkuantisasi dan mulai gunakan dengan Jan, Misty, GPT4ALL, atau Ollama.

Ikuti tutorial Fine-tuning Llama 3.2 dan Menggunakannya Secara Lokal: Panduan Langkah demi Langkah untuk mempelajari cara melakukan fine-tuning model Llama 3.2 pada dataset dukungan pelanggan, menggabungkan dan mengekspor model ke Hugging Face Hub, serta mengonversi model yang telah di-fine-tune ke format GGUF agar dapat digunakan secara lokal dengan aplikasi Jan.

Sumber: kingabzpro/Llama-3.1-8B-MATH

Jika Anda menghadapi masalah saat memuat dan menggabungkan LoRA dengan model dasar, silakan lihat notebook Kaggle Merging LoRA Adopter with Unsloth untuk bantuan lebih lanjut. 

Saya juga merekomendasikan Anda membaca blog 12 LLM Projects For All Levels. Artikel ini memuat daftar proyek LLM untuk pemula, menengah, mahasiswa tahun akhir, dan ahli.

Kesimpulan

Dalam tutorial ini, kita mempelajari cara melakukan fine-tuning model Llama 3.1 3B secara efektif dengan sumber daya komputasi rendah dan mencapai kecepatan 2x lebih cepat dari metode tradisional.

 Kita juga mempelajari cara menjalankan inferensi model cepat, menggabungkan LoRA dengan model dasar, dan mendorongnya ke Hugging Face Hub. 

Selain itu, kita mengonversi model ke format llama.cpp dan mengkuantisasinya sehingga model hasil fine-tuning dapat dengan mudah digunakan secara lokal di laptop menggunakan aplikasi Jan atau GPT4ALL.

Untuk meningkatkan kinerja model, kami sangat menyarankan melakukan fine-tuning pada seluruh dataset, mengoptimalkan hiperparameter, dan menyempurnakan gaya prompt. Bahkan setelah fine-tuning, Anda masih dapat meningkatkan kinerja aplikasi AI melalui function calling dan pipeline RAG.

Pelajari solusi mana yang lebih baik untuk kasus spesifik Anda dengan mengikuti panduan RAG vs Fine-Tuning: A Comprehensive Tutorial with Practical Example. Di dalamnya termasuk kode contoh yang dapat Anda coba pada dataset Anda dan bandingkan hasilnya.

Abid Ali Awan

Penulis

Abid Ali Awan

Sebagai data scientist tersertifikasi, saya bersemangat memanfaatkan teknologi mutakhir untuk menciptakan aplikasi machine learning yang inovatif. Dengan latar belakang kuat di pengenalan ucapan, analisis dan pelaporan data, MLOps, conversational AI, dan NLP, saya mengasah keterampilan dalam mengembangkan sistem cerdas yang berdampak nyata. Selain keahlian teknis, saya juga komunikator andal yang mampu menyederhanakan konsep kompleks menjadi bahasa yang jelas dan ringkas. Karena itu, saya menjadi blogger yang dicari di bidang data science, membagikan wawasan dan pengalaman kepada komunitas profesional data yang terus berkembang. Saat ini, saya berfokus pada pembuatan dan penyuntingan konten, bekerja dengan large language model untuk mengembangkan konten yang kuat dan menarik agar membantu bisnis dan individu memaksimalkan data mereka.

Topik

Terkait

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

blogs

Spaghetti Plot dan Jalur Badai