# 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｜>` 令牌！- 或者使用聊天模板格式化器
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` 以对抗非常罕见的标记预测——我发现这对 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="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-3c484081174c631653c8c7bf7e7674f05255f740%2FInShot_20250127_043158375_H8Uu6tyJXYAFwUEIu04Am.gif?alt=media">InShot_20250127_043158375_H8Uu6tyJXYAFwUEIu04Am.gif</a></td></tr><tr><td>1.58bit 动态量化</td><td></td><td></td><td><a href="https://2657992854-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FxhOjnexMCB3dmuQFQ2Zq%2Fuploads%2Fgit-blob-c41eac0fea9362017e94123ee8f9793df21b8e97%2FInShot_20250127_042648160_lrtL8-eRhl4qtLaUDSU87.gif?alt=media">InShot_20250127_042648160_lrtL8-eRhl4qtLaUDSU87.gif</a></td></tr></tbody></table>

使用的提示如下：

{% code overflow="wrap" %}

```
<｜User｜>用 Python 创建一个 Flappy Bird 游戏。你必须包含以下内容：
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｜>用 Python 创建一个 Flappy Bird 游戏。你必须包含以下内容:\n1. 你必须使用 pygame.\n2. 背景颜色应随机选择且为浅色。以浅蓝色开始.\n3. 多次按下 SPACE 将加速小鸟.\n4. 小鸟的形状应随机选择为方形、圆形或三角形。颜色应随机选择为深色.\n5. 在底部放置一些土地，颜色随机为深棕色或黄色.\n6. 在右上角显示分数。通过通过管道且未碰撞时增加分数.\n7. 随机间隔生成管道并保持足够的间距。管道颜色随机为深绿色、浅棕色或深灰色调.\n8. 当你失败时，显示最佳得分。将文本显示在屏幕内。按 q 或 Esc 将退出游戏。重新开始是再次按 SPACE.\n最终游戏应位于 Python 的 markdown 段中。在最终的 markdown 段之前检查你的代码是否有错误并修复它们。<｜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 或 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，见： [docs.openwebui.com/tutorials/integrations/deepseekr1-dynamic/](https://docs.openwebui.com/tutorials/integrations/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 令牌，你应该只调用 *tokenizer.encode(..., add\_special\_tokens = False)* 因为聊天模板也会自动添加一个 BOS。\
对于 llama.cpp / GGUF 推理，你应该跳过 BOS，因为它会自动添加。

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

\<think> 和 \</think> 令牌有各自指定的令牌。对于 Qwen 和 Llama 的蒸馏版本，某些令牌被重新映射，而例如 Qwen 并没有 BOS 令牌，所以必须使用 <|object\_ref\_start|> 来替代。\
\
**分词器 ID 映射：**

| 令牌                        | 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   |
| 填充令牌                      | 2      | 151654  | 128004   |

模型中的原始令牌：

| 令牌                    | Qwen 2.5 32B 基础版         | Llama 3.3 70B 指令版                 |
| --------------------- | ------------------------ | --------------------------------- |
| \<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\|> |
| 填充令牌                  | <\|vision\_pad\|>        | <\|finetune\_right\_pad\_id\|>    |

所有蒸馏版本和原始 R1 版本似乎意外地将填充令牌分配为 <｜end▁of▁sentence｜>，这通常不是一个好主意，尤其是如果你想在这些推理模型上进一步微调。这会导致无限循环生成，因为大多数框架会将 EOS 令牌屏蔽为 -100。\
\
我们已修复所有蒸馏版本和原始 R1 版本的正确填充令牌（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.
