> For the complete documentation index, see [llms.txt](https://unsloth.ai/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unsloth.ai/docs/de/modelle/gpt-oss-how-to-run-and-fine-tune/gpt-oss-reinforcement-learning/tutorial-how-to-train-gpt-oss-with-rl.md).

# Tutorial: Wie man gpt-oss mit RL trainiert

LLMs haben oft Schwierigkeiten mit Aufgaben, die komplexe Umgebungen beinhalten. Durch das Anwenden von [bestärkendem Lernen](/docs/de/loslegen/reinforcement-learning-rl-guide.md) (RL) und das Entwerfen einer benutzerdefinierten [Belohnungsfunktion](/docs/de/loslegen/reinforcement-learning-rl-guide.md#reward-functions-verifiers)können diese Herausforderungen jedoch überwunden werden.

RL kann für Aufgaben wie automatische Kernel- oder Strategieerstellung angepasst werden. Dieses Tutorial zeigt, wie man **gpt-oss** mit [**GRPO**](/docs/de/loslegen/reinforcement-learning-rl-guide.md#from-rlhf-ppo-to-grpo-and-rlvr) und Unsloth trainiert, um 2048 autonom zu schlagen.

| [2048-Notebook](https://colab.research.google.com/github/openai/gpt-oss/blob/main/examples/reinforcement-fine-tuning.ipynb) (Offizielles OpenAI-Beispiel) | [Notebook zur Kernel-Generierung](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/gpt-oss-\(20B\)-GRPO.ipynb) |
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |

**Was Sie erstellen werden:**

* Trainiere gpt-oss-20b so, dass das Modell 2048 automatisch gewinnt
* Erstelle eine minimale 2048-Umgebung, mit der das Modell interagieren kann
* Definiere **Belohnungsfunktionen** die:
  1. Überprüfen, ob die generierte Strategie kompiliert und ausgeführt werden kann,
  2. Reward-Hacking verhindern (externe Imports verbieten) und
  3. den tatsächlichen Spielerfolg belohnen
* Inference ausführen und das Modell exportieren (MXFP4 4-Bit oder zusammengeführtes FP16)

{% hint style="info" %}
**Hardware:** Das 2048-Beispiel läuft auf einer kostenlosen Colab T4, aber das Training wird langsam sein. A100/H100 ist deutlich schneller. 4-Bit-Laden + LoRA ermöglicht es, ein 20B-Modell in moderatem VRAM unterzubringen.
{% endhint %}

{% stepper %}
{% step %}

#### Unsloth installieren

Führen Sie diese Zelle am Anfang eines Notebooks aus (funktioniert auf Colab).

```bash
!pip install --upgrade -qqq uv
try: import numpy; get_numpy = f"numpy=={numpy.__version__}"
except: get_numpy = "numpy"
!uv pip install -qqq \\
    "torch>=2.8.0" "triton>=3.4.0" {get_numpy} torchvision bitsandbytes "transformers==4.56.2" \\
    "unsloth_zoo[base] @ git+https://github.com/unslothai/unsloth-zoo" \\
    "unsloth[base] @ git+https://github.com/unslothai/unsloth" \\
    git+https://github.com/triton-lang/triton.git@05b2c186c1b6c9a08375389d5efe9cb4c401c075#subdirectory=python/triton_kernels
!uv pip install --upgrade --no-deps transformers==4.56.2 tokenizers
!uv pip install --no-deps trl==0.22.2
```

{% endstep %}

{% step %}

#### gpt-oss mit Unsloth laden

Lade das 20B-Modell in 4-Bit-QLoRA für Speichereffizienz und wickle es dann mit einem LoRA-Adapter ein. Sie können es auch in 16-Bit-LoRA trainieren, aber es verwendet 4x mehr Speicher. Weitere Einstellungen finden Sie in unserem [Konfigurationsleitfaden](https://unsloth.ai/docs/de/modelle/gpt-oss-how-to-run-and-fine-tune/gpt-oss-reinforcement-learning/pages/44aed34263310d67280841ab6b72ea1e5648761f#id-2.-choose-the-right-model--method).

```python
from unsloth import FastLanguageModel
import torch

max_seq_length = 768        # Erhöhen, wenn Ihre Aufgabe längere Ausgaben erfordert
lora_rank      = 4          # Höherer Rang → besser, aber mehr VRAM/Rechenleistung

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name        = "unsloth/gpt-oss-20b",  # oder unsloth/gpt-oss-20b-BF16 auf H100
    max_seq_length    = max_seq_length,
    load_in_4bit      = True,                    # False für 16-Bit
    offload_embedding = True,                    # spart ~1 GB VRAM
)

model = FastLanguageModel.get_peft_model(
    model,
    r = lora_rank,
    target_modules = [
        "q_proj", "k_proj", "v_proj", "o_proj",
        "gate_proj", "up_proj", "down_proj",
    ],
    lora_alpha = lora_rank * 2,
    use_gradient_checkpointing = "unsloth",     # großer Speicher-Sparer
    random_state = 3407,
)
```

{% hint style="info" %}
Wenn ein OOM auftritt, versuchen Sie, `max_seq_length`, `lora_rank`oder `num_generations` (später) zu verringern, und lassen Sie `load_in_4bit=True`.
{% endhint %}
{% endstep %}

{% step %}

#### 2048-Spielumgebung (minimal)

* Ein `GameBoard` -Klasse, die **W/A/S/D** -Züge unterstützt
* Merge-/Punkte-Logik
* `execute_with_time_limit` -Wrapper, damit schlecht geschriebene Strategien den Kernel nicht aufhängen können

Sie können schnell einen Smoke-Test mit einer trivialen Politik durchführen:

```python
def always_move_left(board):
    return "W"

steps, outcome = execute_strategy(always_move_left, GameBoard(size=8, seed=42, target=2048, probability_fours=0.10))
```

{% endstep %}

{% step %}

#### Sichere Codeausführung und Anti-Cheat-Prüfungen

Generierte Strategien sind **Python-Funktionen**. Um die Ausführung sicher zu halten und Reward-Hacking zu verhindern:

* **Prüfung der Modulliste** — nur Python-Stdlib-Symbole erlauben:

  ```python
  from unsloth import check_python_modules
  ok, info = check_python_modules("""
  def strategy(board):
      import math
      from typing import Callable
      return "W"
  """)
  # ok == True bedeutet, dass nur Python-Level-Imports verwendet wurden
  ```
* **Verbotene Imports blockieren** (z. B. NumPy):

  ```python
  sample = """
  def strategy(board):
      from numpy import matmul
      return "W"
  """
  ok, info = check_python_modules(sample)  # ok => False
  ```
* **Die Ausführung absichern** in eine Sandbox-Funktion:

  ```python
  from unsloth import create_locked_down_function
  function = """
  def add(a, b):
      def adder(a):
          return a + b
      return adder(b) + b
  """
  f = create_locked_down_function(function)  # Fehler, wenn Globals / Imports verwendet werden
  ```
* **Eine harte Laufzeitbegrenzung erzwingen** für Strategieläufe:

  ```python
  from unsloth import execute_with_time_limit
  @execute_with_time_limit(2)
  def execute_strategy(strategy, game):
      # Schleife bis zum Spielende oder Timeout
      ...
  ```

{% endstep %}

{% step %}
\### Prompt & Datensatz

Wir fordern das Modell auf, **eine kurze Strategie-Funktion auszugeben** innerhalb von dreifachen Backticks:

````
Erstelle eine neue kurze 2048-Strategie, die nur nativen Python-Code verwendet.
Dir wird eine Liste von Listen von Zahlen für den aktuellen Spielbrettzustand gegeben.
Gib eine Aktion für "W", "A", "S", "D" aus, basierend auf dem optimalen nächsten Schritt.
Gib deine neue kurze Funktion in Backticks im folgenden Format aus:
```python
def strategy(board):
    return "W"  # Beispiel
````

Alle Hilfsfunktionen sollten innerhalb von def strategy liegen. Gib nur die kurze Funktion aus `strategy`.

````

Erstelle einen winzigen synthetischen Datensatz (unter Wiederverwendung desselben Prompts) und berechne die Prompt-Länge, damit GRPO weiß, wie viele Completion-Tokens gesampelt werden sollen:

```python
from datasets import Dataset

prompt = ...  # wie oben

maximum_length = len(tokenizer.apply_chat_template(
    [{"role": "user", "content": prompt}], add_generation_prompt=True
))

dataset = Dataset.from_list([
    {"prompt": [{"role": "user", "content": prompt}], "answer": 0, "reasoning_effort": "low"}
] * 1000)
````

{% hint style="info" %} Sie können diesen Datensatz durch echte Prompts für Ihre eigene RL-Aufgabe ersetzen. {% endhint %} {% endstep %}

{% step %}

#### Zeit für die Belohnungsfunktion!

1. **Extrahiere den Codeblock** aus der Antwort des Modells:

   ````python
   def extract_function(text):
       if text.count("```") >= 2:
           first = text.find("```") + 3
           second = text.find("```", first)
           fx = text[first:second].strip()
           fx = fx.removeprefix("python\n")
           fx = fx[fx.find("def"):]
           if fx.startswith("def strategy(board):"):
               return fx
       return None
   ````
2. **`function_works`** - Kompiliert es und erzeugt es eine aufrufbare Funktion?

   ```python
   from unsloth import create_locked_down_function, check_python_modules

   def function_works(completions, **kwargs):
       scores = []
       for completion in completions:
           response = completion[0]["content"]
           function = extract_function(response)
           if function is None:
               scores.append(-2.0)
               continue
           ok, info = check_python_modules(function)
           if "error" in info:
               scores.append(-2.0)
               continue
           try:
               _ = create_locked_down_function(function)
               scores.append(1.0)
           except Exception:
               scores.append(-0.5)
       return scores
   ```
3. **`no_cheating`** - Keine Imports, die nicht aus der Stdlib stammen, erlaubt:

   ```python
   def no_cheating(completions, **kwargs):
       scores = []
       for completion in completions:
           response = completion[0]["content"]
           function = extract_function(response)
           if function is None:
               scores.append(-1.0)
               continue
           ok, _ = check_python_modules(function)
           scores.append(1.0 if ok else -20.0)  # hohe Strafe bei Schummeln
       return scores
   ```
4. **`strategy_succeeds`** - Spiele ein zufälliges Board; Erfolg belohnen:

   ```python
   import numpy as np

   PRINTER = 0  # gelegentlich zum Debuggen ausgeben

   def strategy_succeeds(completions, **kwargs):
       global PRINTER
       scores = []
       seed = np.random.randint(10000)
       for completion in completions:
           response = completion[0]["content"]
           function = extract_function(response)
           if function is None:
               scores.append(-2.0)
               continue
           try:
               new_strategy = create_locked_down_function(function)
           except Exception:
               scores.append(0.0)
               continue
           try:
               game = GameBoard(size=6, seed=seed, target=2048, probability_fours=0.10)
               steps, state = execute_strategy(new_strategy, game)
               if PRINTER % 5 == 0:
                   print(function)
                   print(f"Steps={steps} State={state}")
                   print(game.board().pretty())
               PRINTER += 1
               if state == "success":
                   scores.append(20.0)
               else:
                   scores.append(2.0)   # funktionierte, erreichte aber nicht 2048
           except TimeoutError:
               scores.append(-1.0)      # Timeout
           except Exception:
               scores.append(-3.0)      # abgestürzt
       return scores
   ```

{% endstep %}

{% step %}

#### GRPO konfigurieren

Wir werden den **GRPOTrainer**verwenden. Legen Sie die Prompt-/Completion-Längen fest und erstellen Sie dann eine `GRPOConfig`. Beachten Sie, dass Sie den RL-Algorithmus-Typ auch auf andere wie [GSPO](/docs/de/loslegen/reinforcement-learning-rl-guide/advanced-rl-documentation/gspo-reinforcement-learning.md) oder Dr. GRPO setzen könnten.

```python
from trl import GRPOConfig, GRPOTrainer

max_prompt_length     = maximum_length + 1
max_completion_length = max_seq_length - max_prompt_length

training_args = GRPOConfig(
    temperature=1.0,
    learning_rate=5e-5,
    weight_decay=0.01,
    warmup_ratio=0.1,
    lr_scheduler_type="linear",
    optim="adamw_8bit",
    logging_steps=1,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=1,    # auf 4 erhöhen für glattere Belohnungssignale
    num_generations=2,                # verringern, wenn OOM auftritt
    max_prompt_length=max_prompt_length,
    max_completion_length=max_completion_length,
    max_steps=1000,                   # oder num_train_epochs=1 setzen
    save_steps=100,
    report_to="none",
    output_dir="outputs",
)

trainer = GRPOTrainer(
    model=model,
    processing_class=tokenizer,
    reward_funcs=[function_works, no_cheating, strategy_succeeds],
    args=training_args,
    train_dataset=dataset,
    # Optionaler Eval-Split:
    # train_dataset=new_dataset["train"],
    # eval_dataset=new_dataset["test"],
)
```

{% hint style="info" %} **Logs lesen:** Achten Sie auf `reward` und `reward_std`. Es ist normal, anfangs niedrige/null Belohnungen zu sehen (in den ersten \~100–200 Schritten auf kleinen GPUs). {% endhint %} {% endstep %}

{% step %}

#### Trainiere Ihr Modell

```python
trainer.train()
```

Dies startet die vollständige RL-Schleife: Completions sampeln → mit Ihren Belohnungen bewerten → die Policy optimieren (LoRA). {% endstep %}

{% step %}

#### Inference (nach dem Training)

Generiere eine frische Strategie mit dem trainierten Adapter:

```python
from transformers import TextStreamer

text = tokenizer.apply_chat_template(
    [{"role": "user", "content": prompt}],
    tokenize=False,
    add_generation_prompt=True,
    reasoning_effort="low",
)

_ = model.generate(
    **tokenizer(text, return_tensors="pt").to("cuda"),
    temperature=1.0,
    max_new_tokens=1024,
    streamer=TextStreamer(tokenizer, skip_prompt=False)
```

{% endstep %}

{% step %}

#### Speichern / Exportieren Sie Ihr feinabgestimmtes Modell

* **4-Bit zusammenführen & speichern (MXFP4)**

  ```
  ```

python model.save\_pretrained\_merged("finetuned\_model", tokenizer, save\_method="mxfp4") # oder model.push\_to\_hub\_merged("\<org\_or\_user>/", tokenizer, token="\<hf\_token>", save\_method="mxfp4") \`\`\`

* **16-Bit zusammenführen & speichern**

  ```python
  model.save_pretrained_merged("finetuned_model", tokenizer, save_method="merged_16bit")
  # oder pushen
  model.push_to_hub_merged("<org_or_user>/<repo>", tokenizer, token="<hf_token>", save_method="merged_16bit")
  ```

{% endstep %}

{% step %}

#### Fehlerbehebung & Tipps

* **OOM / langsam**: reduzieren `max_seq_length`, `num_generations`, `lora_rank`; 4-Bit beibehalten; falls verfügbar, A100 ausprobieren.
* **Keine Verbesserung der Belohnung**: Trainingsschritte erhöhen, Strafen abschwächen oder Curriculum hinzufügen (mit kleineren Brettern / niedrigeren Zielen beginnen).
* **Reward-Hacking**: `check_python_modules` streng halten; das Verhalten der Strategie über mehrere Zufalls-Seeds hinweg validieren.
* **Instabiles Training**: erhöhen `gradient_accumulation_steps` um Updates zu glätten; `learning_rate` verringern (z. B. 2e-5).
* **Lange Hänger**: sicherstellen, `execute_with_time_limit` dass jede Strategiausführung umschließt.
  {% endstep %}

{% step %}

#### An Ihre eigene RL-Aufgabe anpassen

* Ersetzen Sie die 2048-Umgebung durch Ihre eigene Umgebung und **drei Belohnungen**: (a) Syntax/Kompilierung, (b) Anti-Cheat/Sicherheit, (c) Aufgabenerfolg.
* Aktualisieren Sie den **Prompt** um die Art von Funktion oder Ausgabe anzufordern, die Sie benötigen.
* Behalten Sie denselben Unsloth- + GRPO-Rahmen bei; tauschen Sie nur Umgebung und Belohnungen aus.
  {% endstep %}
  {% endstepper %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://unsloth.ai/docs/de/modelle/gpt-oss-how-to-run-and-fine-tune/gpt-oss-reinforcement-learning/tutorial-how-to-train-gpt-oss-with-rl.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
