
两年前我第一次把一个“调好的模型”交给部署组的同事时被连问了三个问题模型文件在哪个环境里跑接口的输入输出长什么样出错怎么返回线上推理万一挂了回滚方案是什么当时我只能把训练好的权重文件递过去然后干瞪眼。那一次我才彻底意识到会训练模型和能做AI工程ai-engineering是两码事。这个认知转变就是我眼里“from scratch”的真正含义——不是你从零学会了某个框架而是你从零把一个模型变成了一个可运行、可监控、可迭代的系统。这篇文章写给三类人已经用PyTorch或TensorFlow跑通过几个模型但不知道下一步该干嘛的在算法岗做了两年想往工程方向转型的以及刚入门AI、想系统了解工程全貌不想一上来就被各种工具绕晕的。我会把我个人从零搭建AI工程的全过程、选型理由、踩坑记录和学习路径建议都摊开来讲。没有玄学全是实操出来的经验。1. 先搞清楚AI工程和“能跑通模型”根本不是一回事1.1 三个角色的分工差异我先说一个可能让很多人不太舒服但非常现实的观点算法研究、数据分析、AI工程是三套完全不同的能力体系。算法研究员的目标是验证新方法的有效性。模型在标准数据集上把准确率提升了实验记录写清楚事情就基本结束了。他们可以不用关心推理成本、不用关心用户会不会乱说话、不用关心那条数据为什么读取失败。数据分析师的目标是发现业务规律。他们交付的是洞察和报表核心指标是结论靠不靠谱、能不能指导业务动作。他们的工作对象是历史数据不是在线流量。AI工程师的目标完全不同让模型在一个真实的业务系统里常年稳定运行。交付物不是模型文件而是一个包含数据管线、训练流程、评估体系、部署服务、监控告警、迭代机制的完整系统。核心指标是可用性、延迟、成本、数据质量、迭代周期。我见过很多从算法转工程的人第一个月特别难受。因为在学校里模型训练完就是终点在公司里模型训练完只是起点。工程师要做的事情听起来一点都不性感写数据校验、做压测、处理容器日志、设计回滚机制甚至要和运维吵一晚上“这个镜像到底能不能起”。但这些事恰好决定了模型能不能被真实世界使用。1.2 为什么准确率高不等于能用举个我实际见过的例子。一个客服意图识别模型离线测试准确率92%上线第一周就跌到70%左右。团队第一反应是模型不行要换更大的预训练模型。结果排查下来问题根本不在模型结构而是离线测试数据来自历史工单线上真实用户的路子完全不同——他们会打错字、会有情绪、会在一句话里塞两个意图、会说一半突然问“刚才那个能换吗”。数据分布变了模型表现得就变了。这在工程上叫作“分布漂移”。如果系统里没有数据监控和回流机制你甚至不会发现它已经悄悄变差直到业务方来投诉。再比如推理延迟问题。模型在离线评测环境里跑一次只要几十毫秒上线后发现高并发下平均要200毫秒P99甚至超过一秒。原因并不玄学没有做batch推理、显存分配不合理、模型没有加载预热、日志把CPU打满了。这些问题没有一个是算法问题全是工程问题。所以我的结论一直是一个模型再好如果没人保证它的数据、部署、监控、迭代链路它只能躺在训练日志里当PPT素材。AI工程的核心就是把“偶尔能跑通”变成“持续稳定可用”。2. 从零搭建AI项目的骨架先定边界再写代码2.1 技术栈选型的取舍逻辑我从零开始跑通一个AI项目技术栈基本是固定的不是因为别的不好而是这套组合踩坑成本最低最适合一个人或小团队从零走到上线。Python 3.11不用多解释AI生态的中枢。PyTorch。不是TensorFlow不好而是PyTorch的调试体验更接近普通Python报错信息相对友好从研究到部署之间的沟也更浅。团队如果有新人PyTorch上手更快。FastAPI做服务化封装。自带请求校验、自动文档天然支持异步把模型包成一个HTTP服务非常顺手。性能也够用真正扛不住的时候再换更重的推理框架。PostgreSQL存元数据Redis做缓存和轻量队列。Docker Docker Compose统一环境。每次有人问我“为什么一定要用Docker”我都会反问一句你有没有经历过“在我机器上是好的”AI项目里这个问题尤其致命因为除了代码还有Python版本、CUDA版本、PyTorch版本、依赖库版本任何一个不一致都可能让结果微妙地变化。Docker把这一切锁在一个镜像里是我目前遇到的环境问题里性价比最高的解法。本地能跑线上基本也能跑如果跑了不对至少锅不在环境差异上。2.2 项目目录结构与配置管理项目骨架我建议一开始就按模块拆好不要所有代码堆在一个文件夹里。我常用的结构是这样的my-ai-project/ ├── configs/ # 所有配置集中管理YAML文件 │ ├── data.yaml # 数据路径、校验规则 │ ├── train.yaml # 超参数、训练参数 │ └── serve.yaml # 服务端口、模型路径、批处理参数 ├── data/ │ ├── raw/ # 原始数据只读 │ ├── processed/ # 清洗后的数据 │ └── golden/ # 黄金集只用于评估 ├── src/ │ ├── data/ # 数据下载、清洗、校验 │ ├── features/ # 特征工程与模型解耦 │ ├── models/ # 模型定义与训练脚本 │ └── serving/ # 推理封装、API、监控 ├── tests/ # 测试从第一天就存在 ├── scripts/ # 杂项脚本 └── Makefile # 统一入口make train / make serve这样分的核心原因是数据和模型解耦特征工程独立配置全部落到YAML而不是散落在代码里。很多人嫌配置管理麻烦喜欢在代码里硬编码参数。短期是快但一旦实验数量上来你会发现自己根本记不住哪份数据配了哪个参数。把配置集中到YAML用pydantic或者Hydra做类型校验和加载训练脚本就只需要一行命令。还有一件事我强调很多次tests目录从第一天就要建。AI项目里写测试的比例低得吓人但数据清洗函数、特征转换函数这些逻辑一旦出错整个模型的结果都不可信。你没看错模型训练前先把清洗和特征的测试写了。3. 数据管线AI项目里最容易被低估的工程环节3.1 数据校验与版本管理AI行业有句老话垃圾进垃圾出。模型代码重构一百次都能跑但数据一旦被污染模型学到的就是垃圾而且这种污染很隐蔽通常要到上线后业务侧出问题才会暴露。我在每个项目里固定做三件事。第一件schema校验。字段类型、取值范围、缺失率、唯一性都要在数据进入训练流程前跑一遍检查。我常用pandera定义DataFrame的schema规则跑一个校验函数就能发现大部分异常。比如字段“状态”本来是整数1和0如果上游有一天改成字符串“已完结/处理中”schema校验会立刻报错而不是让模型在脏数据上默默训练。第二件黄金集固定。准备一份经过人工校验、能代表真实线上分布的数据集任何实验都不能用它训练只能用来评估。这个集合的意义有两层一是防止训练集“穿越”导致评估虚高二是防止你为了刷指标反复调评估集。黄金集是模型上线前的最后一道质检线。第三件数据版本管理。我用DVC对数据集做版本控制像管代码一样管数据。每个模型训练时记录数据版本的哈希几个月后可以精确回答“这个模型是用哪份数据训练的”。没有数据版本管理溯源就是一笔烂账。我踩过一个特别典型的坑有一次上游业务改了字段含义工单的“状态”字段从数字标记变成了状态字符串我的清洗代码没适配也没人发现。结果训练出来的模型在线上表现极其诡异查了三天才定位到是数据语义变了。从那以后所有进入训练流程的数据必须过schema校验没有例外。3.2 数据漂移与线上分布的预防机制静态检查只能保证数据格式正确保证不了线上输入分布和训练分布一致。用户的行为会变业务的规则会变模型面对的输入也会慢慢漂移。常用的预防机制是算PSI群体稳定性指数。简单来说就是把训练分布和线上最近一段时间的分布分桶然后量化两者的差异程度。用生活类比你经营一家奶茶店平时顾客点珍珠奶茶的比例稳定在60%某天开始这个比例突然变成20%你肯定要调整备货和推荐策略。PSI就是那把量化“变化有多大”的尺子。我的一般判断标准是PSI小于0.1分布基本稳定不用管0.1到0.25之间开始留意去排查可能的原因超过0.25必须告警并且要手动检查线上数据质量。计算PSI不需要复杂系统一个脚本每天跑一次把每个重要特征的分布变化写进报表就够了。不要一上来就搭一套“实时特征监控平台”先把日级别统计做出来价值立刻就有了。特征层面也要做差异化监控不能眉毛胡子一把抓。重点监控对模型结果影响大的特征或者业务上意义重大的特征。非重要特征的漂移可以记录但不告警否则告警列表会被无意义信息刷爆真正的异常反而被淹没。4. 训练管理让实验可复现、可追溯4.1 实验追踪怎么选怎么用人脑记不住十个以上实验之间的差别。我见过有人把超参数写在文件名里还在微信群里发“谁记得上周那个结果最好的batch size是多少”。正规做法是上实验追踪工具。我用MLflow因为它自托管、免费、表格界面够用数据在自己手里。Weights Biases的界面更漂亮但如果公司对数据出网有要求商用SaaS会受限。选型就一句话看你们团队的隐私要求和预算不要为了界面好看牺牲可控性。每个实验必须记录四样东西超参数、代码版本的git commit id、数据版本、关键指标。训练完成后再把最佳模型的权重路径一并记进去。目标是两周之后你根据记录能完整复现当时的实验条件。这一点怎么强调都不过分。实验可复现有三个典型的坑。第一随机种子没固定模型结果每次跑都不一样实验对比全是噪声。第二依赖版本没锁死requirements.txt里写“numpy1.2”这种写法迟早害人要用精确版本最好配合poetry或pip-tools。第三CUDA环境不一致换一张显卡结果可能微妙地变化用Docker把CUDA和PyTorch版本一起锁住。4.2 从单卡到多卡什么时候才需要分布式很多人一开始就想上分布式训练觉得单卡太慢。我的建议是先搞清瓶颈在哪再决定要不要上。用nvidia-smi和profile工具看一眼GPU利用率。如果利用率不到80%问题不在卡少而在数据加载和预处理太慢。这时候该优化的是DataLoader、缓存和预处理逻辑不是引入分布式。分布式训练能带来什么多卡并行确实能大幅缩短训练时间但代价是工程复杂度直线上升代码要改成DistributedDataParallel数据队列要换分布式采样器调试难度翻倍还要学集群资源管理和任务调度。对于绝大多数业务场景单机多卡已经绰绰有余。我见过有人花一周时间搭分布式训练环境就为把原本只需两小时的训练缩短到四十分钟完全不划算。先把单机流程彻底跑通把数据和模型做对再谈分布式。这不是懒惰是控制工程复杂度。分布式训练只有在模型大到单卡放不下、或者训练时间长到严重拖累迭代节奏时才真正需要。5. 部署上线模型真正干活的地方5.1 模型格式转换与推理优化训练完得到的.pt权重文件不能直接扔给生产服务。原因有两个推理框架加载PyTorch模型需要一整套PyTorch环境又重又容易版本冲突而且PyTorch自带的推理性能一般没有针对线上场景做算子融合等优化。我的标准流程是先转成ONNX。使用torch.onnx.export导出把固定输入尺寸配置好batch维度设为动态轴。ONNX最重要的价值在于它是通用中间格式服务端可以用ONNX Runtime加载CPU上也能跑得很快不用依赖完整的PyTorch环境。如果ONNX Runtime的性能还不够再考虑TensorRT。TensorRT需要NVIDIA显卡转换耗时也不短但推理延迟通常能再降一半左右。我只有在流量大、延迟敏感的实时场景下才用它比如实时反欺诈、交易风控这类。大多数业务用ONNX Runtime就够了。不管转成什么格式转换后必须做“输出对齐”测试喂同样一组输入给原始模型和转换后的模型比较输出张量的最大误差超过阈值说明转换过程中精度受损要重新调整。这一步不能省。我踩过一个经典坑导出ONNX时没注意固定了序列长度结果线上来了一条特别长的文本服务直接报错。模型本身没问题纯粹是转换参数没配好。这类问题文档里都不会写只有真实流量里才能逼得你改掉。5.2 服务化封装与性能测试模型本身只是一个函数要变成服务得包一层API。我用FastAPI理由很实在自带pydantic数据校验输入输出结构清晰出错时能返回结构化错误信息自动生成接口文档联调效率高性能在同类型框架里也算能打。如果追求极致性能可以考虑Triton Inference Server。它支持动态batch、模型并发、多模型管理性能上限很高但部署和运维都复杂。我的建议永远是把FastAPI先跑通评估真实流量和性能瓶颈不够了再换Triton不要一开始就引入重型武器。性能测试必须做而且要做规范。我用locust或wrk做压测重点看四个指标QPS、P50和P99延迟、CPU和GPU利用率、错误率。压测场景也不要只测单请求要覆盖并发请求和极端长度输入。每次模型更新后都要重新压防止性能回归。上线前还有一个经常被忽略的环节模型加载预热。很多推理库在第一次推理时会做初始化或编译优化如果服务刚启动就迎来一波大流量会被第一次请求的慢延迟打趴。解决方法是启动时发几个假请求“暖机”把该做的初始化都做掉再对外开放流量。这个小操作真的救过我好几次。6. 线上监控与迭代上线只是开始6.1 监控指标与告警设计模型上线是开始不是结束。很多团队最大的误区就是部署完就没人管了直到业务方反馈效果变差才想起来看数据。监控分三层。第一层是业务层这个模型服务的业务指标有没有变化。比如是推荐系统就看点击率和转化率是客服工单分类就看解决率和人工介入率。业务指标是模型的最终裁判。第二层是数据层线上输入分布有没有漂移PSI、缺失率、异常类型占比这些。数据层异常通常是业务问题的前兆。第三层是系统层延迟、内存、GPU显存、错误率、QPS。系统层异常会影响可用性是最直接的警报源。告警不能乱设否则会变成“狼来了”的剧本真正出问题时反而没人看。我的原则是系统层告警必须即时服务挂了马上要响数据层告警按天汇总每天看一眼分布变化业务层告警看周粒度趋势因为单天的波动往往不是模型问题而是业务周期性。举一个真实案例工单分类模型上线第三周P99延迟突然从80ms涨到300ms用户倒没明显感知但监控亮黄灯了。查下来不是模型问题是日志打得太频繁把CPU几乎占满了。把日志级别调低、去掉无意义字段后延迟立刻降回去。不监控系统层这种小问题可能要等业务方骂上门才发现。6.2 模型更新与回滚策略模型不可能一劳永逸。用户行为变了业务规则变了模型就得跟着迭代。但模型更新不能像开发小功能那样“改完就发”因为模型更新的风险往往不是程序崩溃而是静默变差。我的标准流程分四步。第一步离线评估。新模型在黄金集上跑一遍和旧模型对比所有指标。没有明确提升就不过这一步是门槛最低也最有效的筛选。第二步影子部署。新模型和旧模型同时接收线上请求但新模型的结果只记录、不返回。用一小段真实流量数据评估新模型的表现。这个步骤最容易被跳过但也是最值得做的——它能在不打扰任何用户的前提下用真实数据回答“新模型到底行不行”。第三步灰度发布。先切5%流量到新模型观察一段时间内的监控指标。没有异常再逐步扩大到20%、50%、100%。每次切量之间留观察窗口出了问题损失可控。第四步保证能快速回滚。发布前确保旧模型镜像还在回滚就是把流量切回旧版本。用Docker镜像tag或Kubernetes的Deployment回滚都能实现关键是“随时能回”。我见过有人发布新模型后旧权重文件被覆盖回滚只能重新训练那个痛苦谁经历谁知道。7. 一次真实项目的从零复盘36小时跑通工单自动分类7.1 需求澄清与数据摸底光讲理论不过瘾我复盘一次真实的从零到上线经历。周五下午接到需求市场部每周有几千封用户邮件要人工分到对应部门希望做一个自动分类。数据方面有过去三个月的历史邮件人工标注过的部门信息可以当标签。第一件事不是写代码是需求澄清。我确认了三件事分类体系一共8类预估流量峰值是每秒5封邮件左右业务上“宁可不归类也不能乱归”因为错误分类比不分类更影响用户体验。最后一条直接决定了评估指标的选择精确率优先级高于召回率。数据摸底发现的问题比预想多大约15%的邮件是转发件、退信、空内容根本不应该进模型训练范围。另外抽样人工核对了100条历史标注数据发现人工打标本身也有错误有些邮件被分配到了错误的部门。和业务确认后我们把低置信度的样本剔除保持了一版相对干净的数据集。数据清洗这一步花了整个项目将近三分之一的时间我早就习惯了。7.2 部署上线的执行顺序当天晚上8点半我开始写训练脚本。基线模型用的是TF-IDF加逻辑回归不是深度模型。原因很简单样本量几千条深度学习在这么小的数据上不会比简单模型好多少但训练、调参、部署的成本高一个数量级。工程上先跑通链路再谈模型提升这是我一直以来的原则。次日早上9点模型训练完成离线F1约0.83和业务方确认可接受。然后做工程化转ONNX、封装FastAPI、写schema校验、全部塞进Docker。本地跑通后我把服务部署到一个影子环境将周末两天到达的新邮件同时发给影子服务但不返回任何结果只做预测记录。下午1点做压测模拟峰值5倍的流量结果是P99延迟21毫秒CPU利用率30%性能余量充足。下午4点开始灰度先5%观察一小时再20%再100%。周一早上人工抽查了一批线上预测结果准确率在可接受范围内模型全量上线。接好监控和告警项目收尾。7.3 复盘哪些步骤不能省这个项目的模型很简单但工程环节一个不少。复盘的时候我很确定最不能省的是四件事需求边界确认、数据清洗校验、影子部署、灰度发布。需求边界确认决定了“预测错”的定义直接影响评估指标和数据筛选方式。数据清洗校验决定了模型学到的东西靠不靠谱这一步乱来后面全是白搭。影子部署让你敢放心用真实流量验证模型不打扰用户。灰度发布把上线这件事从“一次赌博”变成了“一个流程”。这个案例也说明了AI工程里大部分时间到底花在哪不是调模型而是清洗数据、确认需求、部署验证、设计监控。模型本身用最朴素的方法就够了。我特别想让刚入门的同学记住这一点先把一条最朴素的链路从数据到服务完整跑通再考虑花里胡哨的模型结构。8. 关于学习路径我的几条实在建议8.1 先跑通最小链路而不是囤课程很多人学AI工程的姿势是囤课收藏一堆教程、买一堆课程、关注一堆博主然后就没有然后了。我的建议非常简单粗暴选定一个小项目目标是以“从数据到服务的所有环节都经过你的手”为终点哪怕只是一个玩具级的情感分类模型。这个过程中你会被迫去碰数据清洗、特征处理、训练脚本、模型转换、API封装、Docker镜像、压测、监控这些全部碰一遍之后你才对AI工程有真正的体感。课程只是地图上路走一遭才是真的认识路。8.2 先理解朴素方法再上复杂模型如果你刚开始不要一上来就追Transformer、大模型。先用TF-IDF加逻辑回归、随机森林这类朴素方法做一个项目。为什么因为它们边界清晰参数少行为容易理解能帮你快速建立对数据、特征、评估指标的直觉。有了这套直觉再去上深度学习你会知道什么时候该加复杂模型什么时候加了也没用。我见过太多人一上来就用BERT做分类模型表现和TF-IDF差不多但推理成本高了几十倍。而他们根本不知道对比基线是什么。朴素方法的另一个好处是训练快、迭代快你可以在一天内试错十次这种手感在复杂模型上很难获得。8.3 学会读代码亲手部署一次至少要完整读一遍开源项目的核心代码。找一个简单模型的训练脚本逐行搞懂DataLoader是怎么采样、epoch循环怎么组织、optimizer.step()和scheduler.step()的调用顺序有什么影响。调API能让你“能用”读代码才能让你“会改”。然后一定要亲手部署一次。哪怕是个玩具模型也要走一遍Docker化、FastAPI封装、压测、监控告警的流程。没部署过的人总觉得部署很简单部署过的人知道这里有多少细碎但致命的坑。我认识不少研究能力很强的人卡在部署这关过不去其实就是动手太少。8.4 心态上接受“大部分时间不是在训练模型”最后一条是心态层面的。AI工程工作日常里真正在训练模型的时间比例其实不高。更多时间花在数据清洗、写校验、看监控、排查版本冲突、调部署配置上。这不是某种“退步”这就是工程本身。我现在衡量一个AI工程师的标准不是看他会多少模型而是看他能不能把一个朴素的模型做到多可靠。能把一条最简单链路稳定跑上一年、遇到数据漂移能提前发现、发布新模型能轻松回滚这些能力比论文里的SOTA数字值钱得多。这个认知也是我从零做AI工程以来最大的收获。