Inferenz von Textgenerierungs-Modellen
Auf JupyterHub
In diesem Teil unseres Tutorials über LLMs werden wir lernen, wie man ein Modell zur Textgeneration von Huggingface auf JupyterHub verwendet. Wenn du einen lokalen Rechner mit installiertem CUDA hast, sollten alle Schritte gleich sein, aber es kann schwierig sein, die richtige Umgebung zu installieren.
Starte also ein Jupyter-Notebook und wähle den Standard-Kernel. Stelle sicher, dass du beim Start von JupyterHub eine GPU ausgewählt hast. Wenn du auf deine PALMA-Dateien zugreifen willst, wähle auch die Palma storage integration aus. Dies ermöglicht es dir, unter /palma
auf das PALMA-Verzeichnis zuzugreifen.
Wenn du transformers installieren musst, verwende pip in deiner Standard-Python-Umgebung:
pip install transformers
Torch sollte vorinstalliert sein (JupyterHub) oder in deiner Modulkette (PALMA). Auf einem lokalen Rechner kann es schwierig sein, CUDA und dann Torch in der richtigen Umgebung zu installieren.
Hier können wir sehen, ob CUDA verfügbar ist und auf wie viel VRAM wir zugreifen können. Dieses Notizbuch ist für die Verwendung von nur einer GPU geschrieben, normalerweise cuda:0
, sollte aber auch mit cpu
laufen.
Das Huggingface-Caching-Mysterium
Huggingface bietet eine sehr einfache Schnittstelle für Modelle. Das Paket transformers lädt sie automatisch herunter, aber man weiß nicht, wo diese Modelle auf der Festplatte liegen und sie können riesig sein! Wir sollten also vorsichtig sein, wenn wir die Modelle laden.
Wir haben verschiedene Optionen, wo wir unsere Modelle laden können:
- Der Standard-Cache von Huggingface ist ein versteckter Ordner
~/.cache/huggingface/models
. Da die Modelle aber sehr groß sind, kann dies leicht die Partitionen sprengen! - Wenn du PALMA verwendest, kannst du
/scratch/tmp/$USER/huggingface/models/
verwenden und es später entfernen - Ansonsten können wir für kleine Modelle (!) einfach ein nicht verstecktes Cache-Verzeichnis (z.B.
~/huggingface/models
) verwenden und später wieder entfernen. Wenn du hier Fehler bekommst, kann das an den Berechtigungen liegen. Verwende dann den Standard-Cache von Huggingface. - Für größere Modelle kannst du auch einen OpenStack Usershare
/cloud/wwu1/{group}/{share}/cache
verwenden - Oder wir lassen es einfach so, wie es ist, aber sind uns dessen bewusst!
Merke dir jetzt, wo du dein Modell gespeichert hast, denn du wirst das Cache-Verzeichnis später noch brauchen. Wir werden weiterhin das Modell in und aus cache_dir = "/cloud/wwu1/d_reachiat/incubai/cache"
laden. Unten siehst du, wie du das kleinste Pythia-Modell herunterladen und starten kannst. Pythia ist eine Sammlung von Open Source LLMs für die Texterzeugung, ähnlich wie GPT (Closed Source) oder Llama (eingeschränkte Lizenz).
Nun können wir mit dem Prompting fortfahren. Das bedeutet, wir geben dem Modell einen Satz, auf dessen Grundlage es neuen Text generiert, der logisch an den gegebenen Eingangssatz anschließen sollte.
Wie du sehen wirst, ist der von unserem kleinen Pythia-Modell generierte Text repetitiv und nicht sehr gut. Eine Änderung einiger Parameter kann helfen, aber die hier für Testzwecke verwendeten kleinen Modelle sind nicht geeignet, um gute Parameter zu finden.
Um mehr über Strategien zur Textgeneration zu erfahren, kannst du die Huggingface-Seite über Strategien zur Textgeneration besuchen.
Nun kannst du auf die folgende Weise einen Prompt verwenden:
Um diesen Prozess zu vereinfachen, können wir eine Pipeline bauen. Das erste Argument der Pipeline ist die Aufgabe, für die wir die Pipeline verwenden wollen, in unserem Fall Textgenerierung. Die anderen Eingaben sind das zuvor definierte Modell und der Tokenizer, sowie die Argumente der model.generate
Funktion von oben und unser spezifiziertes device.
Wenn du einige Prompts in einer Textdatei hast, kannst du diese Textdatei laden und eine Pipeline zur Verarbeitung verwenden. Es ist effizienter, die Pipeline über die Daten iterieren zu lassen, als eine Schleife über die Pipeline zu verwenden.
Nun waren wir hoffentlich in der Lage:
- ein Textgenerations-Modell herunterzuladen
- das Modell aus einem selbstdefinierten Cache zu laden
- mehrere Prompts zu verwenden, um das Modell zu testen
Benutze ein Python-Skript
Um größere Modelle auf PALMA zu implementieren, müssen wir alles in ein Python-Skript umwandeln. Die Skripte findest du unter incubaitor/2_PALMA/2_2_LLMs-text-generation/scripts/
. Du kannst nun testen, ob das Skript auch läuft, indem du den folgenden Befehl in das Terminal eingibst:
python pythia.py --cache_dir /cloud/wwu1/d_reachiat/incubai/cache --size 70m --prompt "My sample prompt"
Du könntest auch mit mehreren Prompts experimentieren, wie denen in incubaitor/2_PALMA/2_2_LLMs-text-generation/prompts/prompts.txt
und einer Ausgabedatei mit
python pythia.py --cache_dir /cloud/wwu1/d_reachiat/incubai/cache --size 70m --prompt_file ../prompts/prompts.txt --out_file out.csv
wo du eine schöne CSV-Datei deiner Prompts und des vom Modell generierten Text bekommen kannst.
Wenn du das Skript ausführst, bekommst du Informationen über den GPU-Speicher (VRAM) Verbrauch des Modells. Du musst einen CUDA-Overhead von etwa 1 GB hinzufügen, um den erwarteten Speicherverbrauch zu finden. Daher ist das 6.9b-Modell von Pythia zu groß für JupyterHub. Während du die Pipeline ausführst, kannst du ein Terminal öffnen und nvidia-smi
eingeben, um den Speicherverbrauch zu sehen.
Wechsel auf PALMA
Falls alles gut gegangen ist, möchten wir zu PALMA wechseln.
Bevor du es auf PALMA versuchst, stelle zunächst sicher, dass ein kleines Modell auf dem JupyterHub läuft!
Wir wollen dort die GPU-Partitionen nutzen, um größere Modelle zu betreiben, als wir es im JupyterHub können. Anfangs eignet sich die gpuexpress
Partition gut zum Testen.
Wenn du noch nie mit PALMA gearbeitet hast, solltest du unser Tutorial in 2_1_PALMA lesen. Auch das HPC Wiki gibt einen guten Überblick darüber, wie man PALMA benutzt.
Installation der Anforderungen
Jetzt wollen wir die Shell-Skripte im Ordner 2_PALMA/2_2_LLMs-text-generation/jobs
verwenden, um Text aus unseren Modellen zu generieren.
ACHTUNG: Diese Vorgehensweise funktioniert derzeit nicht, da Transformers Torch >= 2.0 benötigt. Deshalb ist der hier aufgeführte Toolchain grad nicht gültig, das Skript install.sh
beachtet dies aber schon. Du kannst dort den (derzeit) geigneten Toolchain einsehen.
Wir verwenden eine spezielle “Toolchain”, um CUDA nutzen zu können. Die folgende Toolchain ist geeignet:
Du kannst diese Toolchain finden, indem du module spider PyTorch
tippst. Da der Login-Knoten jedoch eine andere Architektur hat, musst du ein Jobskript erstellen, um den richtigen Namen und die CUDA-Version auf der anderen Architektur zu finden.
Wenn du diese Befehle in der Kommandozeile eingibst, siehst du, dass das letzte Modul nicht auf dem Login-Knoten verfügbar ist. Deshalb müssen wir, um weitere Pakete zu installieren, in dieser Toolchain sein. Um sicherzustellen, dass die richtigen Python- und PyTorch-Versionen verwendet werden, installieren wir das Paket transformers über pip mit einem Job-Skript namens install.sh. Da wir Torch 1.10 verwenden (eine ziemlich alte Version) müssen wir darauf achten, eine geeignete Version von transformers zu verwenden, zum Beispiel transformers==4.33.1
.
Anschließend können wir das Installationsskript auf der richtigen Architektur mit dem Befehl sbatch install.sh
im Verzeichnis incubaitor/2_PALMA/2_2_LLMs-text-generation/jobs/
ausführen. Wenn der Job abgeschlossen ist, überprüfe die Ausgabedatei mit vi, um sicherzustellen, dass keine neue Torch-Version installiert wurde (was viele Konflikte verursachen könnte).
Falls etwas schiefgelaufen ist, entferne die installierten Pakete in deinem Home-Verzeichnis (da sie durch die Flag --user
in ~/.local/
installiert wurden, kannst du die Ordner dort entfernen).
Das Modell vorbereiten und ausführen
Jetzt sollte hoffentlich alles gut gegangen sein. Überprüfe nun das Skript inference.sh
. Wenn du dein Modell in deinem usershare hast, solltest du es im Skript als Modellverzeichnis verwenden. Wenn du keinen usershare hast, kannst du das gesamte Modellverzeichnis in dein Scratch-Verzeichnis kopieren. Zum Beispiel auf PALMA (!) verwende
cp -r ~/cloud/wwu1/u_jupyterhub/home/<first letter of username>/<username>/.cache/huggingface/models/models--EleutherAI--pythia-70m-deduped $WORK/models/huggingface/
wenn du den Standard Huggingface Cache benutzt hast (siehe Huggingface Cache oben). Es gibt keine schöne Möglichkeit, die Huggingface Modelle direkt herunterzuladen, also falls nötig, starte ein Skript (siehe oben), das die Modelle in das Scratch-Verzeichnis herunterlädt, aber nicht startet (oder aufgrund von Limits abstürzt).
Jetzt sollten die Daten in deinem Scratch-Verzeichnis sein. Wir sollten bereit sein, das erste kleine Modell zu starten. Gehe zurück zu ~/incubaitor/incubaitor/2_PALMA/2_2_LLMs-text-generation/jobs/
und starte den Job mit dem Befehl sbatch inference.sh
.
In der Ausgabedatei kannst du lesen, ob alles gut gelaufen ist, zum Beispiel über vi slurm-pythia-test-1b-express.out
. Außerdem sollte die Ausgabedatei auf deiner Scratch-Partition sein. Du solltest die Inhalte der Ausgabedatei lesen können mit vi /scratch/tmp/<username>/pythia-70m-express.csv
oder auf diese Datei zugreifen können, indem du sie zu $WORK/transfer
kopierst, wenn du die PALMA Nextcloud Integration vorbereitet hast und sie über die Web-Schnittstelle herunterlädst (noch in Entwicklung).
Für weitere Informationen über den Datentransfer besuche die HPC Dokumentation.
Wenn du mit den Ergebnissen zufrieden bist, teste, ob du auch die 1b
Version auf die gleiche Weise zum Laufen bekommen kannst indem du die entsprechenden Parameter im Skript inference.sh
änderst.
Passe das Skript an deine Bedürfnisse an
Wenn du etwas im Skript ändern möchtest oder andere Funktionen des Modells testen möchtest, kannst du auch mit den kleinen Modellen im JupyterHub spielen. Falls Ressourcen verfügbar sind, kannst du auch das jupyter.sh
Skript auf PALMA starten und auf deinem eigenen Rechner herumspielen (passe dieses ggf. selbstständig auf den notwendigen Toolchain an).
Wenn du bereit bist, kannst du diese Änderungen in der Datei inference.py
vornehmen (der beste Weg wäre, sie in dein privates Git zu kopieren, Änderungen vorzunehmen, die Änderungen zu PALMA zu ziehen und das Skript zu Testzwecken auf einem kleinen Modell auszuführen).
Dann, wenn Ressourcen verfügbar sind, kannst du versuchen, Inferenzen auf einem größeren Modell auf Palma durchzuführen. Siehe die Jobscripts für das 6.9b und 12b Modell.
Jenseits der Textgenerierung
Es gibt viele andere Arten von Modellen auf Huggingface. Sie alle arbeiten mit ähnlichen Pipelines. Du kannst auf der Modellkarte (oben rechts </> Use in transformers
) nachsehen, wie die Modelle geladen und eine Pipeline aufgebaut werden kann. Für die Pipeline solltest du aufgrund der Caching-Probleme einen ähnlichen Ansatz wie oben verwenden. (Denke daran, beim downloaden local_files_only=False
zu setzen!)
Dann musst du überprüfen, wie die Pipeline mit Inputs versorgt wird und wie die Outputs aussehen. Dies sollte ebenfalls auf der Modellkarte bereitgestellt werden. Beispielsweise kann das Folgende für Textklassifikation verwendet werden. Stelle sicher, dass das Caching korrekt durchgeführt wird.
Du kannst auch mehrere Fragen (bei mehreren Texten) verwenden, indem du über die pipeline iterierst.
Jetzt kannst du Huggingface-Modelle verwenden! Weitere Modelle zur Audio- oder Bilderkennung benötigen zusätzliche Pakete wie OpenCV, die ebenfalls in der Toolchain von PALMA vorhanden sein können.