{"id":647800,"date":"2025-10-15T05:30:14","date_gmt":"2025-10-15T04:30:14","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=pycharm&#038;p=647800"},"modified":"2025-10-15T05:30:23","modified_gmt":"2025-10-15T04:30:23","slug":"feintuning-und-bereitstellung-von-gpt-modellen-mit-transformers-von-hugging-face","status":"publish","type":"pycharm","link":"https:\/\/blog.jetbrains.com\/de\/pycharm\/2025\/10\/feintuning-und-bereitstellung-von-gpt-modellen-mit-transformers-von-hugging-face\/","title":{"rendered":"Feintuning und Bereitstellung von GPT-Modellen mit Transformers von Hugging Face"},"content":{"rendered":"<p>F\u00fcr Forschende und Interessierte im Bereich des maschinellen Lernens ist Hugging Face mittlerweile zu einem Alltagsbegriff geworden. Zu den gr\u00f6\u00dften Erfolgen von Hugging Face z\u00e4hlt <a href=\"https:\/\/huggingface.co\/docs\/transformers\/en\/index\" target=\"_blank\" rel=\"noopener\">Transformers<\/a>, ein Modelldefinitions-Framework f\u00fcr ML-Modelle in den Bereichen Text, Computer Vision, Audio und Video. Aufgrund der umfangreichen Sammlung modernster Machine-Learning-Modelle, die im <a href=\"https:\/\/huggingface.co\/models\" target=\"_blank\" rel=\"noopener\">Hugging Face Hub<\/a> verf\u00fcgbar sind, und der Kompatibilit\u00e4t mit den meisten Trainingsframeworks wird Transformers h\u00e4ufig f\u00fcr Inferenz und Modelltraining eingesetzt.<\/p>\n<h2 class=\"wp-block-heading\">Warum ben\u00f6tigen KI-Modelle ein Feintuning?<\/h2>\n<p>Das Feintuning von KI-Modellen ist entscheidend, um ihre Leistung an bestimmte Aufgaben und Datensammlungen anzupassen. Dadurch k\u00f6nnen sie im Vergleich zu universellen Modellen eine h\u00f6here Genauigkeit und Effizienz erzielen. Durch das Feintuning eines vortrainierten Modells muss das Training nicht von Grund auf neu erfolgen, sodass Zeit und Ressourcen gespart werden. Dar\u00fcber hinaus k\u00f6nnen spezifische Formate, Nuancen und Sonderf\u00e4lle innerhalb eines bestimmten Bereichs besser gehandhabt werden, was zuverl\u00e4ssigere und besser angepasste Ergebnisse erm\u00f6glicht.<\/p>\n<p>In diesem Blogartikel werden wir ein GPT-Modell f\u00fcr mathematisches Denken optimieren, damit es mathematische Fragen besser beantworten kann.<\/p>\n<h2 class=\"wp-block-heading\">Verwendung von Hugging-Face-Modellen<\/h2>\n<p>In PyCharm k\u00f6nnen wir unkompliziert alle auf Hugging Face bereitgestellten Modelle durchsuchen und hinzuf\u00fcgen. W\u00e4hlen Sie in einer neuen Python-Datei aus dem Men\u00fc <em>Code<\/em> in der oberen Men\u00fcleiste die Option <em>Insert HF Model<\/em>.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594074\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-40.png\" alt=\"Verwendung von Hugging-Face-Modellen\" width=\"946\" height=\"1070\" \/><\/figure>\n<p>Im angezeigten Men\u00fc k\u00f6nnen Sie die Modelle nach Kategorien durchsuchen oder in die Suchleiste oben einen Suchtext eingeben. Wenn Sie ein Modell ausw\u00e4hlen, wird dessen Beschreibung auf der rechten Seite angezeigt.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594085\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-41.png\" alt=\"Hugging-Face-Modelle durchsuchen\" width=\"1600\" height=\"923\" \/><\/figure>\n<p>Wenn Sie auf <em>Use Model<\/em> klicken, wird ein Codeabschnitt in Ihre Datei eingef\u00fcgt. Das war\u2019s \u2013 Sie k\u00f6nnen nun Ihr Hugging-Face-Modell verwenden.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594096\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-42.png\" alt=\"Hugging-Face-Modelle in PyCharm verwenden\" width=\"1600\" height=\"312\" \/><\/figure>\n<h2 class=\"wp-block-heading\">GPT-Modelle (Generative Pre-Trained Transformer)<\/h2>\n<p>GPT-Modelle sind im <a href=\"https:\/\/huggingface.co\/models\" target=\"_blank\" rel=\"noopener\">Hugging Face Hub<\/a> sehr popul\u00e4r \u2013 aber was sind sie eigentlich? GPTs sind trainierte Modelle, die nat\u00fcrliche Sprache verstehen und qualitativ hochwertige Texte generieren. Sie werden haupts\u00e4chlich f\u00fcr Aufgaben im Bereich der textuellen Inferenz, der Beantwortung von Fragen, der semantischen \u00c4hnlichkeit und der Dokumentklassifizierung eingesetzt. Das bekannteste Beispiel ist das <a href=\"https:\/\/openai.com\/index\/chatgpt\/\" target=\"_blank\" rel=\"noopener\">von OpenAI entwickelte ChatGPT<\/a>.<\/p>\n<p>Im <a href=\"https:\/\/huggingface.co\/models\" target=\"_blank\" rel=\"noopener\">Hugging Face Hub<\/a> sind zahlreiche OpenAI-GPT-Modelle verf\u00fcgbar. Wir werden sehen, wie wir diese Modelle mit Transformers verwenden, mit unseren eigenen Daten optimieren und in eine Anwendung integrieren k\u00f6nnen.<\/p>\n<h2 class=\"wp-block-heading\">Vorteile von Transformers<\/h2>\n<p>Transformers stellt in Verbindung mit anderen von Hugging Face bereitgestellten Tools hochentwickelte Instrumente f\u00fcr das Feintuning komplexer Deep-Learning-Modelle bereit. Sie m\u00fcssen nicht die Architektur und die Tokenisierungsmethode jedes einzelnen Modells bis ins Detail verstehen, denn diese Tools erm\u00f6glichen die Plug-and-Play-Nutzung von Modellen mit beliebigen kompatiblen Trainingsdaten und bieten dabei umfangreiche Anpassungsm\u00f6glichkeiten f\u00fcr Tokenisierung und Training.<\/p>\n<h2 class=\"wp-block-heading\">Transformers im Einsatz<\/h2>\n<p>Um einen genaueren Einblick in die Funktionsweise von Transformers zu erhalten, sehen wir uns an, wie wir es f\u00fcr die Interaktion mit einem GPT-Modell verwenden k\u00f6nnen.<\/p>\n<h3 class=\"wp-block-heading\">Inferenz unter Verwendung eines vortrainierten Modells in einer Pipeline<\/h3>\n<p>Nachdem wir das OpenAI-GPT-2-Modell ausgew\u00e4hlt und hinzugef\u00fcgt haben, sieht unser Code wie folgt aus:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from transformers import pipeline\n\n\npipe = pipeline(\"text-generation\", model=\"openai-community\/gpt2\")<\/pre>\n<p>Um das Modell verwenden zu k\u00f6nnen, m\u00fcssen wir einige Vorbereitungen treffen. Zun\u00e4chst m\u00fcssen wir ein Machine-Learning-Framework installieren. In diesem Beispiel verwenden wir <a href=\"https:\/\/pytorch.org\/get-started\/locally\/\" target=\"_blank\" rel=\"noopener\">PyTorch<\/a>. Sie k\u00f6nnen es unkompliziert im PyCharm-Fenster <em>Python Packages<\/em> installieren.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594107\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-43.png\" alt=\"PyTorch in PyCharm installieren\" width=\"920\" height=\"654\" \/><\/figure>\n<p>Anschlie\u00dfend m\u00fcssen wir Transformers mithilfe der Option `torch` installieren. Sie k\u00f6nnen dies im Terminal erledigen, das Sie mit der Schaltfl\u00e4che auf der linken Seite oder mit der Tastenkombination <em>\u2325 F12 <\/em>(macOS) bzw. <em>Alt + F12<\/em> (Windows) \u00f6ffnen k\u00f6nnen.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594118\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-44.png\" alt=\"Transformers im PyCharm-Terminal installieren\" width=\"838\" height=\"502\" \/><\/figure>\n<p>Da wir uv verwenden, nutzen wir im Terminal die folgenden Befehle, um das Paket als Abh\u00e4ngigkeit hinzuzuf\u00fcgen und zu installieren:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">uv add \u201ctransformers[torch]\u201d\nuv sync<\/pre>\n<p>Wenn Sie pip verwenden:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pip install \u201ctransformers[torch]\u201d<\/pre>\n<p>Au\u00dferdem installieren wir einige weitere Bibliotheken, die wir sp\u00e4ter ben\u00f6tigen werden, darunter python-dotenv, datasets<em>, <\/em>notebook und ipywidgets<em>. <\/em>Sie k\u00f6nnen eine der oben genannten Methoden verwenden, um sie zu installieren.<br \/>Anschlie\u00dfend empfiehlt es sich, ein GPU-System hinzuzuf\u00fcgen, um das Modell zu beschleunigen. Je nachdem, wie Ihr System ausgestattet ist, k\u00f6nnen Sie den Device-Parameter der Pipeline anpassen<em>. <\/em>Da ich ein Mac-M2-System verwende, kann ich wie folgt <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">device=\"mps\"<\/code> einstellen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pipe = pipeline(\"text-generation\", model=\"openai-community\/gpt2\", device=\"mps\")<\/pre>\n<p>Wenn Sie CUDA-GPUs haben, k\u00f6nnen Sie auch <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">device=\"cuda\"<\/code> verwenden.<\/p>\n<p>Nachdem wir unsere Pipeline eingerichtet haben, testen wir sie mit einem einfachen Prompt:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from transformers import pipeline\n\n\npipe = pipeline(\"text-generation\", model=\"openai-community\/gpt2\", device=\"mps\")\n\n\nprint(pipe(\"A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?\", max_new_tokens=200))<\/pre>\n<p>F\u00fchren Sie das Skript mit der <em>Run<\/em>-Schaltfl\u00e4che (<img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/AD_4nXf6ZDm7vSGyFlO0DzXegK6WP9JxsStUiJA-bkRZ0mwPsUsmn8M70emV5Sr8f17-fEK6z9V1EQKWEm3RPHdT8n8uqG18faVmQn5y09psVInQLU0CZQKXAEg2q7m7AOsh4hPU7G8gcQ.png\" width=\"30\" height=\"23\" \/>) am oberen Rand aus:<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594129\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-45.png\" alt=\"Skript in PyCharm ausf\u00fchren\" width=\"1050\" height=\"282\" \/><\/figure>\n<p>Das Ergebnis wird in etwa so aussehen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[{'generated_text': 'A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?nnA rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width?nnA rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width?nnA rectangle has a perimeter of 20 cm. If the width is 6 cm, what is the width? A rectangle has a perimeter'}]<\/pre>\n<p>Von Nachdenken ist hier nicht viel zu sehen \u2013 das ist nur ein Haufen Unsinn.<\/p>\n<p>M\u00f6glicherweise wird auch folgende Warnung angezeigt:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Setting `pad_token_id` to `eos_token_id`:50256 for open-end generation.<\/pre>\n<p>Dies ist die Standardeinstellung. Sie k\u00f6nnen auch wie unten gezeigt eine manuelle Einstellung vornehmen, damit diese Warnung verschwindet, aber wir m\u00fcssen uns zu diesem Zeitpunkt nicht allzu viele Gedanken dar\u00fcber machen.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">print(pipe(\"A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?\", max_new_tokens=200, pad_token_id=pipe.tokenizer.eos_token_id))<\/pre>\n<p>Nachdem wir nun gesehen haben, wie sich GPT-2 standardm\u00e4\u00dfig verh\u00e4lt, wollen wir versuchen, seine mathematischen F\u00e4higkeiten durch etwas Feintuning zu verbessern.<\/p>\n<h3 class=\"wp-block-heading\">Eine Datensammlung vom Hugging Face Hub laden und vorbereiten<\/h3>\n<p>Bevor wir mit der Arbeit am GPT-Modell beginnen, ben\u00f6tigen wir zun\u00e4chst Trainingsdaten. Sehen wir uns an, wie wir eine Datensammlung vom Hugging Face Hub beziehen k\u00f6nnen.<\/p>\n<p>Falls Sie dies noch nicht getan haben, erstellen Sie einen Hugging-Face-Account und lassen Sie sich <a href=\"https:\/\/huggingface.co\/docs\/hub\/security-tokens#user-access-tokens\" target=\"_blank\" rel=\"noopener\">einen Zugangstoken ausstellen<\/a>. F\u00fcrs Erste ben\u00f6tigen wir nur einen `read`-Token. Speichern Sie Ihren Token in einer `.env`-Datei:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">HF_TOKEN=your-hugging-face-access-token<\/pre>\n<p>Wir werden dieses <a href=\"https:\/\/huggingface.co\/datasets\/Cheukting\/math-meta-reasoning-cleaned\" target=\"_blank\" rel=\"noopener\">Math Reasoning Dataset<\/a> verwenden, dessen Beschreibung auf mathematisches Denken hinweist. Wir werden unser GPT-Modell mit dieser Datensammlung optimieren, damit es mathematische Probleme effektiver l\u00f6sen kann.<\/p>\n<p>Wir erstellen f\u00fcr das Feintuning ein neues Jupyter-Notebook, da wir so verschiedene Codeabschnitte nacheinander ausf\u00fchren und dabei den Fortschritt \u00fcberwachen k\u00f6nnen.<\/p>\n<p>In der ersten Zelle laden wir mit diesem Skript die Datensammlung vom Hugging Face Hub:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from datasets import load_dataset\nfrom dotenv import load_dotenv\nimport os\n\n\nload_dotenv()\ndataset = load_dataset(\"Cheukting\/math-meta-reasoning-cleaned\", token=os.getenv(\"HF_TOKEN\"))\ndataset<\/pre>\n<p>F\u00fchren Sie diese Zelle aus, um die Datensammlung herunterzuladen (dies kann je nach Ihrer Internetgeschwindigkeit eine Weile dauern). Im Anschluss k\u00f6nnen wir uns das Ergebnis ansehen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DatasetDict({\n    train: Dataset({\n        features: ['id', 'text', 'token_count'],\n        num_rows: 987485\n    })\n})\n<\/pre>\n<p>Wenn Sie neugierig sind und einen Blick in die Daten werfen m\u00f6chten, k\u00f6nnen Sie dies in PyCharm tun. \u00d6ffnen Sie das Fenster <em>Jupyter Variables<\/em> mit der Schaltfl\u00e4che auf der rechten Seite:<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594140\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-46.png\" alt=\"Fenster Jupyter Variables in PyCharm \u00f6ffnen\" width=\"1052\" height=\"740\" \/><\/figure>\n<p>Wenn Sie <em>dataset<\/em> erweitern, sehen Sie neben <em>dataset[&#8216;train&#8217;]<\/em> die Option <em>View as Dataframe<\/em>:<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594152\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-47.png\" alt=\"Das Fenster Jupyter Variables in PyCharm\" width=\"980\" height=\"882\" \/><\/figure>\n<p>Klicken Sie darauf, um die Daten im Toolfenster <em>Data View<\/em> anzuzeigen:<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594163\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-48.png\" alt=\"Toolfenster Data View in PyCharm\" width=\"980\" height=\"1102\" \/><\/figure>\n<p>Als N\u00e4chstes tokenisieren wir den Text in der Datensammlung:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from transformers import GPT2Tokenizer\n\n\ntokenizer = GPT2Tokenizer.from_pretrained(\"openai-community\/gpt2\")\ntokenizer.pad_token = tokenizer.eos_token\n\n\ndef tokenize_function(examples):\n   return tokenizer(examples['text'], truncation=True, padding='max_length', max_length=512)\n\n\ntokenized_datasets = dataset.map(tokenize_function, batched=True)<\/pre>\n<p>Wir verwenden den GPT-2-Tokenizer und setzen <code>pad_token<\/code> auf <code>eos_token<\/code>, also den Token, der das Zeilenende anzeigt. Anschlie\u00dfend zerlegen wir mit einer Funktion den Text in Token. Beim ersten Mal kann die Ausf\u00fchrung einige Zeit in Anspruch nehmen, die Zelle wird jedoch in einem Cache gespeichert, sodass ein erneutes Ausf\u00fchren schneller erfolgt.<\/p>\n<p>Die Datensammlung umfasst knapp eine Million Zeilen, die f\u00fcr das Training verwendet werden k\u00f6nnen. Wenn Sie \u00fcber ausreichende Rechenleistung f\u00fcr die Verarbeitung verf\u00fcgen, k\u00f6nnen Sie alle verwenden. In dieser Demo f\u00fchren wir das Training allerdings lokal auf einem Laptop aus, daher tun wir gut daran, nur einen kleinen Teil zu verwenden!<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">tokenized_datasets_split = tokenized_datasets[\"train\"].shard(num_shards=100, index=0).train_test_split(test_size=0.2, shuffle=True)\ntokenized_datasets_split<\/pre>\n<p>Hier nehme ich nur 1% der Daten und f\u00fchre dann <code>train_test_split<\/code> aus, um die Datensammlung in zwei Teile zu unterteilen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DatasetDict({\n    train: Dataset({\n        features: ['id', 'text', 'token_count', 'input_ids', 'attention_mask'],\n        num_rows: 7900\n    })\n    test: Dataset({\n        features: ['id', 'text', 'token_count', 'input_ids', 'attention_mask'],\n        num_rows: 1975\n    })\n})\n<\/pre>\n<p>Nun sind wir bereit f\u00fcr das Feintuning des GPT-2-Modells.<\/p>\n<h3 class=\"wp-block-heading\">Feintuning eines GPT-Modells<\/h3>\n<p>In der n\u00e4chsten leeren Zelle tragen wir unsere Argumente f\u00fcr das Training ein:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from transformers import TrainingArguments\ntraining_args = TrainingArguments(\n   output_dir='.\/results',\n   num_train_epochs=5,\n   per_device_train_batch_size=8,\n   per_device_eval_batch_size=8,\n   warmup_steps=100,\n   weight_decay=0.01,\n   save_steps = 500,\n   logging_steps=100,\n   dataloader_pin_memory=False\n)<\/pre>\n<p>Die meisten davon sind weitgehend Standard f\u00fcr das Feintuning eines Modells. Je nach Ihrem Computersystem sollten Sie jedoch eventuell einige Einstellungen anpassen:<\/p>\n<ul>\n<li>Batchgr\u00f6\u00dfe \u2013 Es ist wichtig, die optimale Batchgr\u00f6\u00dfe zu finden, denn das Training erfolgt umso schneller, je gr\u00f6\u00dfer die Batches sind. Allerdings steht Ihrer CPU oder GPU nicht unendlich viel Arbeitsspeicher zur Verf\u00fcgung, sodass es hier m\u00f6glicherweise eine Obergrenze gibt.<\/li>\n<li>Epochen \u2013 Mehr Epochen verl\u00e4ngern die Trainingsdauer. Sie k\u00f6nnen selbst entscheiden, wie viele Epochen Sie ben\u00f6tigen.<\/li>\n<li>Speicherschritte \u2013 Die Speicherschritte bestimmen, wie oft ein Verlaufspunkt auf der Festplatte gespeichert wird. Wenn der Trainingsprozess langsam verl\u00e4uft und mit unerwarteten Unterbrechungen zu rechnen ist, sollten Sie eventuell h\u00e4ufiger speichern (und dazu diesen Wert niedriger einstellen).<\/li>\n<\/ul>\n<p>Nachdem wir unsere Einstellungen konfiguriert haben, stellen wir in der n\u00e4chsten Zelle den Trainer zusammen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from transformers import Trainer, DataCollatorForLanguageModeling\n\n\nmodel = GPT2LMHeadModel.from_pretrained(\"openai-community\/gpt2\")\ndata_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)\n\n\ntrainer = Trainer(\n   model=model,\n   args=training_args,\n   train_dataset=tokenized_datasets_split['train'],\n   eval_dataset=tokenized_datasets_split['test'],\n   data_collator=data_collator,\n)\n\n\ntrainer.train(resume_from_checkpoint=False)<\/pre>\n<p>Wir haben `resume_from_checkpoint=False` eingestellt, Sie k\u00f6nnen es jedoch auf `True` setzen, um das Training nach einer Unterbrechung vom letzten Verlaufspunkt aus fortzusetzen.<\/p>\n<p>Nach Abschluss des Trainings testen und speichern wir das Modell:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">trainer.evaluate(tokenized_datasets_split['test'])\ntrainer.save_model(\".\/trained_model\")<\/pre>\n<p>Wir k\u00f6nnen nun das trainierte Modell in der Pipeline einsetzen. Kehren wir nun zu `model.py` zur\u00fcck, wo wir eine Pipeline mit einem vortrainierten Modell verwendet haben:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from transformers import pipeline\n\n\npipe = pipeline(\"text-generation\", model=\"openai-community\/gpt2\", device=\"mps\")\n\n\nprint(pipe(\"A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?\", max_new_tokens=200, pad_token_id=pipe.tokenizer.eos_token_id))<\/pre>\n<p>Wir \u00e4ndern `model=&#8221;openai-community\/gpt2&#8243;` in `model=&#8221;.\/trained_model&#8221;` und sehen uns das Ergebnis an:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[{'generated_text': \"A rectangle has a perimeter of 20 cm. If the length is 6 cm, what is the width?nAlright, let me try to solve this problem as a student, and I'll let my thinking naturally fall into the common pitfall as described.nn---nn**Step 1: Attempting the Problem (falling into the pitfall)**nnWe have a rectangle with perimeter 20 cm. The length is 6 cm. We want the width.nnFirst, I need to find the area under the rectangle.nnLet\u2019s set ( A = 20 - 12 ), where ( A ) is the perimeter.nn**Area under a rectangle:**  n[nA = (20-12)^2 + ((-12)^2)^2 = 20^2 + 12^2 = 24n]nnSo, ( 24 = (20-12)^2 = 27 ).nnNow, I\u2019ll just divide both sides by 6 to find the area under the rectangle.n\"}]<\/pre>\n<p>Das Problem ist leider immer noch nicht gel\u00f6st. Das Modell verwendete jedoch einige mathematische Formeln und \u00dcberlegungen, auf die es zuvor nicht gekommen war. Wenn Sie m\u00f6chten, k\u00f6nnen Sie versuchen, das Modell mit den bisher nicht verwendeten Daten weiter zu optimieren.<\/p>\n<p>Im n\u00e4chsten Abschnitt werden wir uns ansehen, wie wir ein feingetuntes Modell mithilfe der von Hugging Face und FastAPI bereitgestellten Tools an API-Endpunkten bereitstellen k\u00f6nnen.<\/p>\n<h2 class=\"wp-block-heading\">Ein feingetuntes Modell bereitstellen<\/h2>\n<p>Die Verwendung von FastAPI stellt die einfachste Methode dar, um ein Modell in einem Server-Backend bereitzustellen. In einem anderen <a href=\"https:\/\/blog.jetbrains.com\/pycharm\/2024\/09\/how-to-use-fastapi-for-machine-learning\/\">Blogartikel<\/a> habe ich bereits das Deployment eines Machine-Learning-Modells mit FastAPI beschrieben. Auch wenn wir hier nicht genauso detailliert vorgehen, werden wir sehen k\u00f6nnen, wie unser feingetuntes Modell bereitgestellt werden kann.<\/p>\n<p>Mit der Unterst\u00fctzung von <a href=\"https:\/\/www.jetbrains.com\/de-de\/junie\/\" target=\"_blank\" rel=\"noopener\">Junie<\/a> haben wir einige Skripte erstellt, die Sie <a href=\"https:\/\/github.com\/Cheukting\/fine-tune-gpt2\/tree\/main\/app\" target=\"_blank\" rel=\"noopener\">hier<\/a> einsehen k\u00f6nnen. Mit diesen Skripten k\u00f6nnen wir ein Server-Backend mit FastAPI-Endpunkten bereitstellen.<\/p>\n<p>Es gibt einige neue Abh\u00e4ngigkeiten, die wir hinzuf\u00fcgen m\u00fcssen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">uv add fastapi pydantic uvicorn\nuv sync<\/pre>\n<p>Sehen wir uns nun einige interessante Stellen in den Skripten an. In `main.py`:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Initialize FastAPI app\napp = FastAPI(\n   title=\"Text Generation API\",\n   description=\"API for generating text using a fine-tuned model\",\n   version=\"1.0.0\"\n)\n\n\n# Initialize the model pipeline\ntry:\n   pipe = pipeline(\"text-generation\", model=\"..\/trained_model\", device=\"mps\")\nexcept Exception as e:\n   # Fallback to CPU if MPS is not available\n   try:\n       pipe = pipeline(\"text-generation\", model=\"..\/trained_model\", device=\"cpu\")\n   except Exception as e:\n       print(f\"Error loading model: {e}\")\n       pipe = None<\/pre>\n<p>Nach der Initialisierung der App versucht das Skript, das Modell in eine Pipeline zu laden. Wenn keine Metal-GPU verf\u00fcgbar ist, wird die CPU verwendet. Wenn Sie eine CUDA-GPU statt einer Metal-GPU verwenden, k\u00f6nnen Sie `mps` in `cuda` \u00e4ndern.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Request model\nclass TextGenerationRequest(BaseModel):\n   prompt: str\n   max_new_tokens: int = 200\n  \n# Response model\nclass TextGenerationResponse(BaseModel):\n   generated_text: str<\/pre>\n<p>Es werden zwei neue Klassen erstellt, die vom Pydantic-`BaseModel`<em> abgeleitet sind.<\/em><\/p>\n<p>Wir k\u00f6nnen unsere Endpunkte im <em>Endpoints<\/em>-Toolfenster<em> untersuchen. <\/em>Klicken Sie auf den Globus neben `app = FastAPI` in Zeile 11 und w\u00e4hlen Sie <em>Show All Endpoints<\/em>.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594174\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-49.png\" alt=\"Alle Endpunkte in PyCharm anzeigen\" width=\"1600\" height=\"833\" \/><\/figure>\n<p>Wir haben drei Endpunkte. Da der Basis-Endpunkt lediglich eine Begr\u00fc\u00dfungsnachricht zur\u00fcckgibt, sehen wir uns die beiden anderen an.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@app.post(\"\/generate\", response_model=TextGenerationResponse)\nasync def generate_text(request: TextGenerationRequest):\n   \"\"\"\n   Generate text based on the provided prompt.\n  \n   Args:\n       request: TextGenerationRequest containing the prompt and generation parameters\n      \n   Returns:\n       TextGenerationResponse with the generated text\n   \"\"\"\n   if pipe is None:\n       raise HTTPException(status_code=500, detail=\"Model not loaded properly\")\n  \n   try:\n       result = pipe(\n           request.prompt,\n           max_new_tokens=request.max_new_tokens,\n           pad_token_id=pipe.tokenizer.eos_token_id\n       )\n      \n       # Extract the generated text from the result\n       generated_text = result[0]['generated_text']\n      \n       return TextGenerationResponse(generated_text=generated_text)\n   except Exception as e:\n       raise HTTPException(status_code=500, detail=f\"Error generating text: {str(e)}\")\n<\/pre>\n<p>Der Endpunkt `\/generate` nimmt den Prompt entgegen und l\u00e4sst das Modell einen Antworttext generieren.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@app.get(\"\/health\")\nasync def health_check():\n   \"\"\"Check if the API and model are working properly.\"\"\"\n   if pipe is None:\n       raise HTTPException(status_code=500, detail=\"Model not loaded\")\n   return {\"status\": \"healthy\", \"model_loaded\": True}<\/pre>\n<p>Der Endpunkt `\/health` pr\u00fcft, ob das Modell korrekt geladen ist. Dies kann n\u00fctzlich sein, wenn die Clientanwendung eine Pr\u00fcfung durchf\u00fchren soll, bevor der andere Endpunkt in der Bedienoberfl\u00e4che bereitgestellt wird.<\/p>\n<p>In `run.py` f\u00fchren wir mit <a href=\"https:\/\/www.uvicorn.org\/\" target=\"_blank\" rel=\"noopener\">uvicorn<\/a> den Server aus:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import uvicorn\n\n\nif __name__ == \"__main__\":\n   uvicorn.run(\"main:app\", host=\"0.0.0.0\", port=8000, reload=True)<\/pre>\n<p>Wenn wir dieses Skript ausf\u00fchren, wird der Server unter <a href=\"http:\/\/0.0.0.0:8000\/\" target=\"_blank\" rel=\"noopener\">http:\/\/0.0.0.0:8000\/<\/a> gestartet.<\/p>\n<p>Nachdem wir den Server gestartet haben, k\u00f6nnen wir zu <a href=\"http:\/\/0.0.0.0:8000\/docs\" target=\"_blank\" rel=\"noopener\">http:\/\/0.0.0.0:8000\/docs<\/a> navigieren, um die Endpunkte zu testen.<\/p>\n<h2 class=\"wp-block-heading\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/AD_4nXf6PXwz_Vz7VEQoyZs20NJ9TsO36oWJPf0w4iMjwHZ_EBP1Pk9c_8aWR2ybGE-wsmArM1zAQl1s8jHEr09I0g1A3boGD1Kt4i4CemufHZTHnATjIWrJ8x2ZUYg4Q7E4b3tc2XDmmg.png\" width=\"624\" height=\"269\" \/><\/h2>\n<p>Wir probieren einmal den Endpunkt `\/generate` aus:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n  \"prompt\": \"5 people give each other a present. How many presents are given altogether?\",\n  \"max_new_tokens\": 300\n}<\/pre>\n<p>Dies ist die Antwort, die wir erhalten:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n  \"generated_text\": \"5 people give each other a present. How many presents are given altogether?nAlright, let's try to solve the problem:nn**Problem**  n1. Each person gives each other a present. How many presents are given altogether?n2. How many \"gift\" are given altogether?nn**Common pitfall**  nAssuming that each present is a \"gift\" without considering the implications of the original condition.nn---nn### Step 1: Attempting the problem (falling into the pitfall)nnOkay, so I have two people giving each other a present, and I want to know how many are present. I remember that there are three types of gifts\u2014gifts, gins, and ginses.nnLet me try to count how many of these:nn- Gifts: Let\u2019s say there are three people giving each other a present.n- Gins: Let\u2019s say there are three people giving each other a present.n- Ginses: Let\u2019s say there are three people giving each other a present.nnSo, total gins and ginses would be:nn- Gins: ( 2 times 3 = 1 ), ( 2 times 1 = 2 ), ( 1 times 1 = 1 ), ( 1 times 2 = 2 ), so ( 2 times 3 = 4 ).n- Ginses: ( 2 times 3 = 6 ), (\"\n}\n<\/pre>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" class=\"wp-image-594185\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/08\/image-50.png\" alt=\"\" width=\"1600\" height=\"873\" \/><\/figure>\n<p>Sie k\u00f6nnen gerne auch mit anderen Prompts experimentieren.<\/p>\n<h2 class=\"wp-block-heading\">Fazit und n\u00e4chste Schritte<\/h2>\n<p>Nachdem Sie erfolgreich das LLM-Modell GPT-2 mit einer Datensammlung f\u00fcr mathematisches Denken optimiert und mit FastAPI bereitgestellt haben, k\u00f6nnen Sie nun viele weitere im Hugging Face Hub verf\u00fcgbaren Open-Source-LLMs feintunen. Beim Experimentieren mit dem Feintuning anderer LLM-Modelle k\u00f6nnen Sie entweder die dort bereitgestellten quelloffenen Daten oder aber Ihre eigenen Datensammlungen verwenden. Wenn Sie m\u00f6chten (und wenn die Lizenz des Originalmodells es erlaubt), k\u00f6nnen Sie Ihr optimiertes Modell auch in den Hugging Face Hub hochladen. Die dazugeh\u00f6rige <a href=\"https:\/\/huggingface.co\/docs\/transformers\/v4.53.3\/en\/main_classes\/trainer#transformers.Trainer.push_to_hub\" target=\"_blank\" rel=\"noopener\">Dokumentation<\/a> erkl\u00e4rt, wie Sie dabei vorgehen m\u00fcssen.<\/p>\n<p>Eine letzte Anmerkung zur Verwendung oder Optimierung von Modellen mit Ressourcen aus dem Hugging Face Hub: Bitte lesen Sie die Lizenzen aller verwendeten Modelle und Datensammlungen sorgf\u00e4ltig durch, um die Bedingungen zu verstehen, die f\u00fcr die Arbeit mit diesen Ressourcen gelten. Ist eine kommerzielle Nutzung gestattet? M\u00fcssen Sie die verwendeten Ressourcen angeben?<\/p>\n<p>In k\u00fcnftigen Blogartikeln werden wir weitere Codebeispiele f\u00fcr Python, KI, maschinelles Lernen und Datenvisualisierung erkunden.<\/p>\n<p>Meiner Meinung nach bietet <a href=\"https:\/\/www.jetbrains.com\/de-de\/pycharm\/\" target=\"_blank\" rel=\"noopener\">PyCharm<\/a> eine klassenf\u00fchrende Python-Unterst\u00fctzung, die sowohl Geschwindigkeit als auch Korrektheit gew\u00e4hrleistet. Profitieren Sie von der intelligentesten Code-Completion, PEP-8-Pr\u00fcfungen, sinnvollen Refactorings und einer Vielzahl von Inspektionen, die alle Ihre Anforderungen bei der Programmierung abdecken. Wie wir in diesem Blogartikel gesehen haben, bietet PyCharm eine Integration mit dem Hugging Face Hub, sodass Sie Modelle durchsuchen und verwenden k\u00f6nnen, ohne die IDE zu verlassen. Dadurch eignet sich die IDE hervorragend f\u00fcr eine Vielzahl von KI- und LLM-Optimierungsprojekten.<\/p>\n<div class=\"buttons\">\n<div class=\"buttons__row\"><a class=\"btn\" href=\"https:\/\/www.jetbrains.com\/de-de\/pycharm\/\" target=\"\" rel=\"noopener\">PyCharm jetzt herunterladen<\/a><\/div>\n<\/div>\n<p><strong>Autorin des urspr\u00fcnglichen Blogposts<\/strong><\/p>\n\n    <div class=\"about-author \">\n        <div class=\"about-author__box\">\n            <div class=\"row\">\n                <div class=\"about-author__box-img\">\n                    <img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/01\/CheukTingHo-Kimono-e1738750639162-200x200.jpg\" width=\"200\" height=\"200\" alt=\"Cheuk Ting Ho\" loading=\"lazy\"  class=\"avatar avatar-200 wp-user-avatar wp-user-avatar-200 photo avatar-default\">\n                <\/div>\n                <div class=\"about-author__box-text\">\n                                            <h4>Cheuk Ting Ho<\/h4>\n                                                        <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n","protected":false},"author":964,"featured_media":648291,"comment_status":"closed","ping_status":"closed","template":"","categories":[952,1401],"tags":[8900,8428,3252],"cross-post-tag":[8851],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/pycharm\/647800"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/pycharm"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/types\/pycharm"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/users\/964"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/comments?post=647800"}],"version-history":[{"count":2,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/pycharm\/647800\/revisions"}],"predecessor-version":[{"id":648314,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/pycharm\/647800\/revisions\/648314"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/media\/648291"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/media?parent=647800"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/categories?post=647800"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/tags?post=647800"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/de\/wp-json\/wp\/v2\/cross-post-tag?post=647800"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}