# GLM-4.7-Flash：如何本地运行

GLM-4.7-Flash 是 Z.ai 新推出的 30B MoE 推理模型，专为本地部署打造，在编程、智能体工作流和聊天方面提供同类最佳表现。它使用约 3.6B 参数，支持 20 万上下文，并在 SWE-Bench、GPQA 以及推理/聊天基准上领先。

GLM-4.7-Flash 可运行于 **24GB 内存**/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` 修复了指定错误的一个 bug `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/a63fe18206ba278e17e40bf31ce577cda524869c#run-glm-4.7-flash" class="button primary">运行教程</a><a href="/pages/a63fe18206ba278e17e40bf31ce577cda524869c#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)

### ⚙️ 使用指南

为获得最佳性能，请确保你可用的总内存（显存 + 系统内存）超过你下载的量化模型文件大小。如果不足，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" %}
目前，我们 **不建议** 使用 **Ollama** 运行此 GGUF，因为可能存在聊天模板兼容性问题。该 GGUF 在 llama.cpp（或诸如 LM Studio、Jan 等后端）上表现良好。

**记得禁用重复惩罚！或者设置** `--repeat-penalty 1.0`
{% endhint %}

* **最大上下文窗口：** `202,752`

### 🖥️ 运行 GLM-4.7-Flash

根据你的用例，你需要使用不同的设置。一些 GGUF 之所以最终大小相近，是因为模型架构（例如 [gpt-oss](/docs/zh/mo-xing/gpt-oss-how-to-run-and-fine-tune.md)）的维度不能被 128 整除，因此部分内容无法量化到更低位宽。

由于本指南使用 4-bit，你大约需要 18GB 内存/统一内存。为了获得最佳性能，我们建议至少使用 4-bit 精度。

{% hint style="warning" %}
目前，我们 **不建议** 使用 **Ollama** 运行此 GGUF，因为可能存在聊天模板兼容性问题。该 GGUF 在 llama.cpp（或诸如 LM Studio、Jan 等后端）上表现良好。

**记得禁用重复惩罚！或者设置** `--repeat-penalty 1.0`
{% endhint %}

#### 🦥 Unsloth Studio 指南

GLM-4.7-Flash 可以在中运行和微调 [Unsloth Studio](/docs/zh/xin/studio.md)，我们新的用于本地 AI 的开源网页界面。使用 Unsloth Studio，你可以在以下平台本地运行模型： **MacOS、Windows**、Linux 和：

{% columns %}
{% column %}

* 搜索、下载、 [运行 GGUF](/docs/zh/xin/studio.md#run-models-locally) 和 safetensor 模型
* [**自愈式** 工具调用](/docs/zh/xin/studio.md#execute-code--heal-tool-calling) + **网页搜索**
* [**代码执行**](/docs/zh/xin/studio.md#run-models-locally) （Python、Bash）
* [自动推理](/docs/zh/xin/studio.md#model-arena) 参数调优（temp、top-p 等）
* 通过 llama.cpp 实现快速 CPU + GPU 推理
* [训练 LLM](/docs/zh/xin/studio.md#no-code-training) 速度提升 2 倍，VRAM 减少 70%
  {% endcolumn %}

{% column %}

<div data-with-frame="true"><figure><img src="/files/5af4df407c8134f1ff75a4d7535569361c049e51" 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](/docs/zh/xin/studio/chat.md) 标签页并搜索 **GLM-4.7-Flash** 在搜索栏中输入，并下载你想要的模型和量化版本。

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

{% step %}
**运行 GLM-4.7-Flash**

在使用 Unsloth Studio 时，推理参数应会自动设置，不过你仍然可以手动更改。你也可以编辑上下文长度、聊天模板和其他设置。

如需更多信息，你可以查看我们的 [Unsloth Studio 推理指南](/docs/zh/xin/studio/chat.md).

<div data-with-frame="true"><figure><img src="/files/6273055e6bbde016134838582519f00de2201635" 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 的允许将上下文扩展到 20 万。

你也可以尝试 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/zh/ji-chu/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 修复了指定错误的一个 bug** `"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" %}
目前，我们 **不建议** 使用 **Ollama** 运行此 GGUF，因为可能存在聊天模板兼容性问题。该 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 创建一个完全不同的游戏
找出两者中的 bug
把我刚才提到的第一个游戏做成一个独立的 HTML 文件
找出 bug 并展示修复后的游戏
```

这会渲染出如下 HTML 形式的 Flappy Bird 游戏：

<details>

<summary>HTML 中的 Flappy Bird 游戏（可展开）</summary>

```html
<!DOCTYPE html>
<html lang="zh">
<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>游戏结束</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();
    });
    
    // 允许点击游戏结束遮罩来重新开始
    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/d767b0a57bd3a9c5931cf07dfd66b818c4fc1297" alt="" width="188"><figcaption></figcaption></figure> <figure><img src="/files/c867f0e944e7d9329c98fb1d85b76d1588c567c8" 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 时，微调路由层可能不是个好主意，所以我们默认将其禁用。如果你想保留其推理能力（可选），可以使用直接回答和思维链示例的混合。至少使用 <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 量化版本](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) 该模型。我们启用了 FP8，将 KV cache 内存使用量减少 50%，并在 4 张 GPU 上运行。如果你只有 1 张 GPU，请使用 `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（多 token 预测）模块会使生成吞吐量从 1 台 B200 上的 13,000 tokens 降到 1,300 tokens！（慢 10 倍）在 Hopper 上，希望表现会没问题。

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

在 1xB200 上仅有 1,300 tokens/s 的吞吐量（每个用户解码 130 tokens/s）

<figure><img src="/files/a60c85d94f90a6e93660579987249ea9d8bccb8b" alt=""><figcaption></figcaption></figure>

而在 1xB200 上可达 13,000 tokens/s 的吞吐量（每个用户解码仍为 130 tokens/s）

<figure><img src="/files/e873ee3a7ba596f587a5c81bb03bef913ee8ca43" alt=""><figcaption></figcaption></figure>

### :hammer:使用 GLM-4.7-Flash 进行工具调用

查看 [Tool Calling Guide](/docs/zh/ji-chu/tool-calling-guide-for-local-llms.md) 以了解如何进行工具调用的更多细节。在一个新的终端中（如果使用 tmux，请按 CTRL+B+D），我们创建一些工具，比如两数相加、执行 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([
        "很久很久以前，在一个遥远的星系里……",
        "有两个朋友，他们热爱树懒和代码……",
        "世界即将毁灭，因为每只树懒都进化成了超人般的智慧……",
        "其中一位朋友并不知道，另一位不小心写了一个让树懒进化的程序……",
    ])
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,
    "subtract_number": subtract_number,
    "write_a_story": write_a_story,
    "terminal": terminal,
    "python": python,
}
tools = [
    {
        "type": "function",
        "function": {
            "name": "add_number",
            "description": "将两个数字相加。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "第一个数字。",
                    },
                    "b": {
                        "type": "string",
                        "description": "第二个数字。",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "multiply_number",
            "description": "将两个数字相乘。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "第一个数字。",
                    },
                    "b": {
                        "type": "string",
                        "description": "第二个数字。",
                    },
                },
                "required": ["a", "b"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "subtract_number",
            "description": "将两个数字相减。",
            "parameters": {
                "type": "object",
                "properties": {
                    "a": {
                        "type": "string",
                        "description": "第一个数字。",
                    },
                    "b": {
                        "type": "string",
                        "description": "第二个数字。",
                    },
                },
                "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](/docs/zh/ji-chu/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/709a7caf90f687c85c658d21f595e0be8beb2b73" alt=""><figcaption></figcaption></figure>

**用于执行 GLM-4.7-Flash 生成的 Python 代码的工具调用**

{% code overflow="wrap" %}

```python
messages = [{
    "role": "user",
    "content": [{"type": "text", "text": "在 Python 中创建一个 Fibonacci 函数并求 fib(20)。"}],
}]
unsloth_inference(messages, temperature = 1.0, top_p = 0.95, top_k = -1, min_p = 0.01)
```

{% endcode %}

<figure><img src="/files/0b229e56ef0ba6e1bd20edfed3c3cf4b69331bf4" alt="" width="563"><figcaption></figcaption></figure>

### 基准测试

除了 AIME 25 之外，GLM-4.7-Flash 是所有基准中表现最好的 30B 模型。

<figure><img src="/files/751e105423da5bbb021c69aef5dd8936e902c50a" 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/zh/mo-xing/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.
