Part 04 · LLM Internals

Pretraining and Fine-tuning

Next-token predictionPretrainingInstruction tuningRLHFDPO

Internet এর পরের শব্দ আন্দাজ করা থেকে instruction মেনে চলা পর্যন্ত: pretraining, instruction tuning, আর RLHF ও DPO দিয়ে preference training।

⏱ 1-2 ঘণ্টা · Station 28 / 92

জিনিসটা কী, কেন দরকার

নতুন একজন support agent কে train করার কথা ভাবো। প্রথমে সে সব পড়ে: manual, পুরনো ticket, company র wiki, মাসের পর মাসের chat। এখন সে অনেক কিছু জানে, কিন্তু কথোপকথনে কীভাবে আচরণ করতে হয় এখনো জানে না। তারপর একজন senior তাকে কয়েকশো ভালো reply দেখায়: "customer এটা জিজ্ঞেস করলে এভাবে answer দাও"। শেষে senior তার reply গুলো দেখে বলে দুইটা খসড়ার কোনটা ভালো, বারবার, যতক্ষণ না agent এর স্বভাব team এর সাথে মিলে যায়।

LLM ও ঠিক এই তিন ধাপে বানানো হয়। বিশাল পরিমাণ text এ pretraining দেয় জ্ঞান আর সাবলীলতা। Instruction tuning (SFT) model কে শেখায় শুধু text টেনে না নিয়ে answer দিতে। Preference training (RLHF বা DPO) ঠিক করে tone, কতটা কাজের, আর কখন না বলবে। কোন ধাপ কোন আচরণ এনেছে জানলে model উল্টাপাল্টা করলে কী বদলাতে হবে বুঝবে, আর আদৌ fine-tuning লাগবে কিনা (Part 9) সেটাও।

ভেতরে কীভাবে চলে

Pretraining: পরের token predict করা। বিশাল একটা text এর স্তূপ নাও (trillion trillion token: web page, বই, code)। প্রতিটা position এ model পরের token predict করে; loss হলো আসল পরের token এর বিপরীতে cross-entropy। কোনো label লাগে না, কারণ text নিজেই answer key: self-supervised learning। এটা ভালোভাবে করতে গিয়ে model কে ব্যাকরণ, তথ্য, যুক্তির ধরন আর লেখার ঢং শিখতে হয়। ফল হলো একটা base model: তাকে "Where is my order?" দিলে সে হয়তো লিখবে "Where is my refund? Why is support so slow?", কারণ web এ এমন text এভাবেই আসে।

Instruction tuning (supervised fine-tuning, SFT)। মানুষের লেখা বা যাচাই করা হাজার হাজার (prompt, আদর্শ answer) জোড়ায় আরো train করো, chat template এর special token দিয়ে সাজানো। Loss হিসাব হয় শুধু answer এর token এ, তাই model answer লিখতে শেখে, user কে নকল করতে না। অনেক কম data, pretraining এর চেয়ে অনেক সস্তা।

Preference training। অনেক গুণ (কাজের কিন্তু লম্বা না, ভদ্র, বিপজ্জনক request এ না বলা) লেখার চেয়ে বিচার করা সহজ। তাই জোড়া জোগাড় করো: একটা prompt এর জন্য একটা বাছাই করা আর একটা বাতিল answer।

  • RLHF: মানুষ rater দের মতো করে answer score করতে একটা reward model train করো, তারপর reinforcement learning (PPO) দিয়ে LLM কে বেশি score পাওয়া answer দিতে শেখাও, SFT model থেকে বেশি দূরে সরে গেলে জরিমানা সহ।
  • DPO (direct preference optimisation): reward model বাদ। একটা সহজ loss সরাসরি বাছাই করা answer এর log-probability বাড়ায় আর বাতিলটার কমায়, model এর একটা জমিয়ে রাখা reference কপির তুলনায়। সহজ আর বেশি স্থির, তাই ব্যাপকভাবে ব্যবহার হয়।
আগে অনুমান করো

একটা base (শুধু pretrained) model কে prompt দিলে "Translate to Bangla: Where is my order?", আর সে reply দিল "Translate to Bangla: When will it arrive?"। কেন?

ছবিতে দেখো

raw texttrillions of tokensweb pages, books, code: no labels, just texttokenspretrainingnext-token losspredict every next token; weeks on thousands of GPUsweightsbase modelcontinues text"where is my order" -> continues with more questions, not an answer+ examplesSFTprompt → answer pairstens of thousands of good conversations; loss only on the answers+ preferencesRLHF / DPOchosen vs rejectedpeople (or a model) pick the better of two answers; push toward itchat modelassistanthelpful, safefollows instructions in the expected format and tonepretraining gives knowledge; fine-tuning gives behaviour
Trillion trillion token এর কাঁচা text পরের-token loss দিয়ে pretraining এ যায়, আর বের হয় একটা base model যেটা text টেনে নেয়। Prompt আর answer এর জোড়ায় supervised fine-tuning তাকে answer দিতে শেখায়। বাছাই বনাম বাতিল answer দিয়ে preference training (RLHF বা DPO) তার আচরণ গড়ে, আর হয় assistant। Pretraining দেয় জ্ঞান; fine-tuning দেয় আচরণ।

Code এ তিনটা ধাপ

তিনটা ধাপই ছোট্ট আকারে। ছোট একটা text এ পরের token predict করে pretrain করা অক্ষর-ভিত্তিক একটা model; একটা SFT example যে loss mask ব্যবহার করে; আর একটা answer কে আরেকটার চেয়ে পছন্দ করতে শেখার সময় DPO loss।

import math
import torch
import torch.nn.functional as F

torch.manual_seed(0)

# 1) PRETRAINING = next-token prediction on raw text. Here: a character bigram model.
text = ("the rider picked up the order. the order is on the way. "
        "the rider is near the gate. your order has arrived. ") * 20
chars = sorted(set(text))
stoi = {c: i for i, c in enumerate(chars)}
data = torch.tensor([stoi[c] for c in text])
logits_table = torch.zeros(len(chars), len(chars), requires_grad=True)   # score of next char given this char
opt = torch.optim.Adam([logits_table], lr=0.1)
x, y = data[:-1], data[1:]                     # every position predicts the one after it
for step in range(201):
    loss = F.cross_entropy(logits_table[x], y)
    opt.zero_grad(); loss.backward(); opt.step()
    if step in (0, 50, 200):
        print(f"pretraining step {step:>3}: loss {loss.item():.3f}  (uniform guess = ln {len(chars)} = {math.log(len(chars)):.3f})")

g = torch.Generator().manual_seed(1)
c, out = stoi["t"], "t"
for _ in range(60):
    c = torch.multinomial(F.softmax(logits_table[c], -1), 1, generator=g).item()
    out += chars[c]
print("sample:", repr(out))

# 2) INSTRUCTION TUNING (SFT): train on prompt + answer, but only the answer tokens count.
prompt, answer = "Q: where is my order? A:", " it is on the way."
tokens = list(prompt + answer)
loss_mask = [0] * len(prompt) + [1] * len(answer)   # don't teach the model to write the user's question
print(f"\nSFT example: {len(tokens)} tokens, {sum(loss_mask)} of them in the loss")

# 3) PREFERENCE TUNING with DPO: make the chosen answer more likely than the rejected one,
#    relative to a frozen reference copy of the model. Inputs are sums of token log-probs.
def dpo_loss(pol_chosen, pol_rejected, ref_chosen, ref_rejected, beta=0.1):
    margin = beta * ((pol_chosen - ref_chosen) - (pol_rejected - ref_rejected))
    return -F.logsigmoid(torch.tensor(margin)).item()

ref_c, ref_r = -12.0, -11.0      # reference model slightly prefers the rude answer
print("\nDPO loss as the policy learns to prefer the polite answer:")
for shift in (0, 5, 10, 20):
    print(f"  chosen +{shift:>2}, rejected -{shift:>2} log-prob: loss {dpo_loss(ref_c + shift, ref_r - shift, ref_c, ref_r):.3f}")

Output:

pretraining step   0: loss 2.996  (uniform guess = ln 20 = 2.996)
pretraining step  50: loss 1.183  (uniform guess = ln 20 = 2.996)
pretraining step 200: loss 1.164  (uniform guess = ln 20 = 2.996)
sample: 'ther wayorde ive ive teris theas p rde gard the is gas thar e'

SFT example: 42 tokens, 18 of them in the loss

DPO loss as the policy learns to prefer the polite answer:
  chosen + 0, rejected - 0 log-prob: loss 0.693
  chosen + 5, rejected - 5 log-prob: loss 0.313
  chosen +10, rejected -10 log-prob: loss 0.127
  chosen +20, rejected -20 log-prob: loss 0.018

কী দেখলাম:

  • Pretraining: loss শুরু হয় ঠিক ln 20 = 2.996 এ, 20 টা অক্ষরের মধ্যে সমানভাবে আন্দাজ করার খরচ, আর নামে 1.164 এ। কোনো label দেওয়া হয়নি; text নিজেই নিজের answer key।
  • Sample ("ther wayorde ive ... the is gas thar") আবোল তাবোল, কিন্তু ধাঁচটা ঠিক: "the", "way", "order" এর মতো আসল টুকরো। Bigram model শুধু জানে কোন অক্ষরের পরে কোনটা আসে; কোটি কোটি parameter এর transformer একই লক্ষ্য শিখলে এই ধাঁচটাই জ্ঞানে পরিণত হয়।
  • SFT: example এর 42 টা token এর মধ্যে শুধু answer এর 18 টা loss এ গোনা হয়। Model কে answer লিখতে শেখানো হয়, প্রশ্ন কখনো না।
  • DPO: policy যখন reference থেকে আলাদা না, loss ln 2 = 0.693, মানে "এখনো কোনো পছন্দ নেই"। বাছাই করা answer এর log-probability বাড়লে আর বাতিলটার কমলে loss নামে 0.313, 0.127, 0.018 এ। Loss শুধু reference এর তুলনায় ফাঁকটা দেখে, যেটা model কে যথেচ্ছ দূরে সরে যেতে দেয় না।

Production এ যা মাথায় রাখবে

  • তুমি প্রায় কখনো pretrain করবে না। খরচ লাখ লাখ dollar। Team গুলো আগে থেকে থাকা base বা instruct model দিয়ে শুরু করে মানিয়ে নেয়, বেশিরভাগ prompt আর RAG দিয়ে (Part 5), কখনো fine-tuning দিয়ে (Part 9)।
  • Fine-tuning আচরণ শেখায়, তথ্য না। তোমার document এ SFT করে জ্ঞান যোগ করা খারাপ উপায়: model তবুও detail বানিয়ে বলতে পারে। তথ্যের জন্য retrieval, আর format, tone আর কাজের ঢংয়ের জন্য fine-tuning।
  • ঠিক chat template ব্যবহার করো। Instruct model হুবহু নির্দিষ্ট special token আর role marker দিয়ে train করা। অন্য format এ text পাঠালে চুপচাপ মান কমে।
  • Alignment উল্টে যেতে পারে। একটা instruct model কে ছোট, অযত্নের dataset এ fine-tune করলে তার না বলা আর safety এর আচরণ মুছে যেতে পারে। যেকোনো fine-tune এর পরে safety আবার test করো।
  • জ্ঞানের একটা cutoff আছে। Model শুধু তার pretraining data তে যা ছিল তা জানে, একটা তারিখ পর্যন্ত। তার পরের যা কিছু, prompt থেকে আসতে হবে।

এক কথায়

বিশাল text এ পরের token predict করে pretraining একটা base model কে জ্ঞান দেয়; prompt আর answer এর জোড়ায় SFT (loss শুধু answer এ) তাকে উত্তর দিতে শেখায়; বাছাই বনাম বাতিল answer এ RLHF বা DPO তার আচরণ গড়ে।

নিজে করে দেখো

প্রতিটা সমস্যার জন্য বলো কোন ধাপ সবচেয়ে ভালো ঠিক করবে, আর তুমি একজন application engineer হিসেবে বাস্তবে সেটা করতে পারবে কিনা: (a) model তোমার company র return policy জানে না; (b) answer কে সবসময় তিনটা নির্দিষ্ট field এর valid JSON হতে হবে; (c) model এমন শক্ত, formal tone এ লেখে যেটা user রা অপছন্দ করে; (d) model কখনো সিলেটি দেখেনি।

Answer

(a) তোমার policy র জ্ঞান: এটা training এর সমস্যাই না; retrieval দিয়ে policy টা prompt এ দাও (Part 5)। (b) Format: prompting আর structured output দিয়ে শুরু করো (Part 5); তাতে না হলে উদাহরণে ছোট একটা SFT ভালো কাজ করে, আর করা সম্ভব। (c) Tone: আগে prompting; দরকার হলে পছন্দের বনাম অপছন্দের reply দিয়ে SFT বা DPO, এটাও মাঝারি একটা dataset এ করা যায়। (d) নতুন ভাষা বা উপভাষা এমন জ্ঞান যেটা base model এর নেই; প্রচুর সিলেটি text এ continued pretraining লাগে, দামি আর app team এর জন্য খুব কমই বাস্তবসম্মত, তাই এমন model বাছো যেটা আগে থেকেই এটা পারে।

Station stamp

Chapter শেষ করো

পড়া শেষ হলে Complete চাপো, progress save হবে। XP শুধু Pro তে — Pro থাকলে এই chapter এ +10 XP পেতে।

Pro নিয়ে XP পাও →