恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

AI工程从零搭建:大模型训练到推理部署的完整链路

  • 首页
  • 资讯中心
  • /
  • AI工程从零搭建:大模型训练到推理部署的完整链路

相关资讯

HdsNavigation顶部导航毛玻璃模糊效果实现与滚动状态切换实战 2026/9/30 17:51:48
大模型推理优化实战:TensorRT与vLLM部署Qwen3等LLM的工程方法论 2026/9/30 17:46:48
Ubuntu LTS升级为Pro:从5年到10年的安全维护实操指南 2026/9/30 17:46:48

最新资讯

从0搭建RAG管道:解决AI Agent私有知识库检索与幻觉问题
BP神经网络电网故障诊断实战:特征提取与训练参数调优
印刷机火灾频发!认清设备隐患,匹配灭火系统,读懂真实事故警示
基于DeepSeek的CI/CD异常日志智能分析系统设计与实践
手机检测数据集:基于YOLOv8训练目标检测模型的完整实战指南
让 AI 直接查公司数据库?先给 SQL 加三道闸:基于蓝耘 MaaS 的只读查询助手

今日推荐

模型优化器实战:从FP32到INT8的推理加速与精度平衡
LangGraph+FastAPI构建可审计AI编码助手
基于图像预处理与几何特征的人脸脸型发型搭配系统实现

本周热门

从像素到笔画:srt-whiteboard-animation骨架笔迹追踪实现(Zhang-Suen细化+8邻接追踪)
网站建设的英语怎么说?别只背单词,看完这套安全完整流程才敢上线
新手入门看这篇:建设网站加盟避坑指南与SEO实操

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

AI工程从零搭建:大模型训练到推理部署的完整链路

发布时间:2026/9/30 17:51:48
AI工程从零搭建:大模型训练到推理部署的完整链路 接这个项目的时候我面前只有一台没装任何深度学习环境的服务器。任务说得很简单从一个空目录开始搭出一条完整可用的AI工程链路并且让这条路真的跑通产出能让人直接调用的推理能力。这就是我后来在项目笔记里写的ai-engineering-from-scratch。当时“from scratch”恰好是圈子里最热的话题不管是“从零构建大语言模型”还是“从零构建一个推理模型”大家其实都在讨论同一件事不直接套现成方案而是自己把数据、训练、评估、部署整个链条逐一打通。这篇文章是我对这段经历的完整复盘适合正在准备自建AI能力的团队、想独立做模型项目的工程师以及那些希望真正理解大模型内部工作方式而不是只会调API的学习者。1. 项目解读先想清楚“从零”到底是从哪里开始1.1 “AI工程”不是“AI调参”很多人听到AI工程第一反应是训练模型。真上手后才会发现训练只是链条里很小的一段。我当时的实际任务包括收集和处理数据、设计tokenize链路、配置分布式训练、处理断点续训、搭建评估体系、做推理服务化、上线后还要盯监控和迭代。这些事加在一起才配得上“工程”这个词。所以这个项目的第一个设计原则是不要把自己定位成“写模型的人”而是“建设系统的人”。模型结构只是系统的一个组件跟数据、算力、代码、配置、监控是平级的。这个心态转过来之后很多决策就会变得顺理成章。比如你会愿意花三天时间搭实验追踪体系因为这能避免后面十次实验变成一锅粥你会愿意在还没训练之前就写评估脚本因为你不想在拿到模型后才开始纠结“怎样才算效果变好”。这也是我把项目命名为ai-engineering-from-scratch的原因重点是engineering不是model。1.2 为什么选“from scratch”而不是直接调现成接口项目启动前团队内部讨论过直接用商业API不行吗或者拿开源模型微调一下不就行了吗当时从零开始的原因其实兼而有之既有技术层面的考虑也有长期成本和数据合规的因素。我把三种方案的权衡列出来供你参考方案优点缺点适合场景商业API上手快、迭代迅速长期成本高、数据要过第三方、定制能力弱快速验证想法、非核心业务开源模型SFT微调可以私有化、定制程度较高环境搭建复杂、训练调优仍需工程能力有一定基础设施的团队全部自建链路from scratch完全可控、学习价值最大、可深度优化工程量大、周期长、需要跨领域能力研究型团队、核心能力建设、深度学习者需要澄清一点from scratch不是让你从线性代数开始手写Transformer、手写反向传播。现代AI工程说得直白点是“从空仓库开始自己搭体系”。框架该用就用预训练权重该加载就加载真正自建的是环境、数据通道、训练策略、评估闭环、部署管线以及对整个系统每个环节的掌控能力。1.3 选型先于编码五个关键决策点在写第一行代码之前我花了两天时间做决策。这一步别省因为后面几乎所有坑都来自前期没想清楚。我的决策顺序是这样第一步定硬件边界。当时手头有单张24GB的消费级显卡后来又借到一台4卡A100机器。我按最低配置做了设计保证“单卡能跑通、多卡能扩展”。第二步定训练规模。先用1B左右的小模型跑通端到端再考虑切到7B级。这条路线帮我至少省了两周的排错时间。第三步定部署形态。目标很明确最终要能对外提供HTTP推理接口需要支持并发请求因此推理优化必须在设计阶段就留出位置。第四步定评估标准。先固化一套离线评测集每次模型更新都必须在这个评测集上跑出指标不许凭感觉判断“这版好像更好”。第五步定框架选型。训练统一走PyTorch生态分布式用DeepSpeed/DDP推理单独用优化过的服务框架。这套选型思路的核心是“先低估后扩展”。不要一开始就规划一个80GB显存才能训练的模型方案而是先找到当前硬件下最小可运行的闭环把它跑通再逐步放量。2. 环境与工程骨架搭建可复现的地基2.1 环境搭建的版本矩阵与三步验证环境搭建看起来是小事实际是项目前期最消磨耐心的地方。CUDA、PyTorch、cuDNN、Python版本之间一旦错配出现的报错千奇百怪有的说显存不足有的说算子不存在有的直接段错误。我当时的策略是先确定一个自己验证过的版本组合然后整个项目期间不随意升级。以我当时的版本组合为例可以这样操作第一步创建干净的Python虚拟环境conda create -n ai-eng python3.11 -y conda activate ai-eng第二步根据CUDA驱动版本安装对应PyTorch。这里先用nvidia-smi看驱动支持的CUDA最高版本而不是盲目装最新版nvidia-smi pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121第三步验证环境可用python -c import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))看到True和显卡型号基础环境才算通。这里有个我踩过的坑很多人装了PyTorch后只检查import torch不报错却没检查torch.cuda.is_available()结果训练时才发现模型跑在CPU上慢到怀疑人生。2.2 项目目录设计数据与代码的四区分离项目骨架我按照“四区分离”的思路设计这个结构后来被好几个朋友抄走确实好用ai-engineering-from-scratch/ ├── configs/ # 所有实验配置YAML/JSON ├── data/ # 原始数据、中间数据、最终数据集 ├── scripts/ # 一次性脚本、数据清洗脚本、部署脚本 ├── src/ │ ├── data/ # 数据加载、tokenize、dataset实现 │ ├── models/ # 模型结构定义 │ ├── train/ # 训练循环、分布式逻辑、checkpoint管理 │ └── eval/ # 评估指标、评测集加载 ├── experiments/ # 每次实验的输出、日志、曲线 └── tests/ # 单元测试、数据流水线测试这样设计背后的逻辑是数据、代码、配置、实验记录四者彼此隔离又通过显式路径关联。比如configs/exp_001.yaml里写明了数据集的路径指向experiments/exp_001/下保存的是这次实验的输出。任何人包括未来三天的我自己打开目录都能快速定位“这版模型是什么配置、什么数据、什么代码跑出来的”。2.3 显存估算的速算方法先知道死不死训练还没开始就遇到OOM是新手最常见的第一课。与其反复试错不如先做一次显存估算。我后来总结出一个速算方法准确度够用。以7B参数模型为例全参数混合精度训练的显存构成模型权重BF167 × 10^9 × 2字节 约14GB梯度BF16同样约14GBAdamW优化器状态每个参数需要存储fp32的动量(m)和方差(v)外加fp32权重副本合计每参数约12字节也就是约84GB三者相加全参数训练7B模型大约需要112GB显存单张80GB的A100/H100也装不下。这也是为什么很多人说“7B全参微调门槛很高”。但如果改用LoRA可训练参数往往只占全部参数的0.5%到1%。优化器状态直接从几十GB降到1GB以内整体显存占用可以压到20GB量级单张24GB的消费级显卡就能跑。这就是LoRA能普及的根本原因。方案7B模型估算显存单卡24GB是否可行全参数微调约112GB否LoRA微调约20GB左右是需开gradient checkpointing4bit量化推理约6GB是这个估算方法基于标准AdamW和混合精度训练的常见假设具体项目应以实际的profiler为准。但用它做前期方案可行性判断足够了。2.4 从第一天就做实验跟踪别信自己的脑子项目做到第三周时我已经跑了十几个实验。如果没用系统记录我根本说不清哪一版数据清洗逻辑、哪个学习率、哪次随机种子产出了当前的模型。后来养成的习惯是每次训练任务结束强制登记一份实验记录内容包含git commit号数据集版本数据目录的hash值配置文件的完整内容训练关键指标最终loss、eval指标、显存峰值、训练时长当时的硬件环境哪台机器、几张卡我用最简单的JSON格式记录不需要额外平台只要能追溯就行。下面是当时某次实验的节选{ experiment_id: exp_014, git_commit: a3f9c2e1, data_hash: sha256:9f2c..., model: qwen2.5-1.5b-instruct, train_method: sft lora, learning_rate: 2e-5, batch_size: 8, gradient_accumulation: 8, effective_batch_size: 64, gpu: 1x RTX 4090, final_loss: 1.32, eval_score: 0.71, max_memory_used_gb: 18.5 }这套机制让我后面复现模型时轻松很多。所谓“engineer的感觉”就是每个产物的家底清清楚楚。3. 数据流水线与训练链路核心环节的实现3.1 数据是最大的工程难点比模型结构更费心思很多人以为大模型项目里最有价值的是模型结构。实际上对做工程的人来说数据才是最耗精力的部分。模型结构有大量现成实现数据却无法从别处搬走每一份都和应用场景强绑定。我当时做数据清洗时列了一个操作清单逐项执行去重、去除页面模板噪声、过滤低质量内容、统一格式、过滤超长样本、做敏感信息脱敏。其中去重这一步很关键原本以为自己的数据很干净做完MinHash去重后发现重复率高达12%。如果带着这些重复数据训练模型会反复背诵某些段落评估时看着不错一上真实场景就露馅。另一个要防的是数据泄漏。如果训练集里混入了评估集的题目或答案评估分数会虚高而且你自己不知道。我在切分数据时用了一个硬性规则先按内容hash全局去重再去切分训练集和评估集保证两个集合没有交集。这一步对后续所有评估都至关重要的。3.2 从文本到训练样本tokenize里的魔鬼细节数据清洗完后要把自然语言变成模型能读的token序列。这里的细节比想象中多padding策略、truncation长度、attention mask处理、是否做sequence packing。我最初写的dataloader非常朴素每条样本单独tokenizepadding到相同长度。结果训练速度很慢因为大量样本实际长度远短于max_len算力浪费严重。后来改成动态batch sequence packing才把训练吞吐提上去。def tokenize_and_pack(examples, tokenizer, max_len2048): texts examples[text] all_ids [] for text in texts: ids tokenizer.encode(text, add_special_tokensTrue) all_ids.extend(ids) all_ids.append(tokenizer.eos_token_id) # 样本间加分隔 packed [] for i in range(0, len(all_ids) - max_len 1, max_len): chunk all_ids[i:imax_len] packed.append({input_ids: chunk}) return packed这段代码背后的想法是不再给每条样本单独padding而是把一堆样本的token连接起来再切段。每段都是满长度的显存利用率高训练速度快很多。代价是样本边界变得不清晰需要让loss忽略掉那些跨越样本边界的部分。实现上可以给每段再做一个segment_id或者干脆在接受少量噪声的前提下用简单做法。用这个方法同样的硬件和数据量训练吞吐量提升了约40%。这是我在这个项目里早期收益最大的一次优化。3.3 训练循环混合精度、梯度累积与断点续训训练循环看起来就是“前向、反向、更新”但真正工程化之后每行代码背后都有讲究。我当时的训练循环简写如下from torch.cuda.amp import autocast, GradScaler import torch.distributed as dist scaler GradScaler() for step, batch in enumerate(train_loader): with autocast(): outputs model(**batch) loss outputs.loss / gradient_accumulation_steps scaler.scale(loss).backward() if (step 1) % gradient_accumulation_steps 0: scaler.unscale_(optimizer) torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0) scaler.step(optimizer) scaler.update() optimizer.zero_grad()这段代码里有几个关键决策梯度累积是为了模拟更大的batch size。当时我单卡能塞下的batch是8但实验计划里的有效batch是64于是设置累积步数为8。混合精度训练让显存压力和计算速度都改善很多但loss scaling容易出问题表现为训练后期loss突然发散或变成nan。grad clip则是对抗这种发散的第一道防线我习惯设max_norm1.0。断点续训是我节约时间的大功臣。训练7B模型动辄几十个小时不可能保证中途不出问题。我的checkpoint保存逻辑后来在第五节详细讲这里只说结论不保存optimizer和scheduler状态的“假断点”毫无意义恢复训练后不仅指标对不上还可能因为学习率状态错乱把模型训崩。3.4 从语言模型到推理模型一条可以“抄作业”的路线项目后半程我开始收到一个新的需求让模型不只是“接话”而是在回答前先进行推理思考。这也是现在圈子里很热的“从零构建推理模型”路线的本质。一条可行的简化路线是这样走的第一步做SFT用带思维链的样本微调基础模型。样本格式大概是“问题 推理过程 最终答案”。第二步做偏好优化让模型学会“好的推理路径长什么样”。这里我选择了GRPO这类不需要训练额外奖励模型的方案。GRPO的工程实现需要三个模块采样模块对同一个问题采样N条回答奖励模块用规则或模型判断回答好坏策略更新模块根据奖励信号调整策略。我当时用的是简化版规则奖励数学题直接比对最终答案是否正确格式上要求包含“思考过程”和“最终答案”两段符合格式加1分答案正确再加1分。奖励信号非常干净工程实现也不复杂。def compute_reward(prompt, response, answer): if 思考过程 not in response or 最终答案 not in response: return 0.0 score 1.0 if extract_answer(response) answer: score 2.0 return score这整条路线对工程侧的启示是推理模型不是单一的模型结构而是“基座模型 采样器 奖励函数 优化器 数据流水线”的组合。需要自建的环节越多ai-engineering-from-scratch的路线就越有价值因为你无法靠一个API解决全部问题。4. 评估、部署与迭代把模型从实验品变成产品4.1 先定义“效果好”离线评估体系训练之前先写评估脚本听起来有点反直觉但这是我整个项目里最受益的决定。没有评估标准前模型迭代就是无头苍蝇有了评估集后每次改动都能被量化。我建立了三层评估第一层是基础指标loss曲线、困惑度。这层只能反映模型有没有正常学习不能反映任务能力。第二层是任务集指标针对实际业务场景准备的几百道测试题每次跑完都得到准确率。比如常见指令遵循测试、数学计算测试、知识问答测试。第三层是人工bad case评审自动指标之外的抽检和长期记录。评估维度具体方法用途与注意点基础指标训练loss、验证集loss判断是否欠拟合/过拟合不能只看它任务集指标固定数据集的准确率、匹配率版本对比的核心依据集子必须固定人工评审抽样看模型输出记录bad case发现自动指标看不到的质量问题稳定性检查同题多次输出的方差推理类任务要关注随机性输出是否漂移评估集一经确定绝不轻易改题目。我吃过亏评估中途发现几道题本身表述不清晰直接换了题结果新版模型分数提升其实是题目变动带来的误导了我整整两天。4.2 部署与推理优化从训练权重到可用服务模型训练完要变成一个能抗住请求的在线服务还有一段路要走。我的部署流程大致是模型导出 → 格式转换 → 量化 → 单请求测试 → 并发压测 → 上线。量化在消费级显卡上几乎是必须的。7B模型BF16推理大约占14GB显存而4bit量化后只剩约6GB调用成本和显存压力都大幅下降。代价是极端复杂推理任务上质量可能有轻微波动。服务框架我用了专门的推理引擎用起来很简单核心参数包括最大输入长度、最大输出长度、并发批大小。下面是一个部署脚本的简化示意from vllm import LLM, SamplingParams llm LLM(model./qwen2.5-7b-instruct-awq, tensor_parallel_size1, gpu_memory_utilization0.9) params SamplingParams(temperature0.7, top_p0.8, max_tokens1024) def generate(prompt): outputs llm.generate([prompt], params) return outputs[0].outputs[0].text上线前的单请求耗时和并发压测也很有必要。我当时的经验参考单张24GB显卡部署7B量化模型单请求首token延迟约几十毫秒到上百毫秒具体受输入长度影响并发8路时能维持稳定的吞吐但显存占用会明显上升。这组数据在真实场景上应该重新测不能直接搬。4.3 监控、回滚与数据回流上线不是终点模型上线后我见过太多人从此不管了直到用户开始吐槽才发现输出质量崩了。工程链路必须包含监控和迭代闭环。我在线上至少盯着这几类指标请求量、推理延迟、错误率、输入输出的平均长度、用户反馈的打分分布。其中打分分布最有价值如果连续几天发现低分比例上升就该跑一轮测试集对比决定是否需要回滚。数据回流是整个闭环的发动机。线上出现的bad case不能只是看一眼就删掉我会把脱敏后存成新的训练样本等积累到一定量后触发新一轮微调。这就像滚雪球模型会随着真实使用越来越贴合场景。这里的关键是建立“可回滚”机制。每次上线都留上一个版本的权重切流量时做灰度先放少量请求等指标平稳后再放量。AI项目的回滚不丢人模型迭代本来就是试错过程。4.4 消费级硬件怎么跑完整流程我的整个项目并不全在集群上完成很多实验是在一张24GB显卡上跑的。如果你手里的设备更有限可以参考这个思路优先选小模型3B/7B级别足够覆盖大量真实任务。不是所有需求都要70B。用LoRA微调训练显存减少到原先的1/5左右效果在多数任务上和有损微调差距不大。开gradient checkpointing牺牲一点点训练速度换来显存大幅降低。基座模型用4bit量化推理显存压到6GB左右普通工作站就能跑。如果你的目标场景是数学推理这类高难度任务还可以考虑用小模型加蒸馏策略。让大模型生成推理轨迹再用这些轨迹训练小模型。这条路线不需要大显存只需要你愿意花时间做数据性价比非常高。5. 实战排坑与经验心得5.1 高发问题速查表六个崩溃现场项目过程中我记录了不少问题这里挑最典型的六个整理成表遇到时可以直接对号入座。问题现象常见原因排查手段解决方向训练刚开始就OOM显存估算不足batch过大用profiler看峰值显存降低batch开gradient checkpointing切LoRAloss前期正常后期发散或nan学习率过高、数据里有异常样本、loss scaling问题查看前几步梯度范数定位异常batch降低学习率、加强grad clip、清理脏数据验证集指标虚高线上效果差数据泄漏、train和eval有重叠检查样本hash是否有交集重新划分数据去重后再切分训练中断恢复后指标骤变checkpoint没保存optimizer和RNG状态检查checkpoint内容完整保存optimizer、scheduler、dataloader状态同样的代码别人能跑自己就报错依赖版本不一致、cuda版本错配对比环境列表用conda导出锁定依赖版本复制完整环境模型输出大量重复内容训练数据重复、推理参数不当检查数据去重情况看重复率数据去重调高temperature加重复惩罚5.2 断点续训的正确姿势不只是存模型权重断点续训是我在这个项目里学到教训最深的一课。第一次做时我只保存了model.state_dict()恢复训练后不仅指标对不上模型输出明显变差等于白跑。后来才明白一个可用的checkpoint必须包含模型权重optimizer状态尤其是AdamW的动量项和方差项scheduler状态确认当前学习率位置随机数生成器状态包括PyTorch、Python、CUDA的随机状态dataloader的当前位置或者至少是step数简化实现的思路如下checkpoint { model: model.state_dict(), optimizer: optimizer.state_dict(), scheduler: scheduler.state_dict(), rng_state: torch.get_rng_state(), cuda_rng_state: torch.cuda.get_rng_state(), step: step, } torch.save(checkpoint, fcheckpoint_step_{step}.pt)实测下来完整保存这些状态后恢复训练loss曲线能够和中断前无缝衔接。省下的时间和避免的返工比写这些代码花的时间多得多。5.3 复现性把变量锁死模型实验经常遇到“这次跑的和上次不一样”的情况。很多同学第一个念头是模型随机性其实问题往往出在变量没锁住。我后来固定了这些因素全局随机种子、PyTorch的use_deterministic_algorithms、cudnn的benchmark开关、数据加载顺序、tokenizer版本、依赖版本。其中数据加载顺序最容易被忽略如果dataloader里用了多进程shuffle理论上即使固定了seed每次运行的数据顺序也可能不同。def set_seed(seed42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.backends.cudnn.deterministic True torch.backends.cudnn.benchmark False这套配置不能保证跨框架、跨GPU型号完全一比一复现但至少能让同一台机器上的实验具备可对比性。复现性是工程项目的底线没有这个底线所有优化都无从谈起。5.4 复盘后的三条核心心法整个项目结束之后我复盘了很久最后留在脑子里的不是哪个具体技术点而是三条做事的顺序和原则。第一先跑通1%的数据再放量到100%。我见过太多人一开始就把全部数据灌进训练脚本然后花三周去找数据格式和加载逻辑的bug。用小规模数据先跑通一两个step能最快暴露链路问题哪怕只训练5个step也能验证各个模块是通的。第二评估先于训练。第一天就把评估脚本写出来哪怕还没有任何模型可评。这会让每一次实验变得“有锚点”不会在反复训练中迷失方向。我在项目中最浪费时间的阶段恰恰是对评估标准还模糊的那些天。第三环境变更要有记录。每次升级Python包、切换CUDA版本、换GPU驱动都可能是实验结果漂移的元凶。养成把环境变更写进实验笔记的习惯遇到奇怪的复现问题时能少掉一大半头发。这三条心法听起来朴素但实际操作中帮我把大量“玄学问题”变成了可以定位的系统问题。工程能力的提升很多时候不是学会更高级的技巧而是把基本功做到让人放心。结尾如果重新来一次我会怎么做现在再回头看这个项目我最大的体会是ai-engineering-from-scratch的价值不只是产出了一个可用的AI模型而是让我对整个链条的每个环节都有了真实手感。数据清洗有多脏训练中断有多痛评估指标有多容易骗人上线后监控有多必要这些体验不是靠看文档能得到的。如果现在再给我一台裸机重新开始我会比第一次快三倍不是因为技术突飞猛进而是因为我知道了“把日志、评估、回滚三条线放在训练之前”这件事有多重要。最后想给你的建议只有一句话别怕从零开始也别急着追求大模型先把最小闭环跑通每一段链路亲手接一遍你会获得任何现成方案都给不了的掌控感。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号