# LLMs auf Intel-GPUs mit Unsloth feinabstimmen

Sie können jetzt LLMs auf Ihrem lokalen Intel-Gerät mit Unsloth feinabstimmen! Lesen Sie unsere Anleitung, wie Sie genau beginnen können, Ihr eigenes Modell zu trainieren.

Bevor Sie beginnen, stellen Sie sicher, dass Sie:

* **Intel GPU:** Data Center GPU Max Series, Arc Series oder Intel Ultra AIPC
* **Betriebssystem:** Linux (empfohlen: Ubuntu 22.04+) oder Windows 11 (empfohlen)
* **Nur Windows:** Installieren Sie das Intel oneAPI Base Toolkit 2025.2.1 (wählen Sie Version 2025.2.1)
* **Intel Grafiktreiber:** Neuester empfohlener Treiber für Windows/Linux
* **Python:** 3.10+

### Unsloth mit Intel-Unterstützung erstellen

{% stepper %}
{% step %}

#### Erstellen Sie eine neue conda-Umgebung (optional)

```bash
conda create -n unsloth-xpu python==3.10
conda activate unsloth-xpu
```

{% endstep %}

{% step %}

#### Unsloth installieren

```bash
git clone https://github.com/unslothai/unsloth.git
cd unsloth
pip install .[intel-gpu-torch290]
```

{% hint style="info" %}
Nur Linux: Installieren [vLLM](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment/vllm-guide) (Optional)\
Sie können vLLM auch für [Inference](https://unsloth.ai/docs/de/grundlagen/inference-and-deployment) und [RL](https://unsloth.ai/docs/de/los-gehts/reinforcement-learning-rl-guide). Bitte folgen Sie [vLLM's Anleitung](https://docs.vllm.ai/en/latest/getting_started/installation/gpu/#intel-xpu).
{% endhint %}
{% endstep %}

{% step %}

#### Überprüfen Sie Ihre Umgebungen

```python
import torch
print(f"PyTorch-Version: {torch.__version__}")
print(f"XPU verfügbar: {torch.xpu.is_available()}")
print(f"Anzahl XPU-Geräte: {torch.xpu.device_count()}")
print(f"XPU-Gerätename: {torch.xpu.get_device_name(0)}")
```

{% endstep %}

{% step %}

#### Starten Sie die Feinabstimmung.

Sie können direkt unser Unsloth [Notebooks](https://unsloth.ai/docs/de/los-gehts/unsloth-notebooks) oder unsere dedizierten [Feinabstimmungs-](https://unsloth.ai/docs/de/los-gehts/fine-tuning-llms-guide) oder [Verstärkungslern-](https://unsloth.ai/docs/de/los-gehts/reinforcement-learning-rl-guide) Anleitungen ansehen.
{% endstep %}
{% endstepper %}

### Nur Windows - Laufzeitkonfigurationen

Aktivieren Sie in der Eingabeaufforderung mit Administratorrechten die Unterstützung langer Pfade in der Windows-Registry:

```bash
powershell -Command "Set-ItemProperty -Path "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem" -Name "LongPathsEnabled" -Value 1
```

Dieser Befehl muss nur einmal auf einer einzelnen Maschine gesetzt werden. Er muss nicht vor jedem Lauf konfiguriert werden. Dann:

1. Laden Sie level-zero-win-sdk-1.20.2.zip von herunter [GitHub](https://github.com/oneapi-src/level-zero/releases/tag/v1.20.2)
2. Entpacken Sie die level-zero-win-sdk-1.20.2.zip
3. In der Eingabeaufforderung, unter der conda-Umgebung unsloth-xpu:

```bash
call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" -
set ZE_PATH=Pfad\zu\dem\entpackten\level-zero-win-sdk-1.20.2
```

### Beispiel 1: QLoRA-Feinabstimmung mit SFT

Dieses Beispiel zeigt, wie man ein Qwen3-32B-Modell mit 4-bit QLoRA auf einer Intel GPU feinabstimmt. QLoRA reduziert den Speicherbedarf erheblich, sodass große Modelle auf Consumer-Hardware feinabgestimmt werden können.

{% code expandable="true" %}

```python
from unsloth import FastLanguageModel, FastModel
from trl import SFTTrainer, SFTConfig
from datasets import load_dataset
max_seq_length = 2048 # Unterstützt intern RoPE-Skalierung, wählen Sie also beliebig!
# LAION-Datensatz erhalten
url = "https://huggingface.co/datasets/laion/OIG/resolve/main/unified_chip2.jsonl"
dataset = load_dataset("json", data_files = {"train" :
url}, split = "train")

# 4bit vorqualifizierte Modelle, die wir für schnelles Herunterladen + keine OOMs unterstützen.
fourbit_models = [
"unsloth/Qwen3-32B-bnb-4bit",
"unsloth/Qwen3-14B-bnb-4bit",
"unsloth/Qwen3-8B-bnb-4bit",
"unsloth/Qwen3-4B-bnb-4bit",
"unsloth/Qwen3-1.7B-bnb-4bit",
"unsloth/Qwen3-0.6B-bnb-4bit",
# "unsloth/Qwen2.5-32B-bnb-4bit",
# "unsloth/Qwen2.5-14B-bnb-4bit",
# "unsloth/Qwen2.5-7B-bnb-4bit",
# "unsloth/Qwen2.5-3B-bnb-4bit",
# "unsloth/Qwen2.5-1.5B-bnb-4bit",
# "unsloth/Qwen2.5-0.5B-bnb-4bit",
# "unsloth/Llama-3.2-3B-bnb-4bit",
# "unsloth/Llama-3.2-1B-bnb-4bit",
# "unsloth/Llama-3.1-8B-bnb-4bit",
# "unsloth/Llama-3.1-70B-bnb-4bit",
# "unsloth/mistral-7b-bnb-4bit",
# "unsloth/Phi-4",
# "unsloth/Phi-3.5-mini-instruct",
# "unsloth/Phi-3-medium-4k-instruct",
# "unsloth/Phi-3-mini-4k-instruct",
# "unsloth/gemma-2-9b-bnb-4bit",
# "unsloth/gemma-2-27b-bnb-4bit",
] # Mehr Modelle auf https://huggingface.co/unsloth

model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/Qwen3-32B-bnb-4bit",
max_seq_length = max_seq_length,
load_in_4bit = True,
# token = "hf_...", # verwenden Sie einen, wenn Sie gesperrte Modelle wie meta-llama/Llama-2-7b-hf verwenden
)

model = FastLanguageModel.get_peft_model(
model,
r = 16, # Wählen Sie eine beliebige Zahl > 0! Vorgeschlagen: 8, 16, 32, 64, 128
target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj",
],
lora_alpha = 16,
lora_dropout = 0, # Unterstützt jeden Wert, aber = 0 ist optimiert
bias = "none", # Unterstützt jeden Wert, aber = "none" ist optimiert
use_gradient_checkpointing = "unsloth", # True oder "unsloth" für sehr langen Kontext
random_state = 3407,
use_rslora = False, # Wir unterstützen rank-stabilisiertes LoRA
loftq_config = None, # Und LoftQ
)

trainer = SFTTrainer(
model = model,
tokenizer = tokenizer,
train_dataset = dataset,
dataset_text_field = "text",
max_seq_length = max_seq_length,
dataset_num_proc = 1, # Empfohlen unter Windows
packing = False, # Kann das Training für kurze Sequenzen 5x schneller machen.
args = SFTConfig(
per_device_train_batch_size = 2,
gradient_accumulation_steps = 4,
warmup_steps = 5,
max_steps = 60,
learning_rate = 2e-4,
logging_steps = 1,
optim = "adamw_8bit",
weight_decay = 0.01,
lr_scheduler_type = "linear",
seed = 3407,
dataset_num_proc=1, # Empfohlen unter Windows
),
)

trainer.train()
```

{% endcode %}

### Beispiel 2: Verstärkendes Lernen GRPO

GRPO ist eine [Verstärkungslern-](https://unsloth.ai/docs/de/los-gehts/reinforcement-learning-rl-guide) Technik zur Anpassung von Sprachmodellen an menschliche Präferenzen. Dieses Beispiel zeigt, wie man ein Modell trainiert, um einem bestimmten XML-Ausgabeformat mit mehreren Belohnungsfunktionen zu folgen.

#### Was ist GRPO?

GRPO verbessert das traditionelle RLHF durch:

* Verwendung gruppenbasierter Normalisierung für stabileres Training
* Unterstützung mehrerer Belohnungsfunktionen für multi-objektive Optimierung
* Speichereffizienter als PPO zu sein

{% code expandable="true" %}

```python
from unsloth import FastLanguageModel
import re
from trl import GRPOConfig, GRPOTrainer
from datasets import load_dataset, Dataset

max_seq_length = 1024  # Kann für längere Schlussfolgerungsspuren erhöht werden
lora_rank = 32  # Größerer Rang = intelligenter, aber langsamer
max_prompt_length = 256

# Datensatz laden und vorbereiten
SYSTEM_PROMPT = """
Antworten Sie im folgenden Format:
<reasoning>
...
</reasoning>
<answer>
...
</answer>
"""

XML_COT_FORMAT = """\
<reasoning>
{reasoning}
</reasoning>
<answer>
{answer}
</answer>
"""


def extract_xml_answer(text: str) -> str:
    answer = text.split("<answer>")[-1]
    answer = answer.split("</answer>")[0]
    return answer.strip()


def extract_hash_answer(text: str) -> str | None:
    if "####" not in text:
        return None
    return text.split("####")[1].strip()


# Auskommentieren Sie mittlere Nachrichten für 1-Shot-Prompting
def get_gsm8k_questions(split: str = "train") -> Dataset:
    data = load_dataset("openai/gsm8k", "main")[split]  # type: ignore
    data = data.map(
        lambda x: {  # type: ignore
            "prompt": [
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": x["question"]},
            ],
            "answer": extract_hash_answer(x["answer"]),
        }
    )  # type: ignore
    return data  # type: ignore


# Belohnungsfunktionen
def correctness_reward_func(prompts, completions, answer, **kwargs) -> list[float]:
    responses = [completion[0]["content"] for completion in completions]
    q = prompts[0][-1]["content"]
    extracted_responses = [extract_xml_answer(r) for r in responses]
    print(
        "-" * 20,
        f"Frage:\n{q}",
        f"\nAntwort:\n{answer[0]}",
        f"\nAntwort:\n{responses[0]}",
        f"\nExtrahiert:\n{extracted_responses[0]}",
    )
    return [2.0 if r == a else 0.0 for r, a in zip(extracted_responses, answer)]


def int_reward_func(completions, **kwargs) -> list[float]:
    responses = [completion[0]["content"] for completion in completions]
    extracted_responses = [extract_xml_answer(r) for r in responses]
    return [0.5 if r.isdigit() else 0.0 for r in extracted_responses]


def strict_format_reward_func(completions, **kwargs) -> list[float]:
    """Belohnungsfunktion, die überprüft, ob die Vervollständigung ein bestimmtes Format hat."""
    pattern = r"^<reasoning>\n.*?\n</reasoning>\n<answer>\n.*?\n</answer>\n$"
    responses = [completion[0]["content"] for completion in completions]
    matches = [re.match(pattern, r) for r in responses]
    return [0.5 if match else 0.0 for match in matches]


def soft_format_reward_func(completions, **kwargs) -> list[float]:
    """Belohnungsfunktion, die überprüft, ob die Vervollständigung ein bestimmtes Format hat."""
    pattern = r"<reasoning>.*?</reasoning>\s*<answer>.*?</answer>"
    responses = [completion[0]["content"] for completion in completions]
    matches = [re.match(pattern, r) for r in responses]
    return [0.5 if match else 0.0 for match in matches]


def count_xml(text: str) -> float:
    count = 0.0
    if text.count("<reasoning>\n") == 1:
        count += 0.125
    if text.count("\n</reasoning>\n") == 1:
        count += 0.125
    if text.count("\n<answer>\n") == 1:
        count += 0.125
    count -= len(text.split("\n</answer>\n")[-1]) * 0.001
    if text.count("\n</answer>") == 1:
        count += 0.125
    count -= (len(text.split("\n</answer>")[-1]) - 1) * 0.001
    return count


def xmlcount_reward_func(completions, **kwargs) -> list[float]:
    contents = [completion[0]["content"] for completion in completions]
    return [count_xml(c) for c in contents]


if __name__ == "__main__":
    model, tokenizer = FastLanguageModel.from_pretrained(
        model_name="unsloth/Qwen3-0.6B",
        max_seq_length=max_seq_length,
        load_in_4bit=False,  # False für LoRA 16bit
        fast_inference=False,  # vLLM-Schnellinferenz aktivieren
        max_lora_rank=lora_rank,
        gpu_memory_utilization=0.7,  # Verringern, falls kein Speicher mehr verfügbar
        device_map="xpu:0",
    )

    model = FastLanguageModel.get_peft_model(
        model,
        r=lora_rank,  # Wählen Sie eine beliebige Zahl > 0! Vorgeschlagen: 8, 16, 32, 64, 128
        target_modules=[
            "q_proj",
            "k_proj",
            "v_proj",
            "o_proj",
            "gate_proj",
            "up_proj",
            "down_proj",
        ],  # Entfernen Sie QKVO, wenn der Speicher knapp ist
        lora_alpha=lora_rank,
        use_gradient_checkpointing="unsloth",  # Ermöglicht Feinabstimmung mit langem Kontext
        random_state=3407,
    )

    dataset = get_gsm8k_questions()

    training_args = GRPOConfig(
        learning_rate=5e-6,
        adam_beta1=0.9,
        adam_beta2=0.99,
        weight_decay=0.1,
        warmup_ratio=0.1,
        lr_scheduler_type="cosine",
        optim="adamw_torch",
        logging_steps=1,
        per_device_train_batch_size=1,
        gradient_accumulation_steps=1,  # Erhöhen Sie auf 4 für gleichmäßigeres Training
        num_generations=4,  # Verringern Sie bei Speichermangel
        max_prompt_length=max_prompt_length,
        max_completion_length=max_seq_length - max_prompt_length,
        # num_train_epochs=1,  # Setzen Sie auf 1 für einen vollständigen Trainingslauf
        max_steps=20,
        save_steps=250,
        max_grad_norm=0.1,
        report_to="none",  # Kann Weights & Biases verwenden
        output_dir="outputs",
    )

    trainer = GRPOTrainer(
        model=model,
        processing_class=tokenizer,
        reward_funcs=[
            xmlcount_reward_func,
            soft_format_reward_func,
            strict_format_reward_func,
            int_reward_func,
            correctness_reward_func,
        ],
        args=training_args,
        train_dataset=dataset,
        dataset_num_proc=1,  # Empfohlen unter Windows
    )

    trainer.train()

```

{% endcode %}

## Fehlerbehebung

### Out-of-Memory (OOM)-Fehler

Wenn Ihnen der Speicher ausgeht, versuchen Sie diese Lösungen:

1. **Batchgröße reduzieren:** Verringern `per_device_train_batch_size`.
2. **Verwenden Sie ein kleineres Modell:** Beginnen Sie mit einem kleineren Modell, um den Speicherbedarf zu reduzieren.
3. **Sequenzlänge reduzieren:** Verringern `max_seq_length`.
4. **LoRA-Rang reduzieren:** Verwenden Sie `r=8` statt `r=16` oder `r=32`.
5. **Für GRPO, reduzieren Sie die Anzahl der Generierungen:** Verringern `num_generations`.

### (Nur Windows) Intel Ultra AIPC iGPU Shared Memory

Für Intel Ultra AIPC mit aktuellen GPU-Treibern unter Windows ist der gemeinsame GPU-Speicher für die integrierte GPU typischerweise standardmäßig auf **57%** des Systemspeichers eingestellt. Für größere Modelle (z. B. **Qwen3-32B**), oder wenn Sie eine längere maximale Sequenzlänge, größere Batchgröße, LoRA-Adapter mit größerem LoRA-Rang usw. während der Feinabstimmung verwenden, können Sie den verfügbaren VRAM erhöhen, indem Sie den Prozentsatz des dem iGPU zugewiesenen Systemspeichers erhöhen.

Sie können dies anpassen, indem Sie die Registry ändern:

* Pfad: `Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\MemoryManager`
* Zu ändernder Schlüssel:\
  `SystemPartitionCommitLimitPercentage` (auf einen größeren Prozentsatz setzen)
