# DeepSeek-R1：如何本地运行

{% hint style="success" %}
请参见 <https://docs.unsloth.ai/basics/deepseek-r1-0528-how-to-run-locally> 获取更新后的 DeepSeek R1-0528（2025年5月28日版本）
{% endhint %}

## 使用 llama.cpp（推荐）

1. 别忘了 `<｜User｜>` 和 `<｜Assistant｜>` tokens！- 或者使用聊天模板格式化器
2. 获取最新版本 `llama.cpp` 在： [github.com/ggml-org/llama.cpp](https://github.com/ggml-org/llama.cpp)。你也可以按照下面的构建说明进行操作。 **对于 Apple Mac / Metal 设备**，设置 `-DGGML_CUDA=OFF` 然后像平常一样继续——Metal 支持默认开启。

```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=ON -DGGML_CUDA=ON -DLLAMA_CURL=ON
cmake --build llama.cpp/build --config Release -j --clean-first --target llama-quantize llama-cli llama-gguf-split
cp llama.cpp/build/bin/llama-* llama.cpp
```

3. 最好使用 `--min-p 0.05` 来抑制非常罕见的 token 预测——我发现这在 1.58bit 模型上尤其有效。
4. 通过以下方式下载模型：

```python
# pip install huggingface_hub hf_transfer
# import os # 可选，用于更快下载
# os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"

from huggingface_hub import snapshot_download
snapshot_download(
  repo_id = "unsloth/DeepSeek-R1-GGUF",
  local_dir = "DeepSeek-R1-GGUF",
  allow_patterns = ["*UD-IQ1_S*"], # 选择 1.58bit 的量化类型 UD-IQ1_S
)
```

6. 使用 Q4\_0 K 量化缓存的示例 **注意，-no-cnv 会禁用自动对话模式**

```bash
./llama.cpp/llama-cli \
    --model DeepSeek-R1-GGUF/DeepSeek-R1-UD-IQ1_S/DeepSeek-R1-UD-IQ1_S-00001-of-00003.gguf \\
    --cache-type-k q4_0 \\
    -no-cnv --prio 2 \\
    --temp 0.6 \\
    --ctx-size 8192 \\
    --seed 3407 \\
    --prompt "<｜User｜>What is 1+1?<｜Assistant｜>"
```

示例输出：

```txt
 <think>
 好吧，我需要弄清楚 1 加 1 等于多少。嗯，我该从哪里开始呢？我记得在学校里，加法是很基础的，但我想确保自己真正理解它。
 让我想想，1 加 1。也就是说，我有一个物品，然后再加上另一个。也许像一个苹果加另一个苹果。如果我有一个苹果，又有人给我一个，那我现在就有两个苹果。所以，1 加 1 应该等于 2。这很合理。
 等等，但数学有时会很棘手。会不会是别的什么结果？比如在不同的数制里可能不同？但我觉得这个问题很直接，用的是普通数字，不是二进制、十六进制之类的。
 我也记得在算术中，加法就是把数量合并。所以，如果你有两个 1 的数量，把它们合在一起，总数就是 2。对，这看起来是对的。
 有没有一种情况下 1 加 1 不是 2 呢？我想不出来……
```

4. 如果你有一块 GPU（例如 RTX 4090）并且有 24GB 显存，你可以把多层卸载到 GPU 上以加快处理。如果你有多块 GPU，可能可以卸载更多层。

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

5. 要测试我们在这里的博客文章中提到的 Flappy Bird 示例： <https://unsloth.ai/blog/deepseekr1-dynamic>，我们可以使用我们的 1.58bit 动态量化生成如下第二个示例：

<table data-column-title-hidden data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td>原始 DeepSeek R1</td><td></td><td></td><td><a href="/files/45e47ba3b3da13ea9006dd243af90d3bce842a4c">/files/45e47ba3b3da13ea9006dd243af90d3bce842a4c</a></td></tr><tr><td>1.58bit 动态量化</td><td></td><td></td><td><a href="/files/36c6242f53cbd4657c6b42372229b2ff089d0d0c">/files/36c6242f53cbd4657c6b42372229b2ff089d0d0c</a></td></tr></tbody></table>

使用的提示词如下：

{% code overflow="wrap" %}

```
<｜User｜>Create a Flappy Bird game in Python. You must include these things:
1. 你必须使用 pygame。
2. 背景颜色应随机选择，并且是浅色。以浅蓝色开始。
3. 多次按下 SPACE 会加速小鸟。
4. 小鸟的形状应随机选择为正方形、圆形或三角形。颜色应随机选择为深色。
5. 在底部放一些随机选择为深棕色或黄色的地面。
6. 在右上角显示分数。如果你通过管道且没有撞上它们，分数就增加。
7. 随机间隔生成足够空隙的管道。将它们随机设为深绿色、浅棕色或深灰色。
8. 当你失败时，显示最高分。让文字显示在屏幕内。按 q 或 Esc 退出游戏。重新开始时再次按 SPACE。
最终游戏应以 Python 的 markdown 区块形式呈现。在最终 markdown 区块之前检查代码是否有错误并修复它们。<｜Assistant｜>
```

{% endcode %}

要使用这个示例调用 llama.cpp，我们这样做：

```bash
./llama.cpp/llama-cli \
    --model DeepSeek-R1-GGUF/DeepSeek-R1-UD-IQ1_S/DeepSeek-R1-UD-IQ1_S-00001-of-00003.gguf \\
    --cache-type-k q4_0 \\
    -no-cnv --prio 2 \\
    --n-gpu-layers 7 \\
    --temp 0.6 \\
    --ctx-size 8192 \\
    --seed 3407 \\
    --prompt "<｜User｜>Create a Flappy Bird game in Python. You must include these things:\n1. You must use pygame.\n2. The background color should be randomly chosen and is a light shade. Start with a light blue color.\n3. Pressing SPACE multiple times will accelerate the bird.\n4. The bird's shape should be randomly chosen as a square, circle or triangle. The color should be randomly chosen as a dark color.\n5. Place on the bottom some land colored as dark brown or yellow chosen randomly.\n6. Make a score shown on the top right side. Increment if you pass pipes and don't hit them.\n7. Make randomly spaced pipes with enough space. Color them randomly as dark green or light brown or a dark gray shade.\n8. When you lose, show the best score. Make the text inside the screen. Pressing q or Esc will quit the game. Restarting is pressing SPACE again.\nThe final game should be inside a markdown section in Python. Check your code for errors and fix them before the final markdown section.<｜Assistant｜>"
```

5. 另外，如果你想把权重合并后用于 Ollama，例如，使用这个脚本：

```bash
./llama.cpp/llama-gguf-split --merge \\
    DeepSeek-R1-GGUF/DeepSeek-R1-UD-IQ1_S-00001-of-00003.gguf \\
    merged_file.gguf
```

6. DeepSeek R1 有 61 层。例如，对于 24GB GPU 或 80GB GPU，向下取整后你可以预期卸载如下层数（如果超出显存则减 1）：

| 量化      | 文件大小  | 24GB GPU | 80GB GPU | 2x80GB GPU |
| ------- | ----- | -------- | -------- | ---------- |
| 1.58bit | 131GB | 7        | 33       | 全部 61 层    |
| 1.73bit | 158GB | 5        | 26       | 57         |
| 2.22bit | 183GB | 4        | 22       | 49         |
| 2.51bit | 212GB | 2        | 19       | 32         |

### 在 Mac / Apple 设备上运行

对于 Apple Metal 设备，要注意 --n-gpu-layers。如果发现机器内存不足，就降低它。对于 128GB 统一内存的机器，你大约可以卸载 59 层。

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

### 在 Ollama/Open WebUI 中运行

Open WebUI 在这里制作了一个逐步教程，说明如何运行 R1： <https://docs.openwebui.com/tutorials/integrations/llm-providers/deepseekr1-dynamic>

\
如果你想使用 Ollama 对 GGUF 进行推理，你需要先将 3 个 GGUF 分割文件合并为 1 个，如下面的代码所示。然后你需要在本地运行该模型。

```bash
./llama.cpp/llama-gguf-split --merge \\
  DeepSeek-R1-GGUF/DeepSeek-R1-UD-IQ1_S/DeepSeek-R1-UD-IQ1_S-00001-of-00003.gguf \\
	merged_file.gguf
```

## DeepSeek 聊天模板

所有蒸馏版本和主 671B R1 模型都使用相同的聊天模板：

`<｜begin▁of▁sentence｜><｜User｜>What is 1+1?<｜Assistant｜>It's 2.<｜end▁of▁sentence｜><｜User｜>Explain more!<｜Assistant｜>`

BOS 会被强制添加，而 EOS 会分隔每次交互。为了在推理时抵消双重 BOS token，你应只调用 *tokenizer.encode(..., add\_special\_tokens = False)* 因为聊天模板也会自动添加一个 BOS token。\
对于 llama.cpp / GGUF 推理，你应跳过 BOS，因为它会自动添加它。

`<｜User｜>What is 1+1?<｜Assistant｜>`

\<think> 和 \</think> tokens 都有各自专用的 token。对于 Qwen 和 Llama 的蒸馏版本，某些 token 被重新映射，而例如 Qwen 没有 BOS token，因此不得不使用 <|object\_ref\_start|> 代替。\
\
**分词器 ID 映射：**

| Token                     | R1     | 蒸馏 Qwen | 蒸馏 Llama |
| ------------------------- | ------ | ------- | -------- |
| \<think>                  | 128798 | 151648  | 128013   |
| \</think>                 | 128799 | 151649  | 128014   |
| <\|begin\_of\_sentence\|> | 0      | 151646  | 128000   |
| <\|end\_of\_sentence\|>   | 1      | 151643  | 128001   |
| <\|User\|>                | 128803 | 151644  | 128011   |
| <\|Assistant\|>           | 128804 | 151645  | 128012   |
| 填充 token                  | 2      | 151654  | 128004   |

模型中的原始 token：

| Token                 | Qwen 2.5 32B Base        | Llama 3.3 70B Instruct            |
| --------------------- | ------------------------ | --------------------------------- |
| \<think>              | <\|box\_start\|>         | <\|reserved\_special\_token\_5\|> |
| \</think>             | <\|box\_end\|>           | <\|reserved\_special\_token\_6\|> |
| <｜begin▁of▁sentence｜> | <\|object\_ref\_start\|> | <\|begin\_of\_text\|>             |
| <｜end▁of▁sentence｜>   | <\|endoftext\|>          | <\|end\_of\_text\|>               |
| <｜User｜>              | <\|im\_start\|>          | <\|reserved\_special\_token\_3\|> |
| <｜Assistant｜>         | <\|im\_end\|>            | <\|reserved\_special\_token\_4\|> |
| 填充 token              | <\|vision\_pad\|>        | <\|finetune\_right\_pad\_id\|>    |

所有蒸馏版和原始 R1 版本似乎都不小心把填充 token 指派给了 <｜end▁of▁sentence｜>，这通常不是一个好主意，尤其是如果你想在这些推理模型之上继续微调。这会导致无限的生成，因为大多数框架会将 EOS token 屏蔽为 -100。\
\
我们已经为所有蒸馏版和原始 R1 版本修复了正确的填充 token（Qwen 使用 <|vision\_pad|>，Llama 使用 <|finetune\_right\_pad\_id|>，而 R1 使用 <｜▁pad▁｜> 或我们自己添加的 <｜PAD▁TOKEN｜>。

## GGUF R1 表

<table data-full-width="true"><thead><tr><th>MoE 比特数</th><th>类型</th><th>磁盘大小</th><th>准确率</th><th>链接</th><th>详情</th></tr></thead><tbody><tr><td>1.58bit</td><td>UD-IQ1_S</td><td><strong>131GB</strong></td><td>一般</td><td><a href="https://huggingface.co/unsloth/DeepSeek-R1-GGUF/tree/main/DeepSeek-R1-UD-IQ1_S">链接</a></td><td>MoE 全部为 1.56bit。 <code>down_proj</code> MoE 中混合 2.06/1.56bit</td></tr><tr><td>1.73bit</td><td>UD-IQ1_M</td><td><strong>158GB</strong></td><td>好</td><td><a href="https://huggingface.co/unsloth/DeepSeek-R1-GGUF/tree/main/DeepSeek-R1-UD-IQ1_M">链接</a></td><td>MoE 全部为 1.56bit。 <code>down_proj</code> MoE 中保留为 2.06bit</td></tr><tr><td>2.22bit</td><td>UD-IQ2_XXS</td><td><strong>183GB</strong></td><td>更好</td><td><a href="https://huggingface.co/unsloth/DeepSeek-R1-GGUF/tree/main/DeepSeek-R1-UD-IQ2_XXS">链接</a></td><td>MoE 全部为 2.06bit。 <code>down_proj</code> MoE 中混合 2.5/2.06bit</td></tr><tr><td>2.51bit</td><td>UD-Q2_K_XL</td><td><strong>212GB</strong></td><td>最佳</td><td><a href="https://huggingface.co/unsloth/DeepSeek-R1-GGUF/tree/main/DeepSeek-R1-UD-Q2_K_XL">链接</a></td><td>MoE 全部为 2.5bit。 <code>down_proj</code> MoE 中混合 3.5/2.5bit</td></tr></tbody></table>


---

# 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/deepseek-r1-how-to-run-locally.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
