🐋DeepSeek-R1:如何本地运行

关于如何使用 llama.cpp 运行我们为 DeepSeek-R1 提供的 1.58 位动态量化的指南。

circle-check

使用 llama.cpp(推荐)

  1. 别忘了 <|User|><|Assistant|> 令牌!- 或者使用聊天模板格式化器

  2. 获取最新的 llama.cpp 于: github.com/ggml-org/llama.cpparrow-up-right。你也可以按照下面的构建说明进行操作。 针对 Apple Mac / Metal 设备,设置 -DGGML_CUDA=OFF 然后像往常一样继续 - Metal 支持默认开启。

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
  1. 最好使用 --min-p 0.05 以对抗非常罕见的标记预测——我发现这对 1.58bit 模型尤其有效。

  2. 通过以下命令下载模型:

# 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
)
  1. 带 Q4_0 K 量化缓存的示例 注意 -no-cnv 会禁用自动对话模式

示例输出:

  1. 如果你有一块 GPU(例如 RTX 4090)且有 24GB,你可以将多层卸载到 GPU 上以加快处理。如果你有多块 GPU,可能可以卸载更多层。

  1. 要测试我们博客文章中提到的 Flappy Bird 示例,请参见: https://unsloth.ai/blog/deepseekr1-dynamicarrow-up-right,我们可以使用我们的 1.58bit 动态量化生成下面的第二个示例:

Cover

原始 DeepSeek R1

Cover

1.58bit 动态量化

使用的提示如下:

要使用此示例调用 llama.cpp,我们这样做:

  1. 此外,如果你想将权重合并在一起以便在例如 Ollama 中使用,请使用这个脚本:

  1. 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 层左右。

在 Ollama/Open WebUI 中运行

Open WebUI 已经制作了一个逐步教程,说明如何运行 R1,见: docs.openwebui.com/tutorials/integrations/deepseekr1-dynamic/arrow-up-right 如果你想在 Ollama 上对 GGUF 进行推理,首先需要将 3 个 GGUF 分割文件合并为 1 个,如下面代码所示。然后你需要在本地运行模型。

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 表格

MoE 位数
类型
磁盘大小
准确度
链接
详情

1.58bit

UD-IQ1_S

131GB

一般

MoE 全部 1.56bit。 down_proj 在 MoE 中混合为 2.06/1.56bit

1.73bit

UD-IQ1_M

158GB

良好

MoE 全部 1.56bit。 down_proj 在 MoE 中保持为 2.06bit

2.22bit

UD-IQ2_XXS

183GB

更好

MoE 全部 2.06bit。 down_proj 在 MoE 中混合为 2.5/2.06bit

2.51bit

UD-Q2_K_XL

212GB

最佳

MoE 全部 2.5bit。 down_proj 在 MoE 中混合为 3.5/2.5bit

最后更新于

这有帮助吗?