# GLM-4.7-Flash : Comment l'exécuter localement

GLM-4.7-Flash est le nouveau modèle de raisonnement MoE 30B de Z.ai, conçu pour un déploiement local, offrant des performances de premier ordre pour le codage, les workflows agentiques et le chat. Il utilise environ 3,6 milliards de paramètres, prend en charge un contexte de 200K et domine les benchmarks SWE-Bench, GPQA et de raisonnement/chat.

GLM-4.7-Flash s’exécute sur **24 Go de RAM**/VRAM/mémoire unifiée (32 Go pour la précision complète), et vous pouvez désormais affiner avec Unsloth. Pour exécuter GLM 4.7 Flash avec vLLM, voir [#glm-4.7-flash-in-vllm](#glm-4.7-flash-in-vllm "mention")

{% hint style="success" %}
Mise à jour du 21 janv. : `llama.cpp` correction d’un bug spécifiant le mauvais `scoring_func`: `"softmax"` (devrait être `"sigmoid"`). Cela provoquait des boucles et de mauvais résultats. Nous avons mis à jour les GGUF — veuillez retélécharger le modèle pour de bien meilleurs résultats.

Vous pouvez désormais utiliser les paramètres recommandés par Z.ai et obtenir d’excellents résultats :

* **Pour un usage général :** `--temp 1.0 --top-p 0.95`
* **Pour l’appel d’outils :** `--temp 0.7 --top-p 1.0`
* **Pénalité de répétition :** Désactivez-la, ou définissez `--repeat-penalty 1.0`

21 janv. : l’inférence plus rapide est là, car la correction FA pour CUDA a maintenant été fusionnée.
{% endhint %}

<a href="#run-glm-4.7-flash" class="button primary">Tutoriel d’utilisation</a><a href="#fine-tuning-glm-4.7-flash" class="button secondary">Affinage</a>

GLM-4.7-Flash GGUF à exécuter : [unsloth/GLM-4.7-Flash-GGUF](https://huggingface.co/unsloth/GLM-4.7-Flash-GGUF)

### ⚙️ Guide d'utilisation

Pour de meilleures performances, assurez-vous que votre mémoire totale disponible (VRAM + RAM système) dépasse la taille du fichier modèle quantifié que vous téléchargez. Sinon, llama.cpp peut toujours fonctionner via le déchargement sur SSD/HDD, mais l’inférence sera plus lente.

Après avoir parlé avec l’équipe de Z.ai, ils recommandent d’utiliser leurs paramètres d’échantillonnage GLM-4.7 :

| Paramètres par défaut (la plupart des tâches)                      | Terminal Bench, SWE Bench Verified                                 |
| ------------------------------------------------------------------ | ------------------------------------------------------------------ |
| <mark style="background-color:green;">**température = 1.0**</mark> | <mark style="background-color:green;">**température = 0.7**</mark> |
| <mark style="background-color:green;">**top\_p = 0.95**</mark>     | <mark style="background-color:green;">**top\_p = 1.0**</mark>      |
| pénalité de répétition = désactivée ou 1.0                         | pénalité de répétition = désactivée ou 1.0                         |

* Pour un usage général :  `--temp 1.0 --top-p 0.95`
* Pour l’appel d’outils :  `--temp 0.7 --top-p 1.0`
* Si vous utilisez llama.cpp, définissez `--min-p 0.01` car la valeur par défaut de llama.cpp est 0.05
* Parfois, vous devrez expérimenter pour voir quels nombres conviennent le mieux à votre cas d’utilisation.

{% hint style="warning" %}
Pour l’instant, nous **ne recommandons pas** d’exécuter ce GGUF avec **Ollama** en raison de problèmes potentiels de compatibilité du modèle de chat. Le GGUF fonctionne bien sur llama.cpp (ou des backends comme LM Studio, Jan).

**N’oubliez pas de désactiver la pénalité de répétition ! Ou définissez** `--repeat-penalty 1.0`
{% endhint %}

* **Fenêtre de contexte maximale :** `202,752`

### 🖥️ Exécuter GLM-4.7-Flash

Selon votre cas d'utilisation, vous devrez utiliser différents paramètres. Certains GGUF finissent par avoir une taille similaire parce que l'architecture du modèle (comme [gpt-oss](https://unsloth.ai/docs/fr/modeles/gpt-oss-how-to-run-and-fine-tune)) a des dimensions non divisibles par 128, donc certaines parties ne peuvent pas être quantifiées avec moins de bits.

Comme ce guide utilise du 4 bits, vous aurez besoin d’environ 18 Go de RAM/mémoire unifiée. Nous recommandons d’utiliser au moins une précision 4 bits pour de meilleures performances.

{% hint style="warning" %}
Pour l’instant, nous **ne recommandons pas** d’exécuter ce GGUF avec **Ollama** en raison de problèmes potentiels de compatibilité du modèle de chat. Le GGUF fonctionne bien sur llama.cpp (ou des backends comme LM Studio, Jan).

**N’oubliez pas de désactiver la pénalité de répétition ! Ou définissez** `--repeat-penalty 1.0`
{% endhint %}

#### 🦥 Guide Unsloth Studio

GLM-4.7-Flash peut être exécuté et affiné dans [Unsloth Studio](https://unsloth.ai/docs/fr/nouveau/studio), notre nouvelle interface web open source pour l'IA locale. Avec Unsloth Studio, vous pouvez exécuter des modèles localement sur **MacOS, Windows**et Linux, ainsi que :

{% columns %}
{% column %}

* Rechercher, télécharger, [exécuter des GGUF](https://unsloth.ai/docs/fr/nouveau/studio#run-models-locally) et des modèles safetensor
* [**Auto-réparation** appel d’outils](https://unsloth.ai/docs/fr/nouveau/studio#execute-code--heal-tool-calling) + **recherche web**
* [**Exécution de code**](https://unsloth.ai/docs/fr/nouveau/studio#run-models-locally) (Python, Bash)
* [Inférence automatique](https://unsloth.ai/docs/fr/nouveau/studio#model-arena) ajustement des paramètres (temp, top-p, etc.)
* Inférence rapide CPU + GPU via llama.cpp
* [Entraîner des LLM](https://unsloth.ai/docs/fr/nouveau/studio#no-code-training) 2x plus rapide avec 70 % de VRAM en moins
  {% endcolumn %}

{% column %}

<div data-with-frame="true"><figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FFeQ0UUlnjXkDdqhcWglh%2Fskinny%20studio%20chat.png?alt=media&#x26;token=c2ee045f-c243-4024-a8e4-bb4dbe7bae79" alt=""><figcaption></figcaption></figure></div>
{% endcolumn %}
{% endcolumns %}

{% stepper %}
{% step %}
**Installer Unsloth**

Exécutez dans votre terminal :

MacOS, Linux, WSL :

```bash
curl -fsSL https://unsloth.ai/install.sh | sh
```

Windows PowerShell :

```bash
irm https://unsloth.ai/install.ps1 | iex
```

{% hint style="success" %}
**L’installation sera rapide et prendra environ 1 à 2 min.**
{% endhint %}
{% endstep %}

{% step %}
**Lancer Unsloth**

MacOS, Linux, WSL et Windows :

```bash
unsloth studio -H 0.0.0.0 -p 8888
```

Puis ouvrez `http://localhost:8888` dans votre navigateur.
{% endstep %}

{% step %}
**Rechercher et télécharger GLM-4.7-Flash**

Lors du premier lancement, vous devrez créer un mot de passe pour sécuriser votre compte et vous reconnecter plus tard. Vous verrez ensuite un bref assistant d’accueil pour choisir un modèle, un jeu de données et les paramètres de base. Vous pouvez le passer à tout moment.

Ensuite, allez à l’onglet [Studio Chat](https://unsloth.ai/docs/fr/nouveau/studio/chat) onglet et recherchez **GLM-4.7-Flash** dans la barre de recherche, puis téléchargez le modèle et la quantification souhaités.

<div data-with-frame="true"><figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2F4oQKFbYhEz7h2K9H3EuP%2FScreenshot%202026-04-02%20at%201.59.45%E2%80%AFAM.png?alt=media&#x26;token=bf78de14-cbcb-4f99-b9b4-65a500a6dd20" alt="" width="375"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**Exécuter GLM-4.7-Flash**

Les paramètres d’inférence devraient être définis automatiquement lors de l’utilisation d’Unsloth Studio, mais vous pouvez toujours les modifier manuellement. Vous pouvez également modifier la longueur du contexte, le modèle de chat et d’autres paramètres.

Pour plus d’informations, vous pouvez consulter notre [guide d’inférence d’Unsloth Studio](https://unsloth.ai/docs/fr/nouveau/studio/chat).

<div data-with-frame="true"><figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FXPQGEEr1YoKofrTatAKK%2Ftoolcallingif.gif?alt=media&#x26;token=25d68698-fb13-4c46-99b2-d39fb025df08" alt="" width="563"><figcaption></figcaption></figure></div>
{% endstep %}
{% endstepper %}

#### Tutoriel Llama.cpp (GGUF) :

Instructions pour exécuter dans llama.cpp (notez que nous utiliserons du 4 bits pour convenir à la plupart des appareils) :

{% stepper %}
{% step %}
Obtenez la dernière version de `llama.cpp` sur [GitHub ici](https://github.com/ggml-org/llama.cpp). Vous pouvez suivre également les instructions de compilation ci-dessous. Remplacez `-DGGML_CUDA=ON` par `-DGGML_CUDA=OFF` si vous n’avez pas de GPU ou si vous souhaitez simplement une inférence CPU. **Pour les appareils Apple Mac / Metal**, définissez `-DGGML_CUDA=OFF` puis continuez normalement - la prise en charge de Metal est activée par défaut.

{% code overflow="wrap" %}

```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
cmake --build llama.cpp/build --config Release -j --clean-first --target llama-cli llama-mtmd-cli llama-server llama-gguf-split
cp llama.cpp/build/bin/llama-* llama.cpp
```

{% endcode %}
{% endstep %}

{% step %}
Vous pouvez le récupérer directement depuis Hugging Face. Vous pouvez augmenter le contexte jusqu’à 200K selon la capacité de votre RAM/VRAM.

Vous pouvez aussi essayer les paramètres d’échantillonnage GLM-4.7 recommandés par Z.ai :

* Pour un usage général :  `--temp 1.0 --top-p 0.95`
* Pour l’appel d’outils :  `--temp 0.7 --top-p 1.0`
* **N’oubliez pas de désactiver la pénalité de répétition !**

Suivez ceci pour les **instructions générales** cas d'utilisation :

```bash
./llama.cpp/llama-cli \
    -hf unsloth/GLM-4.7-Flash-GGUF:UD-Q4_K_XL \
    --ctx-size 16384 \
    --temp 1.0 --top-p 0.95 --min-p 0.01
```

Suivez ceci pour les **appel d'outils** cas d'utilisation :

```bash
./llama.cpp/llama-cli \
    -hf unsloth/GLM-4.7-Flash-GGUF:UD-Q4_K_XL \
    --ctx-size 16384 \
    --temp 0.7 --top-p 1.0 --min-p 0.01
```

{% endstep %}

{% step %}
Téléchargez le modèle via (après installation de `pip install huggingface_hub`). Vous pouvez choisir `UD-Q4_K_XL` ou d’autres versions quantifiées. Si les téléchargements restent bloqués, voir [hugging-face-hub-xet-debugging](https://unsloth.ai/docs/fr/bases/troubleshooting-and-faqs/hugging-face-hub-xet-debugging "mention")

{% code overflow="wrap" %}

```bash
pip install -U huggingface_hub
hf download unsloth/GLM-4.7-Flash-GGUF \
    --local-dir unsloth/GLM-4.7-Flash-GGUF \
    --include "*UD-Q2_K_XL*"
```

{% endcode %}
{% endstep %}

{% step %}
Puis exécutez le modèle en mode conversation :

{% code overflow="wrap" %}

```bash
./llama.cpp/llama-cli \
    --model unsloth/GLM-4.7-Flash-GGUF/GLM-4.7-Flash-UD-Q4_K_XL.gguf \
    --ctx-size 16384 \
    --seed 3407 \
    --temp 1.0 \
    --top-p 0.95 \
    --min-p 0.01
```

{% endcode %}

Aussi, ajustez **la fenêtre de contexte** selon les besoins, jusqu’à `202752`
{% endstep %}
{% endstepper %}

### :loop:Réduire les répétitions et les boucles

{% hint style="success" %}
**MISE À JOUR DU 21 JANV. : llama.cpp a corrigé un bug spécifiant le mauvais** `"scoring_func": "softmax"` **qui provoquait des boucles et de mauvais résultats (devrait être sigmoid). Nous avons mis à jour les GGUF. Veuillez retélécharger le modèle pour de bien meilleurs résultats.**
{% endhint %}

Cela signifie que vous pouvez maintenant utiliser les paramètres recommandés par Z.ai et obtenir d’excellents résultats :

* Pour un usage général :  `--temp 1.0 --top-p 0.95`
* Pour l’appel d’outils :  `--temp 0.7 --top-p 1.0`
* Si vous utilisez llama.cpp, définissez `--min-p 0.01` car la valeur par défaut de llama.cpp est 0.05
* **N’oubliez pas de désactiver la pénalité de répétition ! Ou définissez** `--repeat-penalty 1.0`

Nous avons ajouté `"scoring_func": "sigmoid"` par `config.json` pour le modèle principal - [voir](https://huggingface.co/unsloth/GLM-4.7-Flash/commit/3fd53b491e04f707f307aef2f70f8a7520511e6d).

{% hint style="warning" %}
Pour l’instant, nous **ne recommandons pas** d’exécuter ce GGUF avec **Ollama** en raison de problèmes potentiels de compatibilité du modèle de chat. Le GGUF fonctionne bien sur llama.cpp (ou des backends comme LM Studio, Jan).
{% endhint %}

### :bird:Exemple de Flappy Bird avec UD-Q4\_K\_XL

À titre d’exemple, nous avons effectué la longue conversation suivante en utilisant UD-Q4\_K\_XL via `./llama.cpp/llama-cli --model unsloth/GLM-4.7-Flash-GGUF/GLM-4.7-Flash-UD-Q4_K_XL.gguf --fit on --temp 1.0 --top-p 0.95 --min-p 0.01` :

```
Bonjour
Combien font 2+2
Crée un jeu Flappy Bird en Python
Crée un jeu totalement différent en Rust
Trouve des bugs dans les deux
Fais le premier jeu que j’ai mentionné, mais dans un fichier HTML autonome
Trouve les bugs et montre le jeu corrigé
```

ce qui a rendu le jeu Flappy Bird HTML suivant :

<details>

<summary>Jeu Flappy Bird en HTML (extensible)</summary>

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Flappy Bird corrigé</title>
    <style>
        body {
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #222;
            font-family: 'Arial', sans-serif;
            overflow: hidden;
            user-select: none;
            -webkit-user-select: none;
            touch-action: none; /* Empêche le zoom sur mobile */
        }

        #game-container {
            position: relative;
            box-shadow: 0 0 20px rgba(0,0,0,0.5);
        }

        canvas {
            background-color: #87CEEB;
            display: block;
            border-radius: 4px;
        }

        /* Superpositions de l’interface */
        #ui-layer {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
        }

        #score-display {
            position: absolute;
            top: 40px;
            left: 50%;
            transform: translateX(-50%);
            font-size: 48px;
            font-weight: bold;
            color: white;
            text-shadow: 3px 3px 0 #000;
            z-index: 10;
            font-family: 'Courier New', Courier, monospace;
        }

        #start-screen, #game-over-screen {
            background: rgba(0, 0, 0, 0.7);
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            color: white;
            pointer-events: auto; /* Autorise les clics */
            cursor: pointer;
        }

        h1 { margin: 0 0 10px 0; font-size: 60px; text-shadow: 4px 4px 0 #000; line-height: 1; }
        p { font-size: 22px; margin: 10px 0; color: #ddd; }
        
        .btn {
            background: linear-gradient(to bottom, #ffeb3b, #fbc02d);
            border: 3px solid #fff;
            color: #333;
            padding: 15px 40px;
            font-size: 28px;
            font-weight: bold;
            cursor: pointer;
            border-radius: 8px;
            box-shadow: 0 6px 0 #c49000, 0 10px 10px rgba(0,0,0,0.3);
            text-transform: uppercase;
            transition: all 0.1s;
            margin-top: 10px;
        }

        .btn:active {
            transform: translateY(4px);
            box-shadow: 0 2px 0 #c49000, 0 4px 4px rgba(0,0,0,0.3);
        }

        .score-board {
            background: #ded895;
            border: 2px solid #543847;
            padding: 20px 40px;
            border-radius: 10px;
            box-shadow: 4px 4px 0 #543847;
            margin-bottom: 30px;
            display: none;
            border: 4px solid #543847;
        }
        
        .score-board h2 { margin: 0 0 5px 0; color: #e86101; font-size: 40px; }
        .score-board span { font-size: 20px; color: #543847; display: block; text-align: center; }

    </style>
</head>
<body>

    <div id="game-container">
        <canvas id="gameCanvas" width="400" height="600"></canvas>
        
        <div id="score-display">0</div>

        <div id="ui-layer">
            <div id="start-screen">
                <h1>FLAPPY<br>BIRD</h1>
                <p>Appuyez ou pressez Espace pour commencer</p>
                <button class="btn" style="display:none;" id="touch-instruction">Cliquez pour commencer</button>
            </div>

            <div id="game-over-screen">
                <h1>FIN DE PARTIE</h1>
                <div class="score-board" id="score-board">
                    <h2>Score : <span id="final-score">0</span></h2>
                </div>
                <button class="btn" id="restart-btn">Réessayer</button>
            </div>
        </div>
    </div>

<script>
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');

    // --- Constantes ---
    const GRAVITY = 0.35; // Gravité légèrement plus forte pour une meilleure sensation
    const JUMP_STRENGTH = -6.5;
    const PIPE_GAP = 180;
    const PIPE_WIDTH = 60;
    const PIPE_SPEED = 2.5;
    const PIPE_SPAWN_RATE = 100;

    // --- État ---
    let frames = 0;
    let score = 0;
    let isGameOver = false;
    let isPlaying = false;
    let gameLoopId;

    const ui = {
        startScreen: document.getElementById('start-screen'),
        gameOverScreen: document.getElementById('game-over-screen'),
        scoreDisplay: document.getElementById('score-display'),
        scoreBoard: document.getElementById('score-board'),
        finalScore: document.getElementById('final-score'),
        restartBtn: document.getElementById('restart-btn')
    };

    const bird = {
        x: 80,
        y: 150,
        radius: 12, // Rayon corrigé
        velocity: 0,
        
        draw: function() {
            // Faire pivoter l’oiseau selon la vitesse pour un rendu plus dynamique
            let angle = Math.min(Math.PI / 4, Math.max(-Math.PI / 4, (this.velocity * 0.1)));
            
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(angle);
            
            // Dessiner le corps
            ctx.fillStyle = '#FFD700';
            ctx.beginPath();
            ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
            ctx.fill();
            
            // Œil
            ctx.fillStyle = 'white';
            ctx.beginPath();
            ctx.arc(4, -4, 4, 0, Math.PI * 2);
            ctx.fill();
            ctx.fillStyle = 'black';
            ctx.beginPath();
            ctx.arc(6, -4, 2, 0, Math.PI * 2);
            ctx.fill();
            
            // Aile
            ctx.fillStyle = '#FFA500';
            ctx.beginPath();
            ctx.arc(-4, 4, 5, 0, Math.PI * 2);
            ctx.fill();

            ctx.restore();
        },

        update: function() {
            this.velocity += GRAVITY;
            this.y += this.velocity;
        },

        jump: function() {
            this.velocity = JUMP_STRENGTH;
        },

        reset: function() {
            this.y = 150;
            this.velocity = 0;
        }
    };

    let pipes = [];

    function createPipe() {
        const minHeight = 50;
        const maxPos = canvas.height - PIPE_GAP - minHeight;
        const topHeight = Math.floor(Math.random() * (maxPos - minHeight + 1)) + minHeight;
        
        pipes.push({
            x: canvas.width,
            topHeight: topHeight,
            bottomY: topHeight + PIPE_GAP,
            width: PIPE_WIDTH,
            passed: false
        });
    }

    function drawPipes() {
        ctx.fillStyle = '#2ecc71';
        ctx.strokeStyle = '#27ae60';
        ctx.lineWidth = 2;
        
        pipes.forEach(pipe => {
            // Tuyau du haut
            ctx.fillRect(pipe.x, 0, pipe.width, pipe.topHeight);
            ctx.strokeRect(pipe.x, 0, pipe.width, pipe.topHeight);
            
            // Tuyau du bas
            ctx.fillRect(pipe.x, pipe.bottomY, pipe.width, canvas.height - pipe.bottomY);
            ctx.strokeRect(pipe.x, pipe.bottomY, pipe.width, canvas.height - pipe.bottomY);

            // Capuchon
            const capH = 20;
            ctx.fillStyle = '#27ae60'; 
            ctx.fillRect(pipe.x - 2, pipe.topHeight - capH, pipe.width + 4, capH);
            ctx.fillRect(pipe.x - 2, pipe.bottomY, pipe.width + 4, capH);
        });
    }

    function updatePipes() {
        if (frames % PIPE_SPAWN_RATE === 0) createPipe();

        for (let i = 0; i < pipes.length; i++) {
            let p = pipes[i];
            p.x -= PIPE_SPEED;

            // --- DÉTECTION DES COLLISIONS CORRIGÉE ---
            // Considérer l’oiseau comme un cercle de rayon 'bird.radius'
            // Le tuyau est un rectangle : x, x+w, y_haut, y_bas
            let birdLeft = bird.x - bird.radius;
            let birdRight = bird.x + bird.radius;
            let birdTop = bird.y - bird.radius;
            let birdBottom = bird.y + bird.radius;

            // Chevauchement horizontal
            if (birdRight > p.x && birdLeft < p.x + p.width) {
                // Chevauchement vertical (touche le tuyau du haut OU du bas)
                if (birdTop < p.topHeight || birdBottom > p.bottomY) {
                    gameOver();
                }
            }

            // --- SCORE CORRIGÉ ---
            // Si le tuyau est hors écran à gauche et n’a pas encore été comptabilisé
            if (p.x + p.width < 0 && !p.passed) {
                score++;
                p.passed = true;
                ui.scoreDisplay.innerText = score;
            }

            if (p.x < -60) {
                pipes.shift();
                i--;
            }
        }
    }

    function checkCollisions() {
        // Sol
        if (bird.y + bird.radius >= canvas.height) {
            gameOver();
        }
        // Plafond
        if (bird.y - bird.radius <= 0) {
            bird.y = bird.radius;
            bird.velocity = 0;
        }
    }

    function drawBackground() {
        // Effacer
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // Sol
        ctx.fillStyle = '#654321';
        ctx.fillRect(0, canvas.height - 10, canvas.width, 10);
        
        // Nuages
        ctx.fillStyle = "rgba(255, 255, 255, 0.6)";
        for(let i=0; i<4; i++) {
            let x = (frames * 0.5 + i * 150) % (canvas.width + 100) - 50;
            let y = (i * 40) + 20;
            let scale = 1 + (Math.sin(frames * 0.02 + i) * 0.1);
            let size = 30 * scale;
            ctx.beginPath();
            ctx.arc(x, y, size, 0, Math.PI * 2);
            ctx.arc(x + 20*scale, y - 10*scale, size * 1.2, 0, Math.PI * 2);
            ctx.arc(x + 40*scale, y, size, 0, Math.PI * 2);
            ctx.fill();
        }
    }

    function update() {
        if (!isPlaying) return;
        bird.update();
        updatePipes();
        checkCollisions();
        frames++;
    }

    function draw() {
        drawBackground();
        drawPipes();
        bird.draw();
    }

    function loop() {
        update();
        draw();
        if (isPlaying || !isGameOver) {
            gameLoopId = requestAnimationFrame(loop);
        }
    }

    function startGame() {
        isPlaying = true;
        isGameOver = false;
        
        // Interface
        ui.startScreen.style.display = 'none';
        ui.gameOverScreen.style.display = 'none';
        ui.scoreBoard.style.display = 'none';
        
        // Logique
        bird.reset();
        pipes = [];
        score = 0;
        frames = 0;
        ui.scoreDisplay.innerText = '0';
        
        loop();
    }

    function gameOver() {
        isPlaying = false;
        isGameOver = true;
        cancelAnimationFrame(gameLoopId);
        
        ui.finalScore.innerText = score;
        ui.gameOverScreen.style.display = 'flex';
        ui.scoreBoard.style.display = 'block';
    }

    // --- Gestion des entrées ---

    function handleInput(e) {
        if (e.type === 'keydown' && e.code === 'Space') e.preventDefault();

        if (isPlaying) {
            bird.jump();
        } else if (!isGameOver) {
            // Clic sur l’écran de démarrage (ou tout clic si le jeu n’a pas commencé)
            startGame();
        }
    }

    // Clavier
    window.addEventListener('keydown', (e) => {
        if (e.code === 'Space') handleInput(e);
    });

    // Souris / Tactile
    window.addEventListener('mousedown', handleInput);
    window.addEventListener('touchstart', (e) => {
        // Empêcher le zoom/le défilement
        // e.preventDefault(); 
        handleInput(e);
    }, {passive: false});

    // Interactions de l’interface
    ui.restartBtn.addEventListener('click', (e) => {
        e.stopPropagation();
        startGame();
    });
    
    // Autoriser le clic sur la superposition de fin de partie pour recommencer
    ui.gameOverScreen.addEventListener('mousedown', (e) => {
        if(e.target === ui.gameOverScreen) startGame();
    });
    ui.gameOverScreen.addEventListener('touchstart', (e) => {
        if(e.target === ui.gameOverScreen) {
            e.preventDefault();
            startGame();
        }
    });

    // Dessin initial
    drawBackground();
    bird.reset();
    bird.draw();

</script>
</body>
</html>
```

</details>

Et nous avons pris quelques captures d’écran (le 4 bits fonctionne) :

<div align="left"><figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FJ85uzHPDWinaXPe6kWyU%2Fimage.png?alt=media&#x26;token=6547f49d-2544-4c48-a7d5-5c1c67d34a87" alt="" width="188"><figcaption></figcaption></figure> <figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FHAc2SjNLo1OsyAC4dArm%2Fimage.png?alt=media&#x26;token=87d4bfea-4ac9-41ef-be1c-1e51664d30b1" alt="" width="188"><figcaption></figcaption></figure></div>

### 🦥 Affinage de GLM-4.7-Flash

Unsloth prend désormais en charge l’affinage de GLM-4.7-Flash, cependant vous devrez utiliser `transformers v5`. Le modèle 30B ne tient pas sur un GPU Colab gratuit ; cependant, vous pouvez utiliser notre notebook. L’affinage LoRA 16 bits de GLM-4.7-Flash utilisera environ **60 Go de VRAM**:

* [Notebook SFT LoRA de GLM-4.7-Flash](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/GLM_Flash_A100\(80GB\).ipynb)

{% hint style="warning" %}
Vous pouvez parfois rencontrer un manque de mémoire lors de l’utilisation d’un A100 avec 40 Go de VRAM. Vous devrez utiliser un H100/A100 avec 80 Go de VRAM pour des exécutions plus fluides.
{% endhint %}

{% embed url="<https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/GLM_Flash_A100(80GB).ipynb>" %}

Lors de l’affinage de modèles MoE, ce n’est probablement pas une bonne idée d’affiner la couche routeur, nous l’avons donc désactivée par défaut. Si vous voulez conserver ses capacités de raisonnement (facultatif), vous pouvez utiliser un mélange de réponses directes et d’exemples de chaîne de pensée. Utilisez au moins <mark style="background-color:green;">75 % de raisonnement</mark> et <mark style="background-color:green;">25 % de non-raisonnement</mark> dans votre jeu de données pour que le modèle conserve ses capacités de raisonnement.

### 🦙 Service et déploiement de llama-server

Pour déployer GLM-4.7-Flash en production, nous utilisons `llama-server` Dans un nouveau terminal, par exemple via tmux, déployez le modèle via :

{% code overflow="wrap" %}

```bash
./llama.cpp/llama-server \
    --model unsloth/GLM-4.7-Flash-GGUF/GLM-4.7-Flash-UD-Q4_K_XL.gguf \
    --alias "unsloth/GLM-4.7-Flash" \
    --seed 3407 \
    --temp 1.0 \
    --top-p 0.95 \
    --min-p 0.01 \
    --ctx-size 16384 \
    --port 8001
```

{% endcode %}

Puis dans un nouveau terminal, après avoir fait `pip install openai`, faites :

{% code overflow="wrap" %}

```python
from openai import OpenAI
import json
openai_client = OpenAI(
    base_url = "http://127.0.0.1:8001/v1",
    api_key = "sk-no-key-required",
)
completion = openai_client.chat.completions.create(
    model = "unsloth/GLM-4.7-Flash",
    messages = [{"role": "user", "content": "What is 2+2?"},],
)
print(completion.choices[0].message.content)
```

{% endcode %}

Ce qui imprimera

{% code overflow="wrap" %}

```
L'utilisateur pose une question simple : « What is 2+2? » La réponse est 4. Fournissez la réponse.

2 + 2 = 4.
```

{% endcode %}

### :computer: GLM-4.7-Flash dans vLLM

Vous pouvez désormais utiliser notre nouvelle [quantification FP8 dynamique](https://huggingface.co/unsloth/GLM-4.7-Flash-FP8-Dynamic) du modèle pour une inférence premium et rapide. Installez d’abord vLLM depuis la version nightly :

{% code overflow="wrap" %}

```bash
uv pip install --upgrade --force-reinstall vllm --torch-backend=auto --extra-index-url https://wheels.vllm.ai/nightly/cu130
uv pip install --upgrade --force-reinstall git+https://github.com/huggingface/transformers.git
uv pip install --force-reinstall numba
```

{% endcode %}

Puis servez [la version FP8 dynamique d’Unsloth](https://huggingface.co/unsloth/GLM-4.7-Flash-FP8-Dynamic) du modèle. Nous avons activé FP8 pour réduire de 50 % l’utilisation mémoire du cache KV, et sur 4 GPU. Si vous avez 1 GPU, utilisez `CUDA_VISIBLE_DEVICES='0'` et définissez `--tensor-parallel-size 1` ou supprimez cet argument. Pour désactiver FP8, supprimez `--quantization fp8 --kv-cache-dtype fp8`

```bash
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:False
CUDA_VISIBLE_DEVICES='0,1,2,3' vllm serve unsloth/GLM-4.7-Flash-FP8-Dynamic \
    --served-model-name unsloth/GLM-4.7-Flash \
    --tensor-parallel-size 4 \
    --tool-call-parser glm47 \
    --reasoning-parser glm45 \
    --enable-auto-tool-choice \
    --dtype bfloat16 \
    --seed 3407 \
    --max-model-len 200000 \
    --gpu-memory-utilization 0.95 \
    --max_num_batched_tokens 16384 \
    --port 8001 \
    --kv-cache-dtype fp8
```

Vous pouvez ensuite appeler le modèle servi via l'API OpenAI :

```python
from openai import AsyncOpenAI, OpenAI
openai_api_key = "EMPTY"
openai_api_base = "http://localhost:8001/v1"
client = OpenAI( # ou AsyncOpenAI
    api_key=openai_api_key,
    base_url=openai_api_base,
)
```

#### :star: Décodage spéculatif vLLM GLM-4.7-Flash

Nous avons constaté que l'utilisation du module MTP (prévision multi-token) de GLM 4.7 Flash fait chuter le débit de génération de 13 000 tokens sur 1 B200 à 1 300 tokens ! (10x plus lent) Sur Hopper, cela devrait aller, espérons-le.

```bash
    --speculative-config.method mtp \
    --speculative-config.num_speculative_tokens 1
```

Seulement 1 300 tokens / s de débit sur 1xB200 (130 tokens / s de décodage par utilisateur)

<figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FCJPJYh1uIS1yL8vskiOF%2Fimage.png?alt=media&#x26;token=f07aaad9-93bd-4507-836f-967a3d39b0e5" alt=""><figcaption></figcaption></figure>

Et 13 000 tokens / s de débit sur 1xB200 (toujours 130 tokens / s de décodage par utilisateur)

<figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FrXaHEknUb1QW1v0arO0q%2Fimage.png?alt=media&#x26;token=dd81b731-90bb-4d1b-a647-a64618f5952a" alt=""><figcaption></figcaption></figure>

### :hammer:Appels d'outils avec GLM-4.7-Flash

Voir [tool-calling-guide-for-local-llms](https://unsloth.ai/docs/fr/bases/tool-calling-guide-for-local-llms "mention") pour plus de détails sur la façon de faire des appels d'outils. Dans un nouveau terminal (si vous utilisez tmux, utilisez CTRL+B+D), nous créons quelques outils comme l'addition de 2 nombres, l'exécution de code Python, l'exécution de fonctions Linux et bien plus encore :

{% code expandable="true" %}

```python
import json, subprocess, random
from typing import Any
def add_number(a: float | str, b: float | str) -> float:
    return float(a) + float(b)
def multiply_number(a: float | str, b: float | str) -> float:
    return float(a) * float(b)
def substract_number(a: float | str, b: float | str) -> float:
    return float(a) - float(b)
def write_a_story() -> str:
    return random.choice([
        "Il était une fois, dans une galaxie très très lointaine...",
        "Il y avait 2 amis qui aimaient les paresseux et le code...",
        "Le monde touchait à sa fin parce que chaque paresseux avait évolué pour posséder une intelligence surhumaine...",
        "À l'insu de l'un des amis, l'autre avait accidentellement codé un programme pour faire évoluer les paresseux...",
    ])
def terminal(command: str) -> str:
    if "rm" in command or "sudo" in command or "dd" in command or "chmod" in command:
        msg = "Impossible d'exécuter les commandes 'rm, sudo, dd, chmod' car elles sont dangereuses"
        print(msg); return msg
    print(f"Exécution de la commande terminal `{command}`")
    try:
        return str(subprocess.run(command, capture_output = True, text = True, shell = True, check = True).stdout)
    except subprocess.CalledProcessError as e:
        return f"La commande a échoué : {e.stderr}"
def python(code: str) -> str:
    data = {}
    exec(code, data)
    del data["__builtins__"]
    return str(data)
MAP_FN = {
    "add_number": add_number,
    "multiply_number": multiply_number,
    "substract_number": substract_number,
    "write_a_story": write_a_story,
    "terminal": terminal,
    "python": python,
}
tools = [
    {
        "type": "function",
        "function": {
            "name": "add_number",
            "description": "Additionner deux nombres.",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "Le premier nombre.",
                    },
                    "b": {
                        "type": "string",
                        "description": "Le deuxième nombre.",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "multiply_number",
            "description": "Multiplier deux nombres.",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "Le premier nombre.",
                    },
                    "b": {
                        "type": "string",
                        "description": "Le deuxième nombre.",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "substract_number",
            "description": "Soustraire deux nombres.",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "Le premier nombre.",
                    },
                    "b": {
                        "type": "string",
                        "description": "Le deuxième nombre.",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "write_a_story",
            "description": "Écrit une histoire aléatoire.",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "terminal",
            "description": "Effectuer des opérations depuis le terminal.",
            "parameters": {
                "type": "object",
                "properties": {
                    "command": {
                        "type": "string",
                        "description": "La commande que vous souhaitez lancer, par ex. `ls`, `rm`, ...",
                    },
                },
                "required": ["command"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "python",
            "description": "Appeler un interpréteur Python avec du code Python qui sera exécuté.",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "Le code Python à exécuter",
                    },
                },
                "required": ["code"],
            },
        },
    },
]
```

{% endcode %}

Nous utilisons ensuite les fonctions ci-dessous (copiez-collez puis exécutez), qui analyseront automatiquement les appels de fonctions et appelleront le point de terminaison OpenAI pour n'importe quel modèle :

{% code overflow="wrap" expandable="true" %}

```python
from openai import OpenAI
def unsloth_inference(
    messages,
    temperature = 0.7,
    top_p = 1.0,
    top_k = -1,
    repetition_penalty = 0.0,
):
    messages = messages.copy()
    openai_client = OpenAI(
        base_url = "http://127.0.0.1:8001/v1",
        api_key = "sk-no-key-required",
    )
    model_name = next(iter(openai_client.models.list())).id
    print(f"Utilisation du modèle = {model_name}")
    has_tool_calls = True
    original_messages_len = len(messages)
    while has_tool_calls:
        print(f"Messages actuels = {messages}")
        response = openai_client.chat.completions.create(
            model = model_name,
            messages = messages,
            temperature = temperature,
            top_p = top_p,
            tools = tools if tools else None,
            tool_choice = "auto" if tools else None,
            extra_body = {"top_k": top_k, "min_p": min_p, "dry_multiplier" :repetition_penalty,}
        )
        tool_calls = response.choices[0].message.tool_calls or []
        content = response.choices[0].message.content or ""
        tool_calls_dict = [tc.to_dict() for tc in tool_calls] if tool_calls else tool_calls
        messages.append({"role": "assistant", "tool_calls": tool_calls_dict, "content": content,})
        for tool_call in tool_calls:
            fx, args, _id = tool_call.function.name, tool_call.function.arguments, tool_call.id
            out = MAP_FN[fx](**json.loads(args))
            messages.append({"role": "tool", "tool_call_id": _id, "name": fx, "content": str(out),})
        else:
            has_tool_calls = False
    return messages
```

{% endcode %}

Après avoir lancé GLM-4.7-Flash via `llama-server` comme dans [#deploy-with-llama-server-and-openais-completion-library](#deploy-with-llama-server-and-openais-completion-library "mention") ou voir [tool-calling-guide-for-local-llms](https://unsloth.ai/docs/fr/bases/tool-calling-guide-for-local-llms "mention") pour plus de détails, nous pouvons alors effectuer quelques appels d'outils :

**Appel d'outil pour les opérations mathématiques pour GLM 4.7**

{% code overflow="wrap" %}

```python
messages = [{
    "role": "user",
    "content": [{"type": "text", "text": "Quelle est la date d'aujourd'hui plus 3 jours ?"}],
}]
unsloth_inference(messages, temperature = 1.0, top_p = 0.95, top_k = -1, min_p = 0.01)
```

{% endcode %}

<figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FoFkZ20QOSGdzT4iz2SOB%2Fimage.png?alt=media&#x26;token=e4ca30b0-dcec-4a26-b019-dd33f0600949" alt=""><figcaption></figcaption></figure>

**Appel d'outil pour exécuter du code Python généré pour GLM-4.7-Flash**

{% code overflow="wrap" %}

```python
messages = [{
    "role": "user",
    "content": [{"type": "text", "text": "Créez une fonction Fibonacci en Python et trouvez fib(20)."}],
}]
unsloth_inference(messages, temperature = 1.0, top_p = 0.95, top_k = -1, min_p = 0.01)
```

{% endcode %}

<figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FhS8sWtZwjwerElezCc2C%2Fimage.png?alt=media&#x26;token=39032ef8-386e-4837-8dd2-c552c80a3ee3" alt="" width="563"><figcaption></figcaption></figure>

### Benchmarks

GLM-4.7-Flash est le modèle 30B le plus performant sur tous les benchmarks, sauf AIME 25.

<figure><img src="https://550366147-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2FuU8GDqR2ni6slcQ1pWzL%2Fglm4.7%20benchmarks.jpg?alt=media&#x26;token=1f609b73-c20b-4e4c-bbf8-0e7213c00b44" alt="" width="375"><figcaption></figcaption></figure>

| Benchmark          | GLM-4.7-Flash | Qwen3-30B-A3B-Thinking-2507 | GPT-OSS-20B |
| ------------------ | ------------- | --------------------------- | ----------- |
| AIME 25            | 91.6          | 85.0                        | 91.7        |
| GPQA               | 75.2          | 73.4                        | 71.5        |
| LCB v6             | 64.0          | 66.0                        | 61.0        |
| HLE                | 14.4          | 9.8                         | 10.9        |
| SWE-bench Verified | 59.2          | 22.0                        | 34.0        |
| τ²-Bench           | 79.5          | 49.0                        | 47.7        |
| BrowseComp         | 42.8          | 2.29                        | 28.3        |


---

# 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/fr/modeles/glm-4.7-flash.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.
