# app.py import gradio as gr import torch from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM import pandas as pd # --- 1. Modelle laden --- # Wir laden die Modelle einmal beim Start der Anwendung, um die Ladezeit bei jeder Anfrage zu vermeiden. # Modell 1: German GPT-2 für Text-Vervollständigung # Wir laden hier Tokenizer und Modell manuell, da wir die Logits für das nächste Wort brauchen, # was die Standard-Pipeline nicht direkt so ausgibt. gpt2_model_name = "dbmdz/german-gpt2" gpt2_tokenizer = AutoTokenizer.from_pretrained(gpt2_model_name) # AutoModelWithLMHead ist veraltet, wir benutzen stattdessen AutoModelForCausalLM gpt2_model = AutoModelForCausalLM.from_pretrained(gpt2_model_name) # Modell 2: BERT für Masken-Füllung # Hier können wir die Pipeline direkt nutzen, da sie genau das tut, was wir wollen. unmasker = pipeline('fill-mask', model='bert-base-multilingual-uncased', top_k=5) # --- 2. Logik-Funktionen für die Modelle --- def predict_next_word(text): """ Diese Funktion nimmt einen Text entgegen, tokenisiert ihn, gibt ihn an das GPT-2 Modell und berechnet die Wahrscheinlichkeitsverteilung für das *unmittelbar* folgende Wort. """ if not text or not text.strip(): return {} # Text in Token-IDs umwandeln inputs = gpt2_tokenizer(text, return_tensors='pt') # Modell-Vorhersage ohne Gradientenberechnung (schneller) with torch.no_grad(): logits = gpt2_model(**inputs).logits # Wir interessieren uns nur für die Logits des letzten Tokens im Input # Shape: [batch_size, sequence_length, vocab_size] -> wir nehmen das letzte Token last_token_logits = logits[0, -1, :] # Wende Softmax an, um Wahrscheinlichkeiten zu erhalten probabilities = torch.nn.functional.softmax(last_token_logits, dim=-1) # Finde die Top 5 wahrscheinlichsten Token-IDs und ihre Wahrscheinlichkeiten top_k_probs, top_k_indices = torch.topk(probabilities, 5) # Konvertiere die Token-IDs zurück in lesbare Tokens (Wörter) top_k_tokens = gpt2_tokenizer.convert_ids_to_tokens(top_k_indices) # Bereinige die Tokens (z.B. 'Ġ' entfernen, das für ein Leerzeichen steht) cleaned_tokens = [token.replace('Ġ', '') for token in top_k_tokens] # Erstelle ein Dictionary für die Ausgabe in Gradio result_dict = {token: prob.item() for token, prob in zip(cleaned_tokens, top_k_probs)} return result_dict def fill_the_mask(text): """ Diese Funktion nutzt die fill-mask Pipeline, um die wahrscheinlichsten Wörter für das [MASK]-Token im Text zu finden. """ # Überprüfen, ob das Masken-Token vorhanden ist mask_token = unmasker.tokenizer.mask_token if mask_token not in text: # Einen Fehler in der Gradio-UI anzeigen raise gr.Error(f"Die Eingabe muss das Masken-Token '{mask_token}' enthalten.") # Pipeline aufrufen predictions = unmasker(text) # Die Ausgabe der Pipeline in ein Dictionary für Gradio umwandeln # Die Pipeline liefert eine Liste von Dictionaries, wir formatieren sie um. result_dict = {pred['token_str']: pred['score'] for pred in predictions} return result_dict # --- 3. Gradio Interface erstellen --- with gr.Blocks(theme=gr.themes.Soft()) as demo: gr.Markdown( """ # Funktionalität von Language Models demonstrieren Diese Anwendung zeigt die Kernfähigkeiten von zwei verschiedenen Arten von Transformer-Modellen: 1. **Causal Language Models (z.B. GPT-2):** Diese Modelle sind darauf trainiert, das nächste Wort in einer Sequenz vorherzusagen. Sie sind ideal für die Textgenerierung. 2. **Masked Language Models (z.B. BERT):** Diese Modelle lernen, fehlende Wörter in einem Satz zu ergänzen. Sie verstehen den Kontext in beide Richtungen (bidirektional) und sind stark in Klassifikations- oder Extraktionsaufgaben. """ ) with gr.Tabs(): # --- Tab 1: Causal LM (GPT-2) --- with gr.TabItem("1. Causal LM (Text-Vervollständigung)"): gr.Markdown( """ ## German GPT-2 (`dbmdz/german-gpt2`) Dieses Modell sagt das wahrscheinlichste *nächste* Wort voraus. ### Anleitung Gib einen deutschen Satzanfang in das Textfeld ein und klicke auf "Nächstes Wort vorhersagen". """ ) with gr.Row(): text_input_gpt = gr.Textbox( label="Dein Satzanfang", placeholder="Tippe hier...", value="Der Sinn des Lebens ist", lines=3 ) predict_button_gpt = gr.Button("Nächstes Wort vorhersagen") gr.Markdown("### Wahrscheinlichste Folgewörter") output_label_gpt = gr.Label(num_top_classes=5) # --- Tab 2: Masked LM (BERT) --- with gr.TabItem("2. Masked LM (Masken-Füllung)"): gr.Markdown( f""" ## Multilingual BERT (`bert-base-multilingual-uncased`) Dieses Modell füllt die Lücke, die durch ein sogenanntes "Masken-Token" (`{unmasker.tokenizer.mask_token}`) markiert ist. ### Anleitung Gib einen Satz mit dem Masken-Token `{unmasker.tokenizer.mask_token}` ein und klicke auf "Maske füllen". """ ) with gr.Row(): text_input_bert = gr.Textbox( label="Satz mit Maske", placeholder="Tippe hier...", value=f"Berlin ist die Hauptstadt von {unmasker.tokenizer.mask_token}.", lines=3 ) fill_mask_button_bert = gr.Button("Maske füllen") gr.Markdown("### Wahrscheinlichste Füllwörter") output_label_bert = gr.Label(num_top_classes=5) # --- 4. Events verknüpfen --- predict_button_gpt.click( fn=predict_next_word, inputs=text_input_gpt, outputs=output_label_gpt, api_name="predict_next_word" ) fill_mask_button_bert.click( fn=fill_the_mask, inputs=text_input_bert, outputs=output_label_bert, api_name="fill_mask" ) # Anwendung starten demo.launch()