# DeepSeek-V3-0324: Wie man lokal ausführt

{% hint style="info" %}
Bitte siehe <https://docs.unsloth.ai/basics/deepseek-r1-0528-how-to-run-locally> (Update vom 28. Mai 2025) um zu erfahren, wie man DeepSeek schneller und effizienter ausführt!
{% endhint %}

DeepSeek ist schon wieder dabei! Nach der Veröffentlichung von V3, R1 Zero und R1 im Dezember 2024 und Januar 2025 hat DeepSeek seine Checkpoints / Modelle für V3 aktualisiert und ein Update vom März veröffentlicht!

Laut DeepSeek sprang MMLU-Pro um +5,3 % auf 81,2 %. **GPQA +9,3 Prozentpunkte**. AIME +19,8 % und LiveCodeBench +10,0 %! Sie stellten ein Diagramm bereit, das zeigte, wie sie sich im Vergleich zum vorherigen V3-Checkpoint und anderen Modellen wie GPT 4.5 und Claude Sonnet 3.7 schlugen. <mark style="background-color:blue;">**Aber wie führen wir lokal ein Modell mit 671 Milliarden Parametern aus?**</mark>

<table data-full-width="true"><thead><tr><th>MoE-Bits</th><th>Typ</th><th>Festplattengröße</th><th>Genauigkeit</th><th>Link</th><th>Details</th></tr></thead><tbody><tr><td>1,78 Bit</td><td>IQ1_S</td><td><strong>173 GB</strong></td><td>Ok</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-IQ1_S">Link</a></td><td>2,06/1,56 Bit</td></tr><tr><td>1,93 Bit</td><td>IQ1_M</td><td><strong>183GB</strong></td><td>Mittel</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-IQ1_M">Link</a></td><td>2.5/2.06/1.56</td></tr><tr><td>2,42 Bit</td><td>IQ2_XXS</td><td><strong>203 GB</strong></td><td><mark style="background-color:blue;"><strong>Empfohlen</strong></mark></td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-IQ2_XXS">Link</a></td><td>2,5/2,06 Bit</td></tr><tr><td>2,71 Bit</td><td>Q2_K_XL</td><td><strong>231 GB</strong></td><td><mark style="background-color:purple;"><strong>Empfohlen</strong></mark></td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-Q2_K_XL">Link</a></td><td>3,5/2,5 Bit</td></tr><tr><td>3,5 Bit</td><td>Q3_K_XL</td><td><strong>320 GB</strong></td><td>Großartig</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-Q3_K_XL">Link</a></td><td>4,5/3,5 Bit</td></tr><tr><td>4,5 Bit</td><td>Q4_K_XL</td><td><strong>406 GB</strong></td><td>Am besten</td><td><a href="https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF/tree/main/UD-Q4_K_XL">Link</a></td><td>5,5/4,5 Bit</td></tr></tbody></table>

{% hint style="success" %}
Der ursprüngliche Upload von DeepSeek V3 liegt in float8 vor und benötigt 715 GB. Mit Q4\_K\_M halbiert sich die Dateigröße auf etwa 404 GB, und unsere dynamische 1,78-Bit-Quantisierung passt auf ungefähr 151 GB. **Wir empfehlen unsere 2,7-Bit-Quantisierung, um Größe und Genauigkeit auszubalancieren! Die 2,4-Bit-Variante funktioniert ebenfalls gut!**
{% endhint %}

## :gear: Offizielle empfohlene Einstellungen

Laut [DeepSeek](https://huggingface.co/deepseek-ai/DeepSeek-V3-0324), dies sind die empfohlenen Einstellungen für die Inferenz:

* <mark style="background-color:blue;">**Temperatur von 0,3**</mark> (Vielleicht 0,0 für Code, da [hier zu sehen](https://api-docs.deepseek.com/quick_start/parameter_settings))
* Min\_P von 0,00 (optional, aber 0,01 funktioniert gut; der Standardwert von llama.cpp ist 0,1)
* Chat-Vorlage: `<｜User｜>Erstelle ein einfaches, spielbares Flappy-Bird-Spiel in Python. Platziere das fertige Spiel in einem Markdown-Abschnitt.<｜Assistant｜>`
* Ein BOS-Token von `<｜begin▁of▁sentence｜>` wird während der Tokenisierung automatisch hinzugefügt (NICHT manuell hinzufügen!)
* DeepSeek erwähnte auch die Verwendung eines <mark style="background-color:green;">**System-Prompts**</mark> (optional) - er ist auf Chinesisch: `该助手为DeepSeek Chat，由深度求索公司创造。\n今天是3月24日，星期一。` was übersetzt lautet: `Der Assistent ist DeepSeek Chat, erstellt von DeepSeek.\nHeute ist Montag, der 24. März.`
* <mark style="background-color:orange;">**Für die KV-Cache-Quantisierung 8-Bit verwenden, NICHT 4-Bit - wir haben festgestellt, dass sie deutlich schlechter abschneidet.**</mark>

## 📖 Tutorial: Wie man DeepSeek-V3 in llama.cpp ausführt

1. Hole dir die neueste `llama.cpp` auf [GitHub hier](https://github.com/ggml-org/llama.cpp). Du kannst auch den untenstehenden Build-Anweisungen folgen. Ändere `-DGGML_CUDA=ON` zu `-DGGML_CUDA=OFF` wenn du keine GPU hast oder nur CPU-Inferenz möchtest. **Für Apple Mac / Metal-Geräte**, setze `-DGGML_CUDA=OFF` und fahre dann wie gewohnt fort - Metal-Unterstützung ist standardmäßig aktiviert.

{% hint style="warning" %}
HINWEIS: Die Verwendung von `-DGGML_CUDA=ON` für GPUs kann 5 Minuten zum Kompilieren benötigen. Nur CPU benötigt 1 Minute zum Kompilieren. Vielleicht interessieren dich die vorcompilierten Binärdateien von llama.cpp.
{% endhint %}

```bash
apt-get update
apt-get install pciutils build-essential cmake curl libcurl4-openssl-dev -y
git clone https://github.com/ggml-org/llama.cpp
cmake llama.cpp -B llama.cpp/build \
    -DBUILD_SHARED_LIBS=OFF -DGGML_CUDA=ON -DLLAMA_CURL=ON
cmake --build llama.cpp/build --config Release -j --clean-first --target llama-quantize llama-cli llama-gguf-split
cp llama.cpp/build/bin/llama-* llama.cpp
```

2. Lade das Modell herunter über (nach der Installation von `pip install huggingface_hub hf_transfer` ). Du kannst `UD-IQ1_S`(dynamische 1,78-Bit-Quantisierung) oder andere quantisierte Versionen wie `Q4_K_M` . <mark style="background-color:green;">**Ich empfehle unsere dynamische 2,7-Bit-Quantisierung**</mark><mark style="background-color:green;">**&#x20;**</mark><mark style="background-color:green;">**`UD-Q2_K_XL`**</mark><mark style="background-color:green;">**&#x20;**</mark><mark style="background-color:green;">**zu verwenden, um Größe und Genauigkeit auszubalancieren**</mark>. Weitere Versionen unter: <https://huggingface.co/unsloth/DeepSeek-V3-0324-GGUF>

{% code overflow="wrap" %}

```python
# !pip install huggingface_hub hf_transfer
import os
os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"
from huggingface_hub import snapshot_download
snapshot_download(
    repo_id = "unsloth/DeepSeek-V3-0324-GGUF-UD",
    local_dir = "unsloth/DeepSeek-V3-0324-GGUF-UD",
    allow_patterns = ["*UD-Q2_K_XL*"], # Dynamische 2,7-Bit (230 GB) Verwende "*UD-IQ_S*" für dynamische 1,78-Bit (151 GB)
)
```

{% endcode %}

3. Führe Unsloths Flappy-Bird-Test wie in unserer 1,58-Bit-Dynamic-Quant für DeepSeek R1 beschrieben aus.
4. Bearbeiten `--threads 32` für die Anzahl der CPU-Threads bearbeiten, `--ctx-size 16384` für die Kontextlänge, `--n-gpu-layers 2` für GPU-Offloading, also für wie viele Layer. Versuchen Sie, dies anzupassen, wenn Ihrem GPU-Speicher der Platz ausgeht. Entfernen Sie es auch, wenn Sie nur CPU-Inferenz haben.

<pre class="language-bash" data-overflow="wrap"><code class="lang-bash">./llama.cpp/llama-cli \
    --model unsloth/DeepSeek-V3-0324-GGUF-UD/blob/main/UD-Q2_K_XL/DeepSeek-V3-0324-UD-Q2_K_XL-00001-of-00006.gguf \
    <a data-footnote-ref href="#user-content-fn-1">--cache-type-k q8_0 </a>\
    <a data-footnote-ref href="#user-content-fn-2">--threads 20</a> \
    <a data-footnote-ref href="#user-content-fn-3">--n-gpu-layers 2</a> \
    -no-cnv \\
    --prio 3 \
    --temp 0.3 \
    --min-p 0,01 \
    <a data-footnote-ref href="#user-content-fn-4">--ctx-size 4096</a> \
    --seed 3407 \\
    --prompt "&#x3C;｜User｜>Erstelle ein Flappy-Bird-Spiel in Python. Du musst diese Dinge einbeziehen:\n1. Du musst pygame verwenden.\n2. Die Hintergrundfarbe sollte zufällig gewählt werden und ein heller Farbton sein. Beginne mit einem hellblauen Farbton.\n3. Mehrfaches Drücken der LEERTASTE beschleunigt den Vogel.\n4. Die Form des Vogels sollte zufällig als Quadrat, Kreis oder Dreieck gewählt werden. Die Farbe sollte zufällig als dunkle Farbe gewählt werden.\n5. Platziere unten etwas Land, das zufällig dunkelbraun oder gelb gefärbt ist.\n6. Zeige oben rechts eine Punktzahl an. Erhöhe sie, wenn du an Rohren vorbeikommst, ohne sie zu berühren.\n7. Erstelle zufällig verteilte Rohre mit genügend Abstand. Färbe sie zufällig dunkelgrün, hellbraun oder in einem dunklen Grauton.\n8. Wenn du verlierst, zeige die Bestpunktzahl an. Platziere den Text innerhalb des Bildschirms. Mit q oder Esc beendest du das Spiel. Ein Neustart erfolgt durch erneutes Drücken der LEERTASTE.\nDas fertige Spiel sollte in einem Markdown-Abschnitt in Python stehen. Prüfe deinen Code auf Fehler und behebe sie vor dem endgültigen Markdown-Abschnitt.&#x3C;｜Assistant｜>"
</code></pre>

<details>

<summary>Wenn wir das Obige ausführen, erhalten wir 2 sehr unterschiedliche Ergebnisse.<br><br><strong>Standard-2-Bit-Version:</strong> Zum Anzeigen des Ergebnisses klicken <em><mark style="color:rot;"><strong>(Anfallswarnung!)</strong></mark></em><br><strong>Dynamische 2-Bit-Version:</strong> Sieh dir das Ergebnis unten an:</summary>

<img src="/files/01fa5fdcda49ebd16ee38bf016f1770aa8ecc1be" alt="" data-size="original">

Standard-2-Bit. Scheitert mit Hintergrund, scheitert bei Kollision

</details>

<div align="center"><figure><img src="/files/e243aaf014a7440ae5d498983a1658347b17c953" alt="" width="240"><figcaption><p>Dynamische 2-Bit. Schafft es, ein spielbares Spiel zu erzeugen.</p></figcaption></figure></div>

5. Wie DeepSeek-R1 hat V3 61 Schichten. Zum Beispiel kannst du bei einer 24-GB- oder 80-GB-GPU nach dem Abrunden mit einem Offload rechnen (um 1 verringern, wenn der Speicher nicht ausreicht):

| Quant   | Dateigröße | 24GB GPU | 80GB GPU | 2x80GB GPU |
| ------- | ---------- | -------- | -------- | ---------- |
| 1.73bit | 173 GB     | 5        | 25       | 56         |
| 2.22bit | 183GB      | 4        | 22       | 49         |
| 2.51bit | 212GB      | 2        | 19       | 32         |

### Ausführung auf Mac / Apple-Geräten

Für Apple-Metal-Geräte sei vorsichtig bei `--n-gpu-layers`. Wenn das Gerät in den Speichermangel läuft, verringere den Wert. Bei einer Maschine mit 128 GB Unified Memory solltest du etwa 59 Schichten auslagern können.

```bash
./llama.cpp/llama-cli \
    --model DeepSeek-R1-GGUF/DeepSeek-V3-0324-UD-IQ1_S/DeepSeek-V3-0324-UD-IQ1_S-00001-of-00003.gguf \
    --cache-type-k q4_0 \\
    --threads 16 \
    --prio 2 \\
    --temp 0.6 \\
    --ctx-size 8192 \\
    --seed 3407 \\
    --n-gpu-layers 59 \\
    -no-cnv \\
    --prompt "<｜User｜>Erstelle ein Flappy-Bird-Spiel in Python.<｜Assistant｜>"
```

## :8ball: Heptagon-Test

Wir testen unsere dynamischen Quants auch über [r/Localllama](https://www.reddit.com/r/LocalLLaMA/comments/1j7r47l/i_just_made_an_animation_of_a_ball_bouncing/) der das Modell beim Erstellen einer einfachen Physik-Engine testet, um Bälle zu simulieren, die in einer sich bewegenden, geschlossenen Heptagon-Form rotieren.

<figure><img src="/files/952ab4bf76e401b6b418003222ed4480fffe97ed" alt="" width="563"><figcaption><p>Das Ziel ist es, das Heptagon zum Drehen zu bringen, und die Bälle im Heptagon sollten sich bewegen.</p></figcaption></figure>

{% code overflow="wrap" %}

```bash
./llama.cpp/llama-cli \
    --model unsloth/DeepSeek-V3-0324-GGUF-UD/blob/main/UD-Q2_K_XL/DeepSeek-V3-0324-UD-Q2_K_XL-00001-of-00006.gguf \
    --cache-type-k q8_0 \
    --threads 20 \
    --n-gpu-layers 2 \
    -no-cnv \\
    --prio 3 \
    --temp 0.3 \
    --min-p 0,01 \
    --ctx-size 4096 \
    --seed 3407 \\
    --prompt "<｜User｜>Schreibe ein Python-Programm, das 20 Bälle zeigt, die in einem rotierenden Heptagon herumprallen:\n- Alle Bälle haben denselben Radius.\n- Alle Bälle tragen eine Nummer von 1 bis 20.\n- Alle Bälle fallen beim Start aus dem Zentrum des Heptagons heraus.\n- Die Farben sind: #f8b862, #f6ad49, #f39800, #f08300, #ec6d51, #ee7948, #ed6d3d, #ec6800, #ec6800, #ee7800, #eb6238, #ea5506, #ea5506, #eb6101, #e49e61, #e45e32, #e17b34, #dd7a56, #db8449, #d66a35\n- Die Bälle sollen von Schwerkraft und Reibung beeinflusst werden und realistisch von den rotierenden Wänden abprallen. Es sollte auch Kollisionen zwischen den Bällen geben.\n- Das Material aller Bälle bestimmt, dass ihre Aufprallhöhe nicht den Radius des Heptagons überschreitet, aber größer als der Ballradius ist.\n- Alle Bälle rotieren mit Reibung; die Zahlen auf dem Ball können verwendet werden, um die Drehung des Balls anzuzeigen.\n- Das Heptagon rotiert um sein Zentrum, und die Rotationsgeschwindigkeit beträgt 360 Grad pro 5 Sekunden.\n- Die Größe des Heptagons sollte groß genug sein, um alle Bälle aufzunehmen.\n- Verwende nicht die pygame-Bibliothek; implementiere Algorithmen zur Kollisions­erkennung und Kollisionsreaktion usw. selbst. Die folgenden Python-Bibliotheken sind erlaubt: tkinter, math, numpy, dataclasses, typing, sys.\n- Alle Codes sollten in einer einzigen Python-Datei abgelegt werden.<｜Assistant｜>"
```

{% endcode %}

<table data-view="cards"><thead><tr><th></th><th data-type="files"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td>Nicht-dynamische 2-Bit-Version. Scheitert - <mark style="background-color:red;">ANFALLWARNUNG</mark> wieder!</td><td><a href="/files/eaddb4503afb0110e225e385a8799eea27dac767">/files/eaddb4503afb0110e225e385a8799eea27dac767</a></td><td><a href="/files/6b5eeec16fb14d0a2173542c96a6c53d14e6aa4d">/files/6b5eeec16fb14d0a2173542c96a6c53d14e6aa4d</a></td></tr><tr><td>Dynamische 2-Bit-Version. Löst das Heptagon-Rätsel tatsächlich korrekt!!</td><td><a href="/files/75b24bc973040315f9c0bdaa1f4bdb73b786ffc5">/files/75b24bc973040315f9c0bdaa1f4bdb73b786ffc5</a></td><td><a href="/files/9f047f3e881e6b83624a29f10928158160de632d">/files/9f047f3e881e6b83624a29f10928158160de632d</a></td></tr><tr><td>Ursprüngliches float8</td><td><a href="/files/75f5b2e830b8406dd254cdc9ec9fd88de0db7160">/files/75f5b2e830b8406dd254cdc9ec9fd88de0db7160</a></td><td><a href="/files/b480b3243cedffa048bffc9218704a7ae651d88f">/files/b480b3243cedffa048bffc9218704a7ae651d88f</a></td></tr></tbody></table>

Die dynamische 2,7-Bit-Quantisierung, die nur 230 GB groß ist, schafft es tatsächlich, das Heptagon-Rätsel zu lösen! Die vollständige Ausgabe für alle 3 Versionen (einschließlich vollem fp8) ist unten:

<details>

<summary>Dynamischer 2-Bit-Heptagon-Code</summary>

```python
import tkinter as tk
import math
import numpy as np
from dataclasses import dataclass
from typing import List, Tuple, Optional

# Konstanten
HEPTAGON_RADIUS = 300
BALL_RADIUS = 20
GRAVITY = 0.2
FRICTION = 0.99
BOUNCE_FACTOR = 0.8
ROTATION_SPEED = 360 / 5  # Grad pro Sekunde
SPIN_FRICTION = 0.98
BALL_COLORS = [
    "#f8b862", "#f6ad49", "#f39800", "#f08300", "#ec6d51",
    "#ee7948", "#ed6d3d", "#ec6800", "#ec6800", "#ee7800",
    "#eb6238", "#ea5506", "#ea5506", "#eb6101", "#e49e61",
    "#e45e32", "#e17b34", "#dd7a56", "#db8449", "#d66a35"
]

@dataclass
class Ball:
    x: float
    y: float
    vx: float
    vy: float
    number: int
    spin: float = 0.0
    color: str = "#000000"

@dataclass
class Wall:
    x1: float
    y1: float
    x2: float
    y2: float

class BouncingBalls:
    def __init__(self, root):
        self.root = root
        self.canvas = tk.Canvas(root, width=800, height=800, bg="white")
        self.canvas.pack()
        self.balls: List[Ball] = []
        self.walls: List[Wall] = []
        self.heptagon_angle = 0
        self.last_time = 0
        
        self.setup_balls()
        self.setup_heptagon()
        
        self.root.after(16, self.update)
        self.root.bind("<space>", self.reset_balls)
    
    def setup_balls(self):
        for i in range(20):
            ball = Ball(
                x=400,
                y=400,
                vx=np.random.uniform(-5, 5),
                vy=np.random.uniform(-5, 5),
                number=i+1,
                color=BALL_COLORS[i]
            )
            self.balls.append(ball)
    
    def setup_heptagon(self):
        # Erstelle anfängliche Heptagon-Wände
        self.update_heptagon_walls(0)
    
    def update_heptagon_walls(self, angle):
        self.walls = []
        center_x, center_y = 400, 400
        angle_rad = math.radians(angle)
        
        for i in range(7):
            angle1 = angle_rad + 2 * math.pi * i / 7
            angle2 = angle_rad + 2 * math.pi * (i + 1) / 7
            
            x1 = center_x + HEPTAGON_RADIUS * math.cos(angle1)
            y1 = center_y + HEPTAGON_RADIUS * math.sin(angle1)
            x2 = center_x + HEPTAGON_RADIUS * math.cos(angle2)
            y2 = center_y + HEPTAGON_RADIUS * math.sin(angle2)
            
            self.walls.append(Wall(x1, y1, x2, y2))
    
    def reset_balls(self, event=None):
        for ball in self.balls:
            ball.x = 400
            ball.y = 400
            ball.vx = np.random.uniform(-5, 5)
            ball.vy = np.random.uniform(-5, 5)
            ball.spin = np.random.uniform(-5, 5)
    
    def update(self):
        current_time = self.root.after_idle(self.root.after, 16, self.update)
        if self.last_time == 0:
            self.last_time = current_time
            return
        
        # Berechne Delta-Zeit (ungefähr)
        dt = 0.016  # Annahme von ~60 FPS
        
        # Heptagon-Rotation aktualisieren
        self.heptagon_angle += ROTATION_SPEED * dt
        self.update_heptagon_walls(self.heptagon_angle)
        
        # Bälle aktualisieren
        for ball in self.balls:
            # Schwerkraft anwenden
            ball.vy += GRAVITY
            
            # Reibung anwenden
            ball.vx *= FRICTION
            ball.vy *= FRICTION
            ball.spin *= SPIN_FRICTION
            
            # Ball bewegen
            ball.x += ball.vx
            ball.y += ball.vy
            
            # Kollisionen mit Wänden prüfen
            self.check_wall_collisions(ball)
            
            # Kollisionen mit anderen Bällen prüfen
            for other in self.balls:
                if other.number != ball.number:
                    self.check_ball_collision(ball, other)
        
        # Alles zeichnen
        self.draw()
    
    def check_wall_collisions(self, ball):
        for wall in self.walls:
            # Nächsten Punkt auf dem Wandsegment zum Ball finden
            closest = self.closest_point_on_segment(
                wall.x1, wall.y1, wall.x2, wall.y2, ball.x, ball.y
            )
            
            # Abstand zur Wand berechnen
            dx = ball.x - closest[0]
            dy = ball.y - closest[1]
            distance = math.sqrt(dx*dx + dy*dy)
            
            if distance < BALL_RADIUS:
                # Kollision erkannt
                # Normalenvektor berechnen
                nx = dx / distance
                ny = dy / distance
                
                # Relative Geschwindigkeit entlang der Normale berechnen
                v_rel = ball.vx * nx + ball.vy * ny
                
                if v_rel < 0:  # Bewegt sich auf die Wand zu
                    # Impuls berechnen
                    j = -(1 + BOUNCE_FACTOR) * v_rel
                    
                    # Impuls anwenden
                    ball.vx += j * nx
                    ball.vy += j * ny
                    
                    # Etwas Spin basierend auf der Kollision hinzufügen
                    ball.spin += (ball.vx * ny - ball.vy * nx) * 0.1
                    
                    # Ball aus der Kollision herausbewegen
                    penetration = BALL_RADIUS - distance
                    ball.x += penetration * nx
                    ball.y += penetration * ny
    
    def check_ball_collision(self, ball1, ball2):
        dx = ball2.x - ball1.x
        dy = ball2.y - ball1.y
        distance = math.sqrt(dx*dx + dy*dy)
        
        if distance < 2 * BALL_RADIUS:
            # Kollision erkannt
            nx = dx / distance
            ny = dy / distance
            
            # Relative Geschwindigkeit berechnen
            v_rel_x = ball2.vx - ball1.vx
            v_rel_y = ball2.vy - ball1.vy
            v_rel = v_rel_x * nx + v_rel_y * ny
            
            if v_rel < 0:  # Bewegen sich aufeinander zu
                # Impuls berechnen
                j = -(1 + BOUNCE_FACTOR) * v_rel / 2
                
                # Impulse anwenden
                ball1.vx -= j * nx
                ball1.vy -= j * ny
                ball2.vx += j * nx
                ball2.vy += j * ny
                
                # Spin basierend auf der Kollision hinzufügen
                ball1.spin += (ball1.vx * ny - ball1.vy * nx) * 0.05
                ball2.spin += (ball2.vx * ny - ball2.vy * nx) * 0.05
                
                # Bälle auseinander bewegen
                penetration = 2 * BALL_RADIUS - distance
                ball1.x -= penetration * nx * 0.5
                ball1.y -= penetration * ny * 0.5
                ball2.x += penetration * nx * 0.5
                ball2.y += penetration * ny * 0.5
    
    @staticmethod
    def closest_point_on_segment(x1, y1, x2, y2, x, y):
        # Vektor vom Punkt zum Segmentanfang
        dx = x - x1
        dy = y - y1
        
        # Segmentvektor
        sx = x2 - x1
        sy = y2 - y1
        
        # Projektion des Punkts auf das Segment
        dot = dx * sx + dy * sy
        len_sq = sx * sx + sy * sy
        param = dot / len_sq if len_sq != 0 else -1
        
        if param < 0:
            return x1, y1
        elif param > 1:
            return x2, y2
        else:
            return x1 + param * sx, y1 + param * sy
    
    def draw(self):
        self.canvas.delete("all")
        
        # Heptagon zeichnen
        points = []
        for wall in self.walls:
            points.extend([wall.x1, wall.y1])
        self.canvas.create_polygon(points, fill="", outline="black", width=2)
        
        # Bälle zeichnen
        for ball in self.balls:
            # Ball zeichnen
            self.canvas.create_oval(
                ball.x - BALL_RADIUS, ball.y - BALL_RADIUS,
                ball.x + BALL_RADIUS, ball.y + BALL_RADIUS,
                fill=ball.color, outline="black"
            )
            
            # Nummer mit Rotation basierend auf dem Spin zeichnen
            angle = ball.spin * 10  # Spin für visuellen Effekt skalieren
            self.canvas.create_text(
                ball.x, ball.y,
                text=str(ball.number),
                font=("Arial", 12, "bold"),
                angle=angle
            )

if __name__ == "__main__":
    root = tk.Tk()
    root.title("Springende Bälle in einem rotierenden Heptagon")
    app = BouncingBalls(root)
    root.mainloop()
```

</details>

<details>

<summary>Nicht-dynamischer 2-Bit-Heptagon-Code</summary>

```python
import tkinter as tk
import math
import random
from dataclasses import dataclass
from typing import List, Tuple, Optional
import sys

# Konstanten
WIDTH, HEIGHT = 800, 800
HEPTAGON_RADIUS = 300
BALL_RADIUS = 15
GRAVITY = 0.5
FRICTION = 0.999
ELASTICITY = 0.8
ROTATION_SPEED = 2 * math.pi / 5  # 360 Grad pro 5 Sekunden
SPIN_DECAY = 0.99

# Farben für die Bälle
BALL_COLORS = [
    "#f8b862", "#f6ad49", "#f39800", "#f08300", "#ec6d51",
    "#ee7948", "#ed6d3d", "#ec6800", "#ec6800", "#ee7800",
    "#eb6238", "#ea5506", "#ea5506", "#eb6101", "#e49e61",
    "#e45e32", "#e17b34", "#dd7a56", "#db8449", "#d66a35"
]

@dataclass
class Ball:
    x: float
    y: float
    vx: float
    vy: float
    radius: float
    color: str
    number: int
    spin: float = 0.0

@dataclass
class Heptagon:
    center_x: float
    center_y: float
    radius: float
    angle: float = 0.0

class BouncingBalls:
    def __init__(self, root):
        self.root = root
        self.canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="white")
        self.canvas.pack()
        
        self.heptagon = Heptagon(WIDTH//2, HEIGHT//2, HEPTAGON_RADIUS)
        self.balls = []
        self.setup_balls()
        
        self.root.after(0, self.update)
        self.root.mainloop()
    
    def setup_balls(self):
        center_x, center_y = WIDTH//2, HEIGHT//2
        for i in range(20):
            self.balls.append(Ball(
                x=center_x,
                y=center_y,
                vx=0,
                vy=0,
                radius=BALL_RADIUS,
                color=BALL_COLORS[i],
                number=i+1,
                spin=0
            ))
    
    def update(self):
        self.canvas.delete("all")
        
        # Heptagon-Winkel aktualisieren
        self.heptagon.angle += ROTATION_SPEED / 60  # Annahme: 60 FPS
        
        # Heptagon zeichnen
        self.draw_heptagon()
        
        # Bälle aktualisieren und zeichnen
        for ball in self.balls:
            # Schwerkraft anwenden
            ball.vy += GRAVITY
            
            # Position aktualisieren
            ball.x += ball.vx
            ball.y += ball.vy
            
            # Reibung anwenden
            ball.vx *= FRICTION
            ball.vy *= FRICTION
            
            # Spin-Abnahme anwenden
            ball.spin *= SPIN_DECAY
            
            # Kollision mit Heptagon-Wänden prüfen
            self.check_heptagon_collision(ball)
            
            # Kollision mit anderen Bällen prüfen
            for other in self.balls:
                if other != ball:
                    if self.check_ball_collision(ball, other):
                        self.resolve_ball_collision(ball, other)
            
            # Den Ball zeichnen
            self.draw_ball(ball)
        
        self.root.after(16, self.update)  # ~60 FPS
    
    def draw_heptagon(self):
        center_x, center_y = self.heptagon.center_x, self.heptagon.center_y
        points = []
        for i in range(7):
            angle = self.heptagon.angle + i * 2 * math.pi / 7
            x = center_x + self.heptagon.radius * math.cos(angle)
            y = center_y + self.heptagon.radius * math.sin(angle)
            points.append((x, y))
        
        # Heptagon zeichnen
        self.canvas.create_polygon(
            [points[0], points[1], points[2], points[3], 
             points[4], points[5], points[6]],
            outline="black", fill="", width=2
        )
    
    def draw_ball(self, ball):
        self.canvas.create_oval(
            ball.x - ball.radius,
            ball.y - ball.radius,
            ball.x + ball.radius,
            ball.y + ball.radius,
            fill=ball.color,
            outline="black"
        )
        
        # Die Nummer zeichnen
        self.canvas.create_text(
            ball.x, ball.y,
            text=str(ball.number),
            fill="black"
        )
    
    def check_heptagon_collision(self, ball):
        center_x, center_y = WIDTH//2, HEIGHT//2
        
        # Abstand vom Zentrum prüfen
        dx = ball.x - center_x
        dy = ball.y - center_y
        dist = math.sqrt(dx**2 + dy**2)
        
        if dist + ball.radius > self.heptagon.radius:
            # Den Normalenvektor vom Zentrum zum Ball finden
            angle = math.atan2(dy, dx)
            normal_x = math.cos(angle)
            normal_y = math.sin(angle)
            
            # Ball wieder ins Heptagon schieben
            overlap = (dist + ball.radius) - self.heptagon.radius
            ball.x -= overlap * normal_x
            ball.y -= overlap * normal_y
            
            # Geschwindigkeit reflektieren
            dot_product = ball.vx * normal_x + ball.vy * normal_y
            ball.vx -= 2 * dot_product * normal_x * ELASTICITY
            ball.vy -= 2 * dot_product * normal_y * ELASTICITY
    
    def check_ball_collision(self, ball1, ball2):
        dx = ball2.x - ball1.x
        dy = ball2.y - ball1.y
        distance = math.sqrt(dx**2 + dy**2)
        return distance < (ball1.radius + ball2.radius)
    
    def resolve_ball_collision(self, ball1, ball2):
        dx = ball2.x - ball1.x
        dy = ball2.y - ball1.y
        distance = math.sqrt(dx**2 + dy**2)
        
        # Normalenvektor
        nx = dx / distance
        ny = dy / distance
        
        # Relative Geschwindigkeit
        dvx = ball2.vx - ball1.vx
        dvy = ball2.vy - ball1.vy
        
        # Impuls berechnen
        impulse = 2 * (dvx * nx + dvy * ny) / 2
        impulse *= ELASTICITY
        
        # Impuls anwenden
        ball1.vx -= impulse * nx
        ball1.vy -= impulse * ny
        ball2.vx += impulse * nx
        ball2.vy += impulse * ny
        
        # Bälle trennen, um Festkleben zu verhindern
        overlap = (ball1.radius + ball2.radius) - distance
        ball1.x -= overlap * nx / 2
        ball1.y -= overlap * ny / 2
        ball2.x += overlap * nx / 2
        ball2.y += overlap * ny / 2
    
    def run(self):
        self.root.mainloop()

if __name__ == "__main__":
    root = tk.Tk()
    root.title("Springende Bälle in einem rotierenden Heptagon")
    app = BouncingBalls(root)
    app.run()
```

</details>

<details>

<summary>Float8-Heptagon-Code</summary>

```python
import tkinter as tk
import math
import numpy as np
from dataclasses import dataclass
from typing import List, Tuple, Optional

# Konstanten
WIDTH, HEIGHT = 800, 800
CENTER_X, CENTER_Y = WIDTH // 2, HEIGHT // 2
GRAVITY = 0.2
FRICTION = 0.99
BALL_RADIUS = 15
HEPTAGON_RADIUS = 300
ROTATION_SPEED = 360 / 5  # Grad pro Sekunde
ELASTICITY = 0.8
SPIN_FRICTION = 0.98

# Farben für die Bälle
BALL_COLORS = [
    '#f8b862', '#f6ad49', '#f39800', '#f08300', '#ec6d51',
    '#ee7948', '#ed6d3d', '#ec6800', '#ec6800', '#ee7800',
    '#eb6238', '#ea5506', '#ea5506', '#eb6101', '#e49e61',
    '#e45e32', '#e17b34', '#dd7a56', '#db8449', '#d66a35'
]

@dataclass
class Ball:
    x: float
    y: float
    vx: float
    vy: float
    radius: float
    color: str
    number: int
    spin: float = 0.0

    def move(self):
        self.x += self.vx
        self.y += self.vy
        self.vy += GRAVITY
        self.vx *= FRICTION
        self.vy *= FRICTION
        self.spin *= SPIN_FRICTION

    def collide_with_ball(self, other: 'Ball'):
        dx = other.x - self.x
        dy = other.y - self.y
        distance = math.hypot(dx, dy)
        
        if distance < self.radius + other.radius:
            # Kollisionsnormal berechnen
            nx = dx / distance
            ny = dy / distance
            
            # Relative Geschwindigkeit berechnen
            dvx = other.vx - self.vx
            dvy = other.vy - self.vy
            
            # Impuls berechnen
            impulse = 2 * (dvx * nx + dvy * ny) / (1/self.radius + 1/other.radius)
            
            # Impuls anwenden
            self.vx += impulse * nx / self.radius
            self.vy += impulse * ny / self.radius
            other.vx -= impulse * nx / other.radius
            other.vy -= impulse * ny / other.radius
            
            # Kugeln trennen, um Kleben zu verhindern
            overlap = (self.radius + other.radius - distance) / 2
            self.x -= overlap * nx
            self.y -= overlap * ny
            other.x += overlap * nx
            other.y += overlap * ny
            
            # Etwas Spin übertragen
            transfer = impulse * 0.01
            self.spin -= transfer
            other.spin += transfer

class HeptagonBounceSimulator:
    def __init__(self, root):
        self.root = root
        self.canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg='white')
        self.canvas.pack()
        
        self.balls = self.create_balls()
        self.heptagon_angle = 0
        self.last_time = 0
        self.running = True
        
        self.root.bind('<space>', self.toggle_pause)
        self.root.bind('<Escape>', lambda e: root.destroy())
        
        self.last_time = self.root.after(0, self.update)
    
    def create_balls(self) -> List[Ball]:
        balls = []
        for i in range(20):
            # Alle Kugeln in der Mitte mit kleiner zufälliger Geschwindigkeit starten
            angle = np.random.uniform(0, 2 * math.pi)
            speed = np.random.uniform(0.5, 2)
            vx = math.cos(angle) * speed
            vy = math.sin(angle) * speed
            
            balls.append(Ball(
                x=CENTER_X,
                y=CENTER_Y,
                vx=vx,
                vy=vy,
                radius=BALL_RADIUS,
                color=BALL_COLORS[i],
                number=i+1,
                spin=np.random.uniform(-2, 2)
            ))
        return balls
    
    def toggle_pause(self, event):
        self.running = not self.running
        if self.running:
            self.last_time = self.root.after(0, self.update)
    
    def get_heptagon_vertices(self) -> List[Tuple[float, float]]:
        vertices = []
        for i in range(7):
            angle = math.radians(self.heptagon_angle + i * 360 / 7)
            x = CENTER_X + HEPTAGON_RADIUS * math.cos(angle)
            y = CENTER_Y + HEPTAGON_RADIUS * math.sin(angle)
            vertices.append((x, y))
        return vertices
    
    def check_ball_heptagon_collision(self, ball: Ball):
        vertices = self.get_heptagon_vertices()
        closest_dist = float('inf')
        closest_normal = (0, 0)
        closest_edge = None
        
        # Kollision mit jeder Kante des Heptagons prüfen
        for i in range(len(vertices)):
            p1 = vertices[i]
            p2 = vertices[(i + 1) % len(vertices)]
            
            # Vektor von p1 nach p2
            edge_x = p2[0] - p1[0]
            edge_y = p2[1] - p1[1]
            edge_length = math.hypot(edge_x, edge_y)
            
            # Kantenvektor normalisieren
            edge_x /= edge_length
            edge_y /= edge_length
            
            # Normalenvektor (senkrecht zur Kante, nach innen zeigend)
            nx = -edge_y
            ny = edge_x
            
            # Vektor von p1 zur Kugel
            ball_to_p1_x = ball.x - p1[0]
            ball_to_p1_y = ball.y - p1[1]
            
            # Kugel auf die Kanten-Normale projizieren
            projection = ball_to_p1_x * nx + ball_to_p1_y * ny
            
            # Wenn die Projektion negativ ist, befindet sich die Kugel außerhalb des Heptagons
            if projection < ball.radius:
                # Den nächstgelegenen Punkt auf der Kante zur Kugel finden
                edge_proj = ball_to_p1_x * edge_x + ball_to_p1_y * edge_y
                edge_proj = max(0, min(edge_length, edge_proj))
                closest_x = p1[0] + edge_proj * edge_x
                closest_y = p1[1] + edge_proj * edge_y
                
                # Abstand von der Kugel zum nächstgelegenen Punkt auf der Kante
                dist = math.hypot(ball.x - closest_x, ball.y - closest_y)
                
                if dist < closest_dist:
                    closest_dist = dist
                    closest_normal = (nx, ny)
                    closest_edge = (p1, p2)
        
        if closest_dist < ball.radius:
            # Rückprallreaktion berechnen
            dot_product = ball.vx * closest_normal[0] + ball.vy * closest_normal[1]
            
            # Rückprall mit Elastizität anwenden
            ball.vx -= (1 + ELASTICITY) * dot_product * closest_normal[0]
            ball.vy -= (1 + ELASTICITY) * dot_product * closest_normal[1]
            
            # Etwas Spin basierend auf dem Aufprall hinzufügen
            edge_vec = (closest_edge[1][0] - closest_edge[0][0], 
                        closest_edge[1][1] - closest_edge[0][1])
            edge_length = math.hypot(edge_vec[0], edge_vec[1])
            if edge_length > 0:
                edge_vec = (edge_vec[0]/edge_length, edge_vec[1]/edge_length)
                # Kreuzprodukt aus Geschwindigkeit und Kantenrichtung
                spin_effect = (ball.vx * edge_vec[1] - ball.vy * edge_vec[0]) * 0.1
                ball.spin += spin_effect
            
            # Kugel außerhalb des Heptagons verschieben, um Kleben zu verhindern
            penetration = ball.radius - closest_dist
            ball.x += penetration * closest_normal[0]
            ball.y += penetration * closest_normal[1]
    
    def update(self):
        if not self.running:
            return
        
        # Leinwand leeren
        self.canvas.delete('all')
        
        # Heptagon-Rotation aktualisieren
        self.heptagon_angle += ROTATION_SPEED / 60  # Annahme: ~60 FPS
        
        # Heptagon zeichnen
        vertices = self.get_heptagon_vertices()
        self.canvas.create_polygon(vertices, outline='black', fill='', width=2)
        
        # Bälle aktualisieren und zeichnen
        for i, ball in enumerate(self.balls):
            # Ball bewegen
            ball.move()
            
            # Kollisionen mit dem Heptagon prüfen
            self.check_ball_heptagon_collision(ball)
            
            # Ball zeichnen
            self.canvas.create_oval(
                ball.x - ball.radius, ball.y - ball.radius,
                ball.x + ball.radius, ball.y + ball.radius,
                fill=ball.color, outline='black'
            )
            
            # Nummer mit Rotation basierend auf dem Spin zeichnen
            angle = ball.spin * 10  # Spin für sichtbare Rotation skalieren
            self.canvas.create_text(
                ball.x, ball.y,
                text=str(ball.number),
                font=('Arial', 10, 'bold'),
                angle=angle
            )
        
        # Kollisionen zwischen Kugeln prüfen
        for i in range(len(self.balls)):
            for j in range(i + 1, len(self.balls)):
                self.balls[i].collide_with_ball(self.balls[j])
        
        # Nächstes Update planen
        self.last_time = self.root.after(16, self.update)  # ~60 FPS

if __name__ == '__main__':
    root = tk.Tk()
    root.title('Hüpfende Kugeln in einem rotierenden Heptagon')
    simulator = HeptagonBounceSimulator(root)
    root.mainloop()
```

</details>

## :detective: Zusätzliche Erkenntnisse & Tipps

1. Unsere empirischen Tests zeigen, dass eine niedrigere KV-Cache-Quantisierung (4 Bit) die Generierungsqualität zu verschlechtern scheint – weitere Tests sind nötig, aber wir empfehlen `q8_0` Cache-Quantisierung. Das Ziel der Quantisierung ist, längere Kontextlängen zu unterstützen, da der KV-Cache recht viel Speicher benötigt.
2. Wir haben festgestellt, dass die `down_proj` in diesem Modell extrem empfindlich gegenüber Quantisierung ist. Wir mussten einige unserer dynamischen Quantisierungen, die 2 Bit für `down_proj` verwendeten, erneut durchführen, und verwenden jetzt 3 Bit als Minimum für all diese Matrizen.
3. Die Verwendung von `llama.cpp` 's Flash-Attention-Backend führt zu etwas schnelleren Decodiergeschwindigkeiten. Verwenden Sie `, und` beim Kompilieren. Beachten Sie, dass es auch am besten ist, Ihre CUDA-Architektur wie in <https://developer.nvidia.com/cuda-gpus> angegeben zu setzen, um die Kompilierzeiten zu reduzieren, und sie dann über `-DCMAKE_CUDA_ARCHITECTURES="80"`
4. zu setzen. Die Verwendung eines `min_p=0.01`ist wahrscheinlich ausreichend. `llama.cpp`ist standardmäßig auf 0.1 eingestellt, was wahrscheinlich nicht notwendig ist. Da ohnehin eine Temperatur von 0.3 verwendet wird, werden wir mit großer Wahrscheinlichkeit sehr unwahrscheinlich Token mit niedriger Wahrscheinlichkeit sampeln, daher ist es eine gute Idee, sehr unwahrscheinliche Token zu entfernen. DeepSeek empfiehlt für Coding-Aufgaben eine Temperatur von 0.0.

[^1]: MUSS 8-Bit verwenden - nicht 4-Bit

[^2]: CPU-Threads, die dein Rechner hat

[^3]: Etwa 2 für eine 24-GB-GPU. Etwa 18 für eine 80-GB-GPU.

[^4]: Kontextlänge


---

# Agent Instructions: 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://unsloth.ai/docs/de/modelle/tutorials/deepseek-v3-0324-how-to-run-locally.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.
