Lewati ke konten utama

Fine-Tuning GPT-OSS

Panduan langkah demi langkah untuk fine-tuning model OpenAI GPT-OSS 20B pada dataset tanya jawab medis demi akurasi dan adopsi gaya.
· 6 mnt Baca

Jelajahi bersama AI

Model GPT-OSS 20B adalah model bahasa open-weight dari seri gpt-oss milik OpenAI, dirancang untuk latensi rendah dan kasus penggunaan khusus. Model ini memiliki 21 miliar parameter (3,6B aktif) dan dioptimalkan agar berjalan efisien pada perangkat konsumen, hanya memerlukan sekitar 16GB memori berkat kuantisasi MXFP4.

Meskipun lebih kecil dari GPT-OSS 120B, model ini tetap mendukung fitur canggih seperti tingkat penalaran yang dapat dikonfigurasi (rendah, sedang, tinggi), akses penuh chain-of-thought untuk debugging dan transparansi, serta kapabilitas agen seperti pemanggilan fungsi, penelusuran web, dan eksekusi kode.

Dalam panduan ini, saya akan memandu Anda melalui proses lengkap menyiapkan dan melakukan fine-tuning GPT-OSS 20B. Ini mencakup:

  1. Menginstal dependensi dan menyiapkan lingkungan
  2. Memuat model dan tokenizer
  3. Membuat gaya prompt menggunakan paket Python OpenAI Harmony yang baru
  4. Memuat dataset dan menerapkan pemformatan Harmony
  5. Menjalankan inferensi model sederhana sebelum fine-tuning
  6. Mengonfigurasi model untuk pelatihan
  7. Melakukan fine-tuning model pada dataset tanya jawab medis
  8. Melakukan inferensi setelah fine-tuning untuk mengevaluasi peningkatan

Ingat bahwa tutorial ini untuk riset dan edukasi, bukan untuk diagnosis atau pengobatan pasien.

Gambar oleh Penulis

1. Menyiapkan Lingkungan Anda

Walaupun model GPT-OSS memiliki 21 miliar parameter, model ini tetap membutuhkan memori GPU yang signifikan, setidaknya 80GB VRAM agar berjalan nyaman. Cara cepat untuk memulai adalah dengan meluncurkan instance RunPod H100 atau lingkungan GPU ber-memori besar yang serupa.

Mesin RunPod H100SXM

Setelah lingkungan siap, instal semua paket Python yang diperlukan untuk pemrosesan data, fine-tuning model, dan pelacakan eksperimen:

%%capture
%pip install -U accelerate 
%pip install -U peft 
%pip install -U trl 
%pip install -U bitsandbytes
%pip install -U transformers
%pip install -U trackio
%pip install -U openai-harmony
%pip install -U tiktoken
%pip install -U pyctcdecode

Terakhir, masuk ke Hugging Face Hub menggunakan API key Anda. Ini memungkinkan Anda menyimpan dan membagikan model serta tokenizer yang telah di-fine-tune langsung ke akun Hugging Face Anda:

from huggingface_hub import notebook_login

notebook_login()

2. Memuat Model dan Tokenizer GPT-OSS

Berikutnya, kita memuat GPT-OSS 20B dengan kuantisasi MXFP4 namun langsung mendekuantisasi bobot ke bfloat16 saat pemuatan, menggunakan attention eager, cache dimatikan, dan penempatan perangkat otomatis.

import torch
from transformers import AutoModelForCausalLM, Mxfp4Config

quantization_config = Mxfp4Config(dequantize=True)
model_kwargs = dict(
    attn_implementation="eager",
    torch_dtype=torch.bfloat16,
    quantization_config=quantization_config,
    use_cache=False,
    device_map="auto",
)

model = AutoModelForCausalLM.from_pretrained("openai/gpt-oss-20b", **model_kwargs)

Selain model, kita juga memerlukan tokenizer dari repositori yang sama. Tokenizer bertugas mengonversi teks menjadi token (ID) yang dapat diproses model, lalu mendekode keluaran model kembali menjadi teks yang dapat dibaca manusia.

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("openai/gpt-oss-20b")

3. Membuat Gaya Prompt menggunakan OpenAI Harmony

OpenAI Harmony adalah format respons khusus yang digunakan oleh model GPT-OSS untuk menstrukturkan percakapan, keluaran penalaran, dan pemanggilan fungsi secara konsisten. 

Format ini mendefinisikan bagaimana pesan diatur antar peran (system, developer, user, assistant) dan memungkinkan model mengeluarkan jawaban melalui beberapa kanal—misalnya memisahkan penalaran chain-of-thought, preambule pemanggilan alat, dan respons akhir untuk pengguna.

Di bagian ini, kita akan membuat fungsi yang menerima pertanyaan dan jawaban lalu memformatnya menjadi prompt percakapan bergaya Harmony. Fungsi ini menggunakan pustaka openai_harmony untuk mengodekan percakapan secara terstruktur.

from openai_harmony import (
    load_harmony_encoding, HarmonyEncodingName,
    Conversation, Message, Role,
    SystemContent, DeveloperContent, ReasoningEffort
)

enc = load_harmony_encoding(HarmonyEncodingName.HARMONY_GPT_OSS)

def render_pair_harmony(question, answer):
    convo = Conversation.from_messages([
        Message.from_role_and_content(
            Role.DEVELOPER,
            DeveloperContent.new().with_instructions(
                "You are a medical expert with advanced knowledge in clinical reasoning and diagnostics. "
                "Respond with ONLY the final diagnosis/cause in ≤5 words."
            )
        ),
        Message.from_role_and_content(Role.USER, question.strip()),
        Message.from_role_and_content(Role.ASSISTANT, answer.strip()),
    ])
    tokens = enc.render_conversation(convo)
    text = enc.decode(tokens)
    return text

4. Memuat dan Memformat Dataset

Sekarang kita akan memuat dataset tanya jawab medis (FreedomIntelligence/medical-o1-verifiable-problem) dan menerapkan fungsi prompt_style_harmony pada setiap contoh. Teks yang telah diubah disimpan di kolom baru bernama "text", memberikan format instruksional yang rapi dan selaras dengan gaya prompt developer.

from datasets import load_dataset

def prompt_style_harmony(examples):
    qs = examples["Open-ended Verifiable Question"]
    ans = examples["Ground-True Answer"]
    outputs = {"text": []}
    for q, a in zip(qs, ans):
        rendered = render_pair_harmony(q, a)
        outputs["text"].append(rendered)
    return outputs

dataset = load_dataset(
    "FreedomIntelligence/medical-o1-verifiable-problem",
    split="train[0:1000]"
)
dataset = dataset.map(prompt_style_harmony, batched=True)
print(dataset.column_names)

print(dataset[0]["text"])

Dataset sekarang memiliki kolom baru "text" yang memuat percakapan berformat Harmony. Ini mencakup:

  • Instruksi developer (mis., jawab secara ringkas dengan diagnosis)
  • Pesan pengguna (pertanyaan medis)
  • Pesan asisten (jawaban ground-truth)
['Open-ended Verifiable Question', 'Ground-True Answer', 'text']
<|start|>developer<|message|># Instructions

You are a medical expert with advanced knowledge in clinical reasoning and diagnostics. Respond with ONLY the final diagnosis/cause in ≤5 words.<|end|><|start|>user<|message|>An 88-year-old woman with osteoarthritis is experiencing mild epigastric discomfort and has vomited material resembling coffee grounds multiple times. Considering her use of naproxen, what is the most likely cause of her gastrointestinal blood loss?<|end|><|start|>assistant<|message|>Gastric ulcer<|end|>

5. Inferensi Model Sebelum Fine-Tuning

Sebelum melatih model, penting untuk mengevaluasi kinerja dasarnya sebagai pembanding setelah fine-tuning. Untuk itu, kita mendefinisikan fungsi pembantu render_inference_harmony yang menyiapkan prompt bergaya Harmony berisi instruksi ketat dari developer dan pertanyaan pengguna, namun membiarkan respons asisten kosong untuk dilengkapi model.

def render_inference_harmony(question):
    convo = Conversation.from_messages([
        Message.from_role_and_content(
            Role.DEVELOPER,
            DeveloperContent.new().with_instructions(
                "You are a medical expert with advanced knowledge in clinical reasoning and diagnostics. "
                "Respond with ONLY the final diagnosis/cause in ≤5 words."
            )
        ),
        Message.from_role_and_content(Role.USER, question.strip()),
    ])
    tokens = enc.render_conversation_for_completion(convo, Role.ASSISTANT)
    text = enc.decode(tokens)
    return text

Berikutnya, kita ambil sampel pertama dari dataset, memformatnya menggunakan fungsi ini, melakukan tokenisasi, dan meneruskannya ke model untuk menghasilkan respons:

question = dataset[0]["Open-ended Verifiable Question"]

text = render_inference_harmony(question)

inputs = tokenizer(
    [text + tokenizer.eos_token], return_tensors="pt"
).to("cuda")
outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=20,
    eos_token_id=tokenizer.eos_token_id,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs)
print(response[0])

Dalam uji ini, keluaran model terlihat lebih panjang dan deskriptif daripada yang diminta, meskipun instruksi developer secara eksplisit meminta diagnosis ringkas (≤5 kata). 

<|start|>developer<|message|># Instructions

You are a medical expert with advanced knowledge in clinical reasoning and diagnostics. Respond with ONLY the final diagnosis/cause in ≤5 words.<|end|><|start|>user<|message|>An 88-year-old woman with osteoarthritis is experiencing mild epigastric discomfort and has vomited material resembling coffee grounds multiple times. Considering her use of naproxen, what is the most likely cause of her gastrointestinal blood loss?<|end|><|start|>assistant<|return|>We have an old woman with NSAID use causing ulcer bleed. The question: "An 88

Alih-alih sekadar menjawab “Gastric ulcer” (label ground-truth), model menghasilkan penjelasan panjang tentang penggunaan NSAID dan perdarahan ulkus.

dataset[0]["Ground-True Answer"]
'Gastric ulcer'

6. Menyiapkan Model untuk Pelatihan

Untuk melakukan fine-tuning secara efisien, kita menggunakan LoRA (Low-Rank Adaptation), yang memungkinkan kita melatih hanya sebagian kecil parameter sementara model dasar tetap dibekukan. Ini secara drastis mengurangi penggunaan memori dan biaya pelatihan.

Kita mulai dengan mendefinisikan LoraConfig yang menentukan rank, faktor penskalaan, dan layer target spesifik tempat adapter LoRA akan disisipkan.

from peft import LoraConfig, get_peft_model

peft_config = LoraConfig(
    r=8,
    lora_alpha=16,
    target_modules="all-linear",
    target_parameters=[
        "7.mlp.experts.gate_up_proj",
        "7.mlp.experts.down_proj",
        "15.mlp.experts.gate_up_proj",
        "15.mlp.experts.down_proj",
        "23.mlp.experts.gate_up_proj",
        "23.mlp.experts.down_proj",
    ],
)
peft_model = get_peft_model(model, peft_config)
peft_model.print_trainable_parameters()

Hanya sekitar ~15M parameter (≈0,07% dari keseluruhan model) yang dapat dilatih, dan ukuran adapter sekitar 16 MB, peningkatan efisiensi besar dibandingkan fine-tuning penuh.

trainable params: 15,040,512 || all params: 20,929,797,696 || trainable%: 0.0719

Selanjutnya, kita mengonfigurasi setup pelatihan menggunakan SFTConfig dari pustaka trl. Ini mencakup hiperparameter seperti learning rate, ukuran batch, akumulasi gradien, warmup ratio, dan jenis scheduler:

from trl import SFTConfig

training_args = SFTConfig(
    learning_rate=2e-4,
    gradient_checkpointing=True,
    num_train_epochs=1,
    logging_steps=10,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,
    max_length=2048,
    warmup_ratio=0.03,
    lr_scheduler_type="cosine_with_min_lr",
    lr_scheduler_kwargs={"min_lr_rate": 0.1},
    output_dir="gpt-oss-20b-medical-qa",
    report_to="trackio",
    push_to_hub=True,
)

7. Melatih Model

Dengan dataset siap, adapter LoRA terpasang, dan argumen pelatihan dikonfigurasi, kita dapat memulai proses fine-tuning. Kita menggunakan SFTTrainer dari pustaka trl, yang mempermudah supervised fine-tuning dengan menangani model, tokenizer, dataset, dan loop pelatihan dalam satu tempat:

from trl import SFTTrainer

trainer = SFTTrainer(
    model=peft_model,
    args=training_args,
    train_dataset=dataset,
    processing_class=tokenizer,
)
trainer.train()

Selama pelatihan, loss menurun secara bertahap, menandakan bahwa model belajar menyelaraskan responsnya dengan dataset tanya jawab medis berformat Harmony.

Loss pelatihan model

Setelah pelatihan selesai, kita menyimpan model yang telah di-fine-tune secara lokal dan kemudian mendorongnya ke Hugging Face Hub. Penting untuk dicatat, hanya bobot adapter LoRA (bukan seluruh model 20B) yang diunggah, sehingga repositori tetap ringan dan mudah dibagikan:

trainer.save_model(training_args.output_dir)
trainer.push_to_hub(dataset_name="kingabzpro/gpt-oss-20b-medical-qa")

Ini membuat repositori model baru di Hugging Face di bawah: kingabzpro/gpt-oss-20b-medical-qa.

Sumber: kingabzpro/gpt-oss-20b-medical-qa

8. Inferensi Model Setelah Fine-Tuning

Setelah fine-tuning, kita dapat menguji model untuk memverifikasi apakah kini model lebih mengikuti instruksi developer. Untuk itu, kita terlebih dahulu memuat model dasar GPT-OSS 20B lalu memasang adapter LoRA yang telah di-fine-tune.

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel

# Load the tokenizer
tokenizer = AutoTokenizer.from_pretrained("openai/gpt-oss-20b")

# Load the original model first
model_kwargs = dict(attn_implementation="eager", torch_dtype="auto", use_cache=True, device_map="auto")
base_model = AutoModelForCausalLM.from_pretrained("openai/gpt-oss-20b", **model_kwargs).cuda()

# Merge fine-tuned weights with the base model
peft_model_id = "gpt-oss-20b-medical-qa"
model = PeftModel.from_pretrained(base_model, peft_model_id)
model = model.merge_and_unload()

Selanjutnya, kita menjalankan inferensi pada sampel dari dataset. Pertanyaan diformat ke gaya Harmony, ditokenisasi, diteruskan ke model, dan didekode kembali menjadi teks:

question = dataset[0]["Open-ended Verifiable Question"]

text = render_inference_harmony(question)

inputs = tokenizer(
    [text + tokenizer.eos_token], return_tensors="pt"
).to("cuda")
outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=20,
    eos_token_id=tokenizer.eos_token_id,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs)
print(response[0])

Model yang telah di-fine-tune kini menghasilkan jawaban singkat dan akurat. Ini jauh lebih mendekati label ground-truth (“Gastric ulcer”) dan mengikuti batas ≤5 kata.

<|start|>developer<|message|># Instructions

You are a medical expert with advanced knowledge in clinical reasoning and diagnostics. Respond with ONLY the final diagnosis/cause in ≤5 words.<|end|><|start|>user<|message|>An 88-year-old woman with osteoarthritis is experiencing mild epigastric discomfort and has vomited material resembling coffee grounds multiple times. Considering her use of naproxen, what is the most likely cause of her gastrointestinal blood loss?<|end|><|start|>assistant<|return|><|message|>Stomach ulcer<|end|><|return|>

Kita juga dapat menguji sampel lain untuk mengonfirmasi konsistensi:

question = dataset[10]["Open-ended Verifiable Question"]

text = render_inference_harmony(question)

inputs = tokenizer(
    [text + tokenizer.eos_token], return_tensors="pt"
).to("cuda")
outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=20,
    eos_token_id=tokenizer.eos_token_id,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs)
print(response[0])

Sempurna. Model yang telah di-fine-tune menghasilkan respons yang ringkas, akurat, dan mengikuti instruksi.

<|start|>developer<|message|># Instructions

You are a medical expert with advanced knowledge in clinical reasoning and diagnostics. Respond with ONLY the final diagnosis/cause in ≤5 words.<|end|><|start|>user<|message|>What substance is primarily filtered in the renal tubules with minimal secretion or re-absorption?<|end|><|start|>assistant<|return|><|message|>creatinine<|end|><|return|>

Kesimpulan

Ini adalah masa yang menarik bagi komunitas AI open-source. Meskipun model GPT-OSS baru mungkin belum memuncaki tolok ukur, model ini menunjukkan potensi kuat, terutama di kelas parameternya masing-masing, di mana model yang lebih kecil pun masih dapat memberikan hasil yang impresif.

Dalam tutorial ini, kita melakukan fine-tuning model GPT-OSS 20B untuk tanya jawab medis menggunakan adapter LoRA dan gaya prompt Harmony. Hasilnya menjanjikan: model yang di-fine-tune menghasilkan jawaban ringkas dan akurat yang selaras dengan tugas penalaran klinis. Dengan lebih banyak epoch pelatihan, dataset yang lebih besar, dan prompt sistem yang disempurnakan, performanya dapat lebih ditingkatkan lagi.

Jika Anda mencari kursus praktis untuk mempelajari fine-tuning, pastikan untuk mengecek Fine-Tuning With Llama 3.

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

Tutorial Korelasi di R