Lewati ke konten utama

Tutorial Tinker: Fine-Tuning LLM dengan Thinking Machines Lab

Panduan praktis mengimplementasikan LoRA melalui Tinker AI untuk melatih Qwen3-8B pada data keuangan Chain-of-Thought (CoT), dioptimalkan untuk generalisasi.
· 15 mnt Baca

Jelajahi bersama AI

Fine-tuning model bahasa besar biasanya berarti berurusan dengan infrastruktur GPU terdistribusi, mengelola kegagalan klaster, dan men-debug skrip pelatihan yang kompleks. Tinker hadir untuk menyelesaikan itu.

Dirilis oleh Thinking Machines Lab milik Mira Murati pada 1 Oktober 2025, Tinker adalah API pelatihan yang menangani seluruh kompleksitas infrastruktur sekaligus memberi Anda kendali penuh atas algoritme dan data. Anda dapat menulis skrip Python sederhana dengan empat fungsi inti, dan Tinker menjalankannya di atas GPU terdistribusi untuk berbagai model open-source seperti Llama 70B atau Qwen 235B.

Platform ini menggunakan fine-tuning Low-Rank Adaptation (LoRA) untuk menekan biaya dan mendukung semuanya mulai dari supervised learning hingga reinforcement learning. Tim riset di Princeton, Stanford, dan Berkeley sudah menggunakannya untuk pekerjaan mereka.

Dalam tutorial ini, saya akan memandu Anda memasang Tinker, memahami API-nya, dan melakukan fine-tuning model tanya jawab (Q&A) keuangan lengkap menggunakan model dasar Qwen3-8B. Jika Anda ingin mempelajari lebih lanjut tentang fine-tuning dengan praktik langsung, saya sarankan melihat kursus tentang Fine-Tuning dengan Llama 3.

Apa itu Tinker?

Thinking Machines Lab membangun Tinker untuk orang-orang yang ingin menyesuaikan cara model belajar tanpa harus menjadi ahli infrastruktur.

Siapa yang menggunakan Tinker?

Platform ini menargetkan tiga kelompok: 

  • Peneliti yang mengeksplorasi metode pelatihan baru
  • Pengembang yang membangun produk AI yang membutuhkan perilaku khusus
  • Builder yang menginginkan hasil berkualitas produksi tanpa sumber daya perusahaan. 

Setiap kelompok berbagi kebutuhan yang sama: mereka tahu apa yang ingin dilakukan modelnya, tetapi antarmuka fine-tuning standar tidak memberi mereka cukup kendali.

Misalnya, tim akademis dapat menggunakannya untuk menguji algoritme baru. Laboratorium kimia mungkin ingin melatih model pada pola penalaran khusus domain yang tidak sesuai dengan template instruction-tuning tipikal. Startup yang membangun bot penasihat keuangan dapat menggunakan model untuk mengikuti format keluaran dan rantai penalaran tertentu. 

Semua kasus penggunaan ini memiliki kesamaan: mereka perlu memodifikasi proses pelatihan itu sendiri, bukan sekadar mengganti dataset.

Apa yang membuat Tinker berbeda?

Kebanyakan platform mengoptimalkan salah satu dari dua hal: kemudahan penggunaan atau fleksibilitas. Pendekatan Tinker adalah bahwa keduanya tidak harus berbenturan. Platform ini memberi Anda akses level rendah ke pelatihan melalui empat operasi inti, tetapi menangani sisanya secara otomatis:

  • Kontrol training loop: Tulis fungsi loss Anda sendiri, strategi akumulasi gradien, atau pola sampling.
  • Pembaruan model: Tentukan secara presisi bagaimana bobot harus berubah selama optimisasi.
  • Evaluasi: Hasilkan keluaran atau hitung probabilitas kapan saja selama pelatihan.
  • Manajemen state: Simpan dan lanjutkan pelatihan dengan kendali penuh atas apa yang dipersistenkan.

Tinker mengekspos kapabilitas ini melalui empat primitif API yang akan Anda pelajari di bagian praktik.

Ini berhasil karena sebagian besar kompleksitas pelatihan berasal dari infrastruktur, bukan dari algoritme itu sendiri. Menjalankan training loop kustom di laptop Anda itu mudah. Menjalankannya di 100 GPU dengan pemulihan kegagalan dan penjadwalan sumber daya itu sulit. Tinker menangani bagian kedua, sehingga Anda dapat fokus pada yang pertama.

Posisi Tinker di ekosistem

Ekosistem tooling AI kira-kira terbagi menjadi tiga lapisan: penyedia komputasi cloud yang memberi Anda GPU mentah, platform terkelola yang menjalankan alur kerja pra-ditentukan, dan framework yang membantu Anda membangun sistem pelatihan dari nol. Tinker berada di antara platform terkelola dan framework. Anda mendapatkan lebih banyak kendali dibandingkan platform seperti Hugging Face AutoTrain, tetapi lebih sedikit pekerjaan infrastruktur daripada menyiapkan klaster kustom di Google Cloud Platform (GCP).

Harga dan kredit Tinker

Tinker menggunakan penetapan harga per-token yang transparan dan bervariasi menurut ukuran model dan jenis operasi. Melatih Qwen3-8B berharga $0,40 per satu juta token. Kabar baiknya: pengguna baru menerima kredit $150 saat mereka lolos dari daftar tunggu, yang lebih dari cukup untuk beberapa percobaan pelatihan seperti dalam tutorial ini.

Harga Tinker

Sumber: Thinking Machines Lab

Contoh Tinker: Fine-Tuning Qwen3-8B untuk Q&A Keuangan

Di bagian ini, saya akan memandu Anda membangun alur kerja fine-tuning lengkap menggunakan API Tinker. Kita akan melakukan fine-tuning Qwen3-8B pada data tanya jawab keuangan menggunakan LoRA, sambil mempelajari keempat primitif API inti dan melihat praktik terbaik produksi secara langsung.

Untuk gambaran model yang lebih rinci, pastikan untuk melihat artikel yang membahas Qwen3 ini.

Catatan penting: Tinker saat ini dalam versi beta dengan akses berbasis daftar tunggu. Jika Anda memiliki akses, Anda dapat mengikuti dan menjalankan kodenya. Jika Anda masih dalam daftar tunggu, Anda tetap dapat membaca untuk memahami betapa sederhananya proses fine-tuning dengan Tinker. Saat mendapatkan akses, Anda siap langsung mulai.

Hasil pelatihan dan pemilihan checkpoint

Mari kita lihat hasil pelatihan terlebih dahulu. Memahami apa yang terjadi membantu Anda mengenali pola ini saat menjalankan pekerjaan fine-tuning sendiri.

Kami melakukan fine-tuning Qwen3-8B pada dataset FinCoT, sebuah dataset penalaran keuangan chain-of-thought, menggunakan LoRA dengan rank 32. Setelah menyaring urutan yang tidak lebih dari 10.000 token, kami memiliki 7.244 contoh pelatihan dan 500 contoh untuk validasi. 

Pelatihan berjalan selama 904 iterasi melintasi empat epoch, memakan waktu sekitar tiga jam untuk selesai, sementara Tinker menangani seluruh koordinasi GPU terdistribusi. 

Satu epoch adalah satu kali lewat lengkap melalui seluruh dataset pelatihan. Karena ada 226 batch per epoch (7.244 contoh dibagi ukuran batch 32), empat epoch menghasilkan total 904 iterasi.

Menganalisis hasil pelatihan

Bagan berikut melacak tiga metrik: training loss (biru), validation loss (merah), dan learning rate (hijau).

Perkembangan pelatihan Tinker

Awal pelatihan (iterasi 0-400) terlihat sehat: baik training loss maupun validation loss turun tajam bersama, dari di atas 1,4 ke di bawah 0,8 dan tetap dalam jarak sekitar 0,1 satu sama lain. 

Periode ini menunjukkan bahwa model secara efektif mempelajari pola yang dapat digeneralisasi dalam data. Learning rate (garis hijau) meningkat mulus selama 200 iterasi pertama, karena warmup menstabilkan pelatihan. 

Sekitar iterasi 400-600, keadaan berubah. Training loss terus turun, tetapi validation loss datar di sekitar 0,75-0,8, memperlebar kesenjangan hingga 0,13 saat model mulai overfit. Pada iterasi 600-900, divergensi menjadi jelas: training loss jatuh ke 0,39 sementara validation loss naik ke 0,8, menunjukkan model bergeser dari mempelajari pola penalaran ke menghafal contoh. 

Pola ini umum saat melakukan fine-tuning model penalaran. Jika Anda tertarik bagaimana kemampuan penalaran berkembang selama pelatihan, lihat tutorial tentang fine-tuning DeepSeek R1, yang mengeksplorasi dinamika serupa.

Model yang disimpan pada checkpoint-400 menawarkan generalisasi terbaik, dengan training loss 0,68, validation loss 0,73, dan kesenjangan kecil hanya 0,05. Meski memiliki training loss lebih tinggi daripada checkpoint akhir, model ini menangani pertanyaan baru dengan lebih baik. Training loss terendah jarang menghasilkan model terbaik, itulah sebabnya metrik validasi penting.

Kita akan memverifikasinya nanti dengan membandingkan model pada checkpoint-400 terhadap model dasar menggunakan LLM judge. Untuk saat ini, mari kita bangun alur kerja fine-tuning ini selangkah demi selangkah.

Langkah 1: Pasang Tinker dan siapkan lingkungan Anda

Catatan: Langkah-langkah berikut menguraikan skrip sekitar 300 baris. Karena penjelasan disisipkan ke dalam potongan kode, kami sarankan Anda membuka skrip lengkapnya di tab baru saat mengikuti agar mendapatkan gambaran utuh.

Anda memerlukan Python 3.11 atau lebih baru dan koneksi internet yang stabil. Karena Tinker menangani pelatihan GPU di server mereka, koneksi yang baik lebih penting daripada komputer yang bertenaga.

Mulailah dengan masuk ke konsol Tinker dan membuat kunci API. Simpan kunci ini di file .env di direktori proyek Anda:

TINKER_API_KEY=your_key_here

Setelah siap, konsol Tinker menjadi pusat Anda untuk memantau run pelatihan dan mengelola checkpoint.

Tinker training-runs

Konsol Tinker melacak semua run pelatihan Anda dengan detail kunci: ID run unik, model dasar, rank LoRA, dan waktu permintaan terakhir. Anda dapat mencari, memfilter, dan mengelola banyak eksperimen dari antarmuka ini.

Pasang paket yang diperlukan. Tinker memiliki peer dependency yang tidak dipasang otomatis, jadi sebutkan secara eksplisit:

pip install tinker transformers torch datasets python-dotenv numpy

Paket transformers dan torch menyediakan tokenisasi dan operasi tensor yang digunakan Tinker secara internal. Pustaka datasets menangani pemuatan data pelatihan dari Hugging Face.

Sekarang siapkan import dan fungsi pembantu retry. Saat melatih di server jarak jauh, Anda mungkin melihat kesalahan koneksi sementara yang tidak selalu berarti ada masalah. Pekerjaan pelatihan Anda tetap berjalan baik di infrastruktur Tinker. Pembungkus retry ini menangani kegagalan sementara tersebut secara otomatis:

import time
import numpy as np
from dotenv import load_dotenv
from datasets import load_dataset
import tinker
from tinker import types

def with_retry(future, max_attempts=3, delay=5):
    """Simple retry logic for API futures"""
    for attempt in range(max_attempts):
        try:
            return future.result()
        except Exception as e:
            if attempt == max_attempts - 1:
                raise
            time.sleep(delay)

Fungsi ini menerima objek future (objek yang merepresentasikan operasi yang belum selesai) dari API Tinker dan mencoba mengambil hasilnya hingga tiga kali, menunggu lima detik di antara setiap percobaan. Sebagian besar kegagalan sementara teratasi dalam jangka waktu ini.

Langkah 2: Inisialisasi ServiceClient dan muat dataset

ServiceClient adalah gerbang Anda ke Tinker. Ia menemukan model yang tersedia dan menangani autentikasi:

load_dotenv()
service_client = tinker.ServiceClient()

Anda tidak akan sering menggunakannya setelah penyiapan awal ini. Fungsinya terutama untuk membuat klien pelatihan dan sampling untuk model tertentu.

Sekarang saatnya memuat dataset FinCoT.  Dataset ini berisi pertanyaan keuangan yang dipasangkan dengan rantai penalaran langkah demi langkah dan jawaban akhir. Tidak seperti dataset Q&A sederhana, FinCoT mengajarkan model untuk menunjukkan proses berpikirnya sebelum memberikan jawaban, keterampilan penting untuk aplikasi penasihat keuangan di mana pengguna perlu memahami alasan di balik rekomendasi.

dataset = load_dataset("TheFinAI/FinCoT")

Dataset Tinker

Dataset ini mencakup split SFT (supervised fine-tuning) dengan rantai penalaran lengkap dan split RL untuk reinforcement learning. Gunakan split SFT untuk pelatihan dan ambil sampel dari split RL untuk validasi agar model menggeneralisasi ke contoh yang berbeda.

train_data_raw = dataset["SFT"]  # 7,686 examples with reasoning chains
val_data_raw = dataset["RL"].shuffle(seed=42).select(range(500))  # 500 validation examples

print(f"Loaded {len(train_data_raw)} training examples")
print(f"Loaded {len(val_data_raw)} validation examples")

Langkah 3: Buat klien pelatihan LoRA Anda

Sekarang buat klien pelatihan LoRA untuk Qwen3-8B:

training_client = service_client.create_lora_training_client(
    base_model="Qwen/Qwen3-8B",
    rank=32
)

Mari uraikan apa yang terjadi di sini:

  • Qwen/Qwen3-8B: Ini adalah model dengan 8 miliar parameter, cukup kuat untuk tugas nyata namun tetap efisien untuk dilatih. Ini titik manis yang baik untuk belajar. Anda dapat melihat semua model yang tersedia di daftar model Tinker.
  • LoRA (Low-Rank Adaptation): Alih-alih memperbarui semua 8 miliar parameter, LoRA melatih lapisan "adapter" kecil yang memodifikasi perilaku model dasar. Anggap seperti menambahkan lensa khusus ke kamera alih-alih membangun ulang seluruh kamera. Model dasar tetap beku di server Tinker; Anda hanya melatih adapter kecil ini.
  • rank=32: Ini mengontrol berapa banyak parameter yang dapat dilatih pada adapter LoRA Anda. Rank 32 bekerja baik untuk dataset dengan 5.000-10.000 contoh. Dataset yang lebih besar mungkin memerlukan rank=64 atau rank=128 untuk kapasitas adaptasi lebih besar.

Untuk penjelasan lebih dalam tentang cara kerja LoRA secara matematis dan cara menala parameter rank, lihat pengantar LoRA Tinker atau panduan komprehensif DataCamp tentang menguasai Low-Rank Adaptation.

Model bahasa tidak bekerja langsung dengan kata. Mereka bekerja dengan "token," yang merepresentasikan potongan teks. Tokenizer memecah teks menjadi potongan-potongan ini. Misalnya, "financial" mungkin menjadi satu token, sementara "understanding" mungkin dipecah menjadi "under" dan "standing." 

Tokenizer mengonversi teks menjadi angka (ID token) yang dapat diproses model. Dengan mengambil tokenizer dari klien pelatihan, Anda memastikan menggunakan tokenisasi yang persis sama seperti yang diharapkan Qwen3-8B.

tokenizer = training_client.get_tokenizer()

Langkah 4: Ubah data ke format Tinker

Tinker membutuhkan data pelatihan Anda dalam format bernama types.Datum. Format ini memisahkan masukan model dari konfigurasi fungsi loss, memberi Anda kendali presisi atas token mana yang berkontribusi pada pelatihan.

Saat melakukan fine-tuning model bahasa, Anda biasanya ingin model belajar menghasilkan jawaban yang baik, bukan menghafal pertanyaan. Anda melakukannya dengan memberi bobot berbeda pada bagian-bagian masukan:

  • Token prompt (pertanyaan): Bobot = 0,0 (jangan belajar dari ini)
  • Token completion (jawaban): Bobot = 1,0 (belajar dari ini)

Mari bangun fungsi transformasi data selangkah demi selangkah. Mulailah dengan tanda tangan fungsi:

def prepare_datum(example, max_length=10000):

Format percakapan menggunakan template chat Qwen3

Model berbeda mengharapkan pemformatan berbeda untuk percakapan multi-giliran. Qwen3 menggunakan token khusus seperti <|im_start|> dan <|im_end|> untuk menandai batas pesan. Pisahkan setiap pesan menjadi bagian "observation" (header peran) dan bagian "action" (isi aktual):

   # Qwen3 chat format - split into observation and action parts
    user_ob = "<|im_start|>user\n"
    user_ac = f"{example['Question']}<|im_end|>"
    
    assistant_ob = "\n<|im_start|>assistant\n"
    # Include both reasoning process AND final answer
    assistant_ac = f"{example['Reasoning_process']}\n\nFinal Answer: {example['Final_response']}<|im_end|>"

Dataset FinCoT menyediakan penalaran terstruktur, jadi kita menggabungkan field Reasoning_process dan Final_response. Ini mengajarkan model untuk menunjukkan proses berpikir sebelum menjawab.

Tokenisasi tiap bagian secara terpisah 

Untuk melacak di mana bobot harus diterapkan, setiap bagian pesan perlu ditokenisasi secara terpisah.

   # Tokenize each part separately to track weight boundaries
    user_ob_tokens = tokenizer.encode(user_ob, add_special_tokens=False)
    user_ac_tokens = tokenizer.encode(user_ac, add_special_tokens=False)
    assistant_ob_tokens = tokenizer.encode(assistant_ob, add_special_tokens=False)
    assistant_ac_tokens = tokenizer.encode(assistant_ac, add_special_tokens=False)
    
    # Combine all tokens
    all_tokens = user_ob_tokens + user_ac_tokens + assistant_ob_tokens + assistant_ac_tokens

Saring urutan yang terlalu panjang

Beberapa contoh FinCoT mencakup rantai penalaran yang sangat rinci hingga melebihi jendela konteks nyaman Qwen3-8B. Meskipun model secara teknis mendukung 32.768 token, urutan yang sangat panjang dapat menyebabkan ketidakstabilan pelatihan:

   # Check if sequence exceeds max length
    if len(all_tokens) > max_length:
        return None  # Skip this example

Menyaring contoh di atas 10.000 token hanya menghapus 5-6% data, namun secara signifikan meningkatkan keandalan pelatihan.

Tetapkan bobot untuk mengendalikan apa yang dipelajari model

Setel bobot ke 0,0 untuk pertanyaan (agar model tidak belajar memprediksi pertanyaan) dan 1,0 untuk jawaban (agar model belajar menghasilkan respons yang baik):

   # Weights: only train on assistant's answer (action part)
    weights = np.array(
        [0.0] * len(user_ob_tokens) +
        [0.0] * len(user_ac_tokens) +
        [0.0] * len(assistant_ob_tokens) +
        [1.0] * len(assistant_ac_tokens)
    )

Geser token dan bobot untuk prediksi token berikutnya

Model bahasa memprediksi token berikutnya dalam sebuah urutan. Saat model melihat token 0-9, ia harus memprediksi token ke-10. Jadi target Anda selalu masukan yang digeser satu posisi ke depan:

   # CRITICAL: Shift tokens AND weights for next-token prediction
    input_tokens_model = all_tokens[:-1]
    target_tokens = all_tokens[1:]
    weights_shifted = weights[1:]

Penting untuk dicatat bahwa Anda harus menggeser bobot bersama token. Jika tidak, perhitungan loss akan tidak selaras: model akan dilatih untuk memprediksi token jawaban pertama, tetapi bobot pada posisi itu masih 0,0 dari prompt. Bug penyelarasan ini dapat mencegah model belajar dengan benar.

Kembalikan data yang telah diformat

Terakhir, fungsi prepare_datum() mengembalikan data yang telah diformat, siap untuk diproses.

   return types.Datum(
        model_input=types.ModelInput.from_ints(tokens=input_tokens_model),
        loss_fn_inputs=dict(weights=weights_shifted, target_tokens=target_tokens),
    )

Dengan menerapkan fungsi yang telah ditentukan pada subset pelatihan dan validasi mentah, kini kita dapat memproses seluruh dataset:

# Process and filter training data
training_data_raw = [prepare_datum(example) for example in train_data_raw]
training_data = [d for d in training_data_raw if d is not None]
skipped = len(train_data_raw) - len(training_data)

print(f"Processed {len(training_data)} examples (skipped {skipped} too-long sequences)")
# Output: Processed 7,244 examples (skipped 442 too-long sequences)

# Process validation data
val_data_raw_processed = [prepare_datum(example) for example in val_data_raw]
val_data = [d for d in val_data_raw_processed if d is not None]

print(f"Validation set: {len(val_data)} examples")

Langkah 5: Latih model dengan training loop

Training loop menggunakan dua primitif API inti Tinker: forward_backward dan optim_step. Mari membangunnya selangkah demi selangkah dengan pelacakan validasi untuk menangkap overfitting lebih awal.

Definisikan fungsi validation loss

Pertama, definisikan fungsi validation loss. Berbeda dengan training loss, validation loss memberi tahu seberapa baik model Anda menggeneralisasi ke data yang tidak terlihat. Ini krusial untuk mendeteksi overfitting.

def compute_validation_loss(val_data, batch_size=100):
    """Compute loss on validation set (forward only, no backward)"""
    batch_indices = np.random.choice(
        len(val_data), size=min(batch_size, len(val_data)), replace=False
    )
    batch = [val_data[i] for i in batch_indices]
    
    # Forward pass only (no backward!)
    fwd_future = training_client.forward(batch, loss_fn="cross_entropy")
    fwd_result = with_retry(fwd_future)
    
    # Calculate per-token loss
    loss_sum = fwd_result.metrics["loss:sum"]
    total_completion_tokens = sum(
        np.sum(np.array(val_data[i].loss_fn_inputs["weights"].data) > 0)
        for i in batch_indices
    )
    return loss_sum / total_completion_tokens if total_completion_tokens > 0 else 0

Metode forward() menghitung loss tanpa menghitung gradien, sehingga efisien untuk evaluasi saat Anda hanya perlu mengukur performa, bukan memperbarui bobot. Menghitung validation loss menambah beban minimal (hanya forward pass, tanpa perhitungan gradien) tetapi memberi peringatan dini saat kesenjangan antara training dan validation loss melebihi 0,2, menandakan model Anda menghafal alih-alih belajar.

Konfigurasikan parameter pelatihan

Kita perlu menentukan jumlah epoch serta learning rate. LoRA membutuhkan learning rate yang jauh lebih tinggi daripada fine-tuning penuh, biasanya 10-20x lebih besar.

# Training configuration
n_samples = len(training_data)  # 7,244
n_epochs = 4  # More epochs for smaller dataset
batch_size = 32

# Calculate optimal LR for Qwen3-8B with LoRA
# Formula: base_lr * lora_multiplier * (2000 / hidden_size) ** exponent
# For Qwen: base=5e-5, multiplier=10, hidden_size=4096, exponent=0.0775
learning_rate = 5e-5 * 10.0 * (2000 / 4096) ** 0.0775  # ≈ 4.7e-4

Formula ini memperhitungkan ukuran model (Qwen3-8B memiliki hidden size 4.096) dan menggunakan eksponen yang ditentukan secara empiris yang bervariasi menurut keluarga model, seperti yang didokumentasikan dalam Tinker cookbook. Untuk model Qwen, eksponennya 0,0775, sedangkan Llama menggunakan 0,781. Dalam kasus kita, ini menghasilkan learning rate sekitar 4,7e-4, memberikan konvergensi stabil tanpa ledakan gradien.

Atur warmup learning rate

Memulai dengan learning rate penuh dapat menyebabkan ledakan gradien di awal pelatihan saat model belum beradaptasi dengan tugas. Warmup secara bertahap meningkatkan learning rate dari mendekati nol ke nilai target selama 200 iterasi pertama. Anda dapat melihatnya jelas pada visualisasi pelatihan sebelumnya, di mana learning rate (garis hijau) meningkat mulus selama 200 iterasi awal.

# Warmup configuration
warmup_steps = 200

# Calculate iterations from epochs
num_iterations = n_epochs * (n_samples // batch_size)  # 4 * 226 = 904
checkpoint_interval = 200
validation_interval = 50

Mulai training loop

Setelah menginisialisasi daftar untuk melacak loss, kita dapat memulai training loop:

losses = []
per_token_losses = []
val_losses = []

for iteration in range(num_iterations):
    # Sample random batch
    batch_indices = np.random.choice(len(training_data), size=batch_size, replace=False)
    batch = [training_data[i] for i in batch_indices]
    
    # Apply learning rate warmup
    if iteration < warmup_steps:
        current_lr = learning_rate * (iteration + 1) / warmup_steps
    else:
        current_lr = learning_rate

Logika warmup secara bertahap meningkatkan learning rate selama 200 iterasi pertama, mencegah ketidakstabilan awal.

Panggil primitif pelatihan inti Tinker

Pada setiap iterasi, primitif inti Tinker dipanggil sebagai berikut:

   # API Primitive 1: forward_backward - compute gradients
    fwdbwd_future = training_client.forward_backward(batch, loss_fn="cross_entropy")

    # API Primitive 2: optim_step - update parameters
    optim_future = training_client.optim_step(types.AdamParams(learning_rate=current_lr))

    # Wait for results with retry logic
    fwdbwd_result = with_retry(fwdbwd_future)
    optim_result = with_retry(optim_future)

forward_backward menghitung gradien dengan menilai seberapa salah prediksi model dan ke arah mana setiap parameter harus disesuaikan. Ia menggunakan cross-entropy loss, yang mengukur seberapa baik distribusi probabilitas prediksi model cocok dengan token berikut yang sebenarnya. optim_step benar-benar memperbarui parameter model berdasarkan gradien tersebut menggunakan optimizer Adam.

Perhatikan bagaimana kedua metode segera mengembalikan objek "future". Ini memungkinkan Tinker memproses beberapa operasi secara bersamaan, yang mempercepat proses. Memanggil with_retry(future) menunggu operasi spesifik itu selesai.

Lacak dan tampilkan metrik loss

Kita menghitung total loss dan per-token loss lalu menambahkannya ke daftar masing-masing:

   # Track loss
    loss_sum = fwdbwd_result.metrics["loss:sum"]
    total_completion_tokens = sum(
        np.sum(np.array(training_data[i].loss_fn_inputs["weights"].data) > 0)
        for i in batch_indices
    )
    per_token_loss = loss_sum / total_completion_tokens

    losses.append(loss_sum)
    per_token_losses.append(per_token_loss)

    if iteration % 10 == 0:
        warmup_indicator = "🔥" if iteration < warmup_steps else ""
        print(f"{warmup_indicator} Iteration {iteration} | Train: {per_token_loss:.4f} | LR: {current_lr:.6f}")

Per-token loss menormalkan loss berdasarkan jumlah token jawaban, sehingga lebih mudah ditafsirkan lintas ukuran batch yang berbeda. Sesi pelatihan yang baik biasanya dimulai dengan per-token loss sekitar 1,2-1,5 dan turun di bawah 0,8 pada checkpoint-400. Jika loss Anda mulai di atas 2,0 atau tidak turun setelah 50 iterasi, periksa persiapan data dan learning rate.

Tambahkan pemeriksaan validasi berkala dan checkpoint

Menyimpan bobot setiap 200 iterasi menciptakan snapshot yang dapat Anda bandingkan. Seperti yang Anda lihat pada hasil pelatihan sebelumnya, checkpoint-400 menggeneralisasi lebih baik daripada checkpoint akhir meski training loss lebih tinggi. Selalu simpan beberapa checkpoint dan evaluasi pada data yang disisihkan. Checkpoint dipertahankan di server Tinker setelah skrip Anda selesai.

   # Compute validation loss periodically
    if iteration % validation_interval == 0:
        val_loss = compute_validation_loss(val_data)
        val_losses.append((iteration, val_loss))
        gap = val_loss - per_token_loss
        print(f"  📊 Iteration {iteration} | Train: {per_token_loss:.4f} | Val: {val_loss:.4f} | Gap: {gap:+.4f}")

    # Checkpoint every 200 iterations
    if iteration > 0 and iteration % checkpoint_interval == 0:
        training_client.save_weights_for_sampler(name=f"fincot-checkpoint-{iteration}")

Checkpoint Tinker

Tinker mengelompokkan checkpoint ke dalam dua kategori: checkpoint full-state (untuk melanjutkan pelatihan jika terputus) dan bobot sampler (checkpoint ringan untuk inferensi). Perhatikan checkpoint-400 muncul dalam kedua format, memudahkan Anda untuk melanjutkan pelatihan maupun menerapkan model.

Jika run pelatihan Anda terhenti, Anda dapat melanjutkan dari checkpoint mana pun yang tersimpan menggunakan bobot full-state, sehingga dapat meneruskan pelatihan tanpa memulai dari awal.

Untuk referensi API lengkap metode ini, lihat dokumentasi pelatihan dan sampling Tinker.

Langkah 6: Simpan model yang telah di-fine-tune

Setelah pelatihan selesai, simpan bobot model akhir:

sampling_client = training_client.save_weights_and_get_sampling_client(
    name="financial-qa-qwen3-8b-lora"
)

Bobot disimpan di server Tinker, bukan di komputer Anda. Adapter LoRA biasanya hanya memerlukan puluhan megabita. Tinker secara opsional dapat mengekspornya untuk digunakan dengan penyedia inferensi eksternal jika Anda ingin menerapkan model di luar infrastruktur mereka.

Langkah 7: Uji model dengan pertanyaan contoh

Terakhir, uji model yang telah di-fine-tune menggunakan primitif API sample. Pertama, konfigurasikan parameter sampling:

sampling_params = types.SamplingParams(
    max_tokens=200,
    temperature=0.7,
    top_p=0.9,
    stop_sequences=["<|im_end|>"]
)

Mari jelaskan parameter ini:

  • max_tokens: Panjang maksimum respons yang dihasilkan (200 token kira-kira 150 kata).

  • temperature: Mengontrol unsur acak dalam generasi. Nilai lebih rendah (0,1-0,5) membuat keluaran lebih fokus dan deterministik; nilai lebih tinggi (0,7-1,0) memungkinkan lebih banyak kreativitas. Nilai 0,7 menyeimbangkan koherensi dan variasi.

  • top_p (nucleus sampling): Hanya mempertimbangkan himpunan token terkecil yang probabilitas kumulatifnya melebihi nilai ini. 0,9 berarti "hanya pertimbangkan token yang bersama-sama menyumbang 90% massa probabilitas." Ini mencegah model memilih token yang sangat tidak mungkin.

  • stop_sequences: Menginformasikan model untuk berhenti menghasilkan saat mencapai urutan ini. <|im_end|> adalah penanda akhir urutan.

Hasilkan respons untuk pertanyaan uji:

questions = [
    "What are the main risks associated with investing in stocks?",
    "How does diversification help reduce portfolio risk?"
]

for question in questions:
    model_input = types.ModelInput.from_ints(tokenizer.encode(question))

    response = with_retry(
        sampling_client.sample(
            prompt=model_input,
            num_samples=1,
            sampling_params=sampling_params
        )
    )

    answer = tokenizer.decode(response.sequences[0].tokens)
    print(f"Q: {question}")
    print(f"A: {answer}\n")

Berikut dua keluaran contoh dari model yang telah di-fine-tune (dipangkas untuk ilustrasi):

Q: What are the main risks associated with investing in stocks?
A: Investing in stocks carries several key risks. Market risk represents the potential for stock prices to decline due to economic downturns or market volatility. Company-specific risk arises from poor management decisions, competitive pressures, or operational failures that affect individual stocks. Liquidity risk occurs when you cannot sell shares quickly without significantly impacting the price. Additionally, investors face inflation risk, where returns may not keep pace with rising prices...

Q: How does diversification help reduce portfolio risk?
A: Diversification reduces portfolio risk by spreading investments across different asset classes, sectors, and geographic regions. When you hold multiple uncorrelated assets, losses in one investment can be offset by gains in others. For example, if technology stocks decline but healthcare stocks rise, a diversified portfolio experiences less volatility than one concentrated in technology alone. The key principle is that different assets respond differently to market conditions...

Objek respons berisi daftar sequences karena Anda dapat meminta beberapa sampel per prompt. Akses token melalui sequences[0].tokens dan dekode kembali ke teks menggunakan tokenizer yang sama.

Anda sekarang telah mendemonstrasikan keempat primitif API inti:

  1. forward_backward: Menghitung gradien dari data pelatihan Anda

  2. optim_step: Memperbarui parameter model dengan optimizer Adam

  3. save_weights_and_get_sampling_client: Mempersistenkan model yang telah di-fine-tune

  4. sample: Menghasilkan prediksi dari model yang telah di-fine-tune

Pola alur kerja yang sama dapat diperluas ke paradigma pelatihan yang lebih maju. Untuk reinforcement learning atau optimisasi preferensi, Anda menggunakan primitif yang sama tetapi dengan fungsi loss dan format data yang berbeda. Jika Anda tertarik menyelaraskan model dengan preferensi manusia, lihat teknik fine-tuning preferensi, yang dibangun di atas fondasi yang sama. Tinker cookbook menyediakan contoh untuk skenario lanjutan tersebut.

Namun bagaimana Anda tahu apakah fine-tuning benar-benar meningkatkan performa? Alih-alih bergantung pada kesan subjektif, Anda memerlukan evaluasi yang ketat. Di bagian berikut, Anda akan melihat hasil dari evaluasi LLM-as-judge yang membandingkan model yang telah di-fine-tune dengan Qwen3-8B dasar pada 10 pertanyaan keuangan yang beragam.

Mengevaluasi model yang di-fine-tune dengan LLM judge

Untuk mengukur performa secara objektif, kami menggunakan LLM-as-judge: GPT-4o mengevaluasi checkpoint-400 dibandingkan Qwen3-8B dasar pada 10 pertanyaan keuangan yang beragam, menilai setiap respons berdasarkan akurasi, kejelasan, kelengkapan, dan terminologi keuangan.

Model yang di-fine-tune meraih skor 8,5/10, dibandingkan 6,5 untuk model dasar, dan menang dalam semua 10 perbandingan. Putusan mengungkap alasannya: model menyajikan penjelasan lengkap dengan penalaran yang percaya diri dan terstruktur, sementara model dasar cenderung "menebak" dengan "saya pikir" dan "mungkin," meninggalkan pemikiran yang tidak tuntas.

Ini memvalidasi performa dunia nyata yang lebih baik dari checkpoint-400. Training loss yang lebih rendah pada iterasi 900 hanya akan memberi kita hafalan, bukan penalaran.

Lihat skrip perbandingan dan hasil terperinci untuk menjalankan evaluasi serupa pada model Anda.

Kesimpulan

Anda telah melihat bagaimana Tinker menyederhanakan fine-tuning tanpa mengorbankan kendali. Empat primitif API inti, forward_backward, optim_step, save_weights_and_get_sampling_client, dan sample, memberi Anda fondasi untuk alur kerja pelatihan kustom sementara Tinker menangani infrastruktur terdistribusi.

Model Q&A keuangan yang kita bangun menunjukkan praktik terbaik produksi: pelacakan validasi menangkap overfitting lebih awal, checkpoint-400 mengungguli model akhir dengan fokus pada generalisasi, dan evaluasi LLM-as-judge mengonfirmasi peningkatan 2 poin dibanding model dasar. Pola ini berlaku apakah Anda melakukan fine-tuning model 8B atau 70B parameter.

Platform ini dalam tahap beta dengan akses daftar tunggu, tetapi konsep yang Anda pelajari dapat diterapkan langsung begitu mendapatkan akses. Run pelatihan yang saya lakukan untuk tutorial ini (termasuk yang gagal dan eksperimental) menghabiskan 150 kredit awal, jadi dengan kredit awal, Anda dapat menjalankan tutorial ini 6 kali plus eksperimen tambahan, memberi banyak ruang untuk belajar dan beriterasi pada proyek fine-tuning Anda sendiri.

Langkah selanjutnya? Coba fine-tuning pada data spesifik domain Anda, bereksperimen dengan rank LoRA dan learning rate yang berbeda, atau jelajahi paradigma pelatihan lanjutan seperti reinforcement learning from human feedback. Tinker cookbook menawarkan contoh untuk skenario tersebut. Mulailah memikirkan use case Anda sekarang—perilaku apa yang ingin Anda ajarkan ke model Anda?

Jika Anda ingin mengembangkan keterampilan yang lebih luas dalam melatih dan melakukan fine-tuning model AI terbaru untuk produksi, pastikan untuk melihat jalur karier Associate AI Engineer for Developers.

Bexruz (Bex) Tuychiev

Penulis

Bexruz (Bex) Tuychiev

Saya adalah kreator konten data science dengan pengalaman lebih dari 2 tahun dan salah satu dengan jumlah pengikut terbesar di Medium. Saya suka menulis artikel mendalam tentang AI dan ML dengan sedikit gaya sarkastik—karena harus ada sesuatu untuk membuatnya tidak terlalu membosankan. Saya telah menghasilkan lebih dari 130 artikel dan satu kursus di DataCamp, dengan satu lagi sedang dalam proses. Konten saya telah dilihat oleh lebih dari 5 juta pasang mata, dan 20 ribu di antaranya menjadi pengikut di Medium dan LinkedIn. 

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026