
做AI工程这一年多我最大的感受是真正让你崩溃的往往不是模型训不出来而是模型明明训出来了却跑不进生产环境或者跑进去了线上效果稀烂。这个项目代号就叫“ai-engineering-from-scratch”本质是我从零开始把一套AI能力完整落地到业务侧的记录和复盘。我见过太多团队把AI项目做成算法DemoPPT汇报时一切正常一接真实流量立刻原形毕露。问题不总出在算法上而是出在算法周围的工程系统上——数据管道、评估体系、服务架构、监控告警哪一环松动整个项目就跟着塌。这篇文章不是复述某个框架的文档也不是搬运论文里的公式而是把我从环境搭建到上线稳定运行这条路上踩过的坑、验证过的方法、最终沉淀下来的工程套路按实战链路重新捋了一遍。适合那些算法背景想转工程或者开发背景想切入AI项目的人也适合小团队里被迫一人全栈的AI工程师。当时我给这个项目定的原则只有一条不以跑通Demo为终点以稳定运行为起点。后面所有的选型、架构、排坑都是围绕这条原则展开的。1. 别着急训模型先把“AI工程”和“AI研究”这两件事分开很多人一听“ai-engineering-from-scratch”下意识觉得是从零开始学习机器学习算法。这是一个挺大的误解。从零开始搞AI工程和从零开始搞AI研究路径完全不同研究讲究探索未知边界工程讲究在有限资源下交付稳定可用的系统。这两者需要的能力模型、工具链、评价标准几乎没有重叠。1.1 研究和工程的本质区别决定了你的学习路径我用一个最直观的对比来说明这两者的差异。研究场景下的核心问题是“这个模型能不能work”工程场景下的核心问题是“这个模型能不能一直work”。这两句话只差几个字背后付出的工作量差出几个数量级。维度AI研究AI工程核心目标验证假设、刷新指标交付可用、持续稳定评价标准离线指标准确率、AUC等在线指标、可用性、成本、延迟数据环境公开数据集、干净标注脏数据、缺失、延迟到达时间尺度周、月为单位探索分钟级告警、秒级响应失败代价论文不发表、方向重来线上故障、资损、口碑崩塌核心技能数学、算法、实验设计工程架构、数据管道、监控运维拿我自己举例。项目刚开始的第一个月我把80%的精力花在调一个多模态模型的精度上用公开数据集跑分效果看起来很喜人准确率接近95%。结果到了真实业务数据上准确率直接跌到76%而且数据还在持续变差。后来我才意识到我做的根本不是工程而是拿着生产环境当实验室用。这也是为什么很多AI项目死在“从技术验证到规模落地”这一步——技术验证环节是工程师在理想条件下做的规模落地环节是要对抗现实世界所有的不确定性。数据质量不稳定、上游字段改了名字、特征分布偏移、推理时间超出接口超时上限随便一个因素都足以让模型从“可用”变成“不可用”。1.2 从零开始真正要搭的是围绕模型的整套闭环系统那AI工程到底在做什么我的理解是围绕模型构建一个完整的数据闭环涵盖数据接入、数据处理、模型训练、离线评估、在线服务、监控反馈、迭代优化七个环节。这个闭环里模型只是中间的一环而不是全部。举一个具体的例子。假设你要做一个内容风险识别系统。从工程视角看你需要解决的不只是“模型能不能识别出风险内容”还包括数据从哪些渠道进来进来的数据格式是否统一数据标注怎么做标注质量怎么把控特征怎么计算线上线下的特征逻辑是否完全一致模型服务怎么部署单机QPS能扛多少超过怎么办模型误判之后用户的反馈怎么回流成为下一轮训练的样本数据分布变了怎么感知多久需要重新训练一次。这些问题每一个单拎出来都可以写一篇长文但它们在项目里是一环扣一环的。数据管道不健壮模型吃的就是脏数据再好的算法也白搭线上服务不稳定离线指标再高也没有意义评估体系不完善模型迭代就是一个玄学。所以我建议那些真正想“从零开始搞AI工程”的人第一步不是去刷论文、复现模型而是先在脑子里建立一个系统视图。你可以不用马上理解每一个细节但必须知道一个能跑生产的AI系统至少由哪些部分组成、每个部分的职责边界在哪。有了这个框架后面遇到具体问题时你才知道自己卡在哪一环。2. 从零搭一套能跑生产的技术栈一次选型少走半年弯路确定要做AI工程之后第一件具体的事就是搭技术栈。这一节我给出一套我实际验证过、维护成本相对可控的组合。无论你是单枪匹马还是小团队这套组合都能覆盖从数据处理到模型服务的完整链路。2.1 基础环境Python版本、依赖管理、GPU资源规划基础环境是整个项目的地基但也是我最常看到有人翻车的地方。先说Python版本直接上Python 3.11或3.12不要再用3.8、3.9了。很多新的深度学习库、大模型推理框架都对高版本有优化而且Python 3.12的GIL改动让某些多线程场景获益明显。我见过不少人因为项目早期锁死在Python 3.8后面想升新的向量数据库SDK都费劲只能手动打补丁纯属给自己找不痛快。依赖管理我用的是uv而不是pip或conda。uv本身用Rust写的安装依赖的速度比pip快一个量级而且它生成的锁文件能保证团队成员之间的环境完全一致。如果你还在用pip freeze导出requirements.txt的方式管理依赖我建议尽快换掉那种方式根本锁不住传递依赖的版本换台机器就是灾难。GPU方面如果是刚开始探索不用急着买卡。云厂商的按量付费GPU实例完全够用训练阶段用完就释放比自建机房省心得多。真正需要考虑自建GPU集群的场景是你已经验证了业务量级和资源模型比如每天固定跑若干轮训练、推理QPS稳定这时候再算自建的投资回报率才有意义。单卡训练和单机多卡之间的工程复杂度差距很大初学者先从单卡入门等实在吃不下了再考虑分布式。2.2 数据管道从“脚本堆起来”到“可编排可回溯”数据管道是我在这个项目里花时间最多、也最容易被低估的一块。很多AI项目前期是写一堆Python脚本直接跑数据从A文件读到B文件没有任何依赖管理和任务编排。这种方式的痛苦在数据源少、更新频率低的时候不明显一旦上游字段变了、任务失败了你根本不知道跑的是哪一份数据、处理逻辑是哪个版本。我的选型是Prefect做任务编排dbt做数据转换。选Prefect而不是Airflow的原因很简单Prefect的部署和维护成本更低纯Python代码定义流程支持动态DAG对中小团队更友好Airflow虽然生态更大、调度更强但它的运维成本足以让一个只有两三个工程师的团队陷入日常琐事。dbt是另外一回事它让数据转换有了工程化的感觉——每个模型就是一个SQL文件有版本管理、有依赖关系、有测试校验这比在Python里拼字符串SQL靠谱几个数量级。我强烈建议在项目一开始就把数据管道纳入版本管理哪怕是最简单的脚本也要放到Git里并且明确输入输出的Schema。我在实际项目里就吃过一次亏一个用了三个月的训练数据脚本因为某天上游日志里某个字段类型从字符串变成了数组脚本没有报错只是默默生成了错误数据导致模型在脏数据上训练了将近一个月。如果当时有简单的Schema校验这个问题在数据入口就会被拦截。2.3 模型训练与实验追踪没有追踪等于白做实验模型训练这一层我默认你已经选定了一个框架PyTorch或基于PyTorch的高层库。再强调一次框架选型不重要重要的是实验追踪。我见过不少团队做实验跑了十几次结果只记得最后两个模型的跑分中间过程一概不记得。这样的实验做一百次也是原地踏步。实验追踪统一用MLflow开源自部署没有额外的SaaS费用。每个实验记录训练数据版本、代码版本、超参数、评估指标、模型产物五要素缺一不可。做到这一点之后你会发现模型的每一次进步和回落都有迹可循而不是靠直觉“加了一层网络之后效果好像变好了”。具体到关键依赖库我做了一份对比方便你参考选型思路环节我的选择替代方案选择理由实验追踪MLflowWB可自部署数据不出内网免费额度够用特征存储Feast自建统一线上线下的特征计算逻辑模型服务FastAPI Ray ServeTriton、vLLM灵活度高和Python生态无缝衔接任务编排PrefectAirflow运维成本低代码定义流程更直观2.4 模型服务与部署FastAPI打底容器化是标配模型服务这一层在线推理接口我用FastAPI打底。FastAPI的优势是轻、快、自带OpenAPI文档而且和Python生态的兼容性极好。模型不管是什么格式打包成一个Python类在FastAPI里暴露一个POST接口输入是特征输出是预测结果工作就完成了。复杂一点的场景比如需要对多个模型做组合推理、需要结果缓存、需要动态batch可以用Ray Serve来做模型编排它就是为这种场景设计的。部署方式统一容器化Docker镜像打到镜像仓库然后部署到Kubernetes集群或者云托管的容器服务。我知道很多小团队觉得Kubernetes太重了直接用Docker Compose跑。这么说吧如果你的AI服务只需要跑在一台机器上、不涉及自动扩缩容Docker Compose完全够用一旦涉及多实例、流量波动、滚动更新Kubernetes是绕不开的建议从一开始就给镜像打好标签后面迁移到K8s会顺滑很多。3. 数据、特征、训练三个阶段最容易翻车的位置和解决办法技术栈搭好之后正式开始数据到模型的流程。这个阶段我最常听到别人说“模型效果不好”但拆开来看要么数据有问题要么特征没对齐要么训练细节没把控。下面这三个环节是我认为从零开始做AI工程时最值得细心打磨的地方。3.1 数据泄漏是头号杀手比模型效果差更可怕数据泄漏指的是训练数据里混入了目标信息导致模型在训练集上表现完美在真实场景中一塌糊涂。更麻烦的是数据泄漏往往表现得悄无声息——你是看到了极好的离线指标才意识到的而那时候已经浪费了几天时间。举一个我实际踩过的例子。当时做流失预测有一个特征是“用户最近一次会话时长”。训练时这个特征是用全量数据窗口算出来的平均值而推理时只能用截止到当前时刻的会话数据。结果训练和推理时看到的分布差异非常大模型线上效果远低于离线。问题的根源就是特征计算窗口没有对齐导致数据泄漏。怎么避免呢几个基本功必须做到位训练集和验证集的切分严格按照时间顺序严禁随机切分所有特征的计算和填充逻辑必须同时检查训练和推理两套路径的一致性定期检查特征和目标变量之间的相关性如果某个特征的相关系数高得不正常第一反应不应该是“我们找到了一个强特征”而是“这个特征是不是泄漏了”。3.2 特征工程的一致性是线上效果不翻车的最后一道防线特征一致性这个词很多新手第一次听到时会觉得抽象但它直接决定了线上真实效果和离线评估是否对齐。特征一致性的意思是模型在离线训练时看到的特征和线上服务时计算出来的特征必须是完全相同的定义、完全相同的统计口径、完全相同的缺失值填充策略。举一个反例。训练时对某个连续特征做了缺失值填充填的是训练集的中位数但线上推理时中位数没有持久化每次请求来了直接填0。这一改特征分布变了模型预测的置信度全乱套。这种问题在离线测试阶段几乎不可能被发现因为离线测试用的还是训练时那份填充好的数据只有到了线上才暴雷。最稳妥的方案是利用特征存储Feature Store工具比如我前面提到的Feast。把特征定义、特征计算、特征版本都统一管理起来线上和线下共用同一份特征定义和同一份特征数据。如果你的项目规模还不到需要上特征存储的程度那也至少要让训练代码和推理代码共用同一个特征处理函数禁止两份代码各自维护一套特征逻辑。手动同步特征逻辑而不经过共同代码是后期维护最大的隐患。3.3 训练细节决定了下限随机种子、数据顺序、评估指标一个都不能含糊训练细节这件事我把它定义为“项目的下限控制”。模型能达到多好的效果由算法和数据决定但模型不会因为随机性而表现失常这是工程问题。具体来说有三件事需要注意。第一随机种子。每次训练必须固定随机种子包括PyTorch的种子、NumPy的种子、Python的random种子。我多次遇到同一个代码文件运行两遍结果差0.5个百分点一开始还以为是模型稳定性问题最后发现就是随机种子没固定。不固定随机种子的实验是无效实验因为你无法判断指标变化是模型改进带来的还是随机波动带来的。第二数据顺序。如果你的数据流是流式的或者每次运行都从数据库拉取数据请务必在进入训练之前对数据做全局shuffle并且把这个shuffle后的顺序缓存下来。数据顺序会影响优化器的收敛轨迹顺序不同最终模型的参数就不同。我会在每次训练前把shuffle后的数据缓存成一个本地的parquet文件并在MLflow里记录该文件的哈希值保证任何实验的可追溯性。第三评估指标。绝大多数人一上来就选准确率或者AUC但工程项目的评估指标应该直接关联业务目标。你要回答的问题是我对错误预测的容忍度是什么哪些错误的代价更高比如做内容风险识别把一个正常内容判成风险内容损失的是用户体验把一个风险内容判成正常内容损失的可能就是合规和安全。这两种错误的代价完全不同你必须用加权指标来评估模型而不是用一个笼统的准确率掩盖所有问题。4. 部署上线远不是终点延迟、成本、稳定性才是AI工程的主战场模型训练完成、离线指标达标这才走了一半路。我见过太多项目在部署上线这个环节戛然而止——模型脚本能跑FastAPI接口能调通就以为大功告成。实际上部署之后才是AI工程真正开始的地方。4.1 先明确你的推理场景在线、离线、流式各有各的架构部署模型之前先想清楚你的推理场景是哪种类型不同类型的架构思路完全不一样。在线推理Online/Synchronous Inference适合对延迟敏感的场景用户发起请求需要立刻返回结果。典型例子是实时风控、智能客服、个性化推荐。这类场景要求模型服务具备低延迟和高并发能力通常会用FastAPI包装模型配合GPU推理加速后端再挂上负载均衡和自动扩缩容。延迟的硬指标通常在200ms到2s之间超过这个范围用户就能感觉到卡顿。离线批处理Batch Inference适合不要求实时性的场景比如每日一次的用户分群、定时生成的报表摘要。这类场景不需要在线服务而是用任务调度框架Prefect、Airflow等定时触发大规模预测。离线推理的好处是可以把计算资源打满不用为峰值预留冗余成本低很多。流式推理Streaming Inference介于两者之间数据源源不断流进来系统需要近实时地处理每条数据但不需要同步等待结果。典型场景是日志实时解析、监控异常检测。一般会接消息队列Kafka或云上消息服务Spark或Flink消费消息并调用模型推理。有一点很容易被忽略同一个模型如果既要在线推理又要离线批处理那这套打分逻辑就必须在两边完全一致否则就会出现同一份用户数据在线接口和离线任务打分不同的怪事。4.2 推理优化的三板斧量化、缓存、批处理模型部署上线之后第一波压力测试就会发现性能不达标。不要急着加GPU先把推理优化的三板斧试一遍。第一板斧是量化和精度压缩。如果你的模型是深度学习模型把FP32精度降到FP16甚至INT8推理速度通常能提升2到4倍显存占用同步下降。大多数模型在线上的精度损失在可接受范围内。我实际做过一个排序模型INT8量化之后延迟从38ms降到12ms线上指标几乎无感。前提是量化后一定要做离线回归验证确认精度不掉出安全范围。第二板斧是缓存。这意味着相同或相似的请求不要重复计算。比如做推荐系统时同一个用户在一小时内多次请求推荐结果可以直接命中缓存。再比如做内容审核时同一个文本片段被多次提交完全可以在前一层做哈希去重。加一层Redis缓存往往比加一块GPU便宜得多。我见过不少团队明明流量特征适合缓存却执着于优化模型推理速度属于典型的用错力。第三板斧是动态批处理。把多个请求攒在一起一次性通过GPU推理吞吐量远高于单个请求单独推理。比如单条文本推理延迟30ms但把32条文本合成一个batch推理平均每条延迟可能不到5ms。Ray Serve内置了dynamic batching的支持FastAPI自己实现也不难。4.3 用一页纸做推理成本预算别让GPU账单吓到自己自建GPU服务还是调用现成的推理API这个选择题很多人在项目起步时没有认真算过。我自己的习惯是任何模型在上线之前先算一页纸的成本预算。按8月O不好意思重写的云厂商A10实例来算假设一个模型输入输出平均500 tokens以常用大模型API的价格估算成本和自建成本差距很大。详细不好都写但告诉你结论如果推理量每天在百万次级别以上自建GPU有明显的成本优势如果每天只有几万次用推理API或厂商托管服务更划算。核心判断标准是真实业务量和资源利用率。GPU是很贵的东西闲置GPU更是成本无底洞——很多团队买了一堆卡一天推理量只占30%的资源这就是花大钱办小事。4.4 监控体系延迟、流量、漂移三大件上线不挂监控等于裸奔。AI服务的监控和普通Web服务的监控差别很大除了常规的CPU、内存、延迟、错误率还要额外盯三样东西。一是模型漂移Model Drift。模型在上线后的某个时间点由于数据分布变化预测准确度开始下滑。如果只看准确率很难及时发现。更常用的方式是监控模型输出的分布比如模型预测的类别比例是否发生明显变化、预测置信度的均值是否大幅下降。一旦分布偏移超过阈值就触发告警并自动重新训练。二是数据漂移Data Drift。输入数据的分布同样会变化。比如做电商推荐的突然上架了一大批新品类目特征分布一定漂移。这个指标可以理解为“模型看到的东西是不是它训练时看到的东西”。ps。监控每个特征的分布用KS检验或PSI指标通用。三是在线效果指标。比如推荐场景的点击率、风控场景的拦截率、客服场景的解决率这些业务指标比模型指标更接近真实价值。把这些和模型的预测结果做一个因果关联你才能明确地知道“模型改版是变好还是变坏”。5. 离线评估明明很好一上线就被用户教做人评估体系需要重新设计关于评估我再单独展开说一下。因为在AI工程里评估体系的严谨程度直接决定了模型迭代的速度和质量。而这个环节恰恰是很多从零开始的工程师最容易偷懒的地方。5.1 离线评估和在线效果脱节的原因基本就是这三条大多数情况下离线评估指标漂亮但线上效果差逃不出三个原因。第一数据分布不一致。离线用的测试集是历史数据线上面对的是实时数据。哪怕只是相隔一天也可能会出现新的内容形态、新的用户群体这些在离线测试集里根本不存在。第二评估指标选错了。离线看的是AUC或准确率线上产品看的是留存、转化。有一次我把一个推荐模型的AUC提高了两个百分点产品完全无感后来发现用户根本不会点这种内容。离线指标与业务目标的脱节让整个优化过程在做无用功。第三实验误差没有被度量。离线评估结果本身有置信区间。某些情况下测试集上0.5%的差异完全在随机波动范围内。如果不做多次重复实验、不看置信区间看到的“提升”可能是噪声。5.2 Golden Set和回归测试是模型迭代的安全气囊我强烈建议每一个AI工程从第一天起就维护一个Golden Set也就是一组固定的、经过人工确认的高质量样本。这个集合的特点是规模不必很大几百到几千条即可但必须覆盖核心业务场景且每条样本的标签都是经过人工复核的可信度极高。每次模型迭代先在Golden Set上做回归测试。如果新模型的Golden Set指标不低于旧模型才允许进入下一步如果Golden Set指标明显下降不管其他测试集跑分多高都直接打回。这一套机制相当于给模型迭代套了一个安全气囊防止优化A场景指标时意外破坏B场景能力。Golden Set本身也要迭代定期补充线上新出现的典型样本同时淘汰过时的样本保证它始终能代表当前的核心业务。这套机制做下来模型迭代的稳定性会大幅提升不再出现改版上线后用户反馈变差的突发事故。5.3 影子模式和A/B测试是上生产环境前的最后一道验证如果做一个高风险的模型改版直接全量上线再回滚的策略风险太高我建议采用影子模式加A/B测试的组合拳。影子模式Shadow Mode的逻辑是新模型在后台跑同时接收请求但它的预测结果不直接影响线上业务只被记录下来用于对比。也就是说用户看到的是旧模型的结果新模型的表现在“暗处”被评估。跑一周影子模式把新旧模型的预测输出做对比就能在零风险的情况下评估新模型的真实表现。A/B测试就更直接了把一部分流量切给新模型一部分留在旧模型对比两者的业务指标。做A/B测试有两个关键点一是样本量足够大至少到置信水平能识别出1%的业务指标差异二是实验时长不能太短至少覆盖一个完整的业务周期比如包含周末和工作日避免周期的偶然性影响判断。6. 从零到一这条路上的真实踩坑实录以及我的三个月路线建议最后这一部分写几个真实踩过的坑再给一份从零开始可以参考的路线建议。这些内容是我在复盘这个项目时记录下来的如果你正在走类似的路应该能帮你省下不少时间。6.1 三个让我印象深刻的翻车场景第一个坑是模型服务的显存泄漏。部署一个BERT类模型时刚开始一切正常跑了半天之后内存持续上涨直到进程被系统杀掉。排查后发现在一个循环里处理请求时没有释放张量而且没有设置torch.no_grad()导致显存被累积的图占满。这个问题的教训是模型服务不是训练脚本所有用不到梯度的推理路径上都必须显式禁用梯度计算否则每一个请求都会在你不知道的地方留下一块显存碎片。第二个坑是异步框架里跑同步推理直接把服务线程池打满。我用FastAPI接大模型因为模型调用是同步阻塞的而FastAPI的事件循环是异步的导致每个模型推理请求都占着一个工作线程QPS一高整个服务就全部排队。解决方式是把模型的同步推理打包成一个独立进程池通过队列通信让慢推理不阻塞事件循环。这个坑的教训是模型推理不是普通的IO操作它有着一个让所有异步框架都无奈的阻塞特性工程师必须对同步阻塞和异步并发有清醒认识。第三个坑是评估集被污染。我为了扩充测试集把一些训练时的数据也拷贝了进来导致离线指标虚高。当时的模型准确率看起来提升了3个点实际上模型在“背答案”。因为做数据清洗时没有严格切分时间窗口一些新数据实际上包含了历史信息。这个坑的教训是AI工程的评估集保卫战是长期的事情每一条评估样本的存在理由都必须经得起追问。6.2 三个月从零到能接手AI工程的路线建议如果你正在从零开始给自己三个月的时间参考这条路线第一个月重点打数据基础。学习SQL不丢人数据管道不熟练更不丢人。每天花时间清洗真实数据用Pandas或Polars做数据处理学会怎么识别脏数据、怎么处理缺失值、怎么做数据可视化探查。同时把Git和Docker用熟这两个是工程的基本功。完成指标是给你一份10GB的CSV你能在半天内完成清洗、统计特征分布、输出一份可解释的数据报告。第二个月进入模型训练和服务化。选一个中小规模的开源模型从HuggingFace上拉下来完成微调训练然后用FastAPI把它包成一个HTTP接口。把MLflow的追踪加进去每次训练记录参数和指标。完成指标是一个接口能跑、指标能查、结果可复现的完整链路别人按你的文档能一字不差地复现所有结果。第三个月做完整闭环和稳定性加固。把数据管道、模型训练、模型评估、模型部署、监控告警串成一条完整的CI/CD流水线。你改了一行特征逻辑从数据更新到模型重新训练再到发布上线全流程自动完成。完成指标是线上服务至少稳定运行两周监控告警全部生效并且你能在五分钟内找到任意指标变化的根因。6.3 一点实话最后说几句实在话。AI工程这个方向在一开始的时候很容易让人沮丧因为需要懂的东西太多了——数据、模型、系统、业务。你在任何一个单项上的积累都不如那些专精的同事深。但一旦你把这些东西串成一个闭环你会发现它的价值恰恰在这里你能看到整全局你能让模型在每个环节都不掉链子你能在别人都在研究“更强大的模型”时稳稳地把现有模型用出十倍的价值。这个项目做到现在我越来越觉得“from scratch”的精髓不在于你从零学会了多少算法和框架而在于你从零建立了一套系统性的工程意识永远先问数据是否可靠永远先问指标是否对齐永远先问上线之后如何监控永远先问这个改动的回滚路径是什么。带上这套意识再去看任何新的AI技术你的视角会和单纯研究算法完全不同。