> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/guides/guides_v2-de/training/trl.md).

# TRL (RLHF/DPO-Training)

**TRL** (Transformer Reinforcement Learning) ist HuggingFaces offizielle Bibliothek zum Training von Sprachmodellen mit Verstärkungslernverfahren. Mit über 10.000 GitHub-Sternen bietet sie hochmoderne Implementierungen von RLHF, DPO, PPO, GRPO und anderen Alignments-Algorithmen für LLMs.

{% hint style="success" %}
Alle Beispiele können auf GPU-Servern ausgeführt werden, die über [CLORE.AI Marketplace](https://clore.ai/marketplace).
{% endhint %}

***

## Was ist TRL?

TRL ist die Bibliothek hinter vielen der heute am besten ausgerichteten Sprachmodelle. Sie bietet:

* **SFT (Supervised Fine-Tuning)** — standardmäßiges Instruction-Tuning im ChatML-Format
* **RLHF/PPO** — klassisches Proximal Policy Optimization mit einem Reward-Modell
* **DPO** — Direct Preference Optimization (kein Reward-Modell erforderlich!)
* **GRPO** — Group Relative Policy Optimization (Methode von DeepSeek-R1)
* **KTO** — Kahneman-Tversky Optimization (funktioniert mit ungepaarten Präferenzen)
* **Reward Modeling** — trainiere ein Reward-Modell aus menschlichen Präferenzdaten
* **IterativeSFT** — Online-RL mit einer einfacheren Einrichtung
* **ORPO** — Odds Ratio Preference Optimization

TRL integriert sich nativ in das HuggingFace-Ökosystem: `transformers`, `peft`, `datasets`, `accelerate`, und `bitsandbytes`.

{% hint style="info" %}
**Welchen Algorithmus sollten Sie verwenden?**

* **DPO** — am einfachsten, am stabilsten. Verwenden, wenn Sie gepaarte Präferenzdaten (gewählt/abgelehnt) haben.
* **PPO** — am leistungsfähigsten, aber komplex. Verwenden, wenn Sie ein Reward-Modell oder eine Bewertungsfunktion haben.
* **GRPO** — großartig für Aufgaben mit Reasoning/Mathematik. Trainingsmethode von DeepSeek-R1.
* **SFT** — beginnen Sie immer hier, bevor Sie eine RL-Methode anwenden.
  {% endhint %}

***

## Serveranforderungen

| Komponente     | Minimum                   | Empfohlen                |
| -------------- | ------------------------- | ------------------------ |
| GPU            | RTX 3090 (24 GB)          | A100 80 GB / H100        |
| VRAM           | 16 GB (SFT/DPO 7B + LoRA) | 80 GB (Full-Finetune 7B) |
| RAM            | 32 GB                     | 64 GB+                   |
| CPU            | 8 Kerne                   | 16+ Kerne                |
| Speicher       | 100 GB                    | 300 GB+                  |
| Betriebssystem | Ubuntu 20.04+             | Ubuntu 22.04             |
| Python         | 3.9+                      | 3.11                     |
| CUDA           | 11.8+                     | 12.1+                    |

### VRAM nach Aufgabe

| Aufgabe | Modell      | Methode     | VRAM             |
| ------- | ----------- | ----------- | ---------------- |
| SFT     | Llama 3 8B  | QLoRA 4-Bit | \~8 GB           |
| DPO     | Llama 3 8B  | LoRA        | \~20 GB          |
| PPO     | Llama 3 8B  | Vollständig | \~80 GB (2×A100) |
| GRPO    | Qwen 7B     | LoRA        | \~24 GB          |
| SFT     | Llama 3 70B | QLoRA 4-Bit | \~48 GB          |
| DPO     | Llama 3 70B | LoRA        | \~80 GB          |

***

## Ports

| Port | Dienst | Hinweise                                   |
| ---- | ------ | ------------------------------------------ |
| 22   | SSH    | Terminalzugang, Dateitransfer, Überwachung |

TRL ist eine Trainingsbibliothek — sie läuft als CLI-/Python-Skript, kein Webserver erforderlich.

***

## Installation auf Clore.ai

### Schritt 1 — Miete einen Server

1. Gehe zu [Clore.ai Marketplace](https://clore.ai/marketplace)
2. Filtere nach **VRAM ≥ 24 GB** (RTX 3090, A100 oder H100)
3. Wähle ein **PyTorch** oder **CUDA 12.1** Basis-Image
4. Wähle **Speicher ≥ 200 GB** für Modelle und Datensätze
5. Öffne Port **22** für SSH-Zugang

### Schritt 2 — Verbinden via SSH

```bash
ssh root@<server-ip> -p <ssh-port>
```

### Schritt 3 — Installiere TRL

```bash
# Erstelle Python-virtuelle Umgebung
python3 -m venv /opt/trl
source /opt/trl/bin/activate

# Installiere TRL mit allen Abhängigkeiten
pip install trl

# Installiere zusätzliche Abhängigkeiten für vollständige Workflows
pip install \
    transformers \
    datasets \
    peft \
    accelerate \
    bitsandbytes \
    wandb \
    scipy \
    sentencepiece \
    protobuf

# Überprüfe GPU-Unterstützung
python3 -c "import torch; print(f'CUDA: {torch.cuda.is_available()}, GPU: {torch.cuda.get_device_name(0)}')"
```

### Schritt 4 — HuggingFace-Authentifizierung

```bash
# Login, um auf gesperrte Modelle (Llama, Gemma) zuzugreifen
huggingface-cli login
# Gib dein HF-Token ein von https://huggingface.co/settings/tokens

# Oder setze eine Umgebungsvariable
export HF_TOKEN=hf_your-token-here
```

### Schritt 5 — Optional: Weights & Biases Tracking

```bash
# Richte Experiment-Tracking ein (sehr empfohlen)
pip install wandb
wandb login  # Gib deinen W&B API-Schlüssel ein von https://wandb.ai/settings

# Oder deaktiviere W&B
export WANDB_DISABLED=true
```

***

## Supervised Fine-Tuning (SFT)

SFT ist immer der erste Schritt vor jeder RL-Technik.

### Bereite dein Dataset vor

```python
# Format: datasets-Bibliothek mit 'messages' oder 'text' Spalte
# ChatML-Format (empfohlen)
from datasets import Dataset

data = [
    {
        "messages": [
            {"role": "system", "content": "You are a helpful GPU cloud assistant."},
            {"role": "user", "content": "How do I rent a GPU on Clore.ai?"},
            {"role": "assistant", "content": "Visit clore.ai/marketplace, filter by GPU specs, select a server, and click Rent. SSH access is provided immediately after payment."}
        ]
    },
    # ... weitere Beispiele
]

dataset = Dataset.from_list(data)
dataset.save_to_disk("data/sft_dataset")
dataset.push_to_hub("your-username/my-sft-dataset")  # optional
```

### SFT-Trainingsskript

```python
# sft_train.py
from trl import SFTTrainer, SFTConfig
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
from datasets import load_dataset
import torch

# Modellkonfiguration
model_name = "meta-llama/Llama-3.2-8B-Instruct"

# QLoRA: 4-Bit-Quantisierungs-Konfiguration
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

# Modell laden
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto",
    trust_remote_code=True,
)

# Tokenizer laden
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

# LoRA-Konfiguration
lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# Dataset laden
dataset = load_dataset("trl-lib/ultrachat_200k", split="train_sft[:10%]")

# Trainingskonfiguration
training_config = SFTConfig(
    output_dir="./sft_output",
    num_train_epochs=3,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=4,
    learning_rate=2e-4,
    warmup_ratio=0.05,
    lr_scheduler_type="cosine",
    fp16=False,
    bf16=True,
    max_seq_length=2048,
    dataset_text_field="messages",
    logging_steps=10,
    save_steps=100,
    save_total_limit=3,
    push_to_hub=False,
    report_to="wandb",  # oder "none"
)

# Trainer initialisieren
trainer = SFTTrainer(
    model=model,
    args=training_config,
    train_dataset=dataset,
    peft_config=lora_config,
    tokenizer=tokenizer,
)

# Trainieren
trainer.train()
trainer.save_model("./sft_final")
```

```bash
# Training ausführen
python3 sft_train.py
```

***

## DPO (Direct Preference Optimization)

DPO ist die populärste Alignment-Methode — kein Reward-Modell nötig, nur Präferenzpaare.

### Bereite DPO-Dataset vor

```python
# Format: jedes Beispiel hat 'prompt', 'chosen', 'rejected'
from datasets import Dataset

data = [
    {
        "prompt": "Erkläre, wie man die GPU-Auslastung optimiert",
        "chosen": "Um die GPU-Auslastung zu optimieren: 1) Verwenden Sie größere Batch-Größen, um die Auslastung zu maximieren, 2) Aktivieren Sie Mixed Precision (bf16/fp16), 3) Profilieren Sie mit nvidia-smi, um Engpässe zu identifizieren, 4) Verwenden Sie CUDA-Streams für parallele Operationen.",
        "rejected": "Benutze einfach mehr GPUs."
    },
    # ... mehr Präferenzpaare
]

dataset = Dataset.from_list(data)
```

### DPO-Trainingsskript

```python
# dpo_train.py
from trl import DPOTrainer, DPOConfig
from transformers import AutoTokenizer, AutoModelForCausalLM
from datasets import load_dataset
import torch

model_name = "./sft_final"  # Starte von deinem SFT-Modell!

# SFT-Modell laden (die Policy, die ausgerichtet werden soll)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

# Referenzmodell (eingefrorene Kopie des SFT-Modells)
ref_model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

# Präferenz-Dataset laden
dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train[:5%]")

# DPO-Konfiguration
dpo_config = DPOConfig(
    output_dir="./dpo_output",
    num_train_epochs=1,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=4,
    learning_rate=5e-7,           # Viel niedriger als bei SFT
    beta=0.1,                     # KL-Strafkoeffizient
    loss_type="sigmoid",          # Standard-DPO-Loss
    max_length=2048,
    max_prompt_length=512,
    bf16=True,
    logging_steps=10,
    save_steps=50,
    report_to="wandb",
)

trainer = DPOTrainer(
    model=model,
    ref_model=ref_model,
    args=dpo_config,
    train_dataset=dataset,
    tokenizer=tokenizer,
)

trainer.train()
trainer.save_model("./dpo_final")
```

***

## PPO (Proximal Policy Optimization)

PPO ist der klassische RLHF-Ansatz — verwenden, wenn Sie ein Reward-Signal haben:

```python
# ppo_train.py
from trl import PPOTrainer, PPOConfig, AutoModelForCausalLMWithValueHead
from transformers import AutoTokenizer, pipeline
from datasets import load_dataset
import torch

model_name = "./sft_final"

# Policy-Modell (mit Value-Head für PPO)
model = AutoModelForCausalLMWithValueHead.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
)

tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

# Reward-Modell (kann jede Bewertungsfunktion sein)
sentiment_pipe = pipeline(
    "sentiment-analysis",
    model="distilbert/distilbert-base-uncased-finetuned-sst-2-english",
    device=0,
)

def reward_fn(texts):
    """Bewerte jede Antwort. Gib eine Liste von Reward-Tensoren zurück."""
    results = sentiment_pipe(texts)
    rewards = []
    for result in results:
        score = result["score"] if result["label"] == "POSITIVE" else -result["score"]
        rewards.append(torch.tensor(score))
    return rewards

ppo_config = PPOConfig(
    output_dir="./ppo_output",
    learning_rate=1.41e-5,
    mini_batch_size=1,
    batch_size=4,
    gradient_accumulation_steps=4,
    kl_penalty="kl",
    target_kl=6.0,
    cliprange=0.2,
    vf_coef=0.1,
)

trainer = PPOTrainer(
    config=ppo_config,
    model=model,
    ref_model=None,  # Kopiert das Anfangsmodell automatisch als Referenz
    tokenizer=tokenizer,
)

# Trainingsschleife
dataset = load_dataset("imdb", split="train[:1000]")
for epoch in range(3):
    for batch in trainer.dataloader:
        queries = batch["input_ids"]
        
        # Generiere Antworten
        responses = trainer.generate(queries, max_new_tokens=100)
        
        # Bewerte Antworten
        texts = tokenizer.batch_decode(responses, skip_special_tokens=True)
        rewards = reward_fn(texts)
        
        # PPO-Update
        stats = trainer.step(queries, responses, rewards)
        trainer.log_stats(stats, batch, rewards)
```

***

## GRPO (Group Relative Policy Optimization)

GRPO wird in DeepSeek-R1 für Reasoning-Training verwendet:

```python
# grpo_train.py
from trl import GRPOTrainer, GRPOConfig
from transformers import AutoTokenizer, AutoModelForCausalLM
from datasets import Dataset
import re, torch

model_name = "Qwen/Qwen2.5-7B-Instruct"

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# Mathe-Dataset
def make_math_dataset():
    examples = [
        {"prompt": "What is 2+2?", "answer": "4"},
        {"prompt": "What is 15 * 7?", "answer": "105"},
        # ... weitere Mathematikaufgaben
    ]
    return Dataset.from_list(examples)

dataset = make_math_dataset()

def correctness_reward(completions, answer, **kwargs):
    """Belohne mit 1.0 wenn die Antwort korrekt ist, sonst 0.0."""
    rewards = []
    for completion in completions:
        # Extrahiere die letzte Zahl aus der Completion
        numbers = re.findall(r'\d+', completion[-1]["content"])
        if numbers and numbers[-1] == answer:
            rewards.append(1.0)
        else:
            rewards.append(0.0)
    return rewards

grpo_config = GRPOConfig(
    output_dir="./grpo_output",
    num_train_epochs=3,
    per_device_train_batch_size=4,
    num_generations=8,       # GRPO generiert G Antworten pro Prompt
    learning_rate=5e-7,
    bf16=True,
    logging_steps=10,
)

trainer = GRPOTrainer(
    model=model,
    args=grpo_config,
    train_dataset=dataset,
    reward_funcs=correctness_reward,
    tokenizer=tokenizer,
)

trainer.train()
```

***

## Multi-GPU-Training

Verwende `accelerate` für verteiltes Training:

```bash
# Konfiguriere accelerate für Multi-GPU
accelerate config

# Beispielkonfiguration für 4 GPUs:
# - compute_environment: LOCAL_MACHINE
# - distributed_type: MULTI_GPU
# - num_processes: 4
# - mixed_precision: bf16

# Starte Training über alle GPUs
accelerate launch sft_train.py
accelerate launch dpo_train.py

# Oder gib GPUs explizit an
CUDA_VISIBLE_DEVICES=0,1,2,3 accelerate launch \
  --num_processes 4 \
  --mixed_precision bf16 \
  sft_train.py
```

***

## Verwendung der TRL-CLI

TRL bietet praktische CLI-Befehle:

```bash
# SFT über CLI
trl sft \
  --model_name_or_path meta-llama/Llama-3.2-8B-Instruct \
  --dataset_name trl-lib/ultrachat_200k \
  --dataset_text_field messages \
  --output_dir ./cli_sft_output \
  --num_train_epochs 3 \
  --per_device_train_batch_size 2 \
  --gradient_accumulation_steps 4 \
  --learning_rate 2e-4 \
  --bf16 \
  --use_peft \
  --lora_r 16 \
  --lora_alpha 32

# DPO über CLI
trl dpo \
  --model_name_or_path ./cli_sft_output \
  --dataset_name trl-lib/ultrafeedback_binarized \
  --output_dir ./cli_dpo_output \
  --num_train_epochs 1 \
  --beta 0.1 \
  --bf16
```

***

## Überwachung des Trainings

```bash
# GPU-Auslastung beobachten
watch -n 1 nvidia-smi

# Trainingsverlust überwachen (wenn W&B verwendet wird)
# Öffne https://wandb.ai/your-username im Browser

# Prüfe Ausgabeverzeichnis auf Checkpoints
ls -lh sft_output/checkpoint-*/

# Von Checkpoint fortsetzen
python3 sft_train.py --resume_from_checkpoint sft_output/checkpoint-500/
```

***

## Clore.ai GPU-Empfehlungen

TRL-Training ist eine der VRAM-intensivsten Workloads. Wähle deine GPU basierend auf Modellgröße und Methode:

| Aufgabe                                     | GPU                | Hinweise                                                                                         |
| ------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------ |
| SFT / DPO auf 7–8B (QLoRA)                  | **RTX 3090** 24 GB | \~8 GB für QLoRA 4-Bit; passt komfortabel; \~0,12 $/Std. auf Clore.ai                            |
| SFT / DPO auf 7–8B (LoRA bf16)              | **RTX 4090** 24 GB | Gleicher VRAM wie 3090, aber \~30 % schnellerer Compute; großartig für Iterationsgeschwindigkeit |
| Full SFT auf 7B oder DPO auf 13B            | **A100 40 GB**     | 40 GB fassen 7B Full-Precision-Training; ECC-Speicher vermeidet stille Fehler                    |
| PPO / Full-Finetune 7B oder jedes 70B QLoRA | **A100 80 GB**     | PPO benötigt 2× Policy+Referenzmodell im VRAM; 80 GB betreibt beide ohne OOM                     |

**Praktischer Tipp:** Starte auf RTX 3090 mit QLoRA zum Experimentieren — trainiere Llama 3 8B in \~2 Std. auf 10.000 Beispielen. Sobald die Pipeline validiert ist, wechsle zu A100 80 GB für Full-Precision-Runs oder 70B-Modelle.

**Geschwindigkeitszahlen (Llama 3 8B SFT, QLoRA, batch=4, seq=2048):**

* RTX 3090: \~1.100 Tokens/Sekunde Trainingsdurchsatz
* RTX 4090: \~1.450 Tokens/Sekunde
* A100 80GB: \~2.800 Tokens/Sekunde (voll bf16, keine Quantisierung)

***

## Fehlerbehebung

### CUDA Out of Memory

```bash
# Reduziere die Batch-Größe
per_device_train_batch_size=1
gradient_accumulation_steps=16  # Effektive Batch-Größe gleich halten

# Verwende 4-Bit-Quantisierung (QLoRA)
# Füge BitsAndBytesConfig mit load_in_4bit=True hinzu

# Aktivieren Sie Gradient Checkpointing
gradient_checkpointing=True

# Sequenzlänge reduzieren
max_seq_length=1024  # statt 2048+

# GPU-Speicher prüfen
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
```

### Loss ist NaN

```bash
# Häufige Ursache: Lernrate zu hoch
learning_rate=1e-5  # Versuche niedriger

# Häufige Ursache: schlechte Daten (leere Strings, None-Werte)
# Datensatz validieren:
python3 -c "
from datasets import load_from_disk
ds = load_from_disk('data/sft_dataset')
print(ds[0])
print(f'Length: {len(ds)}')
# Auf None prüfen
none_count = sum(1 for x in ds if x.get('messages') is None)
print(f'None count: {none_count}')
"

# bf16 statt fp16 aktivieren (stabiler)
bf16=True
fp16=False
```

### DPO: `chosen_rewards > rejected_rewards` ist False

```bash
# Das bedeutet, dass das Modell abgelehnte Antworten bevorzugt — Overfitting oder schlechte Daten
# Lösungen:
# 1. Überprüfe die Qualität deines Datensatzes
# 2. Beta reduzieren (weniger KL-Strafe)
# 3. Lernrate reduzieren
# 4. Mehr SFT-Training vor DPO hinzufügen
beta=0.05  # Versuche kleinere Werte
```

### Training ist sehr langsam

```bash
# Flash Attention 2 aktivieren
pip install flash-attn --no-build-isolation

# In deinem Code:
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    attn_implementation="flash_attention_2",
    torch_dtype=torch.bfloat16,
)

# Verwende bf16 statt fp16 auf Ampere+ GPUs (A100, RTX 3000+)
bf16=True

# DataLoader-Worker erhöhen
dataloader_num_workers=4

# Prüfen, ob GPU tatsächlich verwendet wird
nvidia-smi  # Sollte hohe GPU-Auslastung anzeigen
```

### `tokenizer.pad_token` Warnung

```bash
# Standardlösung für Llama/Mistral-Tokenizer
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"  # Wichtig für Trainingsstabilität
```

### Zugriff verweigert / HuggingFace 401

```bash
# Erneut einloggen
huggingface-cli login

# Token in der Umgebung setzen
export HF_TOKEN=hf_your-token

# Für private Modelle/Datasets sicherstellen, dass du Zugriff hast:
# Gehe zu https://huggingface.co/meta-llama/Llama-3.2-8B-Instruct
# Klicke auf "Request access" und akzeptiere die Lizenz
```

***

## Dein Modell speichern und teilen

```bash
# LoRA-Gewichte in das Basismodell mergen
python3 << 'EOF'
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

base_model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-8B-Instruct",
    torch_dtype=torch.bfloat16,
    device_map="auto"
)
model = PeftModel.from_pretrained(base_model, "./sft_final")
merged = model.merge_and_unload()
merged.save_pretrained("./merged_model")

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-8B-Instruct")
tokenizer.save_pretrained("./merged_model")
print("Zusammengeführtes Modell gespeichert!")
EOF

# Zu HuggingFace hochladen
huggingface-cli upload your-username/my-trl-model ./merged_model
```

***

## Nützliche Links

* **GitHub**: <https://github.com/huggingface/trl> ⭐ 10K+
* **Dokumentation**: <https://huggingface.co/docs/trl>
* **DPO Papier**: <https://arxiv.org/abs/2305.18290>
* **GRPO / DeepSeek-R1**: <https://arxiv.org/abs/2501.12599>
* **PPO Papier (RLHF)**: <https://arxiv.org/abs/2203.02155>
* **HuggingFace PEFT**: <https://github.com/huggingface/peft>
* **Weights & Biases**: <https://wandb.ai>
* **Flash Attention**: <https://github.com/Dao-AILab/flash-attention>
* **Clore.ai Marketplace**: <https://clore.ai/marketplace>


---

# 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:

```
GET https://docs.clore.ai/guides/guides_v2-de/training/trl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
