मुख्य सामग्री पर जाएँ

GPT-OSS का फाइन-ट्यूनिंग

OpenAI GPT-OSS 20B मॉडल को चिकित्सकीय प्रश्न-उत्तर डेटासेट पर सटीकता और शैली अपनाने हेतु फाइन-ट्यून करने की चरण-दर-चरण मार्गदर्शिका।
· 6 मि॰ पढ़ें

AI के साथ खोजें

GPT-OSS 20B OpenAI की gpt-oss शृंखला का एक ओपन-वेट भाषा मॉडल है, जिसे कम-विलंबता और विशेषीकृत उपयोग मामलों के लिए बनाया गया है। इसमें 21 अरब पैरामीटर्स (3.6B सक्रिय) हैं और MXFP4 क्वांटाइज़ेशन के कारण यह उपभोक्ता हार्डवेयर पर कुशलता से चलता है, जिसके लिए लगभग 16GB मेमोरी ही चाहिए।

GPT-OSS 120B से छोटा होने के बावजूद, यह फिर भी उन्नत सुविधाओं का समर्थन करता है, जैसे कॉन्फ़िगरेबल रीजनिंग स्तर (निम्न, मध्यम, उच्च), पूर्ण चेन-ऑफ़-थॉट एक्सेस डिबगिंग और पारदर्शिता के लिए, तथा एजेंटिक क्षमताएँ जैसे फ़ंक्शन कॉलिंग, वेब ब्राउज़िंग, और कोड निष्पादन।

इस मार्गदर्शिका में, मैं आपको GPT-OSS 20B को सेटअप करने और फाइन-ट्यून करने की संपूर्ण प्रक्रिया से लेकर चलूँगा। इसमें शामिल हैं:

  1. डिपेंडेंसीज़ इंस्टॉल करना और परिवेश तैयार करना
  2. मॉडल और टोकनाइज़र लोड करना
  3. नए OpenAI Harmony Python पैकेज का उपयोग कर प्रॉम्प्ट शैली बनाना
  4. डेटासेट लोड करना और Harmony फ़ॉर्मेटिंग लागू करना
  5. फाइन-ट्यूनिंग से पहले साधारण मॉडल इन्फ़ेरेंस चलाना
  6. ट्रेनिंग के लिए मॉडल कॉन्फ़िगर करना
  7. मेडिकल Q&A डेटासेट पर मॉडल को फाइन-ट्यून करना
  8. फाइन-ट्यूनिंग के बाद सुधारों का आकलन करने हेतु इन्फ़ेरेंस करना

ध्यान रखें कि यह ट्यूटोरियल शोध और शिक्षा के लिए है, न कि रोगी के निदान या उपचार के लिए।

चित्र: लेखक द्वारा

1. अपना परिवेश सेटअप करना

हालाँकि GPT-OSS मॉडल में 21 अरब पैरामीटर्स हैं, फिर भी इसे पर्याप्त GPU मेमोरी की आवश्यकता होती है—मॉडल को सहजता से संभालने के लिए कम-से-कम 80GB VRAM। शुरू करने का एक तेज़ तरीका RunPod H100 इंस्टेंस या इसी तरह के उच्च-मेमोरी GPU परिवेश को लॉन्च करना है।

RunPod H100SXM machine

परिवेश तैयार होने के बाद, डेटा प्रोसेसिंग, मॉडल फाइन-ट्यूनिंग, और एक्सपेरिमेंट ट्रैकिंग के लिए सभी आवश्यक Python पैकेज इंस्टॉल करें:

%%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

अंत में, अपनी API कुंजी का उपयोग करके Hugging Face Hub में लॉग इन करें। इससे आप फाइन-ट्यून किया गया मॉडल और टोकनाइज़र सीधे अपने Hugging Face खाते में सेव और साझा कर पाएँगे:

from huggingface_hub import notebook_login

notebook_login()

2. GPT-OSS मॉडल और टोकनाइज़र लोड करना

अब हम MXFP4 क्वांटाइज़ेशन के साथ GPT-OSS 20B लोड करेंगे, पर लोड के समय ही वेट्स को bfloat16 में डी-क्वांटाइज़ कर देंगे, ईगर अटेंशन का उपयोग करेंगे, कैश डिसेबल होगा, और डिवाइस प्लेसमेंट ऑटोमैटिक रहेगा।

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)

मॉडल के साथ-साथ, हमें उसी रिपॉज़िटरी से टोकनाइज़र भी चाहिए। टोकनाइज़र का काम पाठ को टोकन (ID) में बदलना है ताकि मॉडल उसे प्रोसेस कर सके, और फिर मॉडल के आउटपुट को मानव-पठनीय पाठ में डिकोड करना।

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

3. OpenAI Harmony का उपयोग करके प्रॉम्प्ट शैली बनाना

OpenAI Harmony एक विशेष रेस्पॉन्स फ़ॉर्मेट है जिसका उपयोग GPT-OSS मॉडल वार्तालाप, तर्क-निष्कर्ष आउटपुट और फ़ंक्शन कॉल्स को एक समान ढाँचे में संरचित करने के लिए करते हैं। 

यह परिभाषित करता है कि संदेश विभिन्न भूमिकाओं (system, developer, user, assistant) के बीच कैसे संगठित होते हैं और मॉडल को एकाधिक चैनलों में आउटपुट देने में सक्षम बनाता है—जैसे चेन-ऑफ़-थॉट तर्क को अलग रखना, टूल-कॉलिंग का प्रीएंबल, और अंतिम उपयोगकर्ता-मुखी उत्तर।

इस खंड में, हम एक फ़ंक्शन बनाएँगे जो एक प्रश्न और उत्तर लेता है और उन्हें Harmony-शैली के वार्तालाप प्रॉम्प्ट में फ़ॉर्मेट करता है। यह बातचीत को संरचित रूप में एन्कोड करने के लिए openai_harmony लाइब्रेरी का उपयोग करता है।

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. डेटासेट लोड करना और फ़ॉर्मेट करना

अब हम मेडिकल Q&A डेटासेट (FreedomIntelligence/medical-o1-verifiable-problem) लोड करेंगे और प्रत्येक उदाहरण पर prompt_style_harmony फ़ंक्शन लागू करेंगे। ट्रांसफ़ॉर्म किया गया पाठ "text" नामक नए कॉलम में संग्रहीत होगा, जो डेवलपर की प्रॉम्प्ट शैली के अनुरूप एक साफ, निर्देश-आधारित फ़ॉर्मेट देता है।

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"])

अब डेटासेट में एक नया कॉलम "text" है, जिसमें Harmony-फ़ॉर्मेटेड वार्तालाप है। इसमें शामिल हैं:

  • डेवलपर निर्देश (जैसे, निदान संक्षेप में बताना)
  • उपयोगकर्ता संदेश (चिकित्सकीय प्रश्न)
  • सहायक संदेश (ग्राउंड-ट्रुथ उत्तर)
['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. फाइन-ट्यूनिंग से पहले मॉडल इन्फ़ेरेंस

मॉडल को ट्रेन करने से पहले, फाइन-ट्यूनिंग के बाद तुलना हेतु इसके बेसलाइन प्रदर्शन का मूल्यांकन करना आवश्यक है। इसके लिए, हम एक सहायक फ़ंक्शन render_inference_harmony परिभाषित करते हैं, जो डेवलपर के कड़े निर्देश और उपयोगकर्ता के प्रश्न वाला Harmony-शैली का प्रॉम्प्ट तैयार करता है, पर सहायक का उत्तर खाली छोड़ देता है ताकि मॉडल उसे पूरा करे।

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

इसके बाद, हम डेटासेट से पहला सैंपल लेते हैं, उसे इस फ़ंक्शन से फ़ॉर्मेट करते हैं, टोकनाइज़ करते हैं, और मॉडल से होकर गुजारते हैं ताकि उत्तर जेनरेट हो सके:

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

इस परीक्षण में, डेवलपर निर्देशों में स्पष्ट रूप से संक्षिप्त निदान (≤5 शब्द) माँगे जाने के बावजूद, मॉडल का आउटपुट काफ़ी लंबा और वर्णनात्मक आया। 

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

“Gastric ulcer” (ग्राउंड-ट्रुथ लेबल) जैसा सीधा उत्तर देने के बजाय, मॉडल ने NSAID उपयोग और अल्सर ब्लीडिंग के बारे में विस्तार से समझाया।

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

6. ट्रेनिंग के लिए मॉडल सेटअप करना

मॉडल को कुशलतापूर्वक फाइन-ट्यून करने के लिए हम LoRA (Low-Rank Adaptation) का उपयोग करते हैं, जो बेस मॉडल को फ्रीज़ रखते हुए केवल थोड़े पैरामीटर्स ट्रेन करने देता है। इससे मेमोरी उपयोग और ट्रेनिंग लागत काफ़ी घटती है।

हम LoraConfig परिभाषित करने से शुरू करते हैं, जिसमें रैंक, स्केलिंग फ़ैक्टर, और वे विशिष्ट टार्गेट लेयर्स होंगी जहाँ LoRA अडैप्टर्स डाले जाएँगे।

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

केवल ~15M पैरामीटर्स (पूर्ण मॉडल के ≈0.07%) ट्रेन करने योग्य हैं, और अडैप्टर का आकार लगभग 16 MB है—पूर्ण फाइन-ट्यूनिंग की तुलना में यह बहुत बड़ा दक्षता लाभ है।

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

इसके बाद, हम trl लाइब्रेरी के SFTConfig से ट्रेनिंग सेटअप कॉन्फ़िगर करते हैं। इसमें हाइपरपैरामीटर्स आते हैं, जैसे लर्निंग रेट, बैच साइज़, ग्रेडिएंट एक्यूमुलेशन, वॉर्मअप रेशियो, और शेड्यूलर प्रकार:

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. मॉडल को ट्रेन करना

डेटासेट तैयार होने, LoRA अडैप्टर जोड़ने, और ट्रेनिंग आर्ग्युमेंट्स कॉन्फ़िगर करने के बाद, हम अब फाइन-ट्यूनिंग प्रक्रिया शुरू कर सकते हैं। हम trl लाइब्रेरी के SFTTrainer का उपयोग करते हैं, जो एक ही स्थान पर मॉडल, टोकनाइज़र, डेटासेट और ट्रेनिंग लूप संभालकर सुपरवाइज्ड फाइन-ट्यूनिंग को सरल बनाता है:

from trl import SFTTrainer

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

ट्रेनिंग के दौरान लॉस धीरे-धीरे घटता है, जो दर्शाता है कि मॉडल Harmony-फ़ॉर्मेटेड मेडिकल Q&A डेटासेट के अनुरूप अपने उत्तरों को संरेखित करना सीख रहा है।

Model training loss

ट्रेनिंग पूर्ण होने पर, हम फाइन-ट्यून किया गया मॉडल लोकली सेव करते हैं और फिर इसे Hugging Face Hub पर पुश करते हैं। महत्वपूर्ण रूप से, केवल LoRA अडैप्टर वेट्स (पूर्ण 20B मॉडल नहीं) अपलोड होते हैं, जिससे रिपॉज़िटरी हल्की और साझा करने में आसान रहती है:

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

इससे Hugging Face पर यह नया मॉडल रिपॉज़िटरी बनती है: kingabzpro/gpt-oss-20b-medical-qa।

स्रोत: kingabzpro/gpt-oss-20b-medical-qa

8. फाइन-ट्यूनिंग के बाद मॉडल इन्फ़ेरेंस

फाइन-ट्यूनिंग के बाद, हम जाँच सकते हैं कि अब मॉडल डेवलपर के निर्देशों का अधिक नज़दीकी से पालन करता है या नहीं। इसके लिए, पहले हम बेस GPT-OSS 20B मॉडल लोड करते हैं और फिर फाइन-ट्यून किए गए LoRA अडैप्टर्स जोड़ते हैं।

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

इसके बाद, हम डेटासेट के एक सैंपल पर इन्फ़ेरेंस चलाते हैं। प्रश्न को Harmony शैली में फ़ॉर्मेट किया जाता है, टोकनाइज़ किया जाता है, मॉडल से गुज़ारा जाता है, और फिर पाठ में डिकोड किया जाता है:

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

फाइन-ट्यून किया गया मॉडल अब छोटा और सटीक उत्तर देता है। यह ग्राउंड-ट्रुथ लेबल (“Gastric ulcer”) के बहुत करीब है और ≤5 शब्द की बाधा का पालन करता है।

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

हम एक और सैंपल पर भी परीक्षण कर सकते हैं ताकि स्थिरता की पुष्टि हो सके:

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

उत्तम। फाइन-ट्यून किया गया मॉडल संक्षिप्त, सटीक और निर्देशों का पालन करने वाले उत्तर जेनरेट कर रहा है।

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

निष्कर्ष

ओपन-सोर्स AI समुदाय के लिए यह रोमांचक समय है। यद्यपि नए GPT-OSS मॉडल अभी बेंचमार्क के शीर्ष पर न हों, वे विशेष रूप से अपने-अपने पैरामीटर वर्गों में मजबूत संभावनाएँ दिखाते हैं, जहाँ छोटे मॉडल भी प्रभावशाली परिणाम दे सकते हैं।

इस ट्यूटोरियल में, हमने GPT-OSS 20B मॉडल को मेडिकल प्रश्नोत्तरी के लिए LoRA अडैप्टर्स और Harmony प्रॉम्प्ट शैली का उपयोग करके फाइन-ट्यून किया। परिणाम उत्साहजनक हैं: फाइन-ट्यून किया गया मॉडल नैदानिक तर्क से जुड़े कार्यों के अनुरूप संक्षिप्त और सटीक उत्तर देता है। अधिक ट्रेनिंग इपॉक्स, बड़े डेटासेट, और परिष्कृत सिस्टम प्रॉम्प्ट के साथ प्रदर्शन को और बेहतर किया जा सकता है।

यदि आप फाइन-ट्यूनिंग से परिचित होने के लिए किसी हैंड्स-ऑन पाठ्यक्रम की तलाश में हैं, तो अवश्य देखें Fine-Tuning With Llama 3।

Abid Ali Awan

लेखक

Abid Ali Awan

एक प्रमाणित डेटा साइंटिस्ट के रूप में, मैं अत्याधुनिक तकनीक का उपयोग करके नवाचारी मशीन लर्निंग अनुप्रयोग बनाने के लिए उत्साहित रहता/रहती हूँ। स्पीच रिकॉग्निशन, डेटा विश्लेषण और रिपोर्टिंग, MLOps, संवादात्मक AI और NLP में मजबूत पृष्ठभूमि के साथ, मैंने ऐसे बुद्धिमान सिस्टम विकसित करने में अपनी विशेषज्ञता निखारी है जो वास्तविक प्रभाव डाल सकें। तकनीकी दक्षता के अलावा, मैं जटिल अवधारणाओं को स्पष्ट और संक्षिप्त भाषा में प्रस्तुत करने में भी निपुण हूँ। परिणामस्वरूप, मैं डेटा साइंस पर एक मांग में रहने वाला/वाली ब्लॉगर बन गया/गई हूँ, और डेटा प्रोफेशनलों के बढ़ते समुदाय के साथ अपने अनुभव और विचार साझा करता/करती हूँ। वर्तमान में, मैं कंटेंट निर्माण और संपादन पर केंद्रित हूँ, बड़े भाषा मॉडलों के साथ काम करते हुए ऐसा प्रभावशाली और आकर्षक कंटेंट विकसित कर रहा/रही हूँ जो व्यवसायों और व्यक्तियों दोनों को अपने डेटा का अधिकतम लाभ उठाने में मदद कर सके।

विषय