第一次认真系统地去啃DeepSeek,还是因为团队里要做大模型落地评估。当时手头资源有限,不可能随便就租一堆高端显卡去试那些几百B的大家伙,所以整个调研都是奔着"开源、可控、能在消费级硬件上跑起来"去的。DeepSeek系列正好符合这个条件,模型权重公开、技术报告详细、社区讨论也多,最关键的是它在开源模型里确实能打,不是那种只能跑demo的花架子。
这篇DeepSeek大模型学习笔记,就是我从最初跑通对话、到深入拆解架构、再到实际部署和微调的全过程记录。内容会更偏向工程实践,不会堆砌论文式推导。如果你正在学大模型落地,或者手头只有一块不算大的显卡,这篇东西应该能帮你少走一些弯路。
1. 为什么把DeepSeek当作大模型学习的主线
1.1 一个合适的学习样本长什么样
大模型学习最怕的就是"什么都看了,什么都记不住"。论文刷了几十篇,问起来还是不知道从哪入手。我后来想明白一件事:与其碎片化地收集知识点,不如找一个足够有代表性的开源模型往深里啃,把架构、部署、优化、微调全部走一遍。DeepSeek就是这轮学习里我选的那个样本。
理由其实很实际。第一,技术报告详细,连训练细节、数据配比、分布式方案都写得明明白白,对于想搞懂模型背后逻辑的人来说,这种透明度太重要了。第二,权重完全开源,而且提供多个尺寸的蒸馏版本,从几B到几百B都有,不管你是单卡玩家还是有多卡集群,都能找到合适的入手点。第三,它的架构设计踩中了最近这两年大模型领域最核心的几个方向:MoE稀疏激活、长上下文推理、强化学习增强推理能力。把这些方向搞明白,回头再看别的模型基本都能举一反三。
所以我在第一篇笔记里就给自己定了位:不追求看懂每个公式,但要把"它为什么比别的模型强"这个why搞清楚。
1.2 我给自己排的四阶段学习路径
接触一个新的大模型,如果直接上手读论文很容易劝退。我自己用的办法是倒着来,先让它跑起来,再回头理解原理,最后才去动训练和微调。大致分四个阶段:
| 阶段 | 目标 | 主要动作 | 产出 |
|---|---|---|---|
| 第一阶段 | 建立直觉 | 用量化版模型跑对话,测试推理、长文本等能力边界 | 掌握基本使用方法 |
| 第二阶段 | 理解架构 | 精读技术报告,重点啃MLA和DeepSeekMoE | 能说清核心设计动机 |
| 第三阶段 | 工程部署 | 用Ollama快速部署,再用vLLM做服务化 | 得到可用推理服务 |
| 第四阶段 | 微调落地 | 用LoRA做指令微调,适配具体业务 | 得到业务模型版本 |
这个顺序背后的逻辑很简单:先感性认识,再理性分析,最后动手改造。很多人一上来就跳到第四阶段,结果模型部署都还没跑通,微调出来的东西也没法验证效果。我踩过这个坑,所以特别提醒一下。
2. DeepSeek核心架构拆解:那些值得反复琢磨的设计
2.1 MLA注意力:它到底省了什么
传统Transformer里的多头注意力MHA在推理时有个很大的问题:每个已经生成的token都要把它的Key和Value缓存下来,供后续token做注意力计算。这个缓存叫KV Cache,序列越长,缓存越大,最终会大到把显存撑爆。
我算过一笔账。假设一个模型有32层、每层8个KV头、每个头维度128,输入序列长度是8192,用FP16存储,那么KV Cache的大小大约是:
2 × 32 × 8 × 128 × 8192 × 2字节 ≈ 1GB
这还只是一个请求占用,并发上来以后,光KV Cache就能吃掉几十GB显存。DeepSeek里用的MLA,也就是多头潜在注意力,思路完全不同:它不缓存完整的K和V,而是先把它们压缩成一个低维的潜在向量,推理时只缓存这个压缩向量,等真正需要时再解压恢复出K和V。
这就好比出门不用再拖一个大行李箱,只需要带一页摘要便签,需要看详细内容时再翻手机里的存档。MLA让KV Cache的体积直接降了一个数量级。在超长上下文、高并发场景里,这个设计带来的工程收益极其明显。我自己实测跑长文本任务时,同样的显存预算,采用MLA思路的模型能支撑的并发数明显更多。
2.2 DeepSeekMoE:用更少算力激活更多参数
MoE,混合专家模型,是DeepSeek另一个标志性设计。传统大模型是稠密模型,每次推理无论输入什么内容,所有参数都得参与计算。MoE的思路则是把网络分成多个"专家"子网络,每个token只激活其中一小部分专家。
DeepSeekMoE和早期MoE方案比有两个改进让我印象很深。一个是细粒度专家切分,把原来少数几个大专家拆成很多个小专家,组合更灵活。另一个是引入共享专家,常驻不参与路由,保证所有输入都有稳定的通用能力底座。再加上按token内容动态选择路由专家,相当于每次只让一小队最合适的人去处理任务,而不是把所有员工都叫过来开会。
总参数量可以做得很大,但每个token推理时的激活参数量可以压得很低。用V3系列来举例,总参数量是671B,但每个token只激活37B左右。这意味着理论上它能装下海量知识,实际推理成本又没有按总参数增长,对工程落地非常有利。
当然也有代价:虽然激活参数少,但模型文件是按总参数存的,显存规划时还是要按总参数来准备。我在日常分享里经常提醒大家,MoE不等于"可以随便在小显存卡上跑大模型",它省的是算力,不是加载空间。
2.3 推理增强和强化学习带来的思路扩展
DeepSeek另一个值得关注的点是推理增强模型的长思维链能力。简单说,它通过在训练中引入大量强化学习,鼓励模型在回答复杂问题时"多想几步",把推理过程拆解成复盘、验证、修正等多个环节,而不是直接给结论。
这个设计对我做业务最大的启发是:模型能力不只是模型结构决定的,训练目标的设计同等重要。我们在微调自己的模型时,也要考虑任务本身的评测方式和奖励设计,一味追求"直接输出正确答案"反而可能限制复杂任务的解决能力。
3. 部署实战:从单卡到服务化的完整过程
3.1 动手之前先把显存账算明白
部署大模型第一件事不是敲命令,而是算清楚显存够不够用。简单估算公式是:
模型权重显存 ≈ 参数量 × 每个参数字节数
FP16下每个参数占2字节,INT4量化下约0.5字节。举例来说,一个7B模型用FP16加载,权重大约是14GB;INT4量化后大约4GB左右。这还没算KV Cache、CUDA context和激活内存,所以实际建议在权重基础上再预留2到4GB。
我用这个公式做过一次选型对比,这里直接分享一个参考表:
| 显卡显存 | 可跑模型参考 | 推荐精度 | 备注 |
|---|---|---|---|
| 8GB | 3B~4B | INT4 | 适合学习和轻量任务 |
| 12GB | 7B | INT4 | 可以流畅对话 |
| 16GB | 7B | FP16 | 质量更好,稍有余量 |
| 24GB | 14B或7B | INT4/FP16 | 24GB是入门甜点卡 |
| 48GB+ | 32B以上 | FP16/AWQ | 适合认真跑业务 |
预算不够的时候优先考虑量化版本,绝大多数对话和文本分析场景,INT4量化后质量损失是可以接受的。我刚开始就是在一块24GB的卡上从14B的int4版本开始跑的。
3.2 五分钟跑通本地对话
如果只是想先体验一下,用Ollama是最快的路径。它内置了多种模型格式支持,并且能自动做量化优化和显存管理,不需要手动配置复杂环境。只要从官网装好Ollama,然后执行:
ollama run deepseek-r1:7b第一次运行会自动下载对应模型,之后就进入交互式对话界面。这种体验跟网页版聊天没什么区别,但模型完全跑在你的本地机器上,数据不出本机。
我当时跑通后的第一反应是:原来开源大模型已经这么顺滑了。然后我马上做了一组测试,包括角色扮演、长文本摘要、代码生成、数学题推理,把它的能力边界大致摸了一遍。实测下来,7B蒸馏版在中文理解、代码方面已经相当能打,但在复杂推理上还是能感觉到和小尺寸强推理模型的差距。这一步很重要,因为后面做推理优化和微调,都需要以这个"初始能力基线"作为参照。
3.3 用vLLM做真正的服务化部署
Ollama适合个人调试,但要支撑业务并发,我一般会切换到vLLM。vLLM的核心优势在于它实现了PagedAttention和Continuous Batching,前者能大幅减少KV Cache碎片,后者能把多个并发请求拼在一起做批量推理,从而提高吞吐。
启动一个OpenAI兼容的推理服务,命令大概是这样的:
python -m vllm.entrypoints.openai.api_server \ --model /path/to/model \ --port 8000 \ --gpu-memory-utilization 0.9 \ --max-model-len 8192参数里有几个值得解释。--gpu-memory-utilization是允许vLLM使用显卡显存的比例,不建议拉到1.0,因为CUDA context和推理过程中的临时张量也需要显存,留出10%左右的余量不容易触发OOM。--max-model-len是最大上下文长度,设置太长会导致正在处理的所有请求共享的KV Cache占用飙升,要根据业务实际需求谨慎设置。我通常按最长输入文本加最大输出长度再留点余量来估算,比如单文档分析场景设到8192就够用,没必要盲目拉到32K。
服务起来后用curl就能直接验证:
curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model": "deepseek-r1", "messages": [{"role": "user", "content": "你好"}]}'返回格式和主流API完全一致,这意味着你之前为API写的所有代码几乎不需要改就能切到本地模型,这种平滑迁移对项目落地特别重要。
3.4 部署完还要做的两件小事
第一件事是压测。不要只试一个并发就以为上线没问题,建议直接用压测工具发一批并发请求,观察延迟和吞吐。第二件事是留日志。记录每次请求的输入长度、输出长度、延迟,这些数据后面做推理优化时就是依据。我第一次部署时没记录这些指标,后来想要对比优化效果只能重新跑压测,白白浪费了不少时间。
4. 推理优化:把成本和延迟一起打下来
4.1 量化选型:精度和速度的平衡
模型量化是推理优化里见效最快的手段。量化就是把模型权重从高精度浮点数压缩到低精度表示。常见选项有这么几类:
| 量化方式 | 体积 | 质量损失 | 特点 |
|---|---|---|---|
| FP16 | 大 | 几乎无损失 | 最高质量,显存要求高 |
| INT8 | 中 | 非常轻微 | 兼容性好 |
| INT4(如GPTQ/AWQ) | 小 | 可感知但通常可接受 | 推理速度快,适合GPU |
| GGUF Q4_K_M | 小 | 可接受 | 在CPU和低显存设备上友好 |
我自己的习惯是:调试阶段用FP16或INT8,方便排查模型自身问题;确定要上生产且显存紧张时,再用INT4量化,并且拿一套业务评测集反复对比量化前后输出质量。
有次我用INT4量化一个推理模型做数学题测试,发现单步骤运算基本不受影响,但涉及长链条推理时偶尔会出现步骤丢失。后来检查发现是量化粒度偏大导致中间结果精度受损。这种情况我会换用混合精度方案,关键层保留高精度,其他层量化,效果会好很多。
4.2 长上下文下的KV Cache优化
上下文长度越长,KV Cache越大,这个问题前期算显存时我就提过。部署后的优化阶段更需要重视。vLLM的PagedAttention已经能缓解显存碎片问题,但如果我们根本没给KV Cache分配足够的显存配额,优化也无从谈起。
实际操作中我会在配置里留出明确的KV Cache空间,然后通过监控工具观察占用率。如果发现长时间接近满载,就需要降并发、降上下文长度或者换用MLA这类节省KV Cache的模型架构。要注意的是,把--max-model-len调大并不等于模型真的能"理解"那么长,很多时候中段信息都会被遗忘掉,这属于模型能力限制,不是显存能解决的问题。
4.3 投机采样:换个思路提升速度
投机采样是一个很有意思的优化技巧。思路是先用一个又小又快的模型快速生成若干个候选token,再交给大模型一次性校验。如果小模型猜得准,大模型只需要验证一次就能接受多个token,省去了逐个生成的串行时间。
我实测过在部分场景下吞吐能提升两到三倍,但前提是小模型和大模型的分布不能差太远,否则拒绝率高,反而更慢。一个简单的判断方法是:先在同一批数据上对比小模型的输出与大模型的匹配率,如果匹配率偏低,就不要硬上投机采样。这个优化很适合那些对延迟有要求、但算力又有限的业务,比如聊天机器人、实时文本生成。
5. 微调实践:让模型真正对齐你的业务
5.1 先想清楚到底要不要微调
很多人一上来就想微调,但我建议先做一道选择题。提示工程、RAG、微调,它们的适用场景完全不一样。
| 方式 | 成本 | 适用场景 |
|---|---|---|
| 提示工程 | 最低 | 需要给模型规定角色、格式、简单规则 |
| RAG | 中等 | 需要引入实时知识、私有文档检索 |
| 微调 | 最高 | 需要改变模型风格、固定输出格式、专业术语 |
如果只是想让它知道某个文档里的知识,RAG更合适,因为不需要动模型本身,知识更新也快。但如果你的业务要求输出固定的JSON结构、特定的报告风格,或者使用大量领域术语且希望模型不再频繁跳出你的预期,这时候微调就值得做了。
5.2 LoRA微调全流程
LoRA(低秩适配)是目前最流行的轻量微调方案。它的核心思路是冻结原模型的全部参数,只在旁边额外增加一组低秩矩阵去学习任务的适配信息。训练时只更新这些新增的小矩阵,显存开销小,训练速度快,而且不同任务的LoRA适配器可以独立保存,需要哪个就加载哪个,互不干扰。
我在做业务微调时,用的是开源社区里常见的训练框架,数据格式长这样,一条样本一行JSON:
{"instruction": "判断以下句子的情感倾向", "input": "这个产品的体验超出预期", "output": "正面"}训练命令的一般形式如下,具体参数名称因框架而异,但核心选项基本一致:
python train.py \ --model_name deepseek-r1 \ --dataset sft_data.jsonl \ --method lora \ --learning_rate 2e-4 \ --num_epochs 2 \ --max_seq_len 2048关于训练参数,我整理了一份比较稳妥的起点配置:
| 参数 | 推荐范围 | 说明 |
|---|---|---|
| LoRA秩 | 16到64 | 秩越大表达能力越强,也更易过拟合 |
| LoRA alpha | 一般为秩的2倍 | 控制更新幅度 |
| 学习率 | 1e-4到2e-4 | 过大会灾难性遗忘,过小收敛慢 |
| 训练轮次 | 1到3 | 小数据集多轮容易过拟合 |
| 最大序列长度 | 2048或4096 | 按业务输入长度设定 |
微调结束后,要把LoRA适配器合并回原模型生成一个新权重,再像部署原生模型一样把它加载起来。我习惯在微调后用一套固定的测试集做对比,看它有没有真的学会目标格式,同时也要防止它把原有的通用能力给"忘"了。
5.3 评估效果别只看一两个例子
微调完最忌讳的事情是拿两三个案例看一眼,觉得"效果不错"就完事了。样本太少,偶然性极大。我做评估时会构造一个小型测试集,大概三五十条,覆盖目标业务里可能出现的主要场景,然后从格式准确率、内容准确率、拒答合理性、通用能力保持这四个维度分别打分。
表格里记录的是每个维度每条样本的得分,最后算平均。这个过程虽然朴素,但能逼着你把"好"和"不好"定义清楚。业务方一提需求就说"让模型更专业",这没法评估;你说"报告格式100%符合模板要求",这才算一个可验证的指标。
6. 我踩过的坑和沉淀下来的经验
6.1 几个反复出现的部署问题
部署和微调过程汇总了我在几次实操里踩过的、以及身边同事常遇到的问题,顺手整理成一张速查表:
| 现象 | 可能原因 | 排查建议 |
|---|---|---|
| 启动后立刻OOM | 显存配额设置太高,没留余量 | 调低gpu-memory-utilization或换量化版本 |
| 推理速度忽快忽慢 | 并发请求导致KV Cache频繁换入换出 | 看看是不是并发数超过了显存承载能力 |
| 输出开头正常后面变乱 | 上下文过长导致注意力分散 | 检查输入长度,考虑截断或摘要 |
| 量化后输出明显变差 | 量化粒度或方法不适合该模型 | 换AWQ/GPTQ,或对关键层保留FP16 |
| 微调后原有对话能力下降 | 学习率太高或训练轮次太多 | 降低学习率,减少epoch,增加通用语料 |
这些坑里最值得说的是OOM问题。我第一次部署时把显存利用率设成0.95,以为能榨干每一块显存,结果一上并发立刻报错。后来才发现,vLLM启动时CUDA context和中间激活已经占了一部分空间,KV Cache再满一点就溢出了。老老实实降到0.85到0.9,再压测就稳了。
6.2 数据质量这件事再怎么重视都不为过
微调效果不好,绝大多数时候问题不在模型,而在数据。我做过一次业务微调,训练集里混了不少标签标错的样本,模型在训练过程中把这些错误也学了过去,评估时某些类别的准确率反而比原始模型还低。
从那以后我给自己定了一条规矩:训练前务必人工抽检数据,按标签维度统计分布,类别严重不均衡的要先做平衡。数据质量检查比调参重要得多,模型能容纳一定的错误标注,但这绝不意味着可以拿脏数据直接开训。
6.3 后续我打算继续深入的方向
这一轮DeepSeek学习笔记做完,我自己最大的收获不是"会用几个部署工具",而是建立了一套从模型选型、显存规划、推理优化到微调评估的完整方法论。
接下来我想继续做两件事。一是把长上下文场景下的KV Cache优化再往细处做,尝试结合PD分离式部署把推理资源利用效率提得更高。二是把评估体系扩大,除了离线测试集,尝试加入线上小流量对比,用真实业务指标验证模型改动带来的收益。这个过程中如果有新的发现,我会继续整理成笔记分享出来。