# 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="/pages/68cc5d489fe86eefb1bb9cd2e351bcdb90866b49#run-glm-4.7-flash" class="button primary">こともできます。</a><a href="/pages/68cc5d489fe86eefb1bb9cd2e351bcdb90866b49#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>      |
| 繰り返しペナルティ = 無効、または 1.0                                             | 繰り返しペナルティ = 無効、または 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](/docs/jp/moderu/gpt-oss-how-to-run-and-fine-tune.md)）の次元が 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](/docs/jp/xin-zhe/studio.md)で実行およびファインチューニングできます。これはローカル AI 向けの新しいオープンソース Web UI です。Unsloth Studio を使えば、モデルをローカルで実行できます **MacOS、Windows**、Linux および:

{% columns %}
{% column %}

* 検索、ダウンロード、 [GGUF を実行](/docs/jp/xin-zhe/studio.md#run-models-locally) し、safetensor モデルを扱う
* [**自己修復** ツール呼び出し](/docs/jp/xin-zhe/studio.md#execute-code--heal-tool-calling) + **Web 検索**
* [**コード実行**](/docs/jp/xin-zhe/studio.md#run-models-locally) （Python、Bash）
* [自動推論](/docs/jp/xin-zhe/studio.md#model-arena) パラメータ調整（temp、top-p など）
* llama.cpp を介した高速な CPU + GPU 推論
* [LLM を学習する](/docs/jp/xin-zhe/studio.md#no-code-training) VRAM を 70% 少なくして 2 倍高速
  {% endcolumn %}

{% column %}

<div data-with-frame="true"><figure><img src="/files/c32867f999db074387ac16732ce548485cc593de" 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 %}
**で実行およびファインチューニングできます**

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

その後、 [Studio Chat](/docs/jp/xin-zhe/studio/chat.md) タブで **GLM-4.7-Flash** を検索バーに入力し、希望するモデルと量子化版をダウンロードしてください。

<div data-with-frame="true"><figure><img src="/files/ca24c876304cbf8074c1511a37a6997169841fd3" alt="" width="375"><figcaption></figcaption></figure></div>
{% endstep %}

{% step %}
**GLM-4.7-Flash を実行**

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

詳細は、 [Unsloth Studio 推論ガイド](/docs/jp/xin-zhe/studio/chat.md).

<div data-with-frame="true"><figure><img src="/files/44d9105dd956eac31f9586bcf01055a289b0ef3e" alt="" width="563"><figcaption></figcaption></figure></div>
{% endstep %}
{% endstepper %}

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

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

{% 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デバッグ](/docs/jp/ji-ben/troubleshooting-and-faqs/hugging-face-hub-xet-debugging.md)

{% 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 でまったく別のゲームを作って
両方のバグを見つけて
先ほど言った 1 つ目のゲームを、単独の HTML ファイルで作って
バグを見つけて、修正済みゲームを表示して
```

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

<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 Fixed</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) {
                // 垂直方向の重なり（上のパイプに当たる OR 下のパイプに当たる）
                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="/files/cc6698126ce26defd572a77475906eb11168e8b7" alt="" width="188"><figcaption></figcaption></figure> <figure><img src="/files/d37d9be118ce0cfa73e55a8432762acc1b437be0" 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": "What is 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 量子化版](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 版](https://huggingface.co/unsloth/GLM-4.7-Flash-FP8-Dynamic) モデルの。KV キャッシュのメモリ使用量を 50% 削減するために FP8 を有効にし、4 GPU で実行しています。GPU が 1 枚の場合は `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="/files/e9c0874380c9e43e94bcb759d01b071abe829da6" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/7249300cd1645f8602474c6d82c07d9ccfd4d5cb" alt=""><figcaption></figcaption></figure>

### :hammer:GLM-4.7-Flash でのツール呼び出し

参照 [Tool Calling Guide](/docs/jp/ji-ben/tool-calling-guide-for-local-llms.md) ツール呼び出しの方法の詳細については。新しい端末で（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 subtract_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"Executing terminal command `{command}`")
    try:
        return str(subprocess.run(command, capture_output = True, text = True, shell = True, check = True).stdout)
    except subprocess.CalledProcessError as e:
        return f"Command failed: {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,
    "subtract_number": subtract_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": "最初の数。",
                    },
                    "b": {
                        "type": "string",
                        "description": "2番目の数。",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "multiply_number",
            "description": "2つの数を掛けます。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "最初の数。",
                    },
                    "b": {
                        "type": "string",
                        "description": "2番目の数。",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "subtract_number",
            "description": "2つの数を引きます。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "最初の数。",
                    },
                    "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"Using model = {model_name}")
    has_tool_calls = True
    original_messages_len = len(messages)
    while has_tool_calls:
        print(f"Current messages = {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](/docs/jp/ji-ben/tool-calling-guide-for-local-llms.md) を参照して詳細を確認すると、いくつかのツール呼び出しを行えます：

**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="/files/13169a592cccb180505dcd6371f3d293a096dc78" 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="/files/2ceb7043fd1f9573d24a2d44261488b25e60c960" alt="" width="563"><figcaption></figcaption></figure>

### ベンチマーク

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

<figure><img src="/files/b8660b7d2b877fea77db231c70e0526345ed4988" 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/tutorials/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.
