[Deepseek-r1] 从源码部署问题分析
发布时间:
目录
前言
想养女儿了, 结果只是想让女儿能听见就好困难, 作为一个微调苦手, 后来想了一下, 还是好好地重新开始从deepseek-r1学习, 才发现在进行小模型部署中存在了大量正常情况不会面临的问题, 于是打算在解决过程中把情况记录一下, 方便大家解决问题. 作为开源产品, 相比起望而却步不如先用起来.
下载
这也是一个比较抽象的问题, 数据源比较容易, 直接在huggingface找到最小模型, 考虑到大部分人难以下载, 也可以从镜像源进行拉取, 以下提供了hf-mirror. 但是源码在GitHub找到deepseek-r1会发现里面竟然只有论文, 喵了个咪, 谁教你这么用仓库的. 但是问题不大, 说明书有如下提示:
DeepSeek-R1 Models Please visit DeepSeek-V3 repo for more information about running DeepSeek-R1 locally.
NOTE: Hugging Face’s Transformers has not been directly supported yet.
注意了, 官方有说撇开责任说: 没有直接支持, 这是人干的事吗?! 可以先去deepseek-v3获取源码及相关说明书, 然后根据说明书调试下载的r1数据, 出问题的话就是后话了.
数据源问题
报错信息
跟随运行调整数据:
python convert.py --hf-ckpt-path /app/inference/DeepSeek-V3 --save-path /app/inference/DeepSeek-V3-Demo --n-experts 128 --model-parallel 4
可能会面临以下情况:
0%| | 0/163 [00:00<?, ?it/s]
Traceback (most recent call last):
File "convert.py", line 96, in
main(args.hf_ckpt_path, args.save_path, args.n_experts, args.model_parallel)
File "convert.py", line 51, in main
with safe_open(file_path, framework="pt", device="cpu") as f:
safetensors_rust.SafetensorError: Error while deserializing header: HeaderTooLarge
解决方法
我在#557上有帮忙过这个问题, 根源是git-lfs插件没有使用好, 导致.safetensors
文件下载失败(或者假成功, 可以比较以下文件大小和hash), 可以通过下载lfs插件进行拉取:
apt install git git-lfs
git lfs install
git lfs clone https://...
对于archlinux可以使用:
sudo pacman -S git git-lfs
git lfs install
git clone https://...
或者直接在源上一个一个下载数据文件, 好处是到底有没有下载成功是明显能看见的, 解决以后应该可以正常处理了(吗?)
数据格式问题
报错信息
可以参考#330, 很遗憾我注意到的时候这个issues已经关闭了, 我们可以分析一下错误信息:
file: convert.py. line 63: assert key in mapping
分析
这是在使用convert.py
脚本的过程中爆出的经典错误, 对main()
函数(实际上函数内传入了4个变量, 不过因为只是对错误进行整理, 且官方代码中已经对变量进行了解释, 我们无需对变量进行研究)进行分析, 通过调试可以发现在model中R1的key
模型节点相比R3预设中多了k_proj
和v_proj
节点, 我第一反应是找ds问个明白, 得到提示模型可能是其他的架构(如LLaMA).
这里有个小插曲, 朋友有使用oLLama快速部署了一个简单的模型, 但因为是被封装好的, 自行调整这一步相对会变得麻烦, 我还是想试试能不能尽可能透明地处理好属于自己的模型.
关键是”LLama”这个东西, 因为ds提出了在我认知中重合的东西, 且这个名字在其他deepseek-r1的相关数据模型中也存在过, 于是我尝试去了解了Llama, Llama是由Meta开源出来的一个大模型.
我们的思路应该换一换, 现在来认识一下DeepSeek-r1数据源的名字吧:
- deepseek-ai
- DeepSeek-R1: 在R1-Zero基础上解决可读性差和语言混合的模型
- DeepSeek-R1-Zero: 以V3-Base为基础采用GRPO作为RL框架提高推理性能的模型
- DeepSeek-R1-Distill-Llama-70B: 使用Llama模型的70B(十亿)数据蒸馏的模型
- DeepSeek-R1-Distill-Qwen-32B: 使用Qwen模型的32B(十亿)数据蒸馏的模型
- DeepSeek-R1-Distill-Qwen-14B: 使用Qwen模型的14B(十亿)数据蒸馏的模型
- DeepSeek-R1-Distill-Llama-8B: 使用Llama模型的8B(十亿)数据蒸馏的模型
- DeepSeek-R1-Distill-Qwen-7B: 使用Qwen模型的7B(十亿)数据蒸馏的模型
- DeepSeek-R1-Distill-Qwen-1.5B: 使用Qwen模型的1.5B(十亿)数据蒸馏的模型
很遗憾Qwen的官方群并没有给出一个明确的回复(可能负责答疑的人也不理解那些节点到底是用来做什么的吧, 笑), 不过我找到了这样一段代码1:
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
class DeepSeekModel:
def __init__(self, model_path="./DeepSeek-R1-Distill-Qwen-1.5B"):
self.device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {self.device}")
# 加载tokenizer和模型
self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
self.model = AutoModelForCausalLM.from_pretrained(
model_path,
trust_remote_code=True,
torch_dtype=torch.float16 if self.device == "cuda" else torch.float32
).to(self.device)
# 设置模型为评估模式
self.model.eval()
def generate_response(self, prompt, max_length=2048, temperature=0.7):
try:
# 对输入进行编码
inputs = self.tokenizer(prompt, return_tensors="pt").to(self.device)
# 生成回答
with torch.no_grad():
outputs = self.model.generate(
**inputs,
max_length=max_length,
temperature=temperature,
top_p=0.9,
pad_token_id=self.tokenizer.pad_token_id,
eos_token_id=self.tokenizer.eos_token_id
)
# 解码输出
response = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
return response
except Exception as e:
print(f"生成回答时发生错误: {str(e)}")
return None
def main():
# 初始化模型
model = DeepSeekModel()
# 测试对话
while True:
user_input = input("\n请输入您的问题 (输入 'quit' 退出): ")
if user_input.lower() == 'quit':
break
response = model.generate_response(user_input)
if response:
print("\nDeepSeek:", response)
if __name__ == "__main__":
main()
当然在正式运行的时候最好根据自己的系统情况改善到适合运行, 但是我们应该明确重要的是, 至少现在我们可以用上这些我们不知道用途的数据了, 接下来 需要以这些代码为基础进行调试, (下次接着写).
解决方法
很遗憾我曾以为这个问题能很快解决, 但是需要进行更麻烦的处理, 在一切成功后我会尝试重新整理一份源码以供使用.
小结
很恨自己什么都不会, 每当看见身边的人努力后就能取得成绩, 相比之下自己是真的糟糕透了. 之前一场比赛因为自己的问题什么都没拿到, 结束后很痛苦, 有人问我以后有什么打算, 我说想好好学习一下AI了, 实际上一篇论文也没看懂.
后来刚好有deepseek的声音, 于是决定自己亲自部署一个(在此之前只是摸了一下minigpt, 源码看起来一言难尽), 过程中其实遇到了很多问题, 包括微调, 资源限制, 空闲时间太少等等等等, 我想起一位师傅说过: “要拼命地去学”, 实际上我也做不到拼命, 我太会逃避了, 不过很多人也是这样. 因为自己以往的一些经验, 遭遇错误后我尝试一点一点进行了排查, 才慢慢有了这篇文章, 往好了说我现在能够继续往下走了, 可是实际上从简历上看我也还是什么都没做到.
人生是一场痛苦的马拉松, 之前聊剧本的时候我想夹带一点私货, 我提出一个场景: 让女朋友抱着他说”没事了, 可以不用继续痛苦了”, 后来讨论了一下, 我们认为这个场景应该在死去以后以意识流的形式呈现. 虽然看起来有点地狱, 但是我有想过, 其实对于大部分人的痛苦是看不到尽头的.
越是温柔, 看到的越多, 也就越容易沉浸在绝望之中, 不想继续痛苦估计只有在一切结束了吧.
参考文献
llama.本地化部署DeepSeek-R1-Distill-Qwen-1.5B[EB/OL].CSDN.https://blog.csdn.net/harebert/article/details/145392582.2025.01.29 ↩