Open-Source AI Cookbook documentation

Kod Dil Modelini Tek GPU’da Fine-Tune Etmek

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Open In Colab

Kod Dil Modelini Tek GPU’da Fine-Tune Etmek

Yazar: Maria Khalusova

Çeviren: Emre Albayrak

Codex, StarCoder ve Code Llama gibi açık kaynak dil modelleri genel programlama ilkelerine ve sözdizimine uygun kod üretme konusunda harikadırlar. Fakat bu modeller, bir kuruluşun dahili kurallarıyla uyumlu olmayabilir veya özel kütüphanelerden haberdar olmayabilir.

Bu notebook’ta, bir modelin bağlamsal farkındalığını artırmak ve kuruluşunuzun ihtiyaçları için kullanılabilirliğini artırmak amacıyla özel kod tabanlarında bir kod dil modeline nasıl fine-tune yapabileceğinizi göstereceğiz. Kod dil modelleri oldukça büyük olduğundan, geleneksel bir şekilde fine-tune yapmak kaynakları tüketebilir. Endişelenmeyin! Fine-tune işlemini tek bir GPU’ya sığacak şekilde nasıl optimize edebileceğinizi göstereceğiz.

Veri Seti

Bu örnek için GitHub’daki en iyi 10 Hugging Face public repo’larını seçtik. Görseller, ses dosyaları, sunumlar gibi kod içermeyen dosyaları verilerden hariç tuttuk. Jupyter notebook’lar için yalnızca kod içeren hücreleri tuttuk. Ortaya çıkan kod, Hugging Face Hub’da smangrul/hf-stack-v1 bağlantısı altında bulabileceğiniz bir veri seti olarak mevcut. Bu veri seti repo’nun kimliğini, dosya yolunu ve dosya içeriğini içeriyor.

Model

Bu rehber için 1 milyar parametreli ve 80’den fazla programlama dilinde eğitilmiş bigcode/starcoderbase-1b modelini seçiyoruz. Bu model, yayıncı tarafından korumaya sahip, bu nedenle bu notebook’u tam olarak bu modelle çalıştırmayı planlıyorsanız, modelin sayfasından erişim sağlamanız gerekir. Erişim izninizi aldıktan sonra, Hugging Face hesabınıza giriş yapın.

Not: Eğer fine-tune edilmiş modelinizi Hugging Face Hub’a yüklemek istiyorsanız, write izni olan bir token girmeniz gerekli.

from huggingface_hub import notebook_login

notebook_login()

Başlamak için gerekli tüm kütüphaneleri yükleyelim. Gördüğünüz gibi, transformers ve datasets kütüphanelerine ek olarak, eğitimi optimize etmek için peft, bitsandbytes ve flash-attn kullanacağız.

Parametre açısından verimli eğitim teknikleri kullanarak, bu notebook’u tek bir A100 High-RAM GPU üzerinde çalıştırabiliriz.

!pip install -q transformers datasets peft bitsandbytes flash-attn

Şimdi biraz hiperparametre tanımlayalım. Değerlerini istediğiniz gibi değiştirebilirsiniz.

MODEL = "bigcode/starcoderbase-1b"  # Hugging Face Hub model adı
DATASET = "smangrul/hf-stack-v1"  # Hugging Face Hub'daki veri seti
DATA_COLUMN = "content"  # kod içeriğinin olduğu sütun adı

SEQ_LENGTH = 2048  # Karakter uzunluğu

# Eğitim argümanları
MAX_STEPS = 2000  # max_steps
BATCH_SIZE = 16  # batch_size
GR_ACC_STEPS = 1  # gradient_accumulation_steps
LR = 5e-4  # learning_rate
LR_SCHEDULER_TYPE = "cosine"  # lr_scheduler_type
WEIGHT_DECAY = 0.01  # weight_decay
NUM_WARMUP_STEPS = 30  # num_warmup_steps
EVAL_FREQ = 100  # eval_freq
SAVE_FREQ = 100  # save_freq
LOG_FREQ = 25  # log_freq
OUTPUT_DIR = "peft-starcoder-lora-a100"  # output_dir
BF16 = True  # bf16
FP16 = False  # no_fp16

# FIM dönüşüm argümanları
FIM_RATE = 0.5  # fim_rate
FIM_SPM_RATE = 0.5  # fim_spm_rate

# LORA argümanları
LORA_R = 8  # lora_r
LORA_ALPHA = 32  # lora_alpha
LORA_DROPOUT = 0.0  # lora_dropout
LORA_TARGET_MODULES = "c_proj,c_attn,q_attn,c_fc,c_proj"  # lora_target_modules

# bitsandbytes config argümanları
USE_NESTED_QUANT = True  # use_nested_quant
BNB_4BIT_COMPUTE_DTYPE = "bfloat16"  # bnb_4bit_compute_dtype

SEED = 0
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    Trainer,
    TrainingArguments,
    logging,
    set_seed,
    BitsAndBytesConfig,
)

set_seed(SEED)

Veri setinin hazırlanması

Verileri yükleyerek başlayalım. Veri setinin oldukça büyük olması muhtemel olduğundan, streaming modunu etkinleştirdiğinizden emin olun.

Streaming modu, tüm veri setini bir kerede indirmek yerine veri seti üzerinde işlem yaptıkça verileri kademeli olarak yüklememizi sağlar.

İlk 4000 örneği validation set (doğrulama kümesi) olarak ayıracağız ve geri kalan her şey eğitim verisi olacak.

from datasets import load_dataset
import torch
from tqdm import tqdm


dataset = load_dataset(
    DATASET,
    data_dir="data",
    split="train",
    streaming=True,
)

valid_data = dataset.take(4000)
train_data = dataset.skip(4000)
train_data = train_data.shuffle(buffer_size=5000, seed=SEED)

Bu adımda, veri seti hala isteğe bağlı uzunlukta kod içeren ham veriler içeriyor. Eğitim için sabit uzunlukta girdilere ihtiyacımız var. Bir metin dosyası akışından (stream) sabit uzunlukta token yığınları döndürecek bir Iterable veri kümesi oluşturalım.

İlk olarak, veri setindeki token başına ortalama karakter sayısını tahmin edelim, bu daha sonra text buffer’daki token sayısını tahmin etmemize yardımcı olacaktır. Varsayılan olarak, veri setinden yalnızca 400 örnek (nb_examples) alacağız. Tüm veri setinin yalnızca bir alt kümesini kullanmak, hesaplama maliyetini düşürürken, genel karakter-token oranının makul bir tahminini sağlayacaktır.

>>> tokenizer = AutoTokenizer.from_pretrained(MODEL, trust_remote_code=True)


>>> def chars_token_ratio(dataset, tokenizer, data_column, nb_examples=400):
...     """
...     Veri kümesindeki token başına ortalama karakter sayısını tahmin eder.
...     """

...     total_characters, total_tokens = 0, 0
...     for _, example in tqdm(zip(range(nb_examples), iter(dataset)), total=nb_examples):
...         total_characters += len(example[data_column])
...         total_tokens += len(tokenizer(example[data_column]).tokens())

...     return total_characters / total_tokens


>>> chars_per_token = chars_token_ratio(train_data, tokenizer, DATA_COLUMN)
>>> print(f"The character to token ratio of the dataset is: {chars_per_token:.2f}")
The character to token ratio of the dataset is: 2.43

Karakter-token oranı, metin tokenizasyonunun kalitesinin bir göstergesi olarak da kullanılabilir. Örneğin, karakter-token oranının 1,0 olması her karakterin bir token ile temsil edildiği anlamına gelir ki bu çok anlamlı değildir. Bu da zayıf bir tokenizasyona işaret eder. Standart İngilizce metinde bir token tipik olarak yaklaşık dört karaktere eşdeğerdir, yani karakter-token oranı 4,0 civarındadır. Kod veri setinde daha düşük bir oran bekleyebiliriz, ancak genel olarak konuşursak, 2,0 ile 3,5 arasında bir sayı yeterince iyi kabul edilebilir.

Opsiyonel FIM dönüşümleri

Autoregressive dil modelleri tipik olarak soldan sağa doğru sekanslar üretir. Model, FIM dönüşümlerini uygulayarak metni doldurmayı da öğrenebilir. Teknik hakkında daha fazla bilgi edinmek için “Efficient Training of Language Models to Fill in the Middle” makalesine göz atın.

FIM dönüşümlerini burada tanımlayacağız ve Iterable veri setini oluştururken bunları kullanacağız. Ancak, dönüşümleri kullanmak istemiyorsanız, fim_rate değerini 0 olarak ayarlayabilirsiniz.

import functools
import numpy as np


# FIM dönüşümleri için önek, sonek ve orta için özel belirteçlerin belirteç kimliklerini almak için yardımcı fonksiyon.
@functools.lru_cache(maxsize=None)
def get_fim_token_ids(tokenizer):
    try:
        FIM_PREFIX, FIM_MIDDLE, FIM_SUFFIX, FIM_PAD = tokenizer.special_tokens_map["additional_special_tokens"][1:5]
        suffix_tok_id, prefix_tok_id, middle_tok_id, pad_tok_id = (
            tokenizer.vocab[tok] for tok in [FIM_SUFFIX, FIM_PREFIX, FIM_MIDDLE, FIM_PAD]
        )
    except KeyError:
        suffix_tok_id, prefix_tok_id, middle_tok_id, pad_tok_id = None, None, None, None
    return suffix_tok_id, prefix_tok_id, middle_tok_id, pad_tok_id


# https://github.com/bigcode-project/Megatron-LM/blob/6c4bf908df8fd86b4977f54bf5b8bd4b521003d1/megatron/data/gpt_dataset.py adresinden uyarlanmıştır.
def permute(
    sample,
    np_rng,
    suffix_tok_id,
    prefix_tok_id,
    middle_tok_id,
    pad_tok_id,
    fim_rate=0.5,
    fim_spm_rate=0.5,
    truncate_or_pad=False,
):
    """
    Bir örnek (token listesi) alarak iki FIM modu yardımıyla fim_rate olasılığı ile bir FIM dönüşümü gerçekleştirir:
    PSM ve SPM (fim_spm_rate olasılığı ile).
    """

    # if koşulu fim_rate olasılığı ile tetiklenecektir
    # Bu, FIM dönüşümlerinin fim_rate olasılığına sahip örneklere uygulanacağı anlamına gelir
    if np_rng.binomial(1, fim_rate):

        # boundaries dizisinde saklanan rastgele oluşturulmuş indekslere göre örneği önek, orta ve sonek olarak ayırır.
        boundaries = list(np_rng.randint(low=0, high=len(sample) + 1, size=2))
        boundaries.sort()

        prefix = np.array(sample[: boundaries[0]], dtype=np.int64)
        middle = np.array(sample[boundaries[0] : boundaries[1]], dtype=np.int64)
        suffix = np.array(sample[boundaries[1] :], dtype=np.int64)

        if truncate_or_pad:
            # önek, orta ve sonek belirten tokenleri dikkate alarak örneğin yeni toplam uzunluğunu hesaplar
            new_length = suffix.shape[0] + prefix.shape[0] + middle.shape[0] + 3
            diff = new_length - len(sample)

            # yeni uzunluk ile orijinal uzunluk arasında bir uzunluk farkı varsa aktarma veya kesme
            if diff > 0:
                if suffix.shape[0] <= diff:
                    return sample, np_rng
                suffix = suffix[: suffix.shape[0] - diff]
            elif diff < 0:
                suffix = np.concatenate([suffix, np.full((-1 * diff), pad_tok_id)])

        # FIM dönüşümlerinin fim_spm_rateapply SPM varyantının olasılığı ile
        # SPM: sonek, önek, orta
        if np_rng.binomial(1, fim_spm_rate):
            new_sample = np.concatenate(
                [
                    [prefix_tok_id, suffix_tok_id],
                    suffix,
                    [middle_tok_id],
                    prefix,
                    middle,
                ]
            )
        # Aksi takdirde, FIM dönüşümlerinin PSM varyantını uygulayın
        # PSM: önek, sonek, orta
        else:

            new_sample = np.concatenate(
                [
                    [prefix_tok_id],
                    prefix,
                    [suffix_tok_id],
                    suffix,
                    [middle_tok_id],
                    middle,
                ]
            )
    else:
        # FIM dönüşümlerini uygulamama
        new_sample = sample

    return list(new_sample), np_rng

Sabit uzunlukta token yığınları döndürecek bir Iterable veri seti olan ConstantLengthDataset‘i tanımlayalım. Bunu yapmak için, boyut sınırlarına ulaşana kadar orijinal veri setinden bir buffer metin okuyacağız ve ardından ham metni tokenize edilmiş girdilere dönüştürmek için tokenizer uygulayacağız. İsteğe bağlı olarak, bazı diziler üzerinde FIM dönüşümleri gerçekleştireceğiz (etkilenen dizilerin oranı fim_rate tarafından kontrol edilir).

Tanımlandıktan sonra, hem eğitim hem de doğrulama verilerinden ConstantLengthDataset örnekleri oluşturabiliriz.

from torch.utils.data import IterableDataset
from torch.utils.data.dataloader import DataLoader
import random

# Bir metin dosyası akışından sabit uzunlukta token parçaları döndüren bir Iterable veri seti oluşturur.


class ConstantLengthDataset(IterableDataset):
    """
    Metin dosyalarının akışından sabit uzunlukta token parçaları döndüren yinelenebilir veri seti.
        Argümanlar:
            tokenizer (Tokenizer): Verileri işlemek için kullanılan işleyicidir.
            veri seti (dataset.Dataset): Metin dosyaları içeren veri seti.
            infinite (bool): True ise, veri seti sona ulaştıktan sonra iterator sıfırlanır, aksi takdirde durur.
            seq_length (int): Döndürülecek token sekanslarının uzunluğu.
            num_of_sequences (int): Buffer'da tutulacak token sequence sayısı.
            chars_per_token (int): Metin buffer'ındaki token sayısını tahmin etmek için kullanılan token başına karakter sayısı.
            fim_rate (float): Numunenin FIM ile permüle edileceği oran (0,0 ila 1,0).
            fim_spm_rate (float): SPM kullanacak FIM permütasyonlarının oranı (0.0 ila 1.0).
            seed (int): Rastgele sayı üreteci için seed.
    """

    def __init__(
        self,
        tokenizer,
        dataset,
        infinite=False,
        seq_length=1024,
        num_of_sequences=1024,
        chars_per_token=3.6,
        content_field="content",
        fim_rate=0.5,
        fim_spm_rate=0.5,
        seed=0,
    ):
        self.tokenizer = tokenizer
        self.concat_token_id = tokenizer.eos_token_id
        self.dataset = dataset
        self.seq_length = seq_length
        self.infinite = infinite
        self.current_size = 0
        self.max_buffer_size = seq_length * chars_per_token * num_of_sequences
        self.content_field = content_field
        self.fim_rate = fim_rate
        self.fim_spm_rate = fim_spm_rate
        self.seed = seed

        (
            self.suffix_tok_id,
            self.prefix_tok_id,
            self.middle_tok_id,
            self.pad_tok_id,
        ) = get_fim_token_ids(self.tokenizer)
        if not self.suffix_tok_id and self.fim_rate > 0:
            print("FIM is not supported by tokenizer, disabling FIM")
            self.fim_rate = 0

    def __iter__(self):
        iterator = iter(self.dataset)
        more_examples = True
        np_rng = np.random.RandomState(seed=self.seed)
        while more_examples:
            buffer, buffer_len = [], 0
            while True:
                if buffer_len >= self.max_buffer_size:
                    break
                try:
                    buffer.append(next(iterator)[self.content_field])
                    buffer_len += len(buffer[-1])
                except StopIteration:
                    if self.infinite:
                        iterator = iter(self.dataset)
                    else:
                        more_examples = False
                        break
            tokenized_inputs = self.tokenizer(buffer, truncation=False)["input_ids"]
            all_token_ids = []

            for tokenized_input in tokenized_inputs:
                # opsiyonel FIM permütasyonları
                if self.fim_rate > 0:
                    tokenized_input, np_rng = permute(
                        tokenized_input,
                        np_rng,
                        self.suffix_tok_id,
                        self.prefix_tok_id,
                        self.middle_tok_id,
                        self.pad_tok_id,
                        fim_rate=self.fim_rate,
                        fim_spm_rate=self.fim_spm_rate,
                        truncate_or_pad=False,
                    )

                all_token_ids.extend(tokenized_input + [self.concat_token_id])
            examples = []
            for i in range(0, len(all_token_ids), self.seq_length):
                input_ids = all_token_ids[i : i + self.seq_length]
                if len(input_ids) == self.seq_length:
                    examples.append(input_ids)
            random.shuffle(examples)
            for example in examples:
                self.current_size += 1
                yield {
                    "input_ids": torch.LongTensor(example),
                    "labels": torch.LongTensor(example),
                }


train_dataset = ConstantLengthDataset(
    tokenizer,
    train_data,
    infinite=True,
    seq_length=SEQ_LENGTH,
    chars_per_token=chars_per_token,
    content_field=DATA_COLUMN,
    fim_rate=FIM_RATE,
    fim_spm_rate=FIM_SPM_RATE,
    seed=SEED,
)
eval_dataset = ConstantLengthDataset(
    tokenizer,
    valid_data,
    infinite=False,
    seq_length=SEQ_LENGTH,
    chars_per_token=chars_per_token,
    content_field=DATA_COLUMN,
    fim_rate=FIM_RATE,
    fim_spm_rate=FIM_SPM_RATE,
    seed=SEED,
)

Modelin Hazırlanması

Veriler hazırlandığına göre, şimdi modeli yükleme zamanı! Modelin kuantize edilmiş versiyonunu yükleyeceğiz.

Kuantizasyon verileri daha az bitle temsil ettiğinden bellek kullanımını azaltmamızı sağlar. Modeli kuantize etmek için transformers ile güzel bir entegrasyona sahip bitsandbytes kütüphanesini kullanacağız. Tek yapmamız gereken bir bitsandbytes config tanımlamak ve ardından modeli yüklerken bunu kullanmak.

4 bit kuantizasyonun farklı varyantları vardır, ancak genellikle daha iyi performans için NF4 kuantizasyonu kullanmanızı öneririz (bnb_4bit_quant_type=“nf4”).

bnb_4bit_use_double_quant seçeneği, parametre başına ek 0,4 bit tasarruf etmek için ilkinden sonra ikinci bir kuantizasyon ekler.

Niceleme hakkında daha fazla bilgi edinmek için “Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA” blog post adresine göz atın.

Tanımlandıktan sonra, modelin kuantize edilmiş versiyonunu yüklemek için yapılandırmayı from_pretrained metoduna aktarın.

from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
from peft.tuners.lora import LoraLayer

load_in_8bit = False

# 4-bit kuantize işlemi
compute_dtype = getattr(torch, BNB_4BIT_COMPUTE_DTYPE)

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=compute_dtype,
    bnb_4bit_use_double_quant=USE_NESTED_QUANT,
)

device_map = {"": 0}

model = AutoModelForCausalLM.from_pretrained(
    MODEL,
    load_in_8bit=load_in_8bit,
    quantization_config=bnb_config,
    device_map=device_map,
    use_cache=False,  # Gradient Checkpoint kullanacağız
    trust_remote_code=True,
    use_flash_attention_2=True,
)

Eğitim için kuantize edilmiş bir model kullanırken, modeli ön işleme tabi tutmak amacıyla prepare_model_for_kbit_training() fonksiyonunu çağırmamız gerekiyor.

model = prepare_model_for_kbit_training(model)

Artık kuantize model hazır olduğuna göre, bir LoRA yapılandırması ayarlayabiliriz. LoRA, eğitilebilir parametrelerin sayısını önemli ölçüde azaltarak fine-tune yapmayı daha verimli hale getirir.

LoRA tekniğini kullanarak bir modeli eğitmek için, temel modeli PeftModel olarak çağırmamız gerekir. Bu, LoraConfig ile LoRA yapılandırmasını tanımlamayı ve LoraConfig kullanarak orijinal modeli get_peft_model() ile çağırmayı içerir.

LoRA ve parametreleri hakkında daha fazla bilgi edinmek için PEFT dokümantasyonuna bakabilirsiniz.

>>> # Lora config ayarları
>>> peft_config = LoraConfig(
...     lora_alpha=LORA_ALPHA,
...     lora_dropout=LORA_DROPOUT,
...     r=LORA_R,
...     bias="none",
...     task_type="CAUSAL_LM",
...     target_modules=LORA_TARGET_MODULES.split(","),
... )

>>> model = get_peft_model(model, peft_config)
>>> model.print_trainable_parameters()
trainable params: 5,554,176 || all params: 1,142,761,472 || trainable%: 0.4860310866343243

Gördüğünüz gibi LoRA tekniğini uyguladığımızda artık parametrelerin %1’inden daha azını eğitmemiz gerekecek.

Modelin Eğitilmesi

Artık verileri hazırladığımıza ve modeli optimize ettiğimize göre, eğitimi başlatmak için her şeyi bir araya getirmeye hazırız.

Bir Trainer objesi oluşturmak için, eğitim konfigürasyonu tanımlamamız gerekiyor. En önemlisi, eğitimi yapılandırmak için tüm öznitelikleri içeren bir sınıf olan TrainingArguments‘tır.

Bunlar, çalıştırabileceğiniz diğer tüm model eğitimlerine benziyor, bu nedenle burada ayrıntılara girmeyeceğiz.

train_data.start_iteration = 0


training_args = TrainingArguments(
    output_dir=f"Your_HF_username/{OUTPUT_DIR}",
    dataloader_drop_last=True,
    evaluation_strategy="steps",
    save_strategy="steps",
    max_steps=MAX_STEPS,
    eval_steps=EVAL_FREQ,
    save_steps=SAVE_FREQ,
    logging_steps=LOG_FREQ,
    per_device_train_batch_size=BATCH_SIZE,
    per_device_eval_batch_size=BATCH_SIZE,
    learning_rate=LR,
    lr_scheduler_type=LR_SCHEDULER_TYPE,
    warmup_steps=NUM_WARMUP_STEPS,
    gradient_accumulation_steps=GR_ACC_STEPS,
    gradient_checkpointing=True,
    fp16=FP16,
    bf16=BF16,
    weight_decay=WEIGHT_DECAY,
    push_to_hub=True,
    include_tokens_per_second=True,
)

Son adım olarak Trainer objesini oluşturun ve train metodunu çağırın.

>>> trainer = Trainer(model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset)

>>> print("Training...")
>>> trainer.train()
Training...

Fine-tune edilmiş modelinizi Hugging Face Hub hesabınıza yükleyebilirsiniz.

trainer.push_to_hub()

Inference

Model Hub’a yüklendikten sonra, inference için kullanılabilir. Bunu yapmak için önce orijinal temel modeli ve onun tokenizer’ını başlatırız. Sonra, fine-tune edilmiş ağırlıkları temel modelle birleştirmemiz gerekir.

from peft import PeftModel
import torch

# önce orijinal modeli yükleyin
tokenizer = AutoTokenizer.from_pretrained(MODEL, trust_remote_code=True)
base_model = AutoModelForCausalLM.from_pretrained(
    MODEL,
    quantization_config=None,
    device_map=None,
    trust_remote_code=True,
    torch_dtype=torch.bfloat16,
).cuda()

# fine-tune edilmiş ağırlıkları orijinal model ile birleştirin
peft_model_id = f"Your_HF_username/{OUTPUT_DIR}"
model = PeftModel.from_pretrained(base_model, peft_model_id)
model.merge_and_unload()

Şimdi inference için birleştirilmiş modeli kullanabiliriz. Kolaylık olması açısından, bir get_code_completion tanımlayacağız - metin oluşturma parametreleriyle deneme yapmaktan çekinmeyin :)

def get_code_completion(prefix, suffix):
    text = prompt = f"""<fim_prefix>{prefix}<fim_suffix>{suffix}<fim_middle>"""
    model.eval()
    outputs = model.generate(
        input_ids=tokenizer(text, return_tensors="pt").input_ids.cuda(),
        max_new_tokens=128,
        temperature=0.2,
        top_k=50,
        top_p=0.95,
        do_sample=True,
        repetition_penalty=1.0,
    )
    return tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]

Şimdi, kodun tamamlanmasını sağlamak için yapmamız gereken tek şey get_code_complete fonksiyonunu çağırmak ve tamamlanmasını istediğimiz ilk birkaç satırı önek olarak, boş bir dizeyi de sonek olarak geçirmek.

>>> prefix = """from peft import LoraConfig, TaskType, get_peft_model
... from transformers import AutoModelForCausalLM
... peft_config = LoraConfig(
... """
>>> suffix = """"""

... print(get_code_completion(prefix, suffix))
from peft import LoraConfig, TaskType, get_peft_model
from transformers import AutoModelForCausalLM
peft_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=8,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.1,
    bias="none",
    modules_to_save=["q_proj", "v_proj"],
    inference_mode=False,
)
model = AutoModelForCausalLM.from_pretrained("gpt2")
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()

Bu notebook’ta daha önce PEFT kütüphanesini kullanmış biri olarak, LoraConfig oluşturmak için üretilen sonucun oldukça iyi olduğunu görebilirsiniz!

Modeli inference için başlattığımız hücreye geri dönersek ve fine-tune edilmiş ağırlıkları birleştirdiğimiz satırları yorum satırı yaparsak, orijinal modelin tam olarak aynı önek için ne üreteceğini görebilirsiniz:

>>> prefix = """from peft import LoraConfig, TaskType, get_peft_model
... from transformers import AutoModelForCausalLM
... peft_config = LoraConfig(
... """
>>> suffix = """"""

... print(get_code_completion(prefix, suffix))
from peft import LoraConfig, TaskType, get_peft_model
from transformers import AutoModelForCausalLM
peft_config = LoraConfig(
    model_name_or_path="facebook/wav2vec2-base-960h",
    num_labels=1,
    num_features=1,
    num_hidden_layers=1,
    num_attention_heads=1,
    num_hidden_layers_per_attention_head=1,
    num_attention_heads_per_hidden_layer=1,
    hidden_size=1024,
    hidden_dropout_prob=0.1,
    hidden_act="gelu",
    hidden_act_dropout_prob=0.1,
    hidden

Python syntax’ı olmasına rağmen, orijinal modelin LoraConfig‘in ne yapması gerektiği konusunda hiçbir anlayışının olmadığını görebilirsiniz.

Bu tür fine-tune’ların tam bir fine-tune ile nasıl karşılaştırıldığını ve bu tür bir modeli VS Code’da Inference Endpoints veya yerel olarak co-pilot olarak nasıl kullanacağınızı öğrenmek için “Personal Copilot: Train Your Own Coding Assistant” blog yazısına göz atın. Bu notebook orijinal blog yazısını tamamlar.

< > Update on GitHub