Installation und imports¶
!pip install -q torch peft bitsandbytes transformers trl accelerate optimum auto-gptq scipy
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments,
pipeline
)
from peft import LoraConfig
from trl import SFTTrainer
Das Grundmodell vorbereiten¶
In diesem Abschnitt wird das Grundmodell (ein vortrainiertes LLM) heruntergeladen und geladen. Wird ein nicht-quantisiertes Modell geladen, kann dieses für das Training quantisiert in den Speicher geladen werden (auskommentiert).
base_model_name = "TheBloke/leo-hessianai-7B-GPTQ"
revision = "gptq-8bit-32g-actorder_True"
tokenizer = AutoTokenizer.from_pretrained(base_model_name, trust_remote_code=False)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right" # Fix for fp16
# Quantization Config (if needed)
quant_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=False
)
# Das Grundmodell
base_model = AutoModelForCausalLM.from_pretrained(
base_model_name,
revision=revision,
)
base_model.config.use_cache = False
base_model.config.pretraining_tp = 1
Den Prompt erstellen¶
Der Prompt besteht aus 3 Teilen:
- dem System-Prompt, der dem System als Startpunkt gegegeben wird
- dem User-Prompt, der später vom User angegeben wird. Da wir lediglich Zitate von Personen haben wollen, wird auch dieser vorformatiert
- dem Assisstent-Prompt, also der eigentlichen Antwort vom LLM, der im Training aber vorgegeben wird.
Das Format ist durch das Grundmodell vorgegeben und in der jeweiligen Modell-Card auf HuggingFace dokumentiert
prompt_format = "<|im_start|>system\n{system_prompt}<|im_end|>\n\
<|im_start|>user\n{prompt}<|im_end|>\n<\
|im_start|>assistant\n{target}<|im_end|>\n"
system_prompt = """Dies ist eine Unterhaltung zwischen einem\
intelligenten, hilfsbereitem KI-Assistenten und einem Nutzer.
Der Assistent gibt Antworten in Form von Zitaten."""
Die Trainingsdaten vorbereiten¶
In diesem Abschnitt laden wir die Trainingsdaten in den Arbeitsspeicher und bereiten diese für das Training vor.
training_data = load_dataset("caretech-owl/wikiquote-de-quotes", split="train")
# Funktion um den kompletten Prompt vorzubereiten
def change_quote(dataitem):
quote = dataitem["quote"]
author = dataitem["author"]
full_prompt = prompt_format.format(system_prompt=system_prompt,
prompt="Zitiere " + author,
target=quote + " - " + author )
dataitem.update({"instruct": full_prompt})
return dataitem
# Datensatz erweitern
training_data = training_data.map(change_quote)
# Text in Token umwandeln, so kann direkt darauf trainiert werden
training_data = training_data.map(lambda samples: tokenizer(samples["instruct"]),
batched=True).shuffle()
Das Lora Modell¶
Nun definieren wir die LoraConfig.
lora_alpha
scaliert die Gewichtung des LoRA im Vergleich zum Hauptmodelllora_dropout
ist die dropout Wahrscheinlichkeitr
ist die LoRA Dimension
refined_model = "../lora/german_quotes"
peft_parameters = LoraConfig(
lora_alpha=16,
lora_dropout=0.1,
r=8,
bias="none",
task_type="CAUSAL_LM",
)
Training¶
Im folgenden werden Trainingsparameter definiert und das eigentliche Training durchgeführt.
# Training Params
train_params = TrainingArguments(
output_dir="../.checkpoints",
num_train_epochs=1,
per_device_train_batch_size=4,
gradient_accumulation_steps=1,
optim="paged_adamw_32bit",
save_steps=25,
logging_steps=25,
learning_rate=2e-4,
weight_decay=0.001,
fp16=False,
bf16=False,
max_grad_norm=0.3,
max_steps=-1,
warmup_ratio=0.03,
group_by_length=True,
lr_scheduler_type="constant",
no_cuda=True # comment out for GPU
)
# Trainer
fine_tuning = SFTTrainer(
model=base_model,
train_dataset=training_data,
peft_config=peft_parameters,
dataset_text_field="instruct",
tokenizer=tokenizer,
args=train_params,
max_seq_length=300
)
# Training (this could take some time)
fine_tuning.train()
# Save Model
fine_tuning.model.save_pretrained(refined_model)
Das Modell testen¶
Ohne neu zu laden...
text_gen = pipeline(task="text-generation", model=fine_tuning.model,
tokenizer=llama_tokenizer, max_length=200)
query = prompt_format.format(system_prompt=system_prompt,
prompt="Zitiere Oscar Wilde")
output = text_gen(query,do_sample=True, top_p=0.95, max_length=200)
print(output[0]['generated_text'])
Das Modell Speichern, quantisieren und veröffentlichen¶
merged_model = peft_model.merge_and_unload()
merged_model.save_pretrained("german_quotes_lora_merged_full")
Das gespeicherte Modell lässt sich nun mit Hilfe der Projekts llama.cpp quantisieren. Dazu
git clone https://github.com/ggerganov/llama.cpp
pip install huggingface_hub gguf sentencepiece
cd llama.cpp
llama.cpp/convert.py german_quotes_lora_merged_full \
--outfile german_quotes_lora_merged_full.gguf --outtype q8_0
huggingface-cli login
Beim letzten Befehl einen Token eingeben, den man hier erstellt: https://huggingface.co/settings/tokens Jetzt muss das Modell nur noch hochgeladen werden!
from huggingface_hub import HfApi
api = HfApi()
model_id = "caretech-owl/leo-hessionai-7B-quotes-gguf"
api.create_repo(model_id, exist_ok=True, repo_type="model")
api.upload_file(
repo_id=model_id,
path_or_fileobj="german_quotes_lora_merged_full.gguf",
path_in_repo="leo-hessionai-7B-quotes.Q8.gguf"
)