简介这套Python搭建的DeepSeek模型源代码面向希望上手多模态视觉语言VL模型的开发者以开源DeepSeek-VL为基础覆盖逻辑图解析、网页与公式识别、科学文献分析、自然图像理解及具身智能等常见场景帮助读者理解视觉与语言联合建模的实现路径。资源包共29个文件核心为18个Python脚本承担模型定义、数据处理、推理与服务等任务另有6张PNG示意图、2个JS脚本、CSS、ICO与JPEG等辅助资源包体仅883KB轻量易部署。目前已有891人浏览学习适合具备一定Python和深度学习基础、想快速搭建并体验DeepSeek多模态能力的开发者。通过源码可了解模型加载、推理流程、工具模块及前端展示的配合方式目录结构清晰便于按需修改和二次开发是学习视觉语言模型落地细节的实用参考。写正文之前先说说我为什么想写这篇东西。最近不少朋友问我DeepSeek模型怎么用Python搭起来跑通翻了翻网上的资料要么只讲API调用、要么丢一个半成品脚本让人自己悟真正能从零讲清楚“源码怎么写、每一行在干什么、踩坑在哪”的教程很少。所以我打算用一篇文章把这件事彻底讲透从环境准备、模型加载、文本生成、流式输出到GPU/CPU推理、本地模型与API调用的代码区别、以及我测试过程中遇到的高频异常一次讲完。无论你是想把DeepSeek接到自己的知识库、做个命令行问答工具还是单纯想研究大模型的推理代码这篇文章应该都能给你帮上忙。1. 为什么“用Python搭建DeepSeek模型”这件事值得自己写代码先别急着复制代码先把思路理清楚。很多人一提到接入DeepSeek第一反应是“这不是有官方API吗直接requests调用不就行了”这话没错官方API确实是最快的路但自己写Python代码跑DeepSeek模型的场景完全不是一回事。我们说的“搭建模型源代码”通常指下面两类需求搞清楚你要的是哪一种后面代码选型才不会跑偏本地加载开源权重把模型权重文件下载到本地用transformers或llama.cpp这类库在Python中加载、推理、微调。适合对数据隐私敏感、需要离线使用、或者要修改模型行为的场景。代码层面集成API把DeepSeek的API封装进自己的Python项目里做对话机器人、Agent工具、批量文本处理等应用开发。这条路不碰权重但同样需要写“源代码”来管理请求、流式输出、多轮上下文。我这篇文章的核心放在本地加载开源模型这条路上因为这条路对源码的要求更高、坑更多、网上资料也最零散。但API调用的代码我也会在第5节完整给出两条路线你都能直接用。另外说句实在的DeepSeek官方开源过多个尺寸的模型包括7B、16B、67B等最近也有多模态版本。用Python搭建的意思本质上就是把HuggingFace上的权重文件、模型配置、分词器通过transformers库加载成一个可对话的推理实例然后封装成自己的方法。这个过程里你写的每一行代码都有明确目的搞清楚这些目的比背代码重要得多。2. 环境准备Python版本、CUDA和三个核心依赖这一步卡住了不少人尤其是CUDA版本不对、torch装错导致模型能下下来但跑不动。我建议严格按照下面这套来别自己随意组合版本。2.1 Python版本和虚拟环境先说结论Python 3.10是当前最省心的版本。我测试过3.8、3.9、3.10、3.11四个版本。3.8和3.9对最新版transformers的部分特性支持不好3.11虽然也能跑但有些依赖库的预编译轮子还没完全跟上遇到问题你得自己编译很痛苦。3.10是深度学习生态最成熟的选择PyTorch、transformers、accelerate全部提供稳定支持。# 创建虚拟环境这一步强烈建议做 conda create -n deepseek python3.10 conda activate deepseek虚拟环境这一条很多人嫌麻烦跳过结果项目里装了一堆乱七八糟的包遇到版本冲突想死的心都有。独立环境带来的隔离性在深度学习项目里能帮你少加一个星期的班。2.2 CUDA与PyTorch最容易翻车的地方PyTorch版本必须和你的显卡驱动、CUDA版本匹配。先用nvidia-smi看一下你机器的驱动支持的最高CUDA版本然后去PyTorch官网选对应的安装命令。# 以CUDA 12.1为例如果驱动支持就用这条 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 # 不确定自己CUDA版本的话可以直接装CPU版先跑通代码 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu如果只是想把代码跑通、做功能验证CPU版完全够用后面再换GPU版不冲突。我自己一开始就是在MacBook上先用CPU版调通逻辑再转到带GPU的服务器上重装torch流程完全无缝。2.3 剩下的依赖一次装齐pip install transformers accelerate sentencepiece protobuf这四个包缺一不可我一个个说transformersHuggingFace的核心库负责加载模型、分词、推理。accelerate多设备推理的加速库加载大模型时自动处理显存分配没有这个包有些模型在单卡上明明能放得下却报OOM。sentencepieceDeepSeek分词器底层依赖的分词工具不装会在加载tokenizer时报错。protobuf模型配置文件解析需要不装同样会报错。版本方面transformers建议4.37以上太老版本的transformers对DeepSeek这类最新架构的支持不完整比如注意力层的参数名对不上加载直接报错。3. 手写第一个DeepSeek源码加载、推理、对话一次跑通环境ok后下面是完整代码。我把每一步都加了解释你能直接复制运行。3.1 完整可运行的源代码import torch from transformers import AutoModelForCausalLM, AutoTokenizer # 1. 指定模型名称这里是HuggingFace上的模型仓库路径 # 也可以换成 deepseek-ai/deepseek-llm-7b-chat 等版本 MODEL_NAME deepseek-ai/deepseek-llm-7b-chat # 2. 加载分词器 # 注意DeepSeek的分词器需要trust_remote_codeTrue # 因为它有自定义的tokenizer实现不走HuggingFace标准流程 tokenizer AutoTokenizer.from_pretrained( MODEL_NAME, trust_remote_codeTrue ) # 3. 加载模型 # device_mapauto 让accelerate自动分配模型层到可用的GPU/CPU上 # torch_dtypetorch.float16 用半精度加载显存占用直降一半 model AutoModelForCausalLM.from_pretrained( MODEL_NAME, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue ) # 4. 打开推理模式省显存、提速 model.eval() # 5. 构造对话的prompt # 注意chat模型对prompt格式敏感不能随便写 def build_prompt(user_input, historyNone): if history is None: history [] messages [] for user, assistant in history: messages.append(User: user \n\nAssistant: assistant \n\n) messages.append(User: user_input \n\nAssistant: ) return .join(messages) # 6. 推理函数 def chat(user_input, max_new_tokens512, temperature0.7): prompt build_prompt(user_input) inputs tokenizer(prompt, return_tensorspt) # 把输入放到模型所在的设备上 inputs {k: v.to(model.device) for k, v in inputs.items()} with torch.no_grad(): outputs model.generate( **inputs, max_new_tokensmax_new_tokens, temperaturetemperature, top_p0.9, do_sampleTrue, pad_token_idtokenizer.eos_token_id ) # 只取新生成的部分去掉输入的前缀 response tokenizer.decode(outputs[0][inputs[input_ids].shape[1]:], skip_special_tokensTrue) return response.strip() # 7. 测试 if __name__ __main__: print(chat(用Python写一个快速排序要求带注释))3.2 关键代码逐段拆解为什么是这些写法这段代码看起来简单但每一处设置都有讲究我把最容易忽略的几处拎出来说。第一个坑点trust_remote_codeTrue。这个参数坑了很多人。DeepSeek不像Llama等模型完全用标准架构它在代码里有自定义的模型实现比如注意力实现效率优化所以HuggingFace加载时必须允许执行模型仓库里附带的自定义Python代码。不填这个参数会直接报ValueError: deepseek-ai/deepseek-llm-7b-chat does not appear to have a file named config.json之类的问题或者提示需要trust_remote_code。安全问题顺便说一句trust_remote_code本质上是允许HuggingFace仓库里的代码在你机器上运行所以只对可信模型仓库开启不要随便加载自己不了解的仓库。第二个点torch_dtypetorch.float16。7B模型如果用FP32加载光权重就占28GB显存绝大多数显卡都扛不住。换float16权重降到14GB大部分24GB显存的卡就能跑。如果你的显卡连14GB都没有还没到绝望的时候后面第4节讲量化方案。第三个点device_mapauto。这个参数的作用是让transformers自动把模型的不同层分配到不同的设备上——比如GPU放不下时自动把部分层放CPU内存GPU放一部分。不需要自己手动写model.to(cuda)。这也是accelerate库存在的意义。我遇到过一些人明明显卡能跑却因为手写model.cuda()导致显存分配不均匀而OOM改用device_mapauto就正常了。第四个点生成参数。max_new_tokens表示最多生成多少新token不是总长度这个概念容易搞混。temperature0.7是采样温度越低回答越确定越高越有发散性。do_sampleTrue表示启用随机采样如果你想要稳定可复现的回答可以设do_sampleFalse并把temperature注释掉。3.3 实测输出与预期效果用上面的代码跑一次正常情况下会输出类似这样的内容具体文字因采样随机性会不同下面是快速排序的Python实现包含详细注释 def quick_sort(arr): # 基线条件当数组长度小于等于1时不需要排序 if len(arr) 1: return arr # 选择中间元素作为基准值 pivot arr[len(arr) // 2] # 将数组分成三部分小于基准值、等于基准值、大于基准值 left [x for x in arr if x pivot] middle [x for x in arr if x pivot] right [x for x in arr if x pivot] # 递归地对左右两部分排序然后合并结果 return quick_sort(left) middle quick_sort(right)看到这个输出说明你本地搭建第一条DeepSeek推理链路已经通了。4. 显存不够怎么办量化加载与CPU推理的两个方案如果你卡在“代码没问题、模型下完了、但一加载就OOM”这一节就是为你准备的。4.1 方案一加载4bit量化版显存降到6GB以内量化本质上是降低权重数值的精度——把16bit降到4bit——让模型体积大幅缩小代价是回答质量轻微下降。这个方案依赖bitsandbytes库安装和加载方式都很简单pip install bitsandbytesfrom transformers import BitsAndBytesConfig # 4bit量化配置 quantization_config BitsAndBytesConfig( load_in_4bitTrue, bnb_4bit_compute_dtypetorch.float16, bnb_4bit_use_double_quantTrue, bnb_4bit_quant_typenf4 ) model AutoModelForCausalLM.from_pretrained( MODEL_NAME, quantization_configquantization_config, device_mapauto, trust_remote_codeTrue )7B模型4bit量化后权重只占约4~5GB边缘显卡也能跑。我实测下来量化后回答质量和fp16没太大差别至少日常任务感知不明显。所以如果你的显卡在20系列、30系列的入门款或者只有8GB显存优先考虑这条路。4.2 方案二纯CPU推理慢但能出结果没有NVIDIA显卡的小伙伴也别放弃。CPU推理确实慢7B模型跑一次问答可能要等几分钟但作为学习验证完全够用。加载方式和第3节几乎一样只改一行model AutoModelForCausalLM.from_pretrained( MODEL_NAME, torch_dtypetorch.float32, # CPU上用float32比float16更稳 device_mapcpu, trust_remote_codeTrue )这里有个小知识点CPU推理时用float32而不是float16是因为CPU上有些算子对float16的支持不如GPU完整反而会更慢。内存方面7B模型float32推理大约需要28GB内存如果你机器只有16GB就需要配合量化把模型压缩到4bit再加载运行。4.3 显存释放与OOM后的恢复技巧实际运行中还常见一种情况上一次推理没释放显存第二次加载模型直接OOM。处理办法是在脚本开头加两行import torch torch.cuda.empty_cache()这能把PyTorch缓存但未释放的显存回收回来。如果你用Jupyter Notebook测试加载模型失败后反复重试经常不行最干脆的方案是重启kernel——别问问就是我也曾经在这里耗过半小时。5. 本地加载与API调用两条路线的代码对照前面我说过“搭建DeepSeek模型”还有另一层理解——通过API把DeepSeek接进自己的Python项目。第3、4节是本地加载的玩法这一节我把API调用的代码也写出来方便你对照着选择。日常开发时API调用往往成本更低、响应更快但本地加载可控性更强是两条不同的技术路线。5.1 DeepSeek API调用的最小可运行代码import requests API_KEY 你的API密钥 API_URL https://api.deepseek.com/v1/chat/completions def chat_with_api(user_input, historyNone): if history is None: history [] messages [] # 历史消息按格式装填 for role, content in history: messages.append({role: role, content: content}) # 当前用户输入 messages.append({role: user, content: user_input}) payload { model: deepseek-chat, messages: messages, temperature: 0.7, max_tokens: 1024, stream: False } headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } resp requests.post(API_URL, jsonpayload, headersheaders) resp.raise_for_status() data resp.json() return data[choices][0][message][content] if __name__ __main__: print(chat_with_api(用Python写一个读取CSV文件并统计每列平均值的程序))这段代码用requests库就够了不需要装额外依赖。注意消息格式是OpenAI兼容的messages数组里按role和content组织对话历史这是当前大模型API的主流设计学会一套就能触类旁通。5.2 API和本地加载怎么选一张表说清楚对比维度本地加载API调用初始成本需要GPU或大内存硬件投入高按量付费门槛极低数据隐私数据不出内网完全可控数据要发给API服务商推理速度取决于显卡通常不及API集群算力延迟稳定离线能力完全离线可用必须联网定制能力权重在手可微调可改逻辑只能通过提示词定制开发效率环境复杂坑多十几行代码跑通我的建议很简单如果你是学习模型原理、要研究源码结构、或者公司有数据合规要求走本地加载如果只是做应用功能、接个对话机器人、想快速出demoAPI就够了没必要折腾显卡。6. 高频异常与排查链路遇到的这几个坑你大概率也会碰上这一节是实打实的经验复盘。下面这几个报错和异常我测试时都遇到过每个都附了排查思路和原因解释。6.1 加载时提示 OSError: Cant load tokenizer现象代码执行到加载tokenizer那行直接报错提示找不到tokenizer相关文件。排查链路先看是不是网络问题模型和tokenizer是从HuggingFace拉取的如果访问不了会卡在下载阶段。再看是不是没加trust_remote_codeTrue——DeepSeek自定义tokenizer必须要有这个参数。最后检查transformers版本老版本对remote code的支持不完整升到4.37以上基本能解决。6.2 显存不够报OOM或CUDA out of memory现象加载模型时报错或者推理过程中途崩溃。排查链路先确认是不是只有最后一个维度的问题——显存确实不够。处理顺序是FP32转FP16、开启device_mapauto、上4bit量化、再用CPU推演。别一上来就上量化量化的加载时间更长而且并非所有算子都被优化过。6.3 生成时中文乱码或出现大量特殊符号现象对话能跑但返回的中文错乱或者伴随很多|endoftext|之类的标记。原因多半是skip_special_tokens没设成True导致tokenizer把特殊token也解码出来了。另一个可能是prompt格式没有保持User: ...Assistant: ...的交互结构模型输出格式错乱。6.4 推理速度极慢生成一个token要好几秒原因模型在CPU上跑这是正常表现或者GPU利用率很低因为模型层部分被分到了CPU上。处理看模型的分布情况打印model.hf_device_map如果大量层在CPU上说明GPU放不下需要量化而不是硬跑。另外一个容易忽略的小点max_new_tokens不要设太大设成512已经能满足绝大多数场景。6.5 模型能加载但每个回答都答非所问原因很可能你用的是基座模型base版不是对话模型chat版。基座模型只做了继续训练没做指令微调它只会续写文本而不会“回答问题”。建议直接用带-chat后缀的模型版本基座模型需要做额外的指令微调才能正常对话。7. 从“能跑”到“好用”流式输出、上下文管理和批量问答最后这部分是我在实际项目里把代码封装成可用工具的进阶经验。跑通上面的代码只是第一步真正放到项目里你还需要解决三个问题。7.1 流式输出让用户不用干等本地模型推理通常要几秒到几十秒直接一次性返回用户体验很差。流式输出解决的是这个体验问题让内容边生成边输出。transformers的TextIteratorStreamer可以配合threading实现from transformers import TextIteratorStreamer from threading import Thread def chat_stream(user_input): prompt build_prompt(user_input) inputs tokenizer(prompt, return_tensorspt).to(model.device) streamer TextIteratorStreamer(tokenizer, skip_special_tokensTrue) generation_kwargs dict( **inputs, max_new_tokens512, temperature0.7, do_sampleTrue, streamerstreamer ) thread Thread(targetmodel.generate, kwargsgeneration_kwargs) thread.start() # 逐片段读取生成结果 for text in streamer: yield text thread.join()调用时就能逐字逐句地拿到输出既可以print到命令行也可以推到WebSocket给前端体验一下就从“卡顿等待”变成了“流畅对话”。7.2 上下文管理别让历史消息无限膨胀多轮对话场景把每一轮的历史消息都塞进prompttoken数会迅速膨胀最后爆掉上下文窗口。简单有效的策略是只保留最近N轮对话。MAX_HISTORY 6 # 保留最近6轮 def build_prompt_with_limit(user_input, history): recent history[-MAX_HISTORY:] # 截断过长的历史 return build_prompt(user_input, recent)这是最基础的做法更智能的做法是估算token数量超过阈值就丢弃最老的轮次或做摘要压缩。但对大多数工具型应用固定轮数的截断已经够用。7.3 批量问答注意并发和失败重试如果你需要批量处理文本比如给1000条评论打标签建议加上重试机制和批大小控制import time def batch_chat(prompts, batch_size8, retry_times3): results [] for i in range(0, len(prompts), batch_size): batch prompts[i:ibatch_size] batch_results [] for prompt in batch: for attempt in range(retry_times): try: resp chat(prompt, max_new_tokens200) batch_results.append(resp) break except Exception as e: print(f第{attempt1}次重试: {e}) time.sleep(2 ** attempt) # 指数退避 results.extend(batch_results) return results这里用指数退避做重试第一次失败等2秒第二次等4秒避免短时间高频失败把自己机器打垮。8. 最后分享一点我的实操体会跑了好几天DeepSeek模型之后最大的感受是这个模型的代码搭建难度90%都在环境匹配和依赖管理上真正的推理代码反而不多。只要把Python版本锁在3.10、transformers升到最新、耐心处理CUDA版本问题整个链路其实是比较顺畅的。还有一个小技巧要分享如果你只是想验证模型效果不想等几十分钟下完整权重可以先加载最小的模型试试水比如deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B这种1.5B级的小模型几百MB的量化版跑起来很快先把prompt格式、推理逻辑全部调通再换大模型这样能节省大量调试时间。我对这个“先小后大”的方法深有体会一开始拿7B模型反复调试prompt格式每次推理动辄半分钟起步一天下来根本调不了几次。换了小模型后调试效率提升了一个量级。如果你打算把DeepSeek接入到现有项目里还有一个方向值得关注模型服务化。也就是用FastAPI把上面写的chat函数包成一个HTTP接口然后你前端、后端、小程序都可以共用这个服务不用每个终端都各自加载一遍模型。这就从一个Python脚本升级成了一个真正的AI服务。方向已经指出来了剩下的就是动手。跑通第3节的代码你就正式进入了这一步。本文还有配套的精品资源点击获取