
准备转AI工程方向的人大概率都经历过一个阶段刷完一大堆模型结构的讲解觉得自己离“AI工程师”就差一个offer了。真正让自己清醒过来的往往是上线后的第一个事故——模型在测试集上表现完美线上却一路拉垮而你连问题出在哪一层都定位不到。AI工程AI engineering这个概念这几年被反复提起但它的本质从来不是“会用几个模型框架”而是一种把模型放进真实系统里、让它持续稳定产出价值的综合能力。这篇文章我想从一个从零开始走完这条路的人的角度聊聊我理解中的AI工程到底在研究什么、学习路径怎么设计、实操时有哪些绕不开的坑以及最后一些工具选型上的个人取舍。内容适合正在入门的新人、算法想补工程能力的转岗者也适合需要在团队里搭AI工程体系的同学参考。1. 先弄清楚AI工程和算法研究差在哪儿1.1 多数人误以为的“AI工程”很多初学者会把AI工程理解成“更高级的算法”觉得只要能把模型训练出来工程就是水到渠成的事。我踩过这个坑而且踩得很疼。刚接触生产项目时我习惯性地把注意力放在模型结构、损失函数、评测指标上觉得这些才是核心。结果第一次做模型上线适配时被一堆“边缘问题”按在地上反复摩擦训练时的文本预处理和推理服务里的预处理版本不一致导致线上效果比线下低好几个点模型导出时动态shape没配好请求一来直接报错训练脚本用了一堆未固定版本的Python包三个月后想复现当时的结果发现连环境都起不来了。这些问题的本质是算法研究和AI工程的目标不同。算法研究的重点在于“模型能力上限在哪里”核心动作是尝试和探索而AI工程的重点在于“模型在真实环境里能不能稳定运行、出了问题能不能快速定位、新需求来了能不能平滑迭代”核心动作是约束和管理。简单类比一下菜谱研发者只需要把一个菜品做到好吃但连锁餐饮的工程团队要解决的是在任何一家门店、任何一批食材、任何一位厨师手里这道菜的口味都能保持一致。AI工程干的就是“餐饮标准化”这件事。1.2 工程化的三个硬指标可复现、可观测、可持续把工程化和算法研究区分开之后你会发现AI工程关心的其实是三个硬指标。第一个是可复现性。训练结果必须能在相同条件下重放。业务要审计模型、团队要协作迭代、模型效果异常要回溯原因这些都建立在“你知道当初怎么训练出这个模型”的前提上。可复现不是靠感觉而是靠机制固定随机种子、锁死依赖版本、保存数据快照和实验参数。第二个是可观测性。模型服务上线后你要能回答三个问题服务本身健康吗推理结果合理吗输入数据的分布变了吗如果答案都是“不知道”那模型再强也是盲飞。第三个是可持续性。模型上线不是终点后续的重新训练、版本更新、业务需求调整都是日常操作。如果你的第一个版本就把自己锁死在一个无法变更的结构里后续每一次迭代都会变成一次推倒重来。这三个指标决定了AI工程的学习路线不能是“黄金圈式”的不是先学理论再学工具而是先建立一个最小闭环在闭环里反复强化这三件事。下面这条路径是我自己在带人时的常用框架。2. 从零开始的四步学习路径2.1 第一步先掌握一套能跑通全流程的最小技能栈最开始的阶段只做一件事掌握Python PyTorch 基础Linux操作。很多人纠结要不要先系统学数据结构、算法导论、概率论我的建议是先放一放。不是它们不重要而是在起步阶段它们的反馈链路太长学一个月可能都体会不到“这东西能用来干嘛”。AI工程需要的是快速建立信心和正反馈所以第一步应该以“能用代码调通模型训练”为目标。这个阶段不追求深只追求通。你知道怎么加载数据、怎么定义模型、怎么写训练循环、怎么保存和加载权重就足够了。框架选择上我推荐PyTorch不是因为别的框架不好而是它的生态最完整——从训练到部署到推理优化你能找到的成熟方案大部分都以PyTorch为中心。这一步走完你已经具备进入下一阶段的资格。2.2 第二步用端到端项目打通“训练到部署”第二步是关键的转折点它的目标是做一个小而完整的项目把“训练好的模型”变成一个“可以被外部请求调用的服务”然后你亲手通过API调用它拿到推理结果。这一步会让你第一次意识到模型文件本身不会自己干活真正干活的是一个完整的服务系统。我当时做的项目是一个情感分类器。数据来自公开的中文评论集模型用的是一个很小的预训练模型做微调训练完导出为ONNX格式用FastAPI包了一个推理服务最后在本地用curl和Python请求分别测了一轮。整个过程耗时不多但信息量极大我被迫处理了输入文本的padding和truncation、动态shape的问题、GPU和CPU推理的差异、请求和响应格式的约定。也就是从这一步起“模型代码”和“系统代码”这两个概念开始在我脑子里分开。如果你需要一套更结构化的参考我当时项目的目录大概长这样sentiment_serve/ ├── config.yaml # 训练和推理的共用配置 ├── data/ │ ├── raw/ # 原始数据 │ └── processed/ # 预处理后的数据 ├── src/ │ ├── train.py # 训练入口 │ ├── evaluate.py # 离线评测 │ ├── export_onnx.py # 模型导出 │ ├── preprocess.py # 统一的预处理逻辑 │ └── serve.py # FastAPI推理服务 └── models/ # 产物目录这个目录结构有一个隐藏好处训练和推理共用同一份预处理逻辑preprocess.py从源头规避了“训练推理处理不一致”的坑。这一点后面还会展开。2.3 第三步用实验管理工具对抗脏乱差当你开始认真做第二个、第三个项目时一定会遇到“这个效果到底是哪次实验跑出来的”“这个数据集是什么时候改的”这类混乱。第三步的目标就是把实验全过程管起来。这里我不建议一开始就上重型平台先用MLflow这类轻量的实验跟踪工具把每次训练的参数、指标、模型产物自动记录下来就够了。MLflow的核心价值是你每次运行训练脚本时会自动记录一份“输入-输出-环境”的快照用了什么代码版本、什么超参数、什么数据、最终指标是多少。它能让你复盘时不再靠脑子回忆。这个阶段同样要引入数据版本管理我用的DVC通过把数据集的元信息和hash记录下来确保“模型训练时用的数据集和记录里写的数据集确实是同一个”。很多人会忽略这一步直到线上事故需要回滚到某个旧版本模型时才意识到自己根本没有“版本”的概念。2.4 第四步把部署、监控、迭代装进同一个闭环走到这里你已经不是新手了要开始关注模型上线之后的“后半生”。第四步的内容是容器化部署、推理性能优化、指标监控、数据漂移检测、模型定期重训。某种意义上这一步已经属于“AI工程的核心深水区”因为它不再把模型当主角而是把整个系统当主角。我自己在这一步投入时间最多的是监控设计。模型服务的监控和普通Web服务不太一样除了常规的延迟和错误率你还要监控模型预测结果的分布。举个例子你训练模型时业务数据的正负样本比例大约是6:4上线三个月后线上预测结果里正样本占比悄悄变成了8:2。这时候模型大概率已经开始偏离业务实际了但准确率可能还没表现出明显问题。要发现这类变化必须依赖数据分布监控。四步走完你已经拥有一个完整的AI工程闭环认识训练、部署、监控、迭代。接下来用一个具体案例把每个环节的关键细节走一遍。3. 实操跑通一套最小可用AI工程的完整链路3.1 数据准备阶段就该做的三件事很多人拿到数据就开始训练这是导致后续一系列问题的根因。数据准备阶段有三件事不能省。第一件定义数据的schema和标注规范。哪怕数据只有两列也要明确列名、类型、取值范围和缺失值策略。第二件做一份数据hash存档。把原始数据集的hash写入实验记录后续所有训练都可以追溯到这一份数据。第三件固定数据拆分的随机种子并且把训练集、验证集、测试集的划分结果保存下来。否则每次重新跑脚本都会得到不同的拆分模型对比就失去了基础。这里给一个简单但可靠的拆分示例from sklearn.model_selection import train_test_split import pandas as pd import hashlib df pd.read_csv(data/raw/reviews.csv) # 固定随机种子保证拆分可复现 train_df, test_df train_test_split(df, test_size0.2, random_state42) train_df, val_df train_test_split(train_df, test_size0.125, random_state42) # 记录数据hash后续训练都会带上该标识 data_hash hashlib.md5(df.to_csv(indexFalse).encode(utf-8)).hexdigest() print(fdata_version{data_hash})这里的random_state42不是随便填的它决定了拆分结果永远不会因为运行次数变化。data_hash则是你后续追踪“哪一次实验用了哪一份数据”的锚点。3.2 训练脚本该怎么组织才安全训练脚本的常见坏习惯是把所有逻辑写成一个很长的顺序流参数散落各处。工程化的训练脚本至少要做到三件事配置与代码分离、日志与指标分离、检查点与产物分离。配置和代码分离的意思是所有超参数不要硬编码在代码里统一放进config.yaml训练入口通过读取配置文件获取参数。日志与指标分离的意思是训练过程中你想看的除了loss还应该有验证集指标并且这些指标要能导出成结构化记录JSON或表格方便后续分析。检查点与产物分离的意思是模型权重、优化器状态、训练指标、导出模型各归其位不要塞在一个文件夹里。训练循环本身的代码量其实不大核心是“别忘了每一轮结束后做一次验证评估并且把结果记录下来”。很多新手的训练代码只输出训练loss等到训练结束才做一次评估这样你根本无法观察泛化变化。我自己习惯每个epoch结束都保存一次检查点并记录当前在验证集上的表现。这样即使训练中断也能从最近一个检查点恢复不用白跑。3.3 模型导出和推理服务化的关键点训练完的PyTorch模型文件直接放进生产环境使用不是不行但会有几个隐患。首先是性能PyTorch的动态图机制在推理场景下不如静态图高效。其次是可移植性生产环境不一定安装了和训练时完全一致的PyTorch版本依赖冲突随时可能出现。所以主流做法是导出为ONNX这是AI工程里一个非常成熟的中立交换格式。ONNX导出看起来很无脑真正容易出问题的是动态shape。如果训练时输入长度是固定128导出模型时没有配置动态轴线上遇到一个长度为200的输入就会直接报错。导出代码里需要明确声明哪些维度是动态的import torch from transformers import AutoTokenizer, AutoModelForSequenceClassification model AutoModelForSequenceClassification.from_pretrained(./models/checkpoint) model.eval() dummy_input torch.randint(0, 3000, (1, 128)) # batch1, seq_len128 torch.onnx.export( model, dummy_input, models/model.onnx, input_names[input_ids], output_names[logits], dynamic_axes{input_ids: {0: batch, 1: seq_len}, logits: {0: batch}}, opset_version14, )导出后用FastAPI提供服务核心代码其实就三部分读模型、做预处理、跑推理。但要注意你必须在服务进程启动时加载模型而不是在每次请求时重新加载。这个错误新手经常犯会导致每次请求都多出几百毫秒的模型加载时间。一个最小可用的服务端代码骨架from fastapi import FastAPI import onnxruntime as ort import numpy as np app FastAPI() # 启动时加载一次全局复用 sess ort.InferenceSession(models/model.onnx) app.post(/predict) def predict(text: str): tokens tokenize(text) # 复用训练时的预处理逻辑 logits sess.run(None, {input_ids: np.array([tokens])})[0] return {label: int(np.argmax(logits))}这个阶段我强烈建议把tokenization和padding逻辑单独抽成一个模块训练和推理共用。我吃过太多“训练时A逻辑、推理时B逻辑”的哑巴亏了。3.4 预测上线后监控指标怎么设计模型服务上线后监控至少分两层。第一层是系统监控延迟、错误率、CPU、GPU、内存这些用常规监控工具就可以覆盖。第二层是模型监控核心是预测分布和特征分布是否稳定。我最常用也最推荐先做的是PSIPopulation Stability Index群体稳定性指数。PSI的公式不复杂本质是比较两个分布在各区间的占比差异PSI Σ((actual_ratio - expected_ratio) * ln(actual_ratio / expected_ratio))实际操作中你把上线后一段时间的预测分数分箱与训练期的预测分数分箱对比。经验阈值是PSI小于0.1表示分布稳定0.1到0.25之间需要关注超过0.25基本可以确定分布已经发生明显漂移模型效果很可能受影响。我第一次见到这个数字飙到0.4时还以为是程序算错了后来排查发现是业务文案风格变了用户输入的句式分布肉眼可见地和训练集不一样。没有监控指标这类问题大概率要等业务方找上门才会发现。4. 踩坑实录AI工程里的五类高频问题4.1 问题一训练和推理的预处理不一致这个坑我前面反复提到过因为它是AI工程里最常见的隐性Bug。典型场景训练时用的tokenizer是版本A推理服务里用的tokenizer是版本B两者对同一句子的切分结果不同或者训练时对数值特征做了标准化推理时忘了加载标准化参数。效果上往往不会直接报错而是线上指标比线下低几个点非常难察觉。排查思路就是在训练和推理之间做输入输出一致性测试用同一批测试样本分别走训练代码和推理服务比较两者的预测结果差异超过阈值就当Bug处理。4.2 问题二模型上线后指标悄悄下滑指标下滑分为突变和渐变。突变通常是上游数据源、业务逻辑或依赖版本变化导致渐变则大概率是数据漂移。我的排查顺序是先确认时间范围从什么时候开始下滑的再看这个时间段内代码、数据、业务有没有变化。如果没有明显变化就去看PSI和特征分布。最忌讳的是“模型指标跌了就立刻重训”因为没找到根因时重训很可能重训后还是一样跌甚至更差。4.3 问题三环境依赖“换一台机器就崩”复现实验时换一台机器结果装环境装了三天最后还跑不出一样的结果这个问题几乎每个人都遇到过。根因就是依赖没有锁定。解决方案说来简单不要只写requirements.txt要锁到精确版本最好用pip-tools生成带hash的锁定文件更进一步所有训练、推理环境都走Docker镜像把Python版本、系统依赖、pip依赖全部固定在一个镜像文件里。这里有一个容易忽略的细节即使你锁了pip版本CUDA、cuDNN、系统库的版本也可能不同。所以最稳妥的方式是训练机的软件环境和推理机的软件环境各维护一份完整Dockerfile镜像就是环境唯一真相。4.4 问题四推理性能不够GPU却吃不饱GPU利用率只有10%线上却频频超时这是很典型的“性能瓶颈不在GPU而在其他环节”的例子。常见原因包括单请求batch为1GPU并行能力完全没用上预处理逻辑太慢CPU成为瓶颈模型显存不足导致反复加载或OOM。我的建议是先把性能画像做出来请求延迟拆成网络层、预处理层、推理层、后处理层看哪一层耗时最高。如果是GPU利用率低可以做动态batching如果是预处理慢把预处理改成并行或缓存如果是模型太大考虑量化、蒸馏或换小模型。盲目加GPU解决不了这类问题。4.5 问题五数据被改得无声无息团队协作时数据文件被悄悄替换是复现性崩溃的头号原因。一个人觉得“这个文件我更新一下很正常”另一个人还在用旧文件做实验两个人跑出来的结果完全对不上。这个问题靠约定是解决不了的必须靠机制。数据目录纳入版本管理每次变更记录hash训练脚本启动时校验数据hash不匹配就拒绝启动。这套机制会在很大程度上减少“玄学”实验。5. 工具选型与我的取舍原则5.1 一张表看常见工具每次聊AI工程都会被问到工具选型。我把常用场景和对应工具整理成一张表方便新手快速建立地图功能场景常用工具适用规模注意事项实验跟踪MLflow个人到团队入门友好部署一次永久受益完整实验平台WB团队协作密集商业服务注意数据隐私边界数据版本管理DVC中大型数据集需要配合Git使用学习成本略高工作流编排Airflow周期性任务复杂重调度器小项目别急着上模型推理服务FastAPI ONNX Runtime通用场景轻量、灵活适合起步高吞吐推理Triton / vLLM生产级高并发功能强运维复杂度也高监控告警Prometheus Grafana系统监控搭配自定义业务监控使用漂移检测Evidently数据质量分析开箱即用指标丰富这些工具组合在一起基本能覆盖一个中小型AI工程项目的全部需要。但工具始终是手段不是目的。5.2 我的两个选型原则第一个原则是“按需引入不要堆工具”。工具是为痛苦服务的不是为简历服务的。只有当实验记录混乱到影响对比时才上MLflow只有当数据版本导致复现失败时才上DVC。一开始就铺开整套工具链大概率的结果是每天都在维护工具而不是推进业务。第二个原则是“先手动后自动”。在流程还没跑通之前先手动记录参数、手动保存模型、手动部署这些都做过一遍之后你才会真正理解自动化工具到底替你解决了什么。直接跳到自动化容易连工具产生的概念都一知半解。我个人的体会是AI工程成长的临界点不在你学会多少个模型结构而在你第一次把一个“幼稚”的模型真刀真枪推到线上再亲手把它一点点修到安稳。从零开始这件事最重要的不是找一份面面俱到的学习清单而是挑一个手边真实存在的小问题把数据、训练、部署、监控这条闭环走通。那个闭环一旦真正闭合过一次后面学任何工具、补任何理论都会变得又快又顺。