作为一名长期做 AI 工程落地的人,我看到越来越多朋友从"跑通一个 Notebook"转向"想让模型真正服务于用户""ai-engineering-from-scratch"这个标题,很多人第一反应是"又要从零学深度学习"。但我想先泼一盆冷水:AI engineering 的核心从来不是调参炫技,而是围绕模型构建一套完整、稳定、可持续迭代的工程系统。数据从哪里来,特征怎么算,训练如何复现,推理如何部署,线上怎么观测,坏了怎么回滚——这些才是真正决定一个 AI 项目能不能活下来的关键。
这篇文章我想以从业者的视角,把从零起步做 AI 工程时最需要想清楚的问题、最值得投入的技术栈、以及我踩过的一些真实坑,系统地梳理一遍。适合刚入门想做第一个端到端项目的同学,也适合已经能跑通模型、但对工程化体系还比较模糊的开发者。内容不追求大而全,而是聚焦真正高效的那条路径。
1. AI engineering 到底在做什么
1.1 它不只是训练模型
很多人会把 AI engineering 和机器学习建模画等号,以为把模型的准确率刷上去就万事大吉。实际工作中完全不是这样。一次完整的 AI 工程项目里,模型训练只占很小的分量,更多时间花在数据管道的构建、训练流程的标准化、模型服务的设计、线上监控与迭代机制的搭建上。
我第一次独立负责一个文本分类项目时,曾经天真地以为核心工作就是"用 Bert 还是 TextCNN 调参"。结果真的开工后才发现,光是清洗历史工单数据就花了两周:字段格式不统一、标签噪声严重、部分样本压根是复制粘贴的脏数据。等我终于把模型跑出不错的指标,又发现线上调用方的数据格式和我训练时用的假设完全不一致——特征顺序、缺失值处理、文本长度分布全都不一样。那个时刻我才真正理解:AI engineering 是把模型当作整个系统的一个组件来对待,而不是当成本身。
从一个更高的视角来看,AI engineering 关心的是"模型 + 数据 + 服务 + 观测 + 迭代"这五个要素的协同。模型只是其中一个变量,而且往往不是最难的那个。真正难的是让这套系统在真实环境里稳定工作,并且能随着数据变化持续进化。
1.2 AI engineering 要解决的核心问题
如果让我用一句话概括,AI engineering 就是把研究思路变成可交付的软件系统。它要解决的核心问题包括:
- 数据层面:数据从哪里来、怎么清洗、如何标注、如何保证训练集与线上分布一致。
- 训练层面:如何让训练过程可复现,模型版本如何管理,超参数如何记录,实验结果如何横向对比。
- 服务层面:如何把模型封装成低延迟、高吞吐、易接入的在线服务,或者离线批处理任务。
- 观测与迭代层面:模型上线后效果如何衡量,数据漂移怎么发现,反馈数据怎么回流,模型怎么定期更新。
我见过不少团队,科研阶段做得漂亮,论文里的离线指标也很亮眼,但一到生产环境就踢到铁板。原因几乎都是把上面某个层面想简单了。比如离线评估做得很好,但线上流量分布和训练集差异巨大;又比如模型服务没有预留超时和降级策略,下游一抖动就全线超时。这些问题,都属于 AI engineering 的范畴,也恰恰是从零开始最值得系统学习的地方。
2. 从零搭建 AI 工程的技术栈与思路
2.1 开发环境与工具链选择
从零开始做 AI 工程,第一件事不是选模型,而是把开发环境搭得干净可靠。我的建议是优先选择 Python 生态,因为无论是数据工具、训练框架还是服务框架,Python 都是当前衔接最顺的语言。不过 Python 的项目管理一直是痛点,早期我用过裸 pip + requirements.txt,后面切到 poetry,现在更推荐 uv——速度快得明显,依赖解析也非常稳定,对多项目隔离支持得很好。
环境层面需要解决两件事:一是 Python 版本和依赖隔离,二是 GPU 驱动的可复现。常见的做法是给项目建立一个标准化的镜像或虚拟环境,把 CUDA、cuDNN 和 Python 依赖全部固化。我自己习惯把环境配置写成代码提交到仓库里,例如用 Dockerfile 定义基础环境,再用 uv.lock 固定 Python 依赖版本。这样不管是新同学加入,还是换一台训练服务器,都能在十分钟内把项目环境恢复到可用状态。
除了语言环境,版本管理工具也很关键。很多人只用 Git 管理代码,但数据和模型常常游离在版本体系之外。我建议从项目一开始就把数据和模型纳入统一管理。轻量方案是用 DVC 做数据版本化,把数据内容和 Git 提交关联起来;更重一点的方案会引入 MLflow,把每次训练的实验参数、指标和产物全部记录下来。这套东西早搭比晚搭省事得多,等项目大了再补的成本会成倍增加。
2.2 数据工程:AI 工程最容易被低估的一环
绝大多数从零开始做 AI 工程的人,都会低估数据工程的复杂度。我见过一个很典型的项目:数据团队给了一堆 CSV,建模同事直接读进来训练,离线指标不错,上线后效果崩盘。排查了很久才发现,训练数据里的缺失值被 pandas 默认策略处理过,而线上服务里对缺失值的处理逻辑完全不同;更隐蔽的是,训练数据里有一个字段是"用户行为标签",在线上根本还没采集到,相当于模型偷看到了未来信息。
数据工程的核心原则,是保证训练管道与推理管道的数据逻辑完全一致。也就是说,离线清洗、特征工程、缺失值填充、归一化策略,必须与线上服务里的处理代码是同一套实现。我在项目中通常会把特征逻辑封装成独立的 Python 包,离线训练和在线推理都直接 import 这个包,从结构上消除两边不一致的可能。
另一个容易被忽视的点是数据质量评估。很多项目只关注样本量是否足够,却很少分析标签分布、重复率、冲突样本、时间漂移等问题。我自己的习惯是,任何一个数据集拿到手,先做一次系统性体检:每个字段的类型和缺失率、目标变量的分布、按时间维度的分布变化、相似样本的近似度。这份体检报告价值极高,它能把后面建模阶段可能遇到的相当一部分问题提前暴露出来。
2.3 训练与模型管理:可复现比跑得更快更重要
训练阶段的核心诉求不是追求 SOTA,而是可复现。今天你跑出一个好结果,过两周想复现,结果发现环境变了、数据变了、随机种子忘了记——这种滋味我体会过太多次。现在我做任何一次训练实验,都会强制记录以下几件事:
- 代码提交的 commit hash
- 数据集的版本标识
- Python 依赖的锁定版本
- 超参数和随机种子
- 训练框架和硬件信息
把这些信息全部写进 MLflow 或者一套自定义的实验记录表里。等积累到一定程度,你会发现这套记录系统本身就是团队最重要的资产之一。它让你能真正回答"为什么这个模型比那个模型好两分"——就是因为超参不同,还是因为数据或者代码变了。
模型管理同样重要。我建议训练产物以统一的模型目录格式落盘,至少包含模型权重、配置信息、预处理逻辑、依赖版本这几部分。不要只丢一个 .pt 或 .h5 文件,那会导致后续部署时各种元素对不上。现在像 Hugging Face 的 safetensors 格式,或者把配置一并打包进 model card,都是不错的选择。核心思路永远是:一个模型产物,应该自带"说明书"。
3. 端到端实操:从原始数据到可调用服务
这一部分我以一个真实的注释分类项目为例——目标是给系统内的用户反馈内容自动打标签,判断它属于"功能建议、问题报告、情感倾诉、其他"中的哪一类。这个项目规模不大,但麻雀虽小五脏俱全,数据、训练、服务、评估全覆盖,很适合作为从零起步的参考样板。
3.1 需求拆解与系统设计
项目启动第一步,不是急着找模型,而是把需求拆清楚。我们和业务方反复确认了两个关键问题:第一,标签体系能不能在起步阶段先收敛为四个粗粒度类别;第二,模型处理不了的样本,系统能不能兜底给人工。这两个问题直接决定了整个系统的复杂度。
需求确定后,我画了一张很简单的系统设计草图,大致包含三条链路:
- 离线管道:原始数据从数仓导入,经过清洗和标注,形成训练集。
- 训练链路:处理好的数据集触发训练任务,产出模型和指标报告。
- 在线服务:用户提交文本到接口,服务完成预处理和推理,返回标签和置信度。
这个设计做在前面,避免了后面"先训练再想怎么部署"的被动局面。系统设计阶段还有一个取舍:要不要上向量数据库或者知识库这类附加组件?这个项目用不到,强行引入只会拖慢交付。我团队的原则是,能用简单可靠的方式解决,就不上复杂的组件。
3.2 数据采集与清洗实现
数据方面,我们从数仓拉取了最近半年的用户反馈文本约 20 万条。清洗逻辑相对简单,但每一步都很重要:去重、去 HTML 标签、过滤过短或过长的文本、统一繁体转简体。其中去重这一步用了 SimHash 做近似去重,把一眼看过去高度重复的模板话术都过滤掉,避免模型被高频重复样本带偏。
清洗完成后是标注。我们没有一开始就请外包,而是先由业务方手动标注了 3000 条种子数据,然后基于这个种子集训练一个草稿模型做预标注,再由人工修正。这套"模型辅助标注"的流程大约节省了 60% 的标注时间。最终我们得到 2 万条高质量标注数据,按时间顺序切分为训练集(80%)、验证集(10%)、测试集(10%)。
这里有个细节值得强调:切分必须按时间切,不能随机切。因为线上遇到的都是未来数据,只有按时间切分才能相对真实地模拟线上效果。如果用随机切分,模型看到的数据分布会和线上差异明显。
3.3 模型训练与评估
模型方面,我们选了一个中等规模的预训练中文模型作为基座,做分类微调。训练框架直接用 Hugging Face Transformers + PyTorch,这没什么神秘的,关键在于把实验规范化。
我定义了一个简单的训练脚本,包含以下配置参数:学习率 2e-5、批次大小 16、最大序列长度 128、训练轮数 3、权重衰减 0.01、随机种子 42。每次实验都会记录到 MLflow,包括训练的 loss、验证集 F1、各类别的精确率和召回率。实际跑下来,验证集整体准确率约为 88%,但仔细看类别报告发现"情感倾诉"的召回率只有 71%,明显偏低。
这个发现促使我们做了两个调整。第一,给"情感倾诉"类别提高了损失权重;第二,检查了该类别的标注噪声,发现有一批样本其实是"功能建议"被误标成了"情感倾诉"。修正标注后,训练了第二轮,整体准确率提升到 91%,情感倾诉的召回率也到了 85%。你看,训练过程中的问题,很多时候根源并不在模型结构,而在数据质量。
3.4 部署与接口设计
模型训练完成后部署,我们选择了最直接的方式——用 FastAPI 包一个推理服务,模型用 ONNX Runtime 加载。选择 ONNX Runtime 而不是直接用 PyTorch 推理,一方面是因为推理速度明显提升,另一方面是它去掉 Python 侧繁杂的运行时依赖,部署更干净。
接口设计上,我坚持所有输入输出都用 JSON,并且对输入做完整校验。接口返回格式固定如下:{"text": "...", "label": "功能建议", "confidence": 0.93}。对于置信度低于 0.6 的样本,服务端会主动标记为"待人工确认",这就是我们在需求拆解阶段说好的兜底策略。
部署过程中还做了一个很关键的细节:模型权重和推理代码分开版本化,模型产物存放在独立的模型仓库中,服务代码通过配置指定加载哪个版本的模型。这样后续模型更新只需要切换版本号,不需要重新发布服务代码。这一招在后续模型迭代时帮了大忙。
4. 让系统真正好用:可观测性与迭代闭环
4.1 日志、监控与指标收敛
模型服务上线只是开始,真正考验工程能力的是持续运行阶段。我在服务上线第一天就要求团队把三类监控全部接通:
- 系统层:CPU、内存、GPU 使用率、请求延迟分位数。
- 业务层:每日请求量、标签分布、平均置信度、兜底率。
- 数据层:文本文本长度分布、关键词频率漂移、未知类别比例。
业务层和数据层监控是 AI 工程特有的部分。普通 Web 服务只需要关心系统层即可,但模型服务必须额外关注输入分布变化。举例来说,如果某天开始用户反馈里大量出现一个新功能相关的热词,模型有可能因为在训练分布里没见过这个词而判断错误,如果我们没监控到分布漂移,就会在业务方反馈问题后才被动去处理。
指标收敛也是一个常被忽略的问题。上线初期我们同时盯着十几个指标,反而抓不住重点。后来收敛为三个核心指标:请求成功率、高置信度比例、人工兜底率。这三个指标能直接反映服务健康和模型效果,其他指标都作为辅助参考。从结果看,这套收敛逻辑非常有效,团队每次例会只看三个数字就能快速定位问题。
4.2 模型上线后的反馈闭环
模型上线后不能停止学习,否则效果会随时间衰减。这里的关键是建立反馈闭环:把线上模型输出中置信度较低或者被用户纠正的样本,定期沉淀到"待标注池",经过人工确认后回流到训练集,再触发新一轮训练。
我一般会设置一个每周自动任务,把一周内新增的待标注样本汇总,人工标注后合并进训练集,然后重新训练并做离线评估。评估通过后,新模型进入灰度阶段,先给一部分流量使用,对比新旧模型的核心指标。如果新模型没有明显回退,再逐步扩大流量。
这套闭环听起来很简单,但落地时最大的阻力往往是流程而非技术。业务方需要习惯去看人工兜底队列,运营需要理解为什么模型每次更新都要灰度。所以从项目早期就让业务方参与到反馈流程设计中,往往比把技术方案做完后再通知他们要用这个流程,顺利得多。
5. 常见问题与避坑指南
5.1 我最常被问到的三个问题
问题一:模型离线指标挺好,线上为什么效果不行?
遇到这种情况,优先排查三个点:训练数据和线上输入的数据分布是否一致、特征工程在离线与在线是否实现一致、评估指标与业务目标是否对齐。我见过太多团队只看准确率,却完全没关注召回的覆盖率和业务口径的对齐。具体到操作上,建议先把线上真实请求抽样保存一份,离线打好标签,用它做一次"影子评估",效果立马见真章。
问题二:需要买多少 GPU 才够用?
这是典型的先问资源再问目标的做法。我的建议是,先把项目规模模拟清楚,再反推资源。比如模型训练需要多少样本、大概多少轮、单卡跑多少分钟,稍微做个预算,再考虑用单卡还是多卡。对大多数从零开始的项目,用云上按需付费的 GPU 实例起步,比直接买整机要理智得多。等业务量稳定了,再考虑长期租赁或采购。
问题三:要不要上 Agent 或者大模型的复杂架构?
我的观点很直接:看问题复杂度。如果一条规则加一个分类模型能解决,绝不上需要维护成本高数倍的 Agent 体系。AI 工程的本质是降低复杂度和交付风险,而不是炫技。从零开始的人最忌讳一步到位把所有先进技术全堆上去,最后要么无法交付,要么线上永远在出问题。
5.2 新手最容易犯的几个工程错误
第一个错误是跳过数据体检直接开训。拿到数据先跑训练脚本,看似节省了时间,实则会为后续的重复训练付出数倍代价。正确做法是先花一天时间做数据体检,把分布异常、泄漏风险、标签噪声全部暴露出来。
第二个错误是不记录实验信息。刚开始做实验时,我也有过"跑完就忘、换个参数重跑"的阶段。后来养成了强制记录实验参数的习惯,每次跑完训练都顺便把配置存一份 JSON 记录,配合 MLflow 自动记录指标,慢慢形成自己的实验数据库。这个习惯让我后期做实验结果对比、查找历史最优模型时,效率提高了不止一个量级。
第三个错误是没有提前设计接口和灰度方案。很多项目把模型训练完,才开始思考怎么接入业务系统,结果因为接口设计不适配、没有灰度机制,发布周期被无限拉长。正确的方式,是在项目设计阶段就让下游业务方参与进来,把接口文档早定好,把灰度比例和回滚方案早定好。
为方便回顾,我把最常见的几个问题整理成速查表:
| 现象 | 排查方向 | 常用手段 |
|---|---|---|
| 离线好线上差 | 分布差异、特征不一致、评估口径错位 | 影子评估、线上抽样回测 |
| 服务偶发超时 | 预处理耗时、GPU 排队、无降级策略 | 性能剖析、批量推理、超时熔断 |
| 模型效果随时间下降 | 数据漂移、反馈未回流 | 漂移监控、定期重训 |
| 训练不可复现 | 依赖版本漂移、数据版本混乱 | 环境固化、数据版本化、实验记录 |
5.3 实操中的几点独门经验
再分享几个从实践中沉淀下来的细节经验。第一个是关于文本预处理的:不要把停用词表做得太激进,很多看似无意义的语气词在中文反馈里反而是分类特征,比如"希望""居然""为什么"这类词在不同场景中能提供明显的情感线索。第二个关于模型推理加速:如果服务并发量上去了,优先考虑 Triton 这类高性能推理框架,FastAPI 裸装 PyTorch 的方式在并发高时很快会顶不住。第三个关于训练资源分配:尽量把训练任务和推理任务拆到不同的资源池,宁可训练等待,也绝不能让推理服务被训练任务抢占了 GPU 导致延迟波动。
另外,模型微调阶段的学习率设置我一直遵循"金字塔式"规律:先用小学习率做短预热,再切换到正常学习率,最后在尾段做一次线性衰减。这套经验和学习率调度器的原理完全一致,能让模型在稳定性和收敛速度之间取得更好的平衡。
6. 从零开始到独当一面的心路历程
说了这么多技术细节,最后想从职业成长的角度聊几句。我见过很多刚开始做 AI 工程的朋友,容易陷入两个极端:要么觉得"AI 工程就是调包侠",缺乏成就感;要么觉得"自己还差得远",迟迟不敢动手做端到端项目。这两个极端我都经历过,现在回头看,真正让一个人快速成长的,就是完整地独立做完一个端到端项目。
从数据清洗到模型服务上线,这个周期可能很痛苦,中间会有大量与模型无关的琐碎工作,但正是这些工作让你真正理解系统是怎么运转的。当你第一次处理完线上事故、第一次完成模型灰度发布、第一次看到业务指标因为你的模型而提升时,那种成就感是跑再多基准数据集都换不来的。
我建议每个想进入 AI 工程领域的读者,不要一头扎进论文和算法推导里,而是挑一个自己熟悉的小业务场景,比如个人的笔记自动分类、博客评论情绪分析、订阅列表的重复内容识别等,完完整整走一遍"数据到服务"的全部流程。完成这个闭环之后,再回头看那些框架文档、最佳实践,你会发现一切都变得从容许多。
最后再分享一个我的小习惯:每当我在项目中遇到一个环境依赖或者部署问题,我都会把解决过程记录下来,哪怕只是几句注释。日积月累,这本"排坑笔记"已经成了团队新人上手最快的学习材料。技术社区里大家都在分享模型结构和新框架,但真实世界里的工程麻烦往往琐碎又具体,记录下来的价值远比自己想象得大。做 AI 工程,归根结底是一门"做中学"的手艺,动手越早,走得越稳。