Spaces:
Paused
Paused
| #!/usr/bin/env python | |
| # -*- coding: utf-8 -*- | |
| import os | |
| from huggingface_hub import login | |
| import gradio as gr | |
| #from transformers import pipeline | |
| import torch | |
| from utils import * | |
| from presets import * | |
| from transformers import Trainer, TrainingArguments | |
| import numpy as np | |
| import evaluate | |
| ##################################################### | |
| #Hilfsfunktionen für das training | |
| ##################################################### | |
| #Datensets in den Tokenizer schieben... | |
| def tokenize_function(examples): | |
| return tokenizer(examples["text"]) | |
| #neues Model testen nach dem Training | |
| ######################################################################## | |
| #Zm Test einen Text zu generieren... | |
| def predict(text, | |
| top_p=0.3, | |
| temperature=0.9, | |
| max_length_tokens=1024, | |
| max_context_length_tokens=2048,): | |
| if text=="": | |
| return | |
| try: | |
| model | |
| except: | |
| return print("fehler model") | |
| inputs = generate_prompt_with_history(text,tokenizer,max_length=max_context_length_tokens) | |
| if inputs is None: | |
| return print("Fehler inputs") | |
| else: | |
| prompt,inputs=inputs | |
| begin_length = len(prompt) | |
| input_ids = inputs["input_ids"][:,-max_context_length_tokens:].to(device) | |
| torch.cuda.empty_cache() | |
| #torch.no_grad() bedeutet, dass für die betreffenden tensoren keine Ableitungen berechnet werden bei der backpropagation | |
| #hier soll das NN ja auch nicht geändert werden 8backprop ist nicht nötig), da es um interference-prompts geht! | |
| print("torch.no_grad") | |
| with torch.no_grad(): | |
| ausgabe = "" | |
| #die vergangenen prompts werden alle als Tupel in history abgelegt sortiert nach 'Human' und 'AI'- dass sind daher auch die stop-words, die den jeweils nächsten Eintrag kennzeichnen | |
| for x in greedy_search(input_ids,model,tokenizer,stop_words=["[|Human|]", "[|AI|]"],max_length=max_length_tokens,temperature=temperature,top_p=top_p): | |
| if is_stop_word_or_prefix(x,["[|Human|]", "[|AI|]"]) is False: | |
| if "[|Human|]" in x: | |
| x = x[:x.index("[|Human|]")].strip() | |
| if "[|AI|]" in x: | |
| x = x[:x.index("[|AI|]")].strip() | |
| x = x.strip() | |
| ausgabe = ausgabe + x | |
| # a, b= [[y[0],convert_to_markdown(y[1])] for y in history]+[[text, convert_to_markdown(x)]],history + [[text,x]] | |
| print("Erzeuge") | |
| yield print(Ausgabe) | |
| if shared_state.interrupted: | |
| shared_state.recover() | |
| try: | |
| print("Erfolg") | |
| return ausgabe | |
| except: | |
| pass | |
| del input_ids | |
| gc.collect() | |
| torch.cuda.empty_cache() | |
| try: | |
| print("erfolg") | |
| return ausgabe | |
| except: | |
| pass | |
| ################################################################################### | |
| ################################################################################### | |
| #Access-Token (in Secrets) | |
| #aus den Secrets importieren (siehe Setting zu diesem Space) | |
| login(token=os.environ["HF_ACCESS_TOKEN"]) | |
| #Modelle und Tokenizer | |
| #Alternativ mit beliebigen Modellen: | |
| #base_model = "project-baize/baize-v2-7b" #load_8bit = False (in load_tokenizer_and_model) | |
| #base_model = "TheBloke/airoboros-13B-HF" #load_8bit = False (in load_tokenizer_and_model) | |
| base_model = "EleutherAI/gpt-neo-1.3B" #load_8bit = False (in load_tokenizer_and_model) | |
| #base_model = "TheBloke/airoboros-13B-HF" #load_8bit = True | |
| tokenizer,model,device = load_tokenizer_and_model(base_model, False) | |
| #tokenizer.add_special_tokens({'pad_token': '[PAD]'}) #not necessary with fast Toekenizers like GPT2 | |
| dataset_neu = daten_laden("alexkueck/tis") | |
| #dataset_neu = daten_laden("EleutherAI/pile") | |
| ############################################# | |
| #Vorbereiten für das Training der neuen Daten | |
| ############################################# | |
| #alles zusammen auf das neue datenset anwenden - batched = True und 4 Prozesse, um die Berechnung zu beschleunigen. Die "text" - Spalte braucht man anschließend nicht mehr, daher weglassen. | |
| tokenized_datasets = dataset_neu.map(tokenize_function, batched=True, num_proc=4, remove_columns=["id","text"]) | |
| #wenn man zum Trainieren erstmal nur einen kleinen Datensatz nehem möchte: | |
| #small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000)) | |
| #small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000)) | |
| print (tokenized_datasets["train"][4]) | |
| #den Text nun zusammenführen (concatenieren) und anschließend in kleine Häppchen aufteilen (block_size=128), die verarbeitet werden können | |
| #das macht die map-Funktion und das Attribut batched = True | |
| #man könnte das weglassen, wenn jeder Satz einzeln gegeben wurde in den Texten... | |
| #eigentlich nimmt man als block_size die max. Länge in der das Model trainiert wurde -> könnte aber zu groß sein für den RAm der GPU , daher hier 128 gewählt | |
| # block_size = tokenizer.model_max_length | |
| block_size = 128 | |
| #nochmal die map-Funktion auf das bereits tokenisierte Datenset anwenden | |
| #die bereits tokenisierten Datensatze ändern sich dadurch: die samples enthalten nun Mengen aus block_size Tokens | |
| lm_datasets = tokenized_datasets.map( | |
| group_texts, | |
| batched=True, | |
| batch_size=1000, | |
| num_proc=4, | |
| ) | |
| print ("lm datasets") | |
| #die Daten wurden nun "gereinigt" und für das Model vorbereitet. | |
| #z.B. anschauen mit: tokenizer.decode(lm_datasets["train"][1]["input_ids"]) | |
| #################################################### | |
| #Training | |
| #################################################### | |
| #Training Args | |
| training_args = TrainingArguments( | |
| output_dir="alexkueck/spaces/LIFineTuned/", | |
| overwrite_output_dir = 'True', | |
| evaluation_strategy = "epoch", | |
| learning_rate=2e-5, | |
| weight_decay=0.01, | |
| save_total_limit = 2, | |
| save_strategy = "no", | |
| load_best_model_at_end=False, | |
| #push_to_hub=True, | |
| ) | |
| print ("training args") | |
| ############################################ | |
| #def trainieren_neu(name): | |
| #Trainer zusammenstellen | |
| trainer = Trainer( | |
| model=model, | |
| args=training_args, | |
| train_dataset=lm_datasets["train"], | |
| eval_dataset=lm_datasets["test"], | |
| #tokenizer=tokenizer, | |
| #compute_metrics=compute_metrics, | |
| ) | |
| print ("trainer") | |
| #trainer ausführen | |
| trainer.train() | |
| print("trained!!!!!") | |
| #in den Hub laden | |
| #trainer.push_to_hub("test-tis", use_auth_token=True) | |
| ############################ | |
| #Test | |
| ############################ | |
| print("Test") | |
| text = "Was ist Tis?" | |
| encoding = tokenizer(text, return_tensors="pt") | |
| encoding = {k: v.to(trainer.model.device) for k,v in encoding.items()} | |
| outputs = trainer.model(**encoding) | |
| logits = outputs.logits | |
| print(logits.shape) | |
| print("Save to Space") | |
| trainer.save_model("alexkueck/spaces/LIFineTuned/") | |
| print("done") | |
| ##################################### | |
| #Push to Hub | |
| #print("push to hub") | |
| #login(token=os.environ["HF_ACCESS_TOKEN"]) | |
| #trainer.push_to_hub("alexkueck/model/finetune-tis") | |
| #print("done") | |
| ############################################## | |
| #Testen des fine-tuned Modells | |
| print("Predict") | |
| antwort = predict("Was ist Tis?") | |
| print(antwort) | |
| print("done") | |
| ####################################################################### | |
| #Darstellung mit Gradio | |
| ''' | |
| with gr.Blocks() as demo: | |
| name = gr.Textbox(label="Model") | |
| output = gr.Textbox(label="Output Box") | |
| start_btn = gr.Button("Start") | |
| start_btn.click(fn=trainieren_neu, inputs=name, outputs=output, api_name="trainieren_neu") | |
| demo.queue(default_enabled=True).launch(debug=True) | |
| ''' |