
去年年初我的主要工作还是“训练模型”——调参、刷指标、在Jupyter Notebook里反复验证想法。直到有几个项目陆续在“上线”这个环节卡住甚至直接烂尾我才意识到自己一直是半个AI工程师真正缺的是从模型到系统的那一公里。后来我花了大半年时间把一套AI服务从零搭到稳定运行把数据、训练、部署、监控全部串起来踩了无数个坑之后算是摸清了“ai-engineering from scratch”这条路该怎么走。这篇文章不聊花哨的算法只讲从零开始工程化落地时真实会遇到的问题和我最终采用的解法希望让正准备转向AI工程方向或者第一次负责整个AI服务的人少走点弯路。1. 从调参侠到AI工程师这个转变卡在了哪里1.1 模型训练只是AI工程的一个环节很多人刚开始接触AI项目时容易把“AI工程”等同于“训练一个高精度模型”。我过去就是这样。模型在离线测试集上跑出不错的准确率就以为任务完成了。但实际上模型训练在整个AI工程链条里占的比例远没有想象中那么大。数据获取与清洗、特征工程、实验管理、模型部署、服务编排、监控反馈、持续迭代这些环节加起来的工作量和复杂度通常比训练本身多出好几倍。我经历的一个真实案例非常典型团队花了三周时间把模型精度从85%调到了92%但上线时发现接口响应需要600毫秒业务方接受不了。于是我们开始折腾推理优化——尝试量化、裁剪、改用更轻量的模型结构最后才把延迟压到120毫秒以下。整个过程又花了快两周而且期间还因为CPU和GPU的推理结果存在微小差异排查了半天。如果一开始就把“端到端响应延迟”纳入工程目标而不是只盯着准确率这些时间完全可以压缩一半。这里就引出一个关键认知AI工程的目标不是“做出最聪明的模型”而是“让模型在真实环境中稳定、高效、可维护地创造价值”。从零搭建一个AI项目最先要考虑的不是选多先进的网络结构而是你要解决什么业务问题数据能不能支撑以及模型上线后如何衡量它是否真的有效。1.2 我亲眼见过多少项目死在工程化这一关我知道的不少AI项目在Paper或Demo阶段很漂亮一到生产环境就露馅。最常见的死法有这么几种离线评估和线上效果差异太大模型看似很好实际业务指标没有变化。模型迭代没有记录版本混乱出问题后根本不知道线上跑的是哪个模型、用的哪份数据。服务接口只能单机跑没有负载均衡、没有容错一个推理进程崩溃整套服务就挂了。训练数据和线上数据的分布悄悄发生偏移但没有任何监控提示模型性能逐渐劣化却没人发现。我自己就经历过线上模型效果突然变差查了两天才发现是上游特征日志格式改版导致特征拼接产生了大量空值。如果没有一套数据质量监控和特征校验机制这种问题会反复出现。所以做AI工程与其说是挑战算法深度不如说是挑战系统化思维——你要把模型当作一个常年运行的软件组件来看待而不是一次性的成果。2. 从零搭建的第一套技术栈选型逻辑与替代方案2.1 数据管线的选择脚本、编排器还是特征平台刚开始做项目时数据预处理经常靠几个Python脚本串起来每天手动跑一次。数据量不大、字段稳定的时候没问题但只要上游数据结构一变、或者需要按天/按小时定时生成训练集这套脚本很快就变成“僵尸代码”——没人敢改跑挂了也没法快速定位。后来我引入了Airflow来做数据任务编排。当时考虑过其他方案比如Prefect、Dagster但团队对Airflow更熟悉文档也多就先用它。其实选什么不是关键关键是你要有一个能被调度、能重试、能记录日志的数据管线框架。Airflow里每个任务节点尽量做到幂等——同一份输入重复执行得到相同结果这样就不会因为某次失败重跑而产生重复数据。另一个容易被忽略的点是特征管理。一开始我只是把特征工程代码放在训练脚本里后来训练和推理都需要用到同一套特征逻辑开始出现“训练代码里特征逻辑一份在线服务里又复制一份”的窘境。特征定义一旦不统一训练和服务的效果就会出现系统性偏差。当时我考虑特征平台比如Feast但后来评估后觉得项目规模还没到那个程度最终采用的方式是把所有特征工程逻辑抽成一个独立的Python包训练和推理共用同一份代码用同一个版本号构建。这样做成本低效果立竿见影。table:需求场景推荐工具注意点定时批量数据处理Airflow / Prefect任务必须幂等日志留存特征逻辑统一独立特征代码包训练与推理必须共用同一份实现超大数据量处理Spark / Ray先评估数据量别过早引入分布式实时特征需求Flink / Redis考虑延迟与一致性尽量后置2.2 实验跟踪与模型注册为什么必须做但总是被拖到最后一刻如果只做过两三个模型实验靠脑子记确实够用。但模型到了二十个以上参数、验证集指标、数据集版本混在一起光靠文件名命名就会彻底失控。我记得有一段时间自己特别自信觉得每个实验都写了备忘结果一周后再看自己都分不清“model_v3_final”和“model_v3_final2”到底差在哪。后来我老老实实接入了MLflow。用它管理实验记录、自动记录参数和指标并把每次实验对应的代码版本、数据版本一并存下来。MLflow还有一个Model Registry功能可以把模型标记为Staging或Production配合部署流程使用。说实话这一套体系并不复杂难的是让大家养成“每次训练都记录完整实验信息”的习惯。我们当时的做法是写了一个统一的训练脚本入口所有参数都通过配置文件传入训练结束后自动写入MLflow避免人工记录造成的遗漏。从零开始的项目我建议尽早引入实验跟踪哪怕团队只有一个人。因为一旦项目进入迭代期任何一次“我随手改了一下”的记录缺失都可能在后面变成几小时的排查成本。2.3 部署与推理优化从Flask到专用推理服务的迁移有很多教程喜欢拿Flask包一个模型接口当示例但生产环境和那种Demo差距很大。首次尝试时我也用FastAPI部署了一个简单模型接口单机能跑延迟也能接受。可后面需要支持批量请求、版本切换、以及多个模型组合调用时Flask方案变得非常难维护。后来迁移到了KServe ONNX Runtime这套组合。模型先导出成ONNX格式再放到KServe上自动拉起弹性服务。这样做有几个好处第一模型版本切换通过配置管理不用改代码第二KServe内置了监控和日志采集第三支持自动扩缩容可以应对突发的流量。对于小团队来说用Triton Inference Server也是一个很稳的选择它支持多模型并发和动态batch能显著提升GPU利用率。我的一个经验是在开始写服务代码之前先明确你的性能指标——P99延迟、吞吐量、并发数——然后用压力测试工具跑一轮再决定要不要上专门的推理服务。很多团队一上来就上Kubernetes和KServe结果流量没多少运维成本倒是先上去了。3. 一个从零起步项目的完整落地记录3.1 需求拆解别急着定模型先定义评估指标我接手过的一个具体项目是“客服对话意图分类”。业务方最开始只给了一个模糊需求“识别用户是不是想退款”。如果直接按这个需求去训练一个二分类模型你会发现很多边缘情况用户说“钱能不能退”是退款意图说“我想找人工客服”算不算说“昨天买的东西不喜欢”是不是要引导退款这类模糊场景如果不在需求阶段理清楚模型上线后就会不断出现“误判”。所以我采取的方法是把需求拆成一个可执行的问题定义业务目标智能识别退款意图提升退款流程自助化比例。模型输出一段对话中用户是否表达退款意愿以及对应的置信度。成功指标线上AUC和业务上的“人工介入率”下降幅度。可接受的延迟单次分类响应小于200毫秒。在这个过程中最重要的是定义“评估指标”和“业务指标”的差异。离线评估可以看精确率、召回率、F1但线上必须看业务指标比如退款请求被准确触达的比例、人工客服转接率。只有把这些指标对齐了模型迭代才有方向。我们在项目管理文档里专门列了一页“指标定义表”每改一版模型都必须同步更新这个表避免后面烂账。3.2 数据清洗最常见的脏数据比想象中更隐蔽很多人以为“数据清洗”就是把空值填一下、去重一下。真实项目里更隐蔽的问题是数据分布不一致和标签噪声。在我这个客服项目里一开始收集了半年客服对话日志按关键词和人工标注组合的方式生成标签。但后来发现一个问题日志里包含大量系统自动回复并不是真实客服回复而且用户消息和客服消息混合在一个字段里需要拆分。更麻烦的是有些对话里用户先说了退款后面又说“算了不退了”按整段对话打标签就很纠结。我采用的清洗流程是这样的第一步按会话ID拆分消息区分用户消息和客服消息。第二步根据退款相关关键词退款、退货、钱、取消订单等做粗筛。第三步人工标注一万条样本建立标注规范明确边界情况。第四步用简单规则模型去自动标注其余样本再抽检一致性。这套流程做下来训练集质量明显提升模型AUC提升了约4%。数据清洗不是花哨的技术活但决定了一个模型的上限。你后面模型调得再好数据是脏的一切都白搭。3.3 训练迭代用实验记录表取代拍脑袋训练过程中最容易犯的错是“调参没记日志凭感觉说哪个版本更好”。在我用了MLflow之后形成了一套固定的迭代流程每次实验前明确要验证的假设比如“加入会话历史信息能否提升分类准确率”。通过config文件设置所有超参数训练脚本读入config并自动记录到MLflow。训练结束时自动记录测试集指标和生成混淆矩阵。每天下班前花十分钟查看当天所有实验的记录比较不同版本差异。这样做了以后团队讨论模型方案时不再靠说“我觉得”而是直接说“你看实验ID 32的召回比29高但精确率明显下降这可能是数据标签噪声导致的”。用数据说话效率高很多。我还遇到过一个特别容易踩的坑训练的时候随便设了随机种子结果两次训练同样的配置结果差异很大让人误以为是某个参数起作用了。后来所有实验固定随机种子使用seed 42并且记录到MLflow。虽然这样不能完全消除随机性但至少每个对照实验差异可控。另外对于训练脚本里的“数据加载”部分我建议把数据集版本作为输入的一部分而不是在脚本里写死路径。这样才能准确知道每个模型用的哪份数据。DVC在这方面很有用可以像管理代码一样管理数据文件版本。我在小项目里没有一开始用DVC后来数据文件被误覆盖过一次损失了半天时间才老老实实补上版本管理。3.4 上线与监控当线上的分钟级延迟故障找上门项目上线第一天就出事了。早上九点多流量开始上来接口P99延迟从150毫秒飙升到4秒部分请求直接超时。当时的临时对策是重启服务并扩容但问题没有根治。后来经过排查定位在两个地方特征计算里有一段对嵌套JSON的解析每次请求都会重新计算一次没有做缓存。模型推理用的是动态batch但batch策略设置不合理在低并发下反而增加延迟。修复方案是把特征计算结果缓存到Redis里同时把推理服务改成FIXED_BATCH模式并调整最大batch等待时间。很快P99延迟恢复到120毫秒左右。这个经历让我深刻明白上线前的压力测试不能只看平均QPS必须单独观察P99和P99.9延迟并且要模拟真实并发模式。监控体系的搭建也从这次故障之后提上了日程。我使用了Prometheus Grafana重点监控以下指标每秒请求数RPS响应延迟的分布P50/P99/P99.9模型推理错误的计数和占比GPU利用率和显存占用缓存命中率数据质量指标比如推理输入中空值比例模型效果本身也需要监控。比如意图分类模型的置信度分布、各分类的调用量占比如果某些分类的占比突然变化往往说明线上数据分布发生了变化。还有更直接的办法定期采样线上预测结果做人工标注评估对比离线测试集的表现。这样一旦发生数据漂移你能尽早发现。4. 工程化避坑清单每个坑我都踩过不止一次4.1 数据版本控制代码回滚了模型和数据呢代码有Git管着但数据和模型文件往往散落在服务器上。某次训练用到了一份手动修正过的CSV文件放在服务器的/tmp目录里后来机器重启文件没了那个实验变成不可复现。更惨的是模型上线后发现效果差想回退到之前更好的一个版本却因为当时没有把模型文件和对应的数据版本一起登记折腾了很久才找到正确的模型文件。现在的做法是每个实验所依赖的所有数据文件都登记在DVC仓库中模型文件上传到模型仓库比如MLflow的artifact store并记录其对应的数据版本、代码Git Commit ID和配置信息。这样任何模型都可以从零复现。虽然前期需要多花一点时间维护但长期看绝对值得。4.2 GPU利用率明明很高为什么推理还是很慢训练阶段大家容易觉得“GPU利用率高速度快”到了推理阶段就发现不一定。我的一个模型在GPU推理时单次请求延迟反而比CPU还高。后来用Nsight分析才发现瓶颈在数据预处理。每个请求进来后都需要做文本分词、向量化这些操作在CPU上执行而且没有和GPU推理并行——GPU大部分时间在等CPU算完。这个问题在在线推理场景里非常常见。解决思路是把预处理操作做成异步模式让GPU推理和CPU预处理重叠。或者使用像Triton这样的推理服务器它会自动调度模型执行的并发绕过Python的GIL锁效率提升非常明显。另外如果输入数据不是固定shape尽量避免每次动态padding最好把数据整理成固定长度或使用动态shape优化。这些细节看起来不起眼但对在线端到端延迟的影响常常是倍数级的。4.3 监控体系别只盯着Loss业务指标才是终点上线初期我的监控面板全是模型相关的训练loss曲线、验证集AUC、线上输出分布。后来发现业务方根本不关心AUC他们关心的是“退款意图被识别出来后有多少用户真的走了自助退款流程”。如果模型输出都正常但业务转化没上来那说明整个系统链路里一定还有其他问题——比如业务逻辑判断条件写错、前端没有正确触发退款引导。所以现在的项目里我至少会设置三层监控基础设施层服务存活、CPU/内存/GPU、网络延迟。模型层面请求量、预测分布、特征数据质量、模型结构版本。业务层面用户响应率、转化率、兜底人工介入率。第三层往往需要和业务系统联动但这个闭环恰恰是AI工程真正产生价值的地方。如果只盯模型指标你只能保证“模型在工作”不能保证“业务在变好”。5. 如果让我从零再来一遍给新人的优先级建议如果现在有人让我带他重新走一遍从零开始做AI工程的路我会建议他按照这个顺序打基础第一先把数据管线和实验管理做扎实。这是AI工程的地基数据不可复用、实验不可复现后面所有优化都是空中楼阁。第二一定要理解“离线评估”和“线上评估”的差异。多花时间设计好线上业务指标和监控方案比多调一个点的AUC重要得多。第三部署方面不要迷信用Kubernetes来彰显“技术含量”。先用单机服务把推理逻辑跑通加上缓存、限流、优雅启动和退出这些最基本的东西就已经完成80%的工作了。第四学会做性能剖析。模型慢不要盲目换更大的GPU先用profile工具看瓶颈在数据加载、预处理、网络传输还是推理本身。我自己就遇到过瓶颈压根不在模型上的情况。最后保持系统思维。AI工程不是一个纯算法问题而是一个融合了数据工程、模型开发、系统架构、DevOps的交叉领域。遇到问题时先想清楚这个问题的边界在哪是数据问题、代码问题还是架构问题再动手修。回顾我自己的成长过程最大的转折点不是学会了一个新框架而是把视角从“怎么把模型训练好”变成了“怎么让整个系统跑起来”包括数据的保质保量、实验的规范管理、服务的稳定迭代、效果的持续评估。这当中没有太多玄学真正稀缺的是愿意补全工程短板的态度。尤其是当项目规模变大、参与的人变多之后规范化带来的价值会指数级上升。这套从零搭建的经验对我来说最重要的收获就是AI工程化的核心竞争力在于让复杂的事情变得可重复、可观测、可演进。如果你也正准备从零开始自己的AI工程实践不妨把这条原则也刻在脑子里。