# GLM-4.7-Flash: ローカルで実行する方法

GLM-4.7-Flash は、ローカル展開向けに構築された Z.ai の新しい 30B MoE 推論モデルで、コーディング、エージェント的ワークフロー、チャットにおいてクラス最高の性能を提供します。約 3.6B のパラメータを使用し、200K のコンテキストをサポートし、SWE-Bench、GPQA、推論/チャットのベンチマークをリードします。

GLM-4.7-Flash は **24GB RAM**/VRAM/ユニファイドメモリ上で動作します（完全精度では 32GB）。また、現在は Unsloth でファインチューニングできます。vLLM で GLM 4.7 Flash を実行するには、こちらを参照してください [#glm-4.7-flash-in-vllm](#glm-4.7-flash-in-vllm "mention")

{% hint style="success" %}
1月21日更新: `llama.cpp` 誤った `scoring_func`: `"softmax"` を指定していたバグを修正しました（ `"sigmoid"`であるべきでした）。これによりループと出力品質の低下が発生していました。GGUF を更新したので、より良い出力のためにモデルを再ダウンロードしてください。

Z.ai 推奨のパラメータを使って、優れた結果を得られるようになりました:

* **一般的な用途では:** `--temp 1.0 --top-p 0.95`
* **ツール呼び出しでは:** `--temp 0.7 --top-p 1.0`
* **リピートペナルティ:** 無効にするか、 `--repeat-penalty 1.0`

1月22日: CUDA 向けの FA 修正がマージされたため、より高速な推論が利用可能になりました。
{% endhint %}

<a href="#run-glm-4.7-flash" class="button primary">実行チュートリアル</a><a href="#fine-tuning-glm-4.7-flash" class="button secondary">ファインチューニング</a>

実行する GLM-4.7-Flash GGUF: [unsloth/GLM-4.7-Flash-GGUF](https://huggingface.co/unsloth/GLM-4.7-Flash-GGUF)

### ⚙️ 使用ガイド

最高の性能を得るには、利用可能な総メモリ（VRAM + システムRAM）が、ダウンロードする量子化モデルファイルのサイズを上回っていることを確認してください。上回っていない場合でも、llama.cppはSSD/HDDオフロードで実行できますが、推論は遅くなります。

Z.ai チームと話した結果、彼らは GLM-4.7 のサンプリングパラメータを使うことを推奨しています:

| デフォルト設定（ほとんどのタスク）                                                  | Terminal Bench、SWE Bench Verified                                  |
| ------------------------------------------------------------------ | ------------------------------------------------------------------ |
| <mark style="background-color:green;">**temperature = 1.0**</mark> | <mark style="background-color:green;">**temperature = 0.7**</mark> |
| <mark style="background-color:green;">**top\_p = 0.95**</mark>     | <mark style="background-color:green;">**top\_p = 1.0**</mark>      |
| repeat penalty = 無効または 1.0                                         | repeat penalty = 無効または 1.0                                         |

* 一般的な用途では:  `--temp 1.0 --top-p 0.95`
* ツール呼び出しでは:  `--temp 0.7 --top-p 1.0`
* llama.cpp を使う場合は、 `--min-p 0.01` を設定してください。llama.cpp のデフォルトは 0.05 です。
* 用途によって最適な数値を見つけるため、試行錯誤が必要な場合があります。

{% hint style="warning" %}
現時点では、 **推奨しません** この GGUF を **Ollama** で実行することは、チャットテンプレートの互換性問題が発生する可能性があるためです。GGUF は llama.cpp（または LM Studio、Jan などのバックエンド）ではうまく動作します。

**リピートペナルティを無効にするのを忘れないでください！または** `--repeat-penalty 1.0`
{% endhint %}

* **最大コンテキストウィンドウ:** `202,752`

### 🖥️ GLM-4.7-Flash を実行

ユースケースによっては、異なる設定を使う必要があります。いくつかのGGUFは、モデルアーキテクチャ（たとえば [gpt-oss](https://unsloth.ai/docs/jp/moderu/gpt-oss-how-to-run-and-fine-tune)）に128で割り切れない次元があるため、パーツをより低いビット数に量子化できず、結果としてサイズが似通うことがあります。

このガイドは 4-bit を使用しているため、約 18GB の RAM/ユニファイドメモリが必要です。最高の性能を得るには、少なくとも 4-bit 精度を使うことを推奨します。

{% hint style="warning" %}
現時点では、 **推奨しません** この GGUF を **Ollama** で実行することは、チャットテンプレートの互換性問題が発生する可能性があるためです。GGUF は llama.cpp（または LM Studio、Jan などのバックエンド）ではうまく動作します。

**リピートペナルティを無効にするのを忘れないでください！または** `--repeat-penalty 1.0`
{% endhint %}

#### 🦥 Unsloth Studioガイド

GLM-4.7-Flash は、 [Unsloth Studio](https://unsloth.ai/docs/jp/xin-zhe/studio)で実行およびファインチューニングできます。これはローカルAI向けの新しいオープンソースWeb UIです。Unsloth Studioを使えば、モデルをローカルで **MacOS、Windows**、Linuxおよび以下で実行できます:

{% columns %}
{% column %}

* GGUFと [GGUFを実行](https://unsloth.ai/docs/jp/xin-zhe/studio#run-models-locally) およびsafetensorモデルを検索・ダウンロード
* [**自己修復** ツール呼び出し](https://unsloth.ai/docs/jp/xin-zhe/studio#execute-code--heal-tool-calling) + **Web検索**
* [**コード実行**](https://unsloth.ai/docs/jp/xin-zhe/studio#run-models-locally) （Python、Bash）
* [自動推論](https://unsloth.ai/docs/jp/xin-zhe/studio#model-arena) パラメータ調整（temp、top-pなど）
* llama.cpp経由の高速CPU + GPU推論
* [LLMを学習](https://unsloth.ai/docs/jp/xin-zhe/studio#no-code-training) VRAMを70%削減しつつ2倍高速
  {% endcolumn %}

{% column %}

<div data-with-frame="true"><figure><img src="https://735611837-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 %}
**Unslothをインストール**

ターミナルで実行：

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" %}
**インストールは迅速で、約1〜2分で完了します。**
{% endhint %}
{% endstep %}

{% step %}
**Unslothを起動**

MacOS、Linux、WSLおよびWindows:

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

次に `http://localhost:8888` をブラウザで開きます。
{% endstep %}

{% step %}
**GLM-4.7-Flash を検索してダウンロード**

初回起動時に、アカウントを保護し後で再度サインインするためのパスワードを作成する必要があります。その後、モデル、データセット、基本設定を選ぶ簡単な初期設定ウィザードが表示されます。いつでもスキップできます。

次に [Studio Chat](https://unsloth.ai/docs/jp/xin-zhe/studio/chat) タブで検索し、 **GLM-4.7-Flash** を検索バーに入力して、必要なモデルと量子化版をダウンロードしてください。

<div data-with-frame="true"><figure><img src="https://735611837-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 %}
**GLM-4.7-Flash を実行**

Unsloth Studioを使うと推論パラメータは自動設定されますが、手動で変更することもできます。コンテキスト長、チャットテンプレート、その他の設定も編集できます。

詳細は、こちらの [Unsloth Studio推論ガイド](https://unsloth.ai/docs/jp/xin-zhe/studio/chat).

<div data-with-frame="true"><figure><img src="https://735611837-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 %}

#### Llama.cpp チュートリアル（GGUF）:

llama.cppで実行するための手順（ほとんどのデバイスに収まるよう、4ビットを使用します）:

{% stepper %}
{% step %}
最新の `llama.cpp` を [GitHubこちら](https://github.com/ggml-org/llama.cpp)から入手してください。下のビルド手順に従うこともできます。 `-DGGML_CUDA=ON` を `-DGGML_CUDA=OFF` に変更してください。GPUがない場合やCPU推論だけを使いたい場合です。 **Apple Mac / Metalデバイスでは**、 `-DGGML_CUDA=OFF` を設定してから通常どおり続行してください。Metalサポートはデフォルトで有効です。

{% 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 %}
Hugging Face から直接取得できます。RAM/VRAM が許す範囲でコンテキストを 200K まで増やせます。

Z.ai 推奨の GLM-4.7 サンプリングパラメータも試せます:

* 一般的な用途では:  `--temp 1.0 --top-p 0.95`
* ツール呼び出しでは:  `--temp 0.7 --top-p 1.0`
* **リピートペナルティを無効にするのを忘れないでください！**

以下を **一般的な命令** のユースケースを実行します:

```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
```

以下を **ツール呼び出し** のユースケースを実行します:

```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 %}
（のインストール後に）モデルをダウンロードします `pip install huggingface_hub`）。 `UD-Q4_K_XL` または他の量子化版。ダウンロードが止まる場合は、こちらを参照してください [hugging-face-hub-xet-debugging](https://unsloth.ai/docs/jp/ji-ben/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 %}
その後、会話モードでモデルを実行します:

{% 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 %}

また、 **コンテキストウィンドウ** 必要に応じて、 `202752`
{% endstep %}
{% endstepper %}

### :loop:反復とループの削減

{% hint style="success" %}
**1月21日更新: llama.cpp は、誤った** `"scoring_func": "softmax"` **を指定していたバグを修正しました。これがループと出力品質の低下を引き起こしていました（sigmoid であるべきでした）。GGUF を更新しました。より良い出力のため、モデルを再ダウンロードしてください。**
{% endhint %}

これにより、Z.ai の推奨パラメータを使って優れた結果を得られるようになりました:

* 一般的な用途では:  `--temp 1.0 --top-p 0.95`
* ツール呼び出しでは:  `--temp 0.7 --top-p 1.0`
* llama.cpp を使う場合は、 `--min-p 0.01` を設定してください。llama.cpp のデフォルトは 0.05 です。
* **リピートペナルティを無効にするのを忘れないでください！または** `--repeat-penalty 1.0`

追加しました `"scoring_func": "sigmoid"` を `config.json` メインモデル用に - [参照](https://huggingface.co/unsloth/GLM-4.7-Flash/commit/3fd53b491e04f707f307aef2f70f8a7520511e6d).

{% hint style="warning" %}
現時点では、 **推奨しません** この GGUF を **Ollama** で実行することは、チャットテンプレートの互換性問題が発生する可能性があるためです。GGUF は llama.cpp（または LM Studio、Jan などのバックエンド）ではうまく動作します。
{% endhint %}

### :bird:UD-Q4\_K\_XL を使った Flappy Bird の例

例として、UD-Q4\_K\_XL を使って以下の長い会話を行いました `./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` :

```
こんにちは
2+2 はいくつ？
Python で Flappy Bird のゲームを作って
Rust でまったく別のゲームを作って
両方のバグを見つけて
最初に言ったゲームを、単体の HTML ファイルで作って
バグを見つけて修正版のゲームを示して
```

その結果、次の Flappy Bird ゲームが HTML 形式でレンダリングされました:

<details>

<summary>HTML の Flappy Bird ゲーム（展開可能）</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 修正版</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; /* モバイルでのズームを防止 */
        }

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

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

        /* UI オーバーレイ */
        #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; /* クリックを許可 */
            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>タップまたはスペースキーで開始</p>
                <button class="btn" style="display:none;" id="touch-instruction">クリックして開始</button>
            </div>

            <div id="game-over-screen">
                <h1>GAME OVER</h1>
                <div class="score-board" id="score-board">
                    <h2>スコア: <span id="final-score">0</span></h2>
                </div>
                <button class="btn" id="restart-btn">もう一度</button>
            </div>
        </div>
    </div>

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

    // --- 定数 ---
    const GRAVITY = 0.35; // 体感を良くするため少し強めの重力
    const JUMP_STRENGTH = -6.5;
    const PIPE_GAP = 180;
    const PIPE_WIDTH = 60;
    const PIPE_SPEED = 2.5;
    const PIPE_SPAWN_RATE = 100;

    // --- 状態 ---
    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, // 半径を修正
        velocity: 0,
        
        draw: function() {
            // 見た目の演出のため、速度に応じて鳥を回転
            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);
            
            // 本体を描画
            ctx.fillStyle = '#FFD700';
            ctx.beginPath();
            ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
            ctx.fill();
            
            // 目
            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();
            
            // 翼
            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 => {
            // 上のパイプ
            ctx.fillRect(pipe.x, 0, pipe.width, pipe.topHeight);
            ctx.strokeRect(pipe.x, 0, pipe.width, pipe.topHeight);
            
            // 下のパイプ
            ctx.fillRect(pipe.x, pipe.bottomY, pipe.width, canvas.height - pipe.bottomY);
            ctx.strokeRect(pipe.x, pipe.bottomY, pipe.width, canvas.height - pipe.bottomY);

            // キャップ
            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;

            // --- 衝突判定を修正 ---
            // 鳥を半径 'bird.radius' の円として扱う
            // パイプは矩形: x, x+w, y_top, y_bottom
            let birdLeft = bird.x - bird.radius;
            let birdRight = bird.x + bird.radius;
            let birdTop = bird.y - bird.radius;
            let birdBottom = bird.y + bird.radius;

            // 水平方向の重なり
            if (birdRight > p.x && birdLeft < p.x + p.width) {
                // 垂直方向の重なり（上パイプに当たった、または下パイプに当たった）
                if (birdTop < p.topHeight || birdBottom > p.bottomY) {
                    gameOver();
                }
            }

            // --- スコア計算を修正 ---
            // パイプが左に画面外へ出ていて、まだ得点されていない場合
            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() {
        // 床
        if (bird.y + bird.radius >= canvas.height) {
            gameOver();
        }
        // 天井
        if (bird.y - bird.radius <= 0) {
            bird.y = bird.radius;
            bird.velocity = 0;
        }
    }

    function drawBackground() {
        // クリア
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // 床
        ctx.fillStyle = '#654321';
        ctx.fillRect(0, canvas.height - 10, canvas.width, 10);
        
        // 雲
        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;
        
        // UI
        ui.startScreen.style.display = 'none';
        ui.gameOverScreen.style.display = 'none';
        ui.scoreBoard.style.display = 'none';
        
        // ロジック
        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';
    }

    // --- 入力処理 ---

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

        if (isPlaying) {
            bird.jump();
        } else if (!isGameOver) {
            // スタート画面のクリック（またはゲーム未開始時の任意のクリック）
            startGame();
        }
    }

    // キーボード
    window.addEventListener('keydown', (e) => {
        if (e.code === 'Space') handleInput(e);
    });

    // マウス / タッチ
    window.addEventListener('mousedown', handleInput);
    window.addEventListener('touchstart', (e) => {
        // ズーム/スクロールを防止
        // e.preventDefault(); 
        handleInput(e);
    }, {passive: false});

    // UI 操作
    ui.restartBtn.addEventListener('click', (e) => {
        e.stopPropagation();
        startGame();
    });
    
    // Game Over オーバーレイをクリックして再開できるようにする
    ui.gameOverScreen.addEventListener('mousedown', (e) => {
        if(e.target === ui.gameOverScreen) startGame();
    });
    ui.gameOverScreen.addEventListener('touchstart', (e) => {
        if(e.target === ui.gameOverScreen) {
            e.preventDefault();
            startGame();
        }
    });

    // 初回描画
    drawBackground();
    bird.reset();
    bird.draw();

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

</details>

そして、いくつかのスクリーンショットを取得しました（4bit で動作します）:

<div align="left"><figure><img src="https://735611837-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://735611837-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>

### 🦥 GLM-4.7-Flash のファインチューニング

Unsloth は現在 GLM-4.7-Flash のファインチューニングをサポートしていますが、 `transformers v5`を使用する必要があります。30B モデルは無料の Colab GPU には収まりませんが、私たちのノートブックを使えます。GLM-4.7-Flash の 16-bit LoRA ファインチューニングでは約 **60GBのVRAM**:

* [GLM-4.7-Flash SFT LoRA ノートブック](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/GLM_Flash_A100\(80GB\).ipynb)

{% hint style="warning" %}
A100 40GB VRAM を使用している場合、時々メモリ不足になることがあります。より安定して実行するには H100/A100 80GB VRAM が必要です。
{% endhint %}

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

MoE のファインチューニングでは、ルーターレイヤーをファインチューニングするのはおそらく良い考えではないので、デフォルトで無効にしています。推論能力を維持したい場合（任意）、直接回答と chain-of-thought の例を混ぜて使えます。少なくとも <mark style="background-color:green;">75%を推論</mark> および <mark style="background-color:green;">25%を非推論</mark> にしてください。

### 🦙Llama-serverによる提供とデプロイ

本番環境で GLM-4.7-Flash をデプロイするには、 `llama-server` を使います。tmuxなどを使って新しいターミナルで、次のようにモデルをデプロイします:

{% 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 %}

その後、新しいターミナルで `pip install openai`を実行してから、次を行います:

{% 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": "2+2はいくつ？"},],
)
print(completion.choices[0].message.content)
```

{% endcode %}

これは次を出力します

{% code overflow="wrap" %}

```
ユーザーは簡単な質問をします: "What is 2+2?" 答えは4です。回答を提供してください。

2 + 2 = 4.
```

{% endcode %}

### :computer: vLLM での GLM-4.7-Flash

新しい [FP8 Dynamic quant](https://huggingface.co/unsloth/GLM-4.7-Flash-FP8-Dynamic) を使って、プレミアムで高速な推論を実現できます。まず nightly 版の vLLM をインストールしてください:

{% 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 %}

次に、 [モデルの Unsloth の動的 FP8 版を提供してください。KV キャッシュのメモリ使用量を 50% 削減するために FP8 を有効にし、4 GPU 上で動作します。1 GPU の場合は、](https://huggingface.co/unsloth/GLM-4.7-Flash-FP8-Dynamic) を使用してください `CUDA_VISIBLE_DEVICES='0'` そして `--tensor-parallel-size 1` を設定するか、この引数を削除してください。FP8 を無効にするには、削除してください `--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
```

その後、OpenAI API経由で提供中のモデルを呼び出せます:

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

#### :star: vLLM GLM-4.7-Flash 推論の投機的デコード

GLM 4.7 Flash の MTP（マルチトークン予測）モジュールを使うと、生成スループットが 1 B200 で 13,000 トークンから 1,300 トークンに低下することが分かりました！(10倍遅い) Hopper 上では、おそらく問題ないはずです。

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

1xB200 でスループットはわずか 1,300 トークン/秒（ユーザーごとのデコードは 130 トークン/秒）

<figure><img src="https://735611837-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>

そして 1xB200 で 13,000 トークン/秒のスループット（それでもユーザーごとのデコードは 130 トークン/秒）

<figure><img src="https://735611837-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:GLM-4.7-Flash でのツール呼び出し

参照 [tool-calling-guide-for-local-llms](https://unsloth.ai/docs/jp/ji-ben/tool-calling-guide-for-local-llms "mention") ツール呼び出しの方法の詳細はこちらをご覧ください。新しいターミナルで（tmux を使っている場合は CTRL+B+D）、2つの数値の加算、Python コードの実行、Linux 関数の実行など、いくつかのツールを作成します:

{% 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([
        "昔々、はるか彼方の銀河系で...",
        "スロースとコードが大好きな2人の友達がいました...",
        "すべてのスロースが超人的な知能を持つよう進化したため、世界は終わろうとしていました...",
        "片方の友達は気づいていませんでしたが、もう一方は誤ってスロースを進化させるプログラムをコードしていました...",
    ])
def terminal(command: str) -> str:
    if "rm" in command or "sudo" in command or "dd" in command or "chmod" in command:
        msg = "'rm, sudo, dd, chmod' コマンドは危険なので実行できません"
        print(msg); return msg
    print(f"ターミナルコマンド `{command}` を実行中")
    try:
        return str(subprocess.run(command, capture_output = True, text = True, shell = True, check = True).stdout)
    except subprocess.CalledProcessError as e:
        return f"コマンドの実行に失敗しました: {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": "2つの数値を加算します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "1つ目の数値。",
                    },
                    "b": {
                        "type": "string",
                        "description": "2つ目の数値。",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "multiply_number",
            "description": "2つの数値を乗算します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "1つ目の数値。",
                    },
                    "b": {
                        "type": "string",
                        "description": "2つ目の数値。",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "substract_number",
            "description": "2つの数値を減算します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "1つ目の数値。",
                    },
                    "b": {
                        "type": "string",
                        "description": "2つ目の数値。",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "write_a_story",
            "description": "ランダムな物語を書きます。",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": [],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "terminal",
            "description": "ターミナルから操作を実行します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "command": {
                        "type": "string",
                        "description": "起動したいコマンド。例: `ls`, `rm`, ...",
                    },
                },
                "required": ["command"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "python",
            "description": "実行される Python コードを指定して Python インタプリタを呼び出します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "実行する Python コード",
                    },
                },
                "required": ["code"],
            },
        },
    },
]
```

{% endcode %}

それから以下の関数を使用します（コピーして貼り付けて実行してください）。これにより関数呼び出しが自動的に解析され、任意のモデルに対して OpenAI エンドポイントが呼び出されます:

{% 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"使用モデル = {model_name}")
    has_tool_calls = True
    original_messages_len = len(messages)
    while has_tool_calls:
        print(f"現在のメッセージ = {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 %}

GLM-4.7-Flash を起動した後 `llama-server` のように [#deploy-with-llama-server-and-openais-completion-library](#deploy-with-llama-server-and-openais-completion-library "mention") または [tool-calling-guide-for-local-llms](https://unsloth.ai/docs/jp/ji-ben/tool-calling-guide-for-local-llms "mention") 詳細については、次にいくつかのツール呼び出しを行えます:

**GLM 4.7 の数値演算のためのツール呼び出し**

{% code overflow="wrap" %}

```python
messages = [{
    "role": "user",
    "content": [{"type": "text", "text": "今日の日付に3日を足すと何日ですか?"}],
}]
unsloth_inference(messages, temperature = 1.0, top_p = 0.95, top_k = -1, min_p = 0.01)
```

{% endcode %}

<figure><img src="https://735611837-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>

**GLM-4.7-Flash の生成された Python コードを実行するためのツール呼び出し**

{% code overflow="wrap" %}

```python
messages = [{
    "role": "user",
    "content": [{"type": "text", "text": "Python でフィボナッチ関数を作成し、fib(20) を求めてください。"}],
}]
unsloth_inference(messages, temperature = 1.0, top_p = 0.95, top_k = -1, min_p = 0.01)
```

{% endcode %}

<figure><img src="https://735611837-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>

### ベンチマーク

GLM-4.7-Flash は、AIME 25 を除くすべてのベンチマークで最高性能の 30B モデルです。

<figure><img src="https://735611837-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>

| ベンチマーク             | 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/jp/moderu/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.
