📚 Modul 1: Grundlagen verstehen – Was sind LLMs? [Anfänger]
Einstieg
Sprachmodelle wie ChatGPT oder Claude sind aus unserem Alltag kaum mehr wegzudenken. Aber was genau steckt eigentlich dahinter? In diesem Modul lernst du die Grundlagen großer Sprachmodelle – der sogenannten LLMs – kennen. Du wirst verstehen, wie sie funktionieren, wo sie eingesetzt werden können und warum sie manchmal Fehler machen.
- erklären, was ein LLM ist und wie es in den Bereich der Künstlichen Intelligenz gehört,
- die Grundidee der Transformer-Architektur beschreiben,
- typische Anwendungsfelder und Grenzen von LLMs erkennen.
Was sind LLMs?
Large Language Models (LLMs) sind große KI-Modelle, die speziell darauf trainiert wurden, Sprache zu verstehen und zu erzeugen. Sie beantworten Fragen, fassen Texte zusammen, schreiben Geschichten oder geben Anleitungen.
LLMs lernen durch das Training auf riesigen Textmengen: Büchern, Webseiten, Artikeln und mehr. Dabei erkennen sie Muster und berechnen, welche Wörter wahrscheinlich folgen.
LLMs denken nicht wie Menschen. Sie berechnen Wahrscheinlichkeiten.
Beispiele für bekannte LLMs:
- ChatGPT (OpenAI)
- Llama (Meta)
- Qwen (Alibaba)
- Mistral (Mistral AI)
LLMs im großen Feld der Künstlichen Intelligenz
Künstliche Intelligenz (KI)
└── Maschinelles Lernen (ML)
└── Deep Learning
└── Sprachmodelle (LLMs)
Zusammenfassung:
- KI: Technologien, die Maschinen „intelligent“ wirken lassen.
- ML: Maschinen lernen aus Beispielen.
- LLMs: Spezialisierte Modelle für Sprache.
Jedes LLM ist eine KI, aber nicht jede KI ist ein LLM!
Wie funktionieren LLMs?
Das Herzstück moderner LLMs ist die Transformer-Architektur. Sie verwendet eine Technik namens Self-Attention: Wörter werden im Zusammenhang mit allen anderen Wörtern im Satz betrachtet.
Beispiel:
„Die Katze, die auf dem Dach sitzt, beobachtet die Vögel.“
Das Modell erkennt, dass „Katze“ zu „sitzt“ und „beobachtet“ gehört – trotz anderer Wörter dazwischen.
Fähigkeiten und Grenzen von LLMs
Stärken:
- Texte verstehen und erzeugen
- Fragen beantworten
- Texte zusammenfassen
- Kreative Inhalte entwickeln
Schwächen:
- Fakten können erfunden werden ("Halluzinationen")
- Schwierigkeiten bei mehrschrittiger Logik
- Kein echtes Weltverständnis
Risiken und ethische Aspekte
- Verbreitung von Vorurteilen (Bias)
- Glaubwürdige, aber falsche Antworten
- Hoher Energieverbrauch beim Training
Nutzer sollten Antworten von LLMs immer kritisch prüfen!
Übungen zum Mitdenken
- Was unterscheidet KI, ML und LLM?
- Nenne drei Anwendungsgebiete für LLMs.
- Warum ist es gefährlich, wenn ein LLM falsche Informationen halluziniert?
- Wofür wird die Transformer-Architektur eingesetzt?
Zusammenfassung
- LLMs sind spezialisierte KI-Modelle für Sprache.
- Sie erzeugen plausible Texte auf Basis von Wahrscheinlichkeiten.
- Transformer-Architektur hilft, komplexe Zusammenhänge zu erkennen.
- Stärken in Sprachverarbeitung, Schwächen bei Logik und Fakten.
📋 Cheatsheet – Modul 1 auf einen Blick
| Thema | Merkregel |
|---|---|
| LLMs | Erzeugen Sprache durch Wahrscheinlichkeitsberechnung |
| KI → ML → LLM | Sprachmodelle sind spezialisierte Formen von KI |
| Transformer | Versteht Beziehungen zwischen Wörtern |
| Stärken | Texte, Zusammenfassungen, kreative Aufgaben |
| Schwächen | Halluzinationen, mangelnde Logik, kein echtes Weltverständnis |
📚 Modul 2: Das Handwerk – Prompt Engineering [Anfänger]
Einstieg
Wenn du mit einem Large Language Model (LLM) arbeitest, beginnt alles mit einem einzigen Schritt: deiner Eingabe – dem Prompt. Ein Prompt ist mehr als nur eine Frage. Er ist eine gezielte Anweisung, die entscheidet, wie gut und sinnvoll ein Modell antwortet.
In diesem Modul lernst du die Grundlagen des Prompt Engineerings kennen. Du erfährst, wie du klare und strukturierte Prompts schreibst, welche Techniken du nutzen kannst, und wie du auch komplexere Aufgaben geschickt steuerst.
Was ist ein Prompt?
Ein Prompt ist eine Eingabeanweisung, die ein LLM dazu bringt, eine bestimmte Aufgabe auszuführen. Je klarer dein Prompt formuliert ist, desto besser kann das Modell arbeiten.
Die Qualität des Prompts bestimmt die Qualität der Antwort.
Beispiel:
| Schwacher Prompt | Besserer Prompt |
|---|---|
| "Erzähl mir etwas über Igel." | "Schreibe eine kurze, lustige Geschichte (3–5 Sätze) über einen Igel, der seinen Bau gegen einen Windstoß verteidigt." |
Wie schreibe ich gute Prompts?
- Klarheit: Formuliere so, dass keine Missverständnisse entstehen.
- Zielorientierung: Gib an, welches Ergebnis du möchtest.
- Struktur: Nutze Absätze, Aufzählungen oder Schritt-für-Schritt-Anweisungen.
Beispiele:
| Aufgabe | Beispiel-Prompt |
|---|---|
| Zusammenfassung | "Fasse den folgenden Text in drei Sätzen zusammen: [Text]" |
| Ideengenerierung | "Nenne fünf kreative Geschenkideen für Studierende." |
| Schritt-für-Schritt-Anleitung | "Erkläre in einfachen Schritten, wie man ein Fahrrad repariert." |
Techniken im Prompt Engineering
Zero-Shot Prompting
Nur Aufgabenstellung geben, keine Beispiele.
"Nenne drei Vorteile von Solarenergie."
Few-Shot Prompting
Ein oder zwei Beispiele liefern.
Beispiel 1: Recycling spart Rohstoffe. Beispiel 2: Recycling schützt die Umwelt. Bitte nenne zwei weitere Vorteile von Recycling.
Chain-of-Thought Prompting
Das Modell auffordern, Schritt für Schritt zu denken.
"Überlege Schritt für Schritt: Wie kann eine Schule ein einfaches Recycling-System einführen?"
Prompt-Kaskaden
Komplexe Aufgaben können durch mehrere aufeinander aufbauende Prompts gelöst werden.
1. Zusammenfassung erstellen
2. Quizfragen zur Zusammenfassung entwickeln
3. Erklärungen zu den Quizfragen geben
Vorteil: Große Aufgaben werden in kleine, lösbare Schritte zerlegt.
Self-Refinement
Das Modell kann angewiesen werden, seine eigene Antwort zu verbessern.
"Schreibe eine kurze Zusammenfassung über Solarenergie."
"Überarbeite deine Antwort: Kürze sie und füge ein praktisches Beispiel hinzu."
Übungsanregungen
- Erstelle einen Zero-Shot Prompt zum Thema "Lebensmittelverschwendung".
- Schreibe einen Few-Shot Prompt zum Thema "konzentriertes Lernen".
- Entwickle eine kleine Prompt-Kaskade für die "Planung eines Wochenendtrips".
Zusammenfassung
- Ein Prompt steuert die Ausgabe eines LLMs.
- Gute Prompts sind klar, strukturiert und zielgerichtet.
- Techniken wie Zero-Shot, Few-Shot, Chain-of-Thought verbessern die Qualität.
- Prompt-Kaskaden und Self-Refinement helfen bei komplexen Aufgaben.
📚 Modul 3: Lokale LLMs starten und betreiben [Anfänger/Fortgeschritten]
Einstieg: Warum lokale LLMs?
Ein LLM lokal zu betreiben bedeutet, selbst die Kontrolle über Modell und Daten zu behalten. Datenschutz, Anpassbarkeit und Unabhängigkeit von Cloud-Diensten sprechen dafür.
Optimale Serverkonfiguration: SSD für System, große HDD für Modelle, großzügiger Arbeits- oder Swap-Speicher.
Möglichkeiten
| Methode | Vorteile | Nachteile |
|---|---|---|
| Native Installation | Volle Leistung, maximale Kontrolle | Komplexere Einrichtung |
| Docker-Container | Einfach, systemunabhängig | Höherer Ressourcenbedarf |
Ollama als einfacher Einstieg
Ollama ermöglicht die schnelle Installation und Nutzung von LLMs auf lokalen Systemen.
curl https://ollama.ai/install.sh | sh
ollama pull qwen3:0.6b
ollama list
ollama run qwen3:0.6b
Ollama übernimmt Modellverwaltung, Optimierung und Hardwareanpassung automatisch.
| Basisbefehle | Bedeutung | Beispiel |
|---|---|---|
| ollama pull Modellname | Lädt Modell | ollama pull qwen3:0.6b |
| ollama list | Zeigt lokal verfügbare Modelle an | ollama list |
| ollama run Modellname | Startet Modell | ollama run qwen3:0.6b |
Modellübersicht: https://ollama.com/search
Hardware-Anforderungen
Faustregel:
Modellgröße × 4 ≈ benötigter VRAM
| Modell | Empfohlener VRAM |
|---|---|
| TinyLlama (1B) | 4–6 GB |
| Mistral (7B) | 28–32 GB |
| Qwen2.5 (32B) | 120–130 GB |
Native Installation
Beispiel Ubuntu Server:
sudo apt update && sudo apt upgrade
sudo do-release-upgrade
sudo reboot
sudo apt install openssh-server
sudo apt install nvidia-driver-535-server
sudo reboot
sudo apt install cuda
curl https://ollama.ai/install.sh | sh
Docker-Alternative
sudo apt install docker.io
sudo apt install nvidia-docker2
sudo systemctl restart docker
docker run --gpus all ollama/ollama
Docker bietet eine einfache, flexible Möglichkeit, LLMs in isolierten Containern zu betreiben.
Da Docker seine Daten unter /var speichert, wurde bei den Installationen der Testrechner bereits eine 3 TB HDD als /var eingebunden.
Testen mit Open WebUI
Open WebUI ist eine browserbasierte Oberfläche zur Steuerung lokaler LLMs über Ollama. Ideal für Tests und erste Projekte.
Installation von Open WebUI mit integrierter Ollama-Unterstützung
Bei dieser Installationsmethode wird ein einzelnes Container-Image verwendet, das Open WebUI mit Ollama kombiniert und so eine einfache Installation mit einem einzigen Befehl ermöglicht.
docker run -d -p 3000:8080 --gpus=all -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama
Über die Webseite bzw. das Webinterface können verschiedene Modelle eingebunden und angepasst werden. So lassen sich der Systemprompt und die Modellparameter festlegen. Außerdem ist es möglich, den einzelnen Modellen einen oder mehrere Wissensspeicher (Knowledgebase) zuzuordnen. Neue Nutzer können einzeln oder im Bulk über eine CSV-Datei angelegt werden.
Mehr Informationen: https://github.com/open-webui/open-webui
Typische Fehler und Lösungen
| Problem | Ursache | Lösung |
|---|---|---|
| Modell startet nicht | Speicher reicht nicht aus | Kleinere Modelle nutzen, Swap vergrößern |
| Docker bricht ab | GPU wird nicht erkannt | nvidia-docker2 prüfen, Treiber aktualisieren |
| GPU wird nicht genutzt | Fehlende CUDA-Installation | CUDA installieren und GPU-Modus aktivieren |
Übungen
- Ollama installieren und erstes Modell starten.
- Konversation mit TinyLlama oder Mistral führen.
- Hardware überprüfen (z.B. mit
nvidia-smi). - (Optional) Open WebUI installieren und testen.
Zusammenfassung
- Lokale LLMs bieten Datenschutz und Kontrolle.
- Ollama vereinfacht den Einstieg enorm.
- Hardwareanforderungen richten sich nach der Modellgröße.
- Typische Fehler können mit einfachen Mitteln behoben werden.
Modul 4: Modelle anpassen – Finetuning kleiner LLMs [Fortgeschritten]
Einstieg: Was bedeutet Finetuning?
Finetuning bedeutet, ein bereits trainiertes LLM gezielt auf neue Aufgaben oder Stile anzupassen. Statt ein Modell komplett neu zu trainieren, nutzt man das bestehende Wissen und spezialisiert es weiter.
Typische Anwendungsfälle:
- Ein LLM soll auf Chemiefragen spezialisiert werden.
- Ein LLM soll FAQ-Daten eines Unternehmens besser verstehen.
- Ein LLM soll in einem bestimmten Stil schreiben (z.B. juristisch präzise, locker, humorvoll).
Unterschied zum Pretraining
- Pretraining: Das Modell lernt grundlegende Sprachstrukturen aus Milliarden Textfragmenten (sehr teuer, viel Rechenleistung).
- (Full-) Fine-Tuning: Das Modell wird gezielt auf neue Daten trainiert – mit vergleichsweise wenig Aufwand.
Finetuning-Varianten im Überblick
| Verfahren | Aufwand | Vorteile | Nachteile |
|---|---|---|---|
| Vollständiges Finetuning | Hoch | Beste Anpassung | Teuer und rechenintensiv |
| Adapter-Methoden (LoRA/QLoRA) | Gering | Schnell, flexibel | Etwas geringere Anpassung |
🔹 LoRA (Low-Rank Adaptation):
- Nur kleine Veränderungen an wichtigen Schichten.
- Basismodell bleibt erhalten.
- Ergebnis: Anpassungen brauchen oft nur wenige GB statt 100+ GB.
🔹 QLoRA (Quantized LoRA):
- Noch effizienter: Basismodell wird komprimiert geladen (z.B. 4-bit statt 16-bit).
- Ideal für Fine-Tuning auf Consumer-GPUs.
LoRA: Kleine Zusatzschichten
QLoRA: Komprimiertes Laden plus kleine Zusatzschichten
Modellauswahl für das Full Fine Tuning
Wie findet man das passende Modell?
- Welches Modell passt zur Sprache und Aufgabe?
Modellübersicht: Models Hugging Face - Welches Modell hat die passende Größe?
Siehe Faustformel für Speicherbedarf
Testen Sie anschließend die verbleibenden Modelle mit den Top 10 Aufgaben bzw. Fragen, um einen geeigneten Kandidaten herauszufiltern. Wenn das ursprüngliche Modell bereits größere Probleme mit den Aufgaben hat, wird das Finetuning in der Regel keinen Erfolg haben.
Voraussetzungen
Hardware:
- Für vollständiges Fine-Tuning benötigt man sehr viel VRAM.
- Sehr kleine Modelle (z.B. 0.5B) benötigen schon 10-12 GB VRAM
- Und kleine Modelle (z.B. 7B) brauchen bereits 40–60 GB VRAM.
- Für LoRA/QLoRA reichen oft schon 12–24 GB VRAM für kleine Modelle.
🔎 Faustformel für Speicherbedarf
Grobformel (pro Schritt, pro Gerät/GPU):
Speicher ≈ Batch_Size × max_length × Modellgröße-Faktor × 4 Byte × Sicherheitsfaktor
Aufgeschlüsselt:
| Parameter | Bedeutung |
|---|---|
| Batch_Size | per_device_train_batch_size |
| max_length | maximale Token-Länge |
| Modellgröße-Faktor | ungefähr 2 × Anzahl der Modell-Parameter (4 Byte 32-bit-Float → pro Wert) (Bei bf16, dann ≈2 Bytes) |
| Sicherheitsfaktor | Puffer für Gradienten, Optimierer, Cache (ca. 1.3–2.0) |
📐 Beispiel Qwen3-0.6B (600 Mio Parameter)
- Parameterzahl: 0,6 Milliarden
- Modellgröße-Faktor ≈ 1,2 bis 1,5 Milliarden (wegen Zwischenspeicherungen/Layer-States)
- 1,5B × 4 Byte ≈ 6 GB theoretischer Bedarf (nur Modell)
👉 Aber:
- Das Modell selbst ist nur einmal im Speicher.
- Der Batch multipliziert sich mit der Aktivierungsspeicherung und Gradienten.
🔢 Beispiel mit Werten aus der Praxis
Batch_Size = 2
max_length = 253
Modellgröße-Faktor ≈ 1,5e9
Precision = bf16 → 2 Byte
Sicherheitsfaktor ≈ 1.5 (wegen Gradient, Optimizer, Sampler usw.)
Berechnung:
Speicher ≈ 2 × 253 × 1,5e9 × 2 Byte × 1.5
Das gibt:
≈ 2 × 253 × 1.5e9 × 2 × 1.5
≈ 2 × 253 × 3e9
≈ 1.518e12 Bytes
≈ 1.518 TB → unrealistisch!
Warum?
Die einfache Formel überschätzt, weil sie davon ausgeht, dass jede Kombination von Batch × Länge × Modellparametern separat gespeichert werden muss (was nicht stimmt).
🧠 Realistischere Faustregel (transformers + PyTorch)
In der Praxis gilt für Causal LM Training:
Speicherverbrauch ≈ Basismodell (6 GB bei 0.6B) +
Batch_Size × max_length × 0.001 bis 0.005 GB
🔎 Beispiel konkret:
| Parameter | Wert |
|---|---|
| Modellgröße | ≈ 6 GB |
| Batch_Size × max_length | 2 × 253 = 506 |
| Speicherzuwachs | 506 × 0.003 GB = 1,5 GB |
| Overhead/Puffer | ≈ 1–1,5 GB |
Gesamt: ≈ 8,5–9 GB
(0.003 ist erfahrungsbasiert für Qwen3 + bf16 + Trainer.)
(Speicherbedarf während des Full-Fine-Tunings war ~7,4 GB → sehr plausibel!)
🔥 Kurzformel VRAM Bedarf
Speicher (GB) ≈ 6 + (Batch_Size × max_length × 0.003) + 1
Speicherbedarf reduzieren
Um den Speicherbedarf eines gegebenen Modells zu reduzieren, haben Sie zwei Stellschrauben zur Verfügung: Zum einen die Batch_Size und zum anderen die max_length. Die Reduzierung der Batch_Size führt zu einem deutlich längeren Trainingslauf. Um die max_length zu verkleinern, ist eine Aufbereitung des Trainingsdatensatzes notwendig.
Für Datensätze, die für Modelle der Qwen-Reihe verwendet werden, wurde ein Python-Skript erstellt, das die Token zählt und die Datensätze, die unter einem angegebenen Schwellwert liegen, in einer neuen Datei speichert.
# token_length_analyse_tool.py Tokens zaehlen und aussortieren
from transformers import AutoTokenizer
import json
import argparse
def analyse_token_lengths(input_file, model_path, output_file=None, max_output_tokens=None):
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
with open(input_file, "r", encoding="utf-8") as f:
data = json.load(f)
bins = {128: 0, 256: 0, 512: 0, 1024: 0, 2048: 0, 4096: 0}
total_examples = 0
max_tokens_found = 0
filtered = []
for item in data:
# 👇 Erkennen, ob "messages" oder "question"/"answer"
if "messages" in item:
chat = ""
for msg in item["messages"]:
role = msg.get("role", "").strip()
content = msg.get("content", "").strip()
chat += f"<|im_start|>{role}\n{content}<|im_end|>\n"
else:
question = item.get("question", "")
answer = item.get("answer", "")
chat = f"<|im_start|>user\n{question}<|im_end|>\n<|im_start|>assistant\n{answer}<|im_end|>\n"
total_tokens = len(tokenizer(chat)["input_ids"])
total_examples += 1
max_tokens_found = max(max_tokens_found, total_tokens)
for limit in bins:
if total_tokens <= limit:
bins[limit] += 1
if max_output_tokens and total_tokens <= max_output_tokens:
filtered.append(item)
print(f"Gesamtzahl der Beispiele: {total_examples}")
print(f"Längster Eintrag hat {max_tokens_found} Tokens.\n")
for limit in sorted(bins):
prozent = bins[limit] / total_examples * 100
print(f"≤ {limit} Tokens: {bins[limit]} Beispiele ({prozent:.1f}%)")
if output_file and max_output_tokens:
with open(output_file, "w", encoding="utf-8") as out_f:
json.dump(filtered, out_f, indent=2, ensure_ascii=False)
print(f"\n✅ {len(filtered)} Beispiele mit ≤ {max_output_tokens} Tokens gespeichert in {output_file}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Tokenlängen-Analyse mit optionalem Speichern kurzer Beispiele.")
parser.add_argument("--input_file", type=str, required=True)
parser.add_argument("--model_path", type=str, required=True)
parser.add_argument("--output_file", type=str, default=None)
parser.add_argument("--max_output_tokens", type=int, default=None)
args = parser.parse_args()
analyse_token_lengths(
input_file=args.input_file,
model_path=args.model_path,
output_file=args.output_file,
max_output_tokens=args.max_output_tokens
)
Starten mit:Ausgabe:python3 token_length_analyse_tool.py --input_file synthetic_latex_tables.json --model_path /home/user/Qwen3 --output_file latex_table_small.json --max_output_tokens 256
Gesamtzahl der Beispiele: 1000
Längster Eintrag hat 646 Tokens.
≤ 128 Tokens: 0 Beispiele (0.0%)
≤ 256 Tokens: 63 Beispiele (6.3%)
≤ 512 Tokens: 911 Beispiele (91.1%)
≤ 1024 Tokens: 1000 Beispiele (100.0%)
≤ 2048 Tokens: 1000 Beispiele (100.0%)
≤ 4096 Tokens: 1000 Beispiele (100.0%)
✅ 63 Beispiele mit ≤ 256 Tokens gespeichert in latex_table_small.json
Vorbereitung Full Finetuning
🖥️ 1. Vorbereitung des Servers
🔹 1.1. Notwendige Pakete installieren
Zuerst aktualisieren wir das System und installieren grundlegende Abhängigkeiten:
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3 python3-venv python3-pip git wget unzip curl
Falls noch nicht vorhanden, installiere NVIDIA-Treiber und CUDA:
sudo apt install -y nvidia-driver-xxx
sudo apt install -y cuda-toolkit-12-0
🔹 1.2. NVIDIA- und CUDA-Version prüfen
nvidia-smi # Zeigt verfügbare GPUs an
nvcc --version # Prüft die CUDA-Version
Falls CUDA noch nicht aktiv ist:
export PATH=/usr/local/cuda-12.0/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.0/lib64:$LD_LIBRARY_PATH
🐍 2. Erstellen einer Python-Umgebung
Erstelle eine virtuelle Umgebung für das Training:
python3 -m venv ~/qwen3-finetune
source ~/qwen3-finetune/bin/activate
Installiere die benötigten Python-Pakete:
pip install --upgrade pip
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install transformers datasets accelerate bitsandbytes peft gradio
📦 3. Modell herunterladen
Für das Training nutzen wir ein kompaktes Modell wie Qwen3-0.6B:
mkdir -p /user/Qwen3
cd /user/Qwen3
wget https://huggingface.co/Qwen/Qwen3-0.6B/resolve/main/config.json
wget https://huggingface.co/Qwen/Qwen3-0.6B/resolve/main/generation_config.json
wget https://huggingface.co/Qwen/Qwen3-0.6B/resolve/main/merges.txt
wget https://huggingface.co/Qwen/Qwen3-0.6B/resolve/main/model.safetensors
wget https://huggingface.co/Qwen/Qwen3-0.6B/resolve/main/tokenizer.json
wget https://huggingface.co/Qwen/Qwen3-0.6B/resolve/main/tokenizer_config.json
wget https://huggingface.co/Qwen/Qwen3-0.6B/resolve/main/vocab.json
🔢 4. Trainer aus der Praxis
# 🚀 tabular_trainer_corrected.py – Fine-Tuning für Qwen3-0.6B (Tabellenumgebung (Standard))
import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments,
Trainer,
DataCollatorForLanguageModeling,
)
from datasets import load_dataset
MODEL_PATH = "/home/user/Qwen3"
DATA_PATH = "/home/user/datasets/tabular_messages.json"
OUTPUT_PATH = "/home/user/tabular_qwen3_results"
model = AutoModelForCausalLM.from_pretrained(
MODEL_PATH,
torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token
dataset = load_dataset("json", data_files=DATA_PATH, split="train")
split = dataset.train_test_split(test_size=0.1, seed=42)
train_dataset = split["train"]
eval_dataset = split["test"]
def tokenize_function(examples):
input_texts, label_texts = [], []
for messages in examples["messages"]:
if not messages:
continue
chat = ""
for msg in messages:
role = msg.get("role", "").strip()
content = msg.get("content", "").strip()
if not role or not content:
continue
chat += "<|im_start|>" + role + "\\n" + content + "<|im_end|>\\n"
assistant_start = chat.find("<|im_start|>assistant\\n")
if assistant_start == -1:
continue
input_part = chat[:assistant_start] + "<|im_start|>assistant\\n"
response_part = chat[assistant_start + len("<|im_start|>assistant\\n"):].strip()
if not response_part:
continue
input_texts.append(input_part)
label_texts.append(response_part + tokenizer.eos_token)
if not input_texts:
return {}
model_inputs = tokenizer(input_texts, truncation=True, padding="max_length", max_length=256)
with tokenizer.as_target_tokenizer():
labels = tokenizer(label_texts, truncation=True, padding="max_length", max_length=256)["input_ids"]
labels = [
[-100 if token == tokenizer.pad_token_id else token for token in label_seq]
for label_seq in labels
]
model_inputs["labels"] = labels
return model_inputs
train_dataset = train_dataset.map(tokenize_function, batched=True, remove_columns=["messages"], num_proc=4)
eval_dataset = eval_dataset.map(tokenize_function, batched=True, remove_columns=["messages"], num_proc=4)
collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
args = TrainingArguments(
output_dir=OUTPUT_PATH,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
bf16=True,
num_train_epochs=5,
logging_steps=10,
save_strategy="epoch",
eval_strategy="epoch",
learning_rate=2e-5,
warmup_ratio=0.1,
lr_scheduler_type="cosine",
remove_unused_columns=False,
report_to="none"
)
trainer = Trainer(
model=model,
args=args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
data_collator=collator,
)
trainer.train()
trainer.save_model(OUTPUT_PATH)
tokenizer.save_pretrained(OUTPUT_PATH)
print("✅ Fine-Tuning abgeschlossen:", OUTPUT_PATH)
Starten mit: CUDA_VISIBLE_DEVICES=0 python3 tabular_trainer_corrected.py
Vorbereitung auf das Finetuning Lora
- Basismodell: TinyLlama, Mistral, Phi-2
- Python-Pakete: transformers, datasets, peft, bitsandbytes
- Hardware: 12–24 GB VRAM für LoRA empfohlen
pip install transformers datasets peft bitsandbytes unsloth
Praxis: Finetuning mit LoRA
Wenn nur vergleichsweise kleine Grafikkarten zur Verfügung stehen, wird bei LoRA das Programm unsloth (unsloth.ai) verwendet, da es teilweise deutliche Einsparungen beim benötigten VRAM-Speicher bietet.
🔢 Trainer aus der Praxis
# Neu_Coder_1-5B_train_qwen.py
import os
import json
import torch
from unsloth import FastLanguageModel
from peft import LoraConfig, get_peft_model
from transformers import AutoTokenizer, TrainingArguments, Trainer
from datasets import Dataset
# 1️⃣ 🚀 GPU-Check
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"🚀 Using device: {device}")
# 2️⃣ 🔥 Modell & Tokenizer laden
MODEL_PATH = "/home2/mike/Qwen2.5-Coder-1.5B"
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
# 3️⃣ 🔥 LaTeX-Spezialtokens hinzufügen
SPECIAL_TOKENS = [
"\\frac", "\\sum", "\\int", "\\begin{align}", "\\end{align}",
"\\begin{equation}", "\\end{equation}", "\\begin{tabular}", "\\end{tabular}",
"\\hline", "\\multicolumn", "\\includegraphics", "\\ce{}", "\\chemfig{}",
"\\begin{itemize}", "\\end{itemize}", "\\begin{frame}", "\\end{frame}",
]
num_added_tokens = tokenizer.add_tokens(SPECIAL_TOKENS)
print(f"✅ {num_added_tokens} neue LaTeX-Spezialtokens hinzugefügt!")
# 4️⃣ 🔥 Tokenizer speichern
tokenizer.save_pretrained("/home2/mike/Qwen2.5-Coder-1.5B-LaTeX-Finetuned/tokenizer")
# 5️⃣ 🔥 Modell mit QLoRA laden
model, _ = FastLanguageModel.from_pretrained(
model_name=MODEL_PATH,
load_in_4bit=True,
max_seq_length=2048,
attn_implementation="flash_attention_2",
device_map="auto", # 🔥 Automatische Multi-GPU-Zuweisung
)
# 🔥 LoRA-Adapter konfigurieren
lora_config = LoraConfig(
r=8,
lora_alpha=16,
lora_dropout=0.05,
bias="none",
target_modules=["q_proj", "v_proj"], # Optimiert für Qwen
)
# 🔥 QLoRA aktivieren (Fix)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# 6️⃣ 🔥 Trainingsdaten laden
DATASET_PATH = "/home2/mike/combined_latex_data.json"
with open(DATASET_PATH, "r", encoding="utf-8") as f:
raw_data = json.load(f)
# 7️⃣ 🔥 Dataset formatieren
dataset = Dataset.from_list(raw_data)
dataset = dataset.shuffle(seed=42)
print(f"📌 Beispiel-Datensatz: {dataset[0]}")
def tokenize_function(examples):
questions = [q if isinstance(q, str) and q.strip() else "Was ist LaTeX?" for q in examples["question"]]
answers = [a if isinstance(a, str) and a.strip() else "LaTeX ist ein Textsatzsystem." for a in examples["answer"]]
return tokenizer(
questions,
text_target=answers,
truncation=True,
padding="max_length",
max_length=512
)
# 8️⃣ 🔥 Tokenisierung
dataset = dataset.map(tokenize_function, batched=True, remove_columns=["question", "answer"])
# 9️⃣ 🔥 Trainings- & Testdaten splitten
split = dataset.train_test_split(test_size=0.2)
train_dataset, eval_dataset = split["train"], split["test"]
# 🔟 🔥 Trainingsparameter
training_args = TrainingArguments(
output_dir="Qwen2.5-Coder-1.5B-LaTeX-Finetuned",
evaluation_strategy="steps",
eval_steps=500,
save_strategy="epoch",
per_device_train_batch_size=64,
per_device_eval_batch_size=64,
gradient_checkpointing=True,
gradient_accumulation_steps=16,
num_train_epochs=3,
save_total_limit=2,
logging_dir="./logs",
logging_steps=100,
learning_rate=5e-5,
weight_decay=0.01,
fp16=False,
bf16=True,
push_to_hub=False,
report_to="none",
remove_unused_columns=False,
)
# 🔥 Trainer definieren
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
tokenizer=tokenizer,
)
# Stelle sicher, dass LoRA-Gewichte Gradient-Berechnung aktiv haben
#for param in model.parameters():
# param.requires_grad = True
# Stelle sicher, dass nur trainierbare LoRA-Parameter Gradienten haben
for param in model.parameters():
if param.dtype in [torch.float16, torch.float32, torch.bfloat16]: # ✅ Nur Gleitkommazahlen
param.requires_grad = True
# 🔥 Fine-Tuning starten!
trainer.train()
# 🔥 Speichern des trainierten Modells
trainer.save_model("Qwen2.5-Coder-1.5B-LaTeX-Finetuned")
print("✅ Training abgeschlossen & Modell gespeichert!")
Jetzt: Dataset laden, Tokenisieren und Training starten!
Vergleich: Vollständiges Finetuning vs. LoRA
| Ziel | Empfehlung |
|---|---|
| Starke Spezialisierung | Vollständiges Finetuning |
| Einfache Anpassung | LoRA oder QLoRA |
Tipps für die Hyperparameter
- Learning Rate: 2e-5 bis 1e-4
- Batchgröße: So groß wie möglich
- Max Steps: 1000–5000
- Checkpoints: Alle 500–1000 Schritte speichern
Mixture of Experts (MoE)
Mixture of Experts (MoE) ist eine Technik, bei der nur ein Teil der Modellparameter in jedem Schritt des Trainings oder der Inferenz verwendet wird. Dies ermöglicht eine erhebliche Reduzierung des benötigten Speichers und der Rechenleistung, ohne die Leistungsfähigkeit des Modells zu beeinträchtigen.
In MoE-Modellen gibt es mehrere Experten (Teilmodelle), aber nur einer oder wenige werden gleichzeitig aktiviert, basierend auf der Eingabe. Diese Technik ist besonders nützlich, um sehr große Modelle effizient zu trainieren und zu betreiben, ohne die gesamten Modellparameter auf einmal zu verwenden.
- Vorteile: Reduziert den Rechenaufwand, spart Speicher, ermöglicht den Einsatz sehr großer Modelle auf weniger leistungsfähiger Hardware.
- Herausforderungen: Komplexität bei der Implementierung und Abstimmung der Experten, potenziell schwierigeres Training aufgrund der sparsamen Aktivierung.
MoE-Modelle haben besonders im Bereich der großen Sprachmodelle (LLMs) an Bedeutung gewonnen, da sie eine effiziente Möglichkeit bieten, mit den wachsenden Anforderungen an Speicher und Rechenleistung umzugehen.
🧠 Grundidee: Mixture of Experts (MoE)
- Statt eines großen Monolith-Modells (z. B. 7B) → mehrere kleine Modelle (z. B. 8×0.6B)
- Bei jeder Inferenz (Anfrage) wird nur ein Teil der Experten aktiviert (z. B. 2 von 8)
- Router-Modul entscheidet, welcher Experte für welche Token zuständig ist
- Vorteile: schneller, skalierbarer, sparsamer in GPU-Ressourcen
🛠️ Beispiel Anwendung
🧱 Eine Basisstruktur für:
- 1 Router-Modell
- 3 Fine-Tuned Expertenmodelle
- gemeinsames Interface
🖥️ Gradio-Frontend, das je nach Eingabe automatisch den passenden Experten anspricht
# 🌐 gradio_router_qwen3.py – Web-Oberfläche für den Qwen3-Router from transformers import AutoModelForCausalLM, AutoTokenizer import torch import gradio as gr DEVICE = "cuda" if torch.cuda.is_available() else "cpu" experts = { "math": "/home/user/math_qwen3_results/checkpoint-228", "tabular": "/home/user/tabular_qwen3_results/checkpoint-228", "biblatex": "/home/user/biblatex_qwen3_results/checkpoint-228", } models = {} tokenizers = {} for name, path in experts.items(): print(f"🔹 Lade {name}...") models[name] = AutoModelForCausalLM.from_pretrained(path, device_map="auto", torch_dtype=torch.bfloat16) tokenizers[name] = AutoTokenizer.from_pretrained(path, trust_remote_code=True) tokenizers[name].pad_token = tokenizers[name].eos_token def route(question): q = question.lower() if any(k in q for k in ["cite", "bibliography", "biblatex", "isbn", "literaturverzeichnis", "zitat"]): return "biblatex" if any(k in q for k in ["table", "tabelle", "tabellen", "spalten", "zeilen", "tabular", "column", "row"]): return "tabular" if any(k in q for k in ["frac", "sum", "equation", "integral", "math", "bruch", "summe", "gleichung"]): return "math" return None def build_prompt(question): return f"""<|im_start|>system Du bist ein hilfsbereiter LaTeX-Assistent.<|im_end|> <|im_start|>user {question}<|im_end|> <|im_start|>assistant """ def ask_expert(expert_name, question): model = models[expert_name] tokenizer = tokenizers[expert_name] prompt = build_prompt(question) inputs = tokenizer(prompt, return_tensors="pt").to(model.device) with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=512, do_sample=False, temperature=0.7, top_k=50, top_p=0.95, eos_token_id=tokenizer.eos_token_id ) decoded = tokenizer.decode(outputs[0], skip_special_tokens=False) start = decoded.find("<|im_start|>assistant\n") + len("<|im_start|>assistant\n") answer = decoded[start:].split("<|im_end|>")[0].strip() return answer def router_interface(user_input): expert = route(user_input) if expert: response = ask_expert(expert, user_input) return f"🔁 Experte: {expert}\n\n📤 Antwort:\n{response}" return "🤷♂️ Kein passender Experte gefunden." demo = gr.Interface( fn=router_interface, inputs=gr.Textbox(lines=3, label="Deine LaTeX-Frage"), outputs=gr.Textbox(label="Antwort"), title="Qwen3 Router – Multi-Experten-Assistent", description="Stellt Fragen zu LaTeX! Der Router entscheidet automatisch, welcher Experte (math, tabular, biblatex) antwortet." ) if __name__ == "__main__": demo.launch(server_name="127.0.0.1", server_port=7860) # Für lokalen Zugriff
🛠️ Paralleles Training
Wenn der verwendete Rechner mehrere Grafikkarten zur Verfügung hat, können mehrere Modelle parallel trainiert werden. Insbesondere bei sehr kleinen Modellen, wie zum Beispiel Qwen3-0.6B, lässt sich die Trainingszeit auf diese Weise deutlich reduzieren.
Auf dem Testrechner standen 4 NVIDIA GeForce GTX TITAN X zur Verfügung, sodass alle drei Trainer parallel arbeiten konnten. Der Start des Trainings erfolgt mit den folgenden Befehlen:
CUDA_VISIBLE_DEVICES=0 python3 math_trainer_corrected.py &
CUDA_VISIBLE_DEVICES=1 python3 tabular_trainer_corrected.py &
CUDA_VISIBLE_DEVICES=2 python3 biblatex_trainer_corrected.py
Dabei wird CUDA_VISIBLE_DEVICES=Nummer verwendet, um eine bestimmte Grafikkarte einem bestimmten Trainer zuzuordnen.
Nach dem Training wurde das Webinterface gestartet und das Ergebnis getestet:
CUDA_VISIBLE_DEVICES=0 python3 gradio_router_qwen3.py
Übungen
- Wähle ein kleines Modell und tune es mit einem eigenen Mini-Dataset.
- Vergleiche Antworten vor und nach dem Finetuning.
Zusammenfassung
- Finetuning macht LLMs anpassungsfähig.
- LoRA/QLoRA spart Speicher und Zeit.
- MoE fassen mehrere kleine LLMs zu einem großen zusammen.
- Gute Datensätze sind wichtiger als große.
Besser 500 hochwertige Beispiele als 50.000 schlechte!
📚 Modul 5: Daten richtig nutzen – Datensätze verstehen und erstellen [Fortgeschritten]
Warum sind Datensätze wichtig?
LLMs lernen ausschließlich durch Beispiele. Die Qualität der Daten bestimmt direkt die Qualität des Modells.
Garbage in - Garbage out!
Datenarten für LLMs
| Datenart | Beschreibung | Beispiel |
|---|---|---|
| Instruktionen | Aufgabe + Antwort | „Wie funktioniert Recycling?“ |
| Dialoge | Frage-Antwort-Verläufe | Chat-Support |
| Klassifikationen | Kategorisierung | Wahr/Falsch |
| Komplexe Aufgaben | Schrittweises Problemlösen | Matheaufgabe |
Tipp: Für kleine Projekte reichen oft Instruktionsdatensätze.
Quellen für Datensätze
- Open-Source: Alpaca, Dolly, OpenAssistant (Lizenz prüfen!)
- Eigene Erstellung: Vollständig angepasst, aber aufwendiger
- Aufbereitung eigener Daten: FAQs, Support-Daten etc.
🔥 Optimales Verhältnis zwischen echten und synthetischen Daten für ein LLM
Das Verhältnis zwischen realen Daten und synthetischen Daten hängt stark vom Ziel des Modells ab. Je nachdem, was Ihr Fine-Tuning erreichen soll, kann das Verhältnis variieren.
📌 1️⃣ Wichtige Faktoren für die Mischung
✅ Echte Daten
- Enthalten reale Fehler & Workarounds → wichtig für echte Nutzerfragen
- Zeigen echte Struktur & Stil → z. B. Mathematik, Dokumente
- Sind begrenzt verfügbar
✅ Synthetische LaTeX-Daten
- Erlauben vollständige Kontrolle über Syntax & Struktur
- Können spezielle Edge-Cases abdecken (z. B. seltene Aufgaben / Fragen)
- Vermeiden Tippfehler & schlechte Praktiken → Modell lernt "saubere" Version
💡 Ziel: Eine Kombination aus beidem, um ein möglichst robustes Modell zu erhalten.
🔥 2️⃣ Optimale Verhältnisse für verschiedene Modelle
Je nach Ziel des Modells gibt es unterschiedliche empfohlene Mischverhältnisse, hier als Beispiel bei einem LaTeX ChatBot:
| Modell-Typ | Reale Daten | Synthetische Daten | Warum? |
|---|---|---|---|
| Fehlertoleranter LaTeX-Assistent | 70% | 30% | Modell muss echte Fehler verstehen und korrigieren. |
| Generativer LaTeX-Code-Erzeuger | 30% | 70% | Fokus auf sauberen Code, wenig "echte" Fehler. |
| Hybrid (beides können) | 50% | 50% | Beste Balance zwischen realer Nutzung und guter Syntax. |
In Fall eines LaTeX-Kurs-Chatbot wäre 50% echte Daten + 50% synthetische Daten eine sehr gute Mischung. 🚀
Soll das LLM nur Beispiele generieren, können 100% synthetische Daten verwendet werden. Je mehr Interaktion zwischen Modell und Nutzer stattfindet, desto mehr reale Daten werden benötigt.
Eigene Datensätze erstellen
- Thema wählen (z.B. Nachhaltigkeit)
- Aufgaben formulieren (klar, realistisch)
- Antworten schreiben (präzise, vollständig)
- Format speichern (JSON oder JSONL)
{
"instruction": "Nenne drei Vorteile von Solarenergie.",
"input": "",
"output": "Solarenergie ist umweltfreundlich, erneuerbar und senkt Energiekosten."
}
Hinweis: Der Aufbau der Daten unterscheidet sich zwischen den verschiedenen Modellfamilien, sodass der Datensatz für andere Modellfamilien in der Regel überarbeitet bzw. konvertiert werden muss.
Qwen Daten Format Aufbau
[
{
"messages": [
{
"role": "user",
"content": "Frage oder Aufgabe"
},
{
"role": "assistant",
"content": "Eine Erklärung / Antwort oder Beispiel zu der Frage."
}
]
}
]
Tipp: Aufgaben und Antworten leicht variieren, um Überanpassung zu vermeiden!
Einfluss der Datenqualität
| Fehlerquelle | Folge |
|---|---|
| Unklare Aufgaben | Unsichere Antworten |
| Fehlerhafte Antworten | Falsches Wissen wird gelernt |
| Doppelte Aufgaben | Einseitiges Modellverhalten |
Qualitätsmerkmale: Vielfalt, Klarheit, Korrektheit, konsistenter Stil.
Balance und Sampling
Empfohlene Mischung:
- 80–90% einfache Aufgaben (z.B. Verständnisfragen)
- 10–20% komplexe Aufgaben (z.B. Schritt-für-Schritt-Analysen)
Zusätzlich:
- Themenvielfalt sicherstellen
- Regelmäßig Stichproben prüfen
- Lizenzen beachten
Übungen
- Erstelle ein Mini-Dataset (10–20 Aufgaben + Antworten)
- Nutze klare Aufgabenstellungen und korrekte Antworten
- Speichere dein Dataset als JSON
- (Optional) Teste dein Dataset auf einem LLM
Zusammenfassung
- Datensätze sind entscheidend für gutes Modellverhalten.
- Instruktionsdatensätze eignen sich ideal für den Einstieg.
- Qualität schlägt Quantität.
- Kleine, saubere Datensätze reichen oft völlig aus.
🧩 Exkurs: Größe des Datensatzes
Eine der wichtigsten Fragen beim Full Fine Tuning ist die Frage nach der Größe des benötigten Datensatzes. Die Größe hat dabei nicht nur einen Einfluss darauf, was das Modell lernt, sondern auch darauf, was das Modell alles vergisst.
Die Antwort fällt in den Bereich „es kommt darauf an“.
- Die Qualität der Daten hat einen großen Einfluss.
- Wie viele Parameter besitzt das Modell?
- Aus welchem Bereich stammt das Modell?
🧠 Faustregeln für sehr kleine Modelle
Bei Modellen, die kleiner als 1B sind, also weniger als 1 Milliarde Parameter besitzen, sollte die Gesamtzahl der verwendeten Tokens (Max Tokens gesamt) zwischen 10 % und 20 % der Parametergröße des Modells liegen.
Berechnung von Max Tokens gesamt:
Max Tokens gesamt = Tokens pro Epoche × Anzahl der Epochen
Tokens pro Epoche sind dabei die Anzahl der Tokens des verwendeten Datensatzes. Diese Anzahl bestimmt sich aus der Anzahl der Datensätze und der max_length dieser.
Tokens pro Epoche = Anzahl der Daten × max_length
Anzahl der Epochen:
- Kleinere Modelle lernen schneller (höhere Perplexity-Reduktion pro Token).
- Ab 5 Epochen → Gefahr von Overfitting (vor allem bei einem homogenen Datensatz).
Hinweis: Wenn die Daten sehr gut zur Grundstruktur des Modells passen, lassen sich bereits mit 1 % gute Ergebnisse erzielen.
🔢 Trainingsgröße & Epochenschätzung
Bei einem Modell mit 0.5B Parametern wird eine Max Tokens Anzahl von ~50–100 Millionen Tokens benötigt. Die Anzahl der Epochen liegt zwischen 3 und 5. Das bedeutet, dass die Anzahl an Tokens pro Epoche bei ~10–20 Millionen liegen sollte. Die Anzahl der Einträge hängt jetzt nur noch von der max_length ab. Bei einer max_length von 256 ergibt sich, dass der Datensatz etwa 100.000 Einträge besitzen sollte.
- 100.000 Einträge × max. 256 Tokens → max. 25,6 Millionen Tokens (realistisch eher ~20 Millionen, weil nicht alle 256 voll ausgenutzt werden).
Es wird also ein Datensatz mit 100.000 Einträgen und einer Trainingsdauer zwischen 3 und 5 Epochen benötigt.
Mögliche Effekte
Mit welchen Effekten kann innerhalb eines solchen Szenarios gerechnet werden?
Szenario:
- Modellgröße: 0,5B (500 Millionen Parameter) → also ein kleineres Modell, gut für spezifische Aufgaben und begrenzte Ressourcen.
- Datensatz: 100.000 Einträge → je nach Länge kann das zwischen 50 Millionen und 200 Millionen Tokens bedeuten.
- Full Fine-Tune → alle Parameter werden aktualisiert, kein LoRA o.ä.
1️⃣ Was können Sie erwarten?
A. Anpassung an Stil & Aufgaben
- Das Modell wird sehr gut den Stil und die Struktur der Daten übernehmen.
- Perfekt für spezialisierte Domänen: z. B. juristische Antworten, LaTeX-Code, technische Anleitungen.
- Für Aufgaben, die im Training oft genug vorkommen, wird das Modell fast deterministisch die gewünschte Form liefern.
B. Katastrophales Vergessen (Catastrophic Forgetting)
- Modelle dieser Größe vergessen relativ schnell Teile ihres ursprünglichen Wissens.
- Allgemeines Weltwissen und Sprachverständnis aus dem Pretraining können stark verdrängt werden, wenn der Datensatz domänenspezifisch und homogen ist.
C. Überanpassung (Overfitting)
- Bei 100k Einträgen besteht potenziell die Gefahr des Overfittings, besonders wenn:
- Der Datensatz sehr repetitiv oder wenig vielfältig (homogen) ist.
- Zu viele Fine-Tuning-Epochen verwendet werden.
- Mit 0.5B ist das aber noch gut steuerbar — kleinere Modelle neigen weniger stark zu „memorization“ als große LLMs (>7B).
2️⃣ Konkret erreichbare Effekte (je nach Datentyp)
| Datentyp | Ergebnis |
|---|---|
| Klares QA-Format (Frage/Antwort) | Sehr hohe Reproduktionstreue, zuverlässige Antworten |
| Freitext/Stil | Modell übernimmt den Stil und den Tonfall gut |
| Programmiersprachen | Gute Reproduktion von Mustercode, aber limitiert bei seltenen Libraries |
| Dialog/Chat | Klare Anpassung an die Gesprächsstruktur, falls gut vertreten |
3️⃣ Grenzen & realistische Erwartungen
- Komplexe Argumentation oder Transferlernen (z. B. logische Kettenbildung) → begrenzt. Für so etwas braucht man oft mindestens 3B–7B Modelle.
- Erweiterung des Wissens → kaum möglich. Das Modell kann vorhandenes Wissen umformen, aber keine echten neuen Fakten „lernen“ wie Retrieval-Augmented-Modelle.
- Stabilität → Gute Stabilität im feingetunten Bereich. Außerhalb deines Fine-Tune-Themas kann es zu Performance-Einbrüchen kommen.
4️⃣ Was ist möglich, was nicht?
| Erwartung | Möglich mit 0.5B + 100k | Realistisch? |
|---|---|---|
| Spezialisierter Stil | ✅ | Sehr gut |
| Reproduzieren von Beispielen | ✅ | Sehr gut |
| Allgemeines Weltwissen halten | ⚠️ (teilweise Verlust) | Mittelmäßig |
| Komplexe Aufgaben lösen | ❌ | Unwahrscheinlich |
| General-Purpose-Chatbot | ❌ | Nicht stabil |
Wahl des passenden Modells
Mit welchen Unterschieden kann zwischen verschiedenen Modellen gerechnet werden? Die Auswahl des passenden Modells ist ebenso wichtig wie die Qualität des Datensatzes.
Im Folgenden werden kurz die Unterschiede zwischen der Qwen2.5-0.5B und Qwen2.5-Coder-0.5B am Beispiel eines LaTeX-Chatbots mit den oben genannten Trainingsdaten gezeigt.
🔥 Zusammenfassung
| Punkt | Qwen2.5 0.5B | Qwen2.5-Coder 0.5B |
|---|---|---|
| Lernrate & Effizienz | Mittel | Deutlich besser |
| Epochs Bedarf | 3–5 | 2–4 |
| Overfitting-Risiko | Moderat bei 5 Epochs | Geringer |
| Antwortqualität im Fine-Tune-Bereich | Hoch | Sehr hoch |
| Weltwissen-Erhalt | Verlust bei Full FT | Etwas besser erhalten |
➡ Fazit
👉 Wenn man auf Qwen2.5-Coder 0.5B fine-tunet, wird der LaTeX-Chatbot präzisere, strukturiertere und stabilere Antworten liefern, kann mit weniger Epochs auskommen und wird etwas weniger Weltwissen verlieren.
🧩 Exkurs: Datensätze generieren
Neben der Nutzung eigener und synthetischer Daten besteht auch die Möglichkeit, ein LLM für die Erstellung der Datensätze zu nutzen. Dabei wird in der Regel ein vergleichsweise großes Modell als Teacher für ein kleineres Modell verwendet. Das große Modell wird zum Beispiel per Ollama zur Verfügung gestellt. Mithilfe eines Skripts, das entweder direkt auf dem Ollama-Server oder remote ausgeführt wird, wird der Datensatz erstellt. Dem großen Modell werden dabei vorab festgelegte Fragen gestellt, und aus den Antworten werden die entsprechenden Datensatz-Einträge generiert. Dieses Vorgehen hat den Vorteil, dass große Modelle mit vergleichsweise geringem VRAM-Einsatz auf einem Ollama-Server betrieben werden können und die Qualität der Antworten meist besser ist als bei kleinen Modellen. Im nachfolgenden Beispiel wurde ein `mixtral:8x7b` für die Erstellung eines Datensatzes für ein Qwen-Modell genutzt. Es wäre jedoch auch möglich, hierfür ein Modell aus der Qwen-Modellreihe zu verwenden, wie zum Beispiel das `qwen2.5-coder:32b` Modell.
# generator_datensatz_local.py
import requests
import json
# Server-IPs
TEACHER_IP = "localhost" # oder "127.0.0.1" # Teacher-Server (Mixtral-8x7B)
TEACHER_MODEL = "mixtral:8x7b"
# Basis-Prompts (werden an Mixtral geschickt)
base_prompts = [
"Wie erstelle ich eine Tabelle in LaTeX?",
"Was ist der Unterschied zwischen \\textbf{} und \\textit{} in LaTeX?",
"Wie kann ich eine Grafik in LaTeX einbinden?",
"Wie erstelle ich eine Matrix in LaTeX?"
]
# Variationen für jede Anfrage (werden nicht an Mixtral geschickt, aber im Datensatz gespeichert)
prompt_variations = {
"Wie erstelle ich eine Tabelle in LaTeX?": [
"Wie kann ich eine Tabelle in LaTeX formatieren?",
"Welche Befehle nutze ich für Tabellen in LaTeX?",
"Wie kann ich Spalten und Zeilen in LaTeX anpassen?",
"Wie funktioniert die tabular-Umgebung in LaTeX?",
],
"Was ist der Unterschied zwischen \\textbf{} und \\textit{} in LaTeX?": [
"Wann sollte ich \\textbf{} anstelle von \\textit{} in LaTeX verwenden?",
"Gibt es eine Regel für \\textbf{} vs. \\textit{}?",
"Was sind die Vorteile von \\textbf{} und \\textit{}?",
"Wie kann ich fette und kursive Schrift in LaTeX kombinieren?",
],
"Wie kann ich eine Grafik in LaTeX einbinden?": [
"Wie binde ich Bilder in LaTeX-Dokumente ein?",
"Was ist der beste Weg, um eine Grafik in LaTeX darzustellen?",
"Welche Pakete brauche ich für Bilder in LaTeX?",
"Wie kann ich die Größe von Grafiken in LaTeX ändern?",
],
"Wie erstelle ich eine Matrix in LaTeX?": [
"Wie funktioniert die Matrix-Umgebung in LaTeX?",
"Welche Matrix-Typen gibt es in LaTeX?",
"Wie kann ich eine große Matrix in LaTeX setzen?",
"Was ist der Unterschied zwischen bmatrix und pmatrix?",
]
}
# API-Funktion, um Modellantworten zu generieren
def generate_response(prompt):
""" Sendet Anfrage an Mixtral-8x7B und gibt Antwort zurück """
url = f"http://{TEACHER_IP}:11434/api/generate"
data = {"model": TEACHER_MODEL, "prompt": prompt, "stream": False}
try:
response = requests.post(url, headers={"Content-Type": "application/json"}, json=data)
response_json = response.json()
return response_json.get("response", "").strip()
except Exception as e:
print(f"⚠ Fehler bei der API-Anfrage für '{prompt}': {e}")
return None # Falls die API fehlschlägt, speichern wir nichts
# **Trainingsdaten generieren**
dataset = []
for base_prompt in base_prompts:
mixtral_response = generate_response(base_prompt) # Eine Antwort von Mixtral holen
if mixtral_response: # Nur speichern, wenn die API-Antwort gültig ist
all_prompts = [base_prompt] + prompt_variations.get(base_prompt, []) # Basis + Variationen
for prompt in all_prompts:
dataset.append({
"messages": [
{"role": "system", "content": "Du bist ein hilfreicher Assistent für LaTeX-Fragen."},
{"role": "user", "content": prompt},
{"role": "assistant", "content": mixtral_response + " <|endoftext|>"}
]
})
# Speichern als JSON-Datei
with open("qwen_training_data.json", "w", encoding="utf-8") as f:
json.dump(dataset, f, ensure_ascii=False, indent=4)
print(f"✅ Trainingsdaten für Qwen gespeichert in 'qwen_training_data.json' ({len(dataset)} Einträge)")
Hinweis: Hier wird bereits eine Variation der Fragestellung vorgenommen.
📚 Modul 6: Eigene Systeme online bringen – Gradio-Apps erstellen [Anfänger/Fortgeschritten]
Was ist Gradio?
Gradio ist eine Open-Source-Python-Bibliothek, die es ermöglicht, LLMs und andere Modelle einfach über eine Weboberfläche zugänglich zu machen.
- Schnelle Prototypenentwicklung
- Kein Webentwicklungswissen nötig
- Lokaler oder öffentlicher Betrieb möglich
Installation
pip install gradio
Unterstützt Windows, macOS und Linux.
Aufbau einer Gradio-App
- Funktion: Bearbeitet Eingabe.
- Interface: Definiert Eingabe- und Ausgabefelder.
- Launch: Startet den lokalen Server.
import gradio as gr
def antworten(text):
return "Ihre Eingabe war: " + text
g.Interface(fn=antworten, inputs="text", outputs="text").launch()
Modelle integrieren
Mit transformers:
from transformers import pipeline
import gradio as gr
model = pipeline("text-generation", model="dein_modell")
def respond(message):
output = model(message, max_length=200, temperature=0.7)
return output[0]['generated_text']
g.Interface(fn=respond, inputs="text", outputs="text").launch()
Mit Ollama:
import subprocess
def chatbot(input_text):
command = f"ollama run mistral \"{input_text}\""
result = subprocess.run(command, shell=True, capture_output=True, text=True)
return result.stdout.strip()
Modelleinstellungen anpassen
| Parameter | Bedeutung | Einfluss |
|---|---|---|
| Temperature | Kreativität der Antworten | Niedrig = exakt, Hoch = kreativ |
| Max Tokens | Maximale Länge der Antwort | Kürzere oder längere Antworten |
| Top_p | Sampling aus den wahrscheinlichsten Optionen | Feineres Antwortverhalten |
Typische Fehlerquellen
| Problem | Ursache | Lösung |
|---|---|---|
| Keine Ausgabe | Fehler in Funktion/Modell | Pfade und Modellaufruf prüfen |
| Port blockiert | Port bereits genutzt | Anderen Port wählen |
| Langsame Antworten | Modell zu groß | Kleineres Modell verwenden |
Übungen
- Installiere Gradio und erstelle eine Minimal-App.
- Erweitere die App mit Temperature- und Max Tokens-Optionen.
- Integriere dein eigenes Modell (z.B. TinyLlama).
- Teste lokal und optional im Netzwerk.
Zusammenfassung
- Gradio ermöglicht schnelle Webinterfaces für LLMs.
- Modelle können lokal oder übers Netzwerk erreichbar sein.
- Einstellungen wie Temperature und Max Tokens beeinflussen die Antworten erheblich.
Mit Gradio bringen Sie Ihr erstes eigenes KI-System schnell online!
📚 Modul 7: Abschlussprojekt – Ihr intelligenter FAQ-Bot [Fortgeschritten]
🎯 Zielsetzung
In diesem Abschlussmodul bauen Sie Ihr erstes eigenes intelligentes System: einen FAQ-Bot, der echte Fragen beantwortet, ein LLM nutzt und über eine Weboberfläche zugänglich ist.
🧠 Aufgabenstellung
Der FAQ-Bot soll:
- Fragen zu einem bestimmten Thema verstehen,
- hilfreiche Antworten liefern,
- über eine einfache Gradio-Weboberfläche erreichbar sein,
- optional auf einem angepassten Modell basieren.
Beispiele für Themen: Nachhaltigkeit, IT-Support, Reisen, Hobbys.
🛠️ Schritt-für-Schritt Umsetzung
- Thema wählen: Definieren Sie Ihr Themenfeld.
- Fragen und Antworten sammeln: Mindestens 10-20 Paare.
- Modell vorbereiten: Standardmodell oder eigenes LoRA-getuntes Modell.
- Gradio-App bauen: Texteingabe und Textausgabe konfigurieren.
- Testen: Antworten prüfen, ggf. Feinschliff vornehmen.
💬 Beispielstruktur der App
import gradio as gr
from transformers import pipeline
model = pipeline("text-generation", model="dein_finetuned_model")
def faq_bot(question):
response = model(question, max_length=200, do_sample=False)
return response[0]['generated_text']
interface = gr.Interface(fn=faq_bot, inputs="text", outputs="text",
title="Mein FAQ-Bot",
description="Stelle eine Frage zu [Thema]!")
interface.launch()
🚀 Optionale Erweiterungen
- Dynamische Temperature- und Top_p-Steuerung einbauen
- Mehrsprachigkeit unterstützen
- Antworten zusammenfassen oder priorisieren
- Fragen- und Antwortlogs speichern
📋 Projektreflexion
- Welche Hürden gab es?
- Was lief besonders gut?
- Wie könnte man den Bot in Zukunft erweitern?
Hinweis: Eine kurze Dokumentation (z.B. 1 Seite) Ihres Bots kann sehr hilfreich sein!
🧠 Zusammenfassung Modul 7
Mit diesem Projekt haben Sie:
- ein Modell für ein bestimmtes Thema angepasst,
- eine funktionierende Weboberfläche gebaut,
- einen vollständigen kleinen KI-Workflow umgesetzt.
📋 Cheat Sheet – Modul 7: Abschlussprojekt
🛠️ Workflow:
| Schritt | Aufgabe |
|---|---|
| Thema wählen | Eindeutiges Fachgebiet definieren |
| Mini-Datensatz erstellen | 10–20 typische Fragen + Antworten |
| Modell wählen/anpassen | Standard oder Finetuned-Modell |
| Gradio-App erstellen | Text-zu-Text Webinterface |
| Testen und verbessern | Antwortqualität prüfen, UI anpassen |
⚡ Tipps:
- Mit einem kleinen, klaren Thema beginnen.
- Antworten präzise und hilfreich formulieren.
- Technische Details wie Ports und GPU-Einsatz im Blick behalten.
✨ Damit haben Sie den vollständigen Prozess von der Idee bis zur Web-App durchlaufen!