mistral-finetuneist eine leichtgewichtige Codebasis, um Mistral-Modelle speichereffizient und mit guter Performance feinabzustimmen; das Repository ist inzwischen archiviert und wird nicht mehr aktiv gepflegt- Das Trainingsverfahren basiert auf LoRA, bei dem der Großteil der Gewichte eingefroren bleibt und nur 1–2 % der zusätzlichen Gewichte in Form niedrig-rangiger Matrixstörungen trainiert werden
- Für maximale Effizienz werden A100- oder H100-GPUs empfohlen; der Code ist für Single-Node-Training mit mehreren GPUs optimiert, kleinere Modelle wie 7B laufen aber auch auf einer einzelnen GPU
- Zu den unterstützten Modellen gehören 7B, Mixtral 8x7B, Mixtral 8x22B, Mistral-Nemo 12B und Mistral Large v2 123B Instruct; für Mistral-Nemo und Large v2 gelten jeweils Einschränkungen bei Sequenzlänge und Lernrate
- Die Daten müssen dem Format
jsonlund einem strikten Schema folgen; vor dem Training ist die Prüfung mitutils.validate_datawichtig, um das Format zu validieren und die Trainingszeit zu schätzen
Projektstatus und Ziel
- Das Repository
mistral-finetunehat den Status Archived und wird nicht mehr aktiv gepflegt - Falls es Community-Nachfrage gibt oder ein Mehrwert für das Fine-Tuning-Ökosystem gesehen wird, könnten künftig eine neue Bibliothek oder größere Updates erscheinen
- Ziel ist es, einen einfachen und angeleiteten Einstiegspunkt für das Fine-Tuning von Mistral-Modellen bereitzustellen
- Diese Codebasis ist besonders beim Datenformat stark meinungsgetrieben und zielt nicht auf ein universelles Tool ab, das viele Modellarchitekturen oder Hardwaretypen abdeckt
- Für einen allgemeineren Ansatz kann man sich Projekte wie torchtune ansehen
Fine-Tuning-Verfahren und Hardware-Empfehlungen
mistral-finetunebasiert auf LoRA- Der Großteil der Modellgewichte bleibt eingefroren
- Es werden nur 1–2 % zusätzlicher Gewichte in Form niedrig-rangiger Matrixstörungen trainiert
- Für maximale Effizienz werden A100- oder H100-GPUs empfohlen
- Der Code ist für Single-Node-Training mit mehreren GPUs optimiert
- Kleinere Modelle wie 7B sind auch mit nur einer GPU praktikabel
Aktuelle Updates bei kompatiblen Modellen
- Seit dem 13. August 2024 ist Mistral Large v2 mit
mistral-finetunekompatibel- Der 123B-Instruct-Checkpoint muss heruntergeladen und
model_id_or_pathauf dieses Checkpoint-Verzeichnis gesetzt werden - Wegen der Modellgröße wird für das Fine-Tuning deutlich mehr Speicher benötigt
- Derzeit muss
seq_lenauf 8192 oder weniger gesetzt werden - Es wird eine niedrigere Lernrate als bei anderen Modellen empfohlen; in den meisten Fällen soll
lr=1e-6gut funktionieren
- Der 123B-Instruct-Checkpoint muss heruntergeladen und
- Seit dem 19. Juli 2024 ist Mistral Nemo mit
mistral-finetunekompatibel- Das 12B-Base- oder Instruct-Modell muss heruntergeladen und
model_id_or_pathauf das Checkpoint-Verzeichnis gesetzt werden - Erforderlich ist eine
mistral-common-Version mit Tekkenizer-Unterstützung; perpip install --upgrade mistral-commonsollte Version>=1.3.1installiert werden - Wegen des großen Vokabulars steigt der Spitzen-Speicherbedarf des CE loss, daher wird aktuell mehr Speicher benötigt
- Derzeit muss
seq_lenauf 16384 oder weniger gesetzt werden - Es wird empfohlen, dieselben Hyperparameter wie bei 7B v3 zu verwenden
- Das 12B-Base- oder Instruct-Modell muss heruntergeladen und
Installation und Modelldownload
- Der Einstieg besteht aus dem Klonen des Repositorys und der Installation der Abhängigkeiten
git clone https://github.com/mistralai/mistral-finetune.gitpip install -r requirements.txt
- Für das Fine-Tuning werden offizielle Mistral-Modelle empfohlen; das README liefert Download-Links und Prüfsummen für folgende Modelle
- 7B Base:
0663b293810d7571dad25dae2f2a5806 - 7B Instruct v3:
80b71fcb6416085bcb4efad86dfb4d52 - 8x7B Base: Hugging-Face-Link
- 8x7B Instruct:
8e2d3930145dc43d3084396f49d38a3f - 8x22 Instruct:
471a02a6902706a2f1e44a693813855b - 8x22B Base:
a2fa75117174f87d1197e3a4eb50371a - 12B Instruct (Mistral-Nemo):
296fbdf911cb88e6f0be74cd04827fe7 - 12 Base (Mistral-Nemo):
c5d079ac4b55fc1ae35f51f0a3c0eb83 - 123B Instruct (Large v2):
fc602155f9e39151fba81fcaab2fa7c4
- 7B Base:
- Bei 8x7B Base V1 und 8x7B Instruct V1 muss vor dem Fine-Tuning der v3-Tokenizer verwendet und die Vokabulargröße auf 32768 erweitert werden
- Der Pfad zum heruntergeladenen Modellordner muss im Trainings-YAML als absoluter Pfad in
model_id_or_pathangegeben werden
Anforderungen an das Datenformat
- Alle Datendateien müssen im Format jsonl vorliegen
- Vortrainingsdaten speichern Klartext unter dem Schlüssel
"text" - Instruction-Daten speichern eine Liste von Dialogen unter dem Schlüssel
"messages"- Jeder Eintrag enthält die Schlüssel
"content"und"role" "role"ist einer von"user","assistant"oder"system"- Der Loss wird nur berechnet, wenn
"role" == "assistant"gilt - Mit
"weight": 0in einer Assistant-Nachricht kann dieses Trainingselement ausgeschlossen werden
- Jeder Eintrag enthält die Schlüssel
- Daten für Function Calling speichern ebenfalls eine Dialogliste unter dem Schlüssel
"messages"- Jeder Eintrag enthält
"role"und entweder"content"oder"tool_calls" "role"ist einer von"user","assistant","system"oder"tool"- Der Loss wird nur berechnet, wenn
"role" == "assistant"gilt "id"in"tool_calls"und"tool_call_id"müssen zufällige Strings mit genau 9 Zeichen Länge sein- Das README empfiehlt, diese automatisch im Skript zur Datenaufbereitung zu erzeugen
- Jeder Eintrag enthält
Datenvalidierung und Beispiel-Workflow
- Vor dem Trainingsstart sollte mit utils.validate_data das Datenformat geprüft und die Trainingszeit geschätzt werden
- Das Instruction-Beispiel nutzt einen Teil von Ultachat_200k
- Die Parquet-Daten werden mit Pandas geladen
- Aufteilung in 95 % Training und 5 % Evaluation
- Speicherung als
jsonl - Die Pfade werden in
data.instruct_dataunddata.eval_instruct_datavonexample/7B.yamleingetragen
- Bei der Validierung kann auffallen, dass einige Dialoge mit der Rolle
userenden- Da nur Assistant-Nachrichten trainiert werden, ist die letzte
user-Nachricht überflüssig - Mit utils.reformat_data.py lassen sich die Daten anpassen
- Da nur Assistant-Nachrichten trainiert werden, ist die letzte
- Nach der Korrektur liefert eine erneute Validierung eine Zusammenfassung mit Anzahl der Datentokens, Anzahl der Trainingstokens, Zahl der Epochen,
max_stepsund geschätzter Laufzeit - Im README-Beispiel durchläuft
max_steps=500den Datensatz etwa fünfmal; für ein 8xH100-Cluster mit rund 30 Minuten Laufzeit wirdmax_steps=300empfohlen
Beispiel für Function-Calling-Fine-Tuning
- Das Function-Calling-Beispiel verwendet den Datensatz Glaive function calling dataset
- Die Daten werden mit Pandas geladen, in 95 % Training und 5 % Evaluation aufgeteilt und dann als
jsonlgespeichert - Der Originaldatensatz folgt nicht dem geforderten Function-Calling-Format und muss daher umformatiert werden
"from"muss zu"user"geändert werden- Überflüssige
"\n"-Zeichen müssen entfernt werden
- Mit utils.reformat_data_glaive.py lässt sich der Großteil der Samples in das richtige Format bringen
- Da es unmöglich ist, ein Reformatierungsskript zu schreiben, das für alle Arten von Datensätzen funktioniert, kann für Datensätze außerhalb des geforderten Formats ein separates Skript nötig sein
- Mit
utils.validate_data --create_correctedlassen sich verbleibende Fehler entfernen und ein.corrected-Datensatz erzeugen
Trainingsstart und Ergebnisbeispiele
- Nach der Datenvalidierung kann das Training gestartet werden
- Für schnelleres Training wird eine Konfiguration mit
max_steps= 300 empfohlen run_dirsollte als Experimentordner gesetzt werden; optional kannwandb.projectangegeben werden, um Logging mit Weights & Biases zu nutzen- Das Training wird mit
torchrunausgeführt;--nproc-per-nodesollte auf die Zahl der verfügbaren GPUs gesetzt werden - UltraChat-Training dauert auf einem 8xH100-Knoten etwa 30 Minuten; die resultierenden Gewichte können auf MT Bench etwa 6,3 erreichen
- Glaive-Training dauert auf einem 8xH100-Knoten etwa 1 Stunde; die resultierenden Gewichte sollen gut für Function Calling funktionieren
Wichtige Punkte der Trainingskonfiguration
model_id_or_path: vortrainiertes Modell oder Pfad zu einem lokalen Modellverzeichnis, von dem das Training startetrun_dir: Verzeichnis zum Speichern von Checkpoints und Metrikenseq_len: Länge der Trainingssequenz; Samples werden zur Effizienz passend aufseq_lengepacktbatch_size: Anzahl der Trainingsbeispiele pro GPU- Die gesamte effektive Token-Batch-Größe ist
num_gpus x batch_size x seq_len
- Die gesamte effektive Token-Batch-Größe ist
max_steps: Gesamtzahl der Trainingsiterationen- Die Gesamtzahl der im Training gesehenen Tokens ist
max_steps x num_gpus x batch_size x seq_len
- Die Gesamtzahl der im Training gesehenen Tokens ist
optim.lr: initiale Lernrate des Optimizersoptim.weight_decay: Weight Decay; das README empfiehlt, 0.1 beizubehaltenoptim.pct_start: Anteil der Warm-up-Phase von PyTorchOneCycleLRlora.rank: Größe des LoRA-Adapters; empfohlen wird 64 oder wenigerseed: Zufalls-Seed für Reproduzierbarkeit bei Initialisierung, Daten-Shuffling und Samplingdata.instruct_data: Pfad zu Instruction-Trainingsdaten- Möglich sind eine einzelne
jsonl-Datei, einjsonl-Verzeichnis oder mehrere gewichtete Datenquellen
- Möglich sind eine einzelne
data.data: optionaler Pfad zu zusätzlichen Vortrainingsdatendata.eval_instruct_data: optionaler Pfad zu Evaluationsdaten für Instructioneval_freq,no_eval,ckpt_freq: steuern die Intervalle für Evaluation, Zwischenevaluation und Checkpoint-Speicherungsave_adapters: legt fest, ob nur LoRA-Checkpoints gespeichert werden oder ob LoRA in das Basismodell gemergt und das Gesamtmodell gespeichert wirdsave_adapters=Falseerfordert genug CPU- und GPU-Speicher, um das vollständige Modell in einem einzelnen Prozess zu speichern, und ist normalerweise nur bei 7B-Modellen möglich
Inferenz und Weights & Biases
- Für die Inferenz mit trainierten Modellen wird mistral-inference empfohlen
- Installation per
pip install mistral_inference - Beim Start von
mistral-chatkönnen LoRA-Gewichte über den unter--lora_pathangegebenen Pfad zulora.safetensorsgenutzt werden - Unterstützung für Weights and Biases ist enthalten, um Trainingsmetriken und Experimente zu überwachen
- Installation per
pip install wandb - Es wird empfohlen, den API-Schlüssel über die Umgebungsvariable
WANDB_API_KEYbereitzustellen - Aus Sicherheitsgründen wird der API-Schlüssel nicht aus der YAML-Konfiguration gelesen
- Trainings-Loss, Evaluations-Loss, Lernrate und weitere Werte werden im Projekt-Dashboard von wandb protokolliert und visualisiert
- Installation per
- Weitere Details stehen in der Weights and Biases documentation
Modellerweiterung und FAQ
- Es lassen sich nur Mistral-Modelle feinabstimmen, die mit dem v3-Tokenizer kompatibel sind
- Kompatible Modelle müssen eine Vokabulargröße von 32768 haben, nicht 32000
- Ältere Modelle mit Vokabulargröße 32000 können mit
utils.extend_model_vocabauf 32768 erweitert werden - Beim Fine-Tuning von MoE-Modellen ist die Leistungsschwankung größer
- Empfohlen wird, dasselbe MoE-Fine-Tuning mehrfach mit unterschiedlichen Seeds auszuführen und das beste Ergebnis auszuwählen
- Bei dichten Modellen wurde eine so hohe Varianz nicht beobachtet
- Die Anzahl der im Training verwendeten Tokens kann geprüft werden, indem die YAML-Trainingsdatei an utils.validate_data.py übergeben wird
- Tritt ein CUDA out-of-memory-Fehler auf, kann die Batch-Größe pro GPU reduziert werden
- Die Batch-Größe ist
seq_len x batch_size - Vorgeschlagen wird,
batch_sizeauf 1 zu setzen undseq_lenzu verringern
- Die Batch-Größe ist
- Die Bibliothek steht unter der Apache 2.0 License
- Diese Bibliothek oder die Modelle dürfen nicht in einer Weise verwendet werden, die Rechte einschließlich geistigen Eigentums Dritter verletzt, missbraucht oder gegen sie verstößt
1 Kommentare
Hacker-News-Kommentare
Entwickeln sich Modelle so schnell weiter – hat Fine-Tuning dann überhaupt noch einen Wert? Mich würden praktische Anwendungsfälle interessieren.
Bloomberg hat zum Beispiel letztes Jahr ein LLM auf GPT-3.5-Niveau mit Finanzdaten trainiert, doch kurz darauf übertraf GPT-4-8k es bei fast allen Finanzaufgaben.
Am Ende konzentrieren wir uns auf hochwertige Evaluationsdaten und auf Architekturen, mit denen man leicht auf neue Modelle wechseln kann.
LLMs haben solche Annotationen nie gesehen, nicht-englische LLMs haben für Unternehmen auch nicht höchste Priorität, und wegen Datenschutz können wir nur Offline-first-Modelle verwenden.
In so einer Situation passt Fine-Tuning eines allgemeinen Sprachmodells sehr gut.
Wenn man mit formatierten Nachrichten fine-tuned, erzeugt das Modell dieses Format automatisch; so spart man bei jedem Prompt viele Tokens, die sonst zur Beschreibung des Ausgabeformats nötig wären.
Fine-Tuning schließt die Lücke zwischen beiden allerdings ein gutes Stück.
Das gilt auch für den Großteil der Programmierung, auch wenn es ein enger Bereich ist. Wenn das Ziel nur ist, ein allgemeines LLM stärker in Richtung der eigenen Daten zu lenken, ist Fine-Tuning wahrscheinlich eher nicht relevant.
Wenn man aber ein sehr konkretes und zugleich mehrdeutiges Problem lösen will und ein LLM nur einen Teil davon bewältigt, ist Fine-Tuning wahrscheinlich die beste Option.
Wenn die App viele Custom Functions hat, die mit Tools interagieren, bevorzugt man möglicherweise Fine-Tuning statt Kontext-Tokens zu verbrauchen.
Welche GPU braucht man dafür? Ich habe die Laptop-Version einer 3060 Ti, einen i9 und 16 GB RAM.
Ich habe keine AWS- oder GCP-Quota und habe von Paperspace gehört, aber ich möchte schnell mit Mistral-Fine-Tuning anfangen, weil ich in einem Kundenprojekt, an dem ich arbeite, einige Mistral-Modelle einsetzen will.
Gaming-GPUs können problemlos 300 W Wärme abführen; eine Laptop-GPU würde dabei schmelzen und ist wahrscheinlich auf ungefähr 100 W begrenzt.
Wärmeabfuhr steht in direktem Verhältnis zur Geschwindigkeit.
Außerdem kann man einen Desktop auf eine schnellere GPU aufrüsten oder mehrere GPUs verwenden.
Allerdings sind insbesondere Multi-GPU-Konfigurationen laut und erzeugen genug Wärme, um ein Zimmer schnell aufzuheizen.
Wenn du in den nächsten Jahren voraussichtlich nicht mehr als 10 % der Zeit die GPU unter Volllast laufen lässt, ist die Cloud wahrscheinlich günstiger.
Dort sind die Hardwareanforderungen je Modell zusammengefasst, und man kann VRAM und Systemspeicher auswählen, um die nutzbaren Modelle zu filtern.
Unser Unternehmen hat dort mit der RTX4000 Mistral und Llama 3 fine-getuned.
Mit nur 20 GB RAM ist das etwas eingeschränkt, aber bei größeren Eingabe-Tokenzahlen hat es geholfen, die Quantisierungsstufe zu senken.
Inzwischen bieten sie auch stundenweise Miete an.
Wir nutzen es derzeit im Unternehmen und haben ziemlich gute Ergebnisse gesehen.
Es ist sehr spannend, welche Tools für die gängigen LLM-Anwendungsfälle zum De-facto-Standard werden.
Das Ökosystem ist so fragmentiert, dass ich das Gefühl habe, von den meisten Tools noch nie gehört zu haben.
Vor ein paar Tagen habe ich Microsofts Olive gesehen, und das war für mich völlig neu.
Da viele Open-Source-LLMs inzwischen bereits „brauchbar“ sind, kommt es jetzt darauf an, die Entwicklung rundherum einfacher zu machen.
Insbesondere müssen Menschen, die sowohl Nutzer als auch Entwickler sind, private Daten nutzen können – genauer gesagt Daten, die nicht im Pretraining des Modells enthalten waren.
Im Repository steht, dass es für große Modelle optimiert ist und A100/H100 benötigt, aber trotzdem habe ich das Gefühl, dass dies kleineren Modellen sogar mehr helfen könnte als großen.
„Wenn man es baut, kommen die Leute“ lässt sich zu „Wenn man die Tools bereitstellt, bauen die Leute“ erweitern.
Der Teil mit den Gewichtungen ist interessant.
HuggingFaces SFTTrainer erlaubt es, wenn man möchte, nur den Completion-Teil zu trainieren; auch wenn das für Menschen natürlich wirkt, ist es für LLMs im Allgemeinen besser, darauf trainiert zu werden, die gesamte Eingabe vorherzusagen.
Mit diesem Ansatz bekommt man die Vorteile beider Seiten.
Könnte man das so optimieren, dass man mit zwei 3090 oder 4090 größere Modellvarianten trainieren kann?
Einen Einstiegspunkt, der einige Optionen behandelt, gibt es hier: https://huggingface.co/blog/trl-peft
Wie könnte ich mein WhatsApp-Chat-Modell trainieren?
Willst du ein Modell mit deinen eigenen WhatsApp-Nachrichten trainieren? Was ist der Zweck? Es hängt davon ab, ob es wie du schreiben soll oder ob du RAG-basierte Fragen und Antworten willst.