1. 为什么是“从零开始”:AI工程到底在造什么
如果你点进这篇文章,大概率和我一样,在某个深夜对着报错的训练脚本发过呆:模型明明在排行榜上跑得很好,为什么一落到自己的业务数据里就各种翻车?这就是我把项目代号定为 ai-engineering-from-scratch 的直接原因——不再满足于“把某个模型跑通”,而是认真把“从零到线上全链路”走了一遍。这个过程既包括训练模型,也包括数据清洗、服务化部署、监控告警、灰度回滚这些看上去不性感的环节。
读完这篇记录,你会得到一个可复制的思考框架:怎么把业务问题翻译成模型问题、怎么搭建最小可用流水线、怎么应对上线后才会出现的问题。内容不依赖特定框架,把我踩过的坑和判断标准都写了出来。不管你是刚转算法的后端、被老板赶鸭子上架的“半个算法岗”,还是在校学生,这份经验都应该能让你少走点弯路。
1.1 算法、模型与AI工程的分工
很多人把“AI工程”理解成“训练模型”,这是第一个误区。算法工程师的产出往往是实验结果和一组权重文件,模型本质上是个零件;而AI工程关心的是这个零件怎么被稳定地放进一个整体系统里。打个比方:算法是从0到1画出发动机的设计图纸,模型是用图纸加工出来的发动机,AI工程则要解决发动机装进整车之后的问题——油路怎么接、散热怎么排、方向盘转向时动力能不能跟上。
从零开始做AI工程,意味着你至少要把六件事走通:数据、训练、评估、部署、监控、迭代。我刚起步的时候只盯着“训练”,花了很多时间调参,结果做出来的东西像一个没有轮子的汽车底盘,只能看不能跑。真正把项目推向前进的,往往是那些枯燥的环节:定义好评估集、把推理接口封装好、日志字段设计齐全、回滚方式想清楚。
所以我会把“AI工程”定义成一句话:用系统化的方式,让模型在一个真实环境里持续、稳定地创造价值。它不追求单个指标刷到极致,而是追求整个链路可控、可解释、可回滚。
1.2 我踩过的第一个坑:测试集漂亮,上线却见光死
这个坑发生在我的第一个分类项目上,业务是商品评论的正负面识别。当时我在公开数据集上训练了一个模型,测试集F1有0.93,觉得自己已经“跑通AI”了。结果把它接到一个内部demo里,输入“退货!”“质量差”这种直白文本时表现还行,一遇到“客服让我找售后处理”“这个质量不服”就乱了;更离谱的是,输入“今天天气不错”,模型直接判成了正面。
为什么?因为公开数据集的评论分布和真实场景根本不一样,测试集里都是“好评”“差评”这种标准表达,而线上用户的话术千奇百怪。我的评估数据全部来自同分布,模型只学到了一些表层词和语气词的相关性,根本没有理解能力。更致命的是,我当时没有任何线上数据回流机制,甚至不知道模型在真实环境里会碰到什么输入。
这个教训成了我后来所有项目的第一步判断标准:评估集必须尽量模拟真实分布,否则一切指标都不可信。从那次之后,我每次做AI方案都会先问一句:我们到底有没有接近线上环境的数据?如果没有,那模型做得再漂亮也只是自娱自乐。
2. 动手之前,先学会把业务诉求翻译成模型任务
从零开始最容易犯的错,不是技术不够,而是接需求的时候直接开干。老板说“用AI给工单自动分类”,如果你第一反应是“那我用哪个模型”,后面八成会翻车。AI工程的起点不是模型选型,而是把模糊的业务诉求翻译成一个明确的机器学习问题。
2.1 四步翻译法:我在工单分类项目里的实践
我后来在做一个客服工单自动分类项目时,总结出四步翻译法,每一步都能减少返工:
- 可行性判断:先看有没有数据、有没有标注、业务能不能接受“可能出错”。工单系统里有过去两年的历史工单和人工标注,数据是具备的;但业务方要求不自动删除工单,只做辅助推荐,这个条件很关键,决定了模型能承担多大的责任。
- 输入输出定义:输入不只是工单正文,还可以包含用户等级、产品线编号;输出不是“类别”这么简单,还要有一个“无法判断”的兜底类。没有兜底类,模型会在自己不确定的时候强行选择一个错类,这对业务是灾难。
- 成功指标:要跟业务收益挂钩。分类准召率之外,我们还要统计人工审核时间有没有下降、误推率有没有控制在5%以内。纯算法指标说得再漂亮,业务不认。
- 基线设置:动手训模型前,先用关键词规则跑一个简单基线。我们当时用规则模板中位数做到了macro F1 0.62,之后模型的目标不是“看起来分数高”,而是超过0.62,同时保证bad case能回溯、能解释。
这四步里,最容易被忽略的是“基线设置”。很多人觉得规则太土,但规则基线有两个不可替代的作用:一是给后续模型提供对照物,二是当模型在线上表现异常时,有个快速回退的位置。后来那个项目的模型做到了接近0.85的macro F1,但线上出现数据漂移时,我第一反应不是调模型,而是把规则基线重新启用顶上一段时间。这种安全感是花再多时间调参都换不来的。
2.2 什么时候该说“这个需求不需要AI”
翻译过程越熟练,你就会越频繁地发现:有些需求根本不应该上AI。作为工程师,学会拒绝“伪AI需求”同样是工程能力的一部分。我总结出几个判断标准:
- 输入空间有限,且可枚举:比如几个固定选项的工单类型判断,用规则和查找表就够了,硬上模型只会引入不可控的随机错误。
- 数据量太小,不足几百条:这种规模下模型很难学到泛化模式,不如先让人工处理,同时积累数据。
- 错误成本极高,且不能复核:比如某些自动化决策直接对用户权益造成影响,如果没有人工兜底和复核流程,全自动模型的风险远大于收益。
说“不需要AI”并不丢人。我甚至认为,一个优秀的AI工程师应该先成为一个“AI祛魅”工程师——知道哪里该用、哪里不该用,才能让团队把资源花在最值得的地方。如果你一上来就觉得自己什么都能用AI解,那大概率会陷入“拿着锤子看什么都像钉子”的状态,做出一堆没人用的模型。
3. 最小可用流水线:数据、训练、评估、服务化的闭环
翻译完需求后,就进入工程的核心环节。很多教程喜欢单独讲“加载数据集—训练—输出准确率”三件套,但真实项目里,这三件套只是冰山一角。我会按自己实际搭建流水线的顺序来讲,从数据到服务化,每一步都有具体操作。
3.1 数据环节:比模型更值得花时间
数据环节决定了整个项目的天花板。我见过太多人急着训模型,却连数据集里的重复样本都没去重。第一个要处理的是标注一致性:如果两个标注人员对同一段文本给出不同标签,模型学到的映射就是混乱的。我的做法是抽100条样本让两个人各标一遍,然后计算Cohen's Kappa一致性系数;低于0.7,就得先坐下来统一标注标准,而不是急着训练。
第二个容易踩的坑是数据切分方式。工单这类带时间戳的数据,绝不能随机切分,必须按时间顺序切:用过去的数据训练,用未来的数据验证。我在另一个项目里曾经用随机切分,模型评估分数很漂亮,上线第二周准确率就明显下滑。后来一查原因,新工单里出现了很多测试集里从未见过的表达方式,而随机切分把未来信息提前泄漏给了模型。改用时间切分之后,虽然评估分数不好看了,但上线后的表现反而更稳。
第三个细节是重复样本。企业内部系统里同一个用户反复提交相同或高度相似的工单非常常见。如果不去重,完全一样的内容可能同时出现在训练集和验证集里,导致评估虚高。我当时用hash做精确去重,再用simhash处理近似重复文本,至少把数据量砍掉了15%。数据规模缩小听起来是损失,但模型学到的东西反而更真实。
3.2 训练与评估:别让指标骗你
训练环节最核心的产出不是模型权重,而是“指标是怎么算出来的”。我习惯在训练前先写一个评估函数,把precision、recall、macro F1都明确下来,并保证它能独立运行。注意,模型入库前我会做三次验证:
- 用时间划分做验证,而不是K-Fold随机交叉验证;
- 检查训练集和验证集之间有没有重复或近似重复样本;
- 把模型预测错误的样本全部抽出来人工看一遍,记录错误模式。
特别是第三点,很多人说“我的模型F1有0.9”,但我问“错误样本长什么样”,他答不上来。如果你没有亲自看过bad case,那0.9就只是一个数字。我在项目里会把OOF(Out-of-Fold)预测结果保存下来,然后按错误类型分组:是不是总是把“退款”误判为“投诉”?是不是某类样本数量太少?这些观察最后会反馈到数据清洗和特征设计里,比盲目调参有用得多。
为了方便排查,我给自己定了一个“指标可信度检查清单”:
- 是否存在重复或近似重复样本?
- 是否按时间顺序切分?
- 测试集是否覆盖了线上可能出现的新类别写法?
- 低置信度的预测结果是否被人工检查过?
- 指标和业务目标之间有没有对应关系?
如果这五条里有任何一条不满足,指标就只是纸面分数。
3.3 服务化的最小配置:先让模型能被人用起来
模型训好后,大多数人会卡在“怎么把它变成服务”这一步。其实最小化路径没有想象的复杂,你只需要把训练时的预处理逻辑和模型权重一起封装起来。最容易出的问题是:训练时你做了归一化、去停用词、截断,但预测接口里没做同样的处理,结果线上结果和离线测试对不上。
我习惯用FastAPI做一个极简推理服务,核心就三步:进程启动时加载一次模型、接收请求、返回预测结果。代码看起来像这样:
from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() model = load_model() # 启动时加载一次,避免每次请求重复加载 class Item(BaseModel): text: str @app.post("/predict") def predict(item: Item): text = preprocess(item.text) # 必须和训练时一致 label, confidence = infer(model, text) return {"label": label, "confidence": confidence}三个配置细节不要省:一是请求日志,至少记录text、label、confidence、耗时四个字段,这是后面监控数据漂移的基础;二是无状态设计,服务实例不保存用户状态,方便水平扩容和回滚;三是依赖锁定,Python环境的依赖版本要固定,千万别在服务器上随手pip install最新包,我把“依赖版本漂移导致线上行为不一致”的坑踩过至少两次。
4. 模型上线那一刻,麻烦才刚刚开始
如果以为模型上线了就是项目结束,那只能说太年轻。我从第一个项目里得到的最大教训是:上线才是AI工程真正开始的地方。延迟、反馈、版本管理、数据漂移,这些问题在离线实验里根本看不到,只有真实流量会告诉你答案。
4.1 延迟、抖动与推理优化
先说延迟。我当时天真地以为,一台8核服务器跑个文本分类绰绰有余。实际压测下来,单条规则匹配不到1毫秒,Python循环处理一批请求还能接受,但用BERT做推理时,单条平均延迟能到50到80毫秒,在并发高峰期P99甚至超过120毫秒,直接触发网关超时。很多公司对接口的响应时间要求是200毫秒以内,但这还没算网络开销和其他业务逻辑。
我采用的优化路径有两步。第一步是加精确缓存:在服务层维护一个小型LRU缓存,如果请求文本和历史出现过完全相同的内容,直接返回上次结果。当时上线后大概有30%的请求命中缓存,模型负载一下子降了下来。第二步是把模型导出成ONNX,并用int8量化压缩。P99延迟从120毫秒降到了40毫秒左右,内存占用也变小了。
准确率有没有损失?多多少少有,换来了延迟的大幅下降。关键是想清楚业务更需要什么:对客服工单分类这种场景,几十毫秒的差距用户感知不强,而可用性更重要。如果做的是实时风控或交互式推荐,那优先级排序可能会完全不一样。优化方案没有标准答案,只有权衡。
4.2 反馈闭环与数据漂移
上线后第二周,我观察到某个类别的预测分布开始明显偏离训练集。比如“退款”相关工单占比从15%涨到25%,但模型还是按照旧分布去卡阈值,导致少量误判。这就是典型的数据漂移。
处理漂移不能靠感觉,我建议在日志里持续记录几个字段:输入文本、预测类别、置信度、人工最终结果(如果业务流里有)。每周固定抽200条样本人工过一遍,把误判样本回流到训练集里,形成数据飞轮。同时用分布差异指标做监控:我当时参考PSI指标,PSI小于0.1说明分布稳定,0.1到0.2需要关注,大于0.2就要告警并考虑补数据重训。
很多团队不做这一步,认为模型上线后就能一劳永逸。实际上,业务环境永远在变:新用户话术出现、产品线调整、季节因素影响。没有反馈闭环的模型,过三个月性能会逐步衰减,而你自己可能毫无知觉,直到业务方来投诉。
4.3 灰度发布与快速回滚
模型不像代码,出问题没法靠git revert立刻解决。我的做法是把模型版本和代码版本绑定管理,接口层返回model_version字段。每次新模型上线,先切5%的流量,观察业务指标没问题后再逐步升到50%、100%。
A/B测试的指标要提前定:对工单分类来说,不能只看准召率,还要看人工复核时间、误推率这些业务侧指标。一旦新模型表现明显不如旧版本,就要能一键切回旧模型。实现回滚的关键在于:旧模型文件不可变、保存的位置不变、服务是无状态的。否则你说“回滚”,实际上还得去改配置、重启服务,那就太慢了。
这里有个容易忽略的细节:模型文件名里一定要带版本号或commit号,千万别用model.pkl这种裸文件名覆盖存。我见过有人把新模型直接覆盖了旧文件,发现效果不对想回退,结果旧模型已经被冲掉了,只能重新训练,白白浪费一周时间。
5. 最容易跑偏的三种学法,以及我现在会走的训练路线
最后聊聊我从零开始这个项目的学习路径。这条路我走了不少弯路,最想吐槽的是网上太多学习路线看起来无比宏大,从数学分析到论文复现,列了几百个小时的内容,普通人根本坚持不下来。如果让我重来,我会更务实地选一条路线。
5.1 三种跑偏路线,我都走过
第一种是纯啃论文开局。我最早花了几周时间读模型相关的经典论文,当时觉得特别有收获,可当我需要部署一个服务时,连FastAPI路由怎么写都摸不着头脑。论文培养的是理论直觉,但它替代不了工程手感。
第二种是复制教程Demo。照着官方文档跑通了情感分析、图像分类,看起来很有成就感,但换个数据集、换个业务场景,我根本不知道从哪开始调。后来才明白,教程的意义是让你理解框架习惯,不是帮你建立工程能力。你如果只复制不思考,那你就只会复制。
第三种是只做模型不做系统。我有一段时间特别喜欢刷榜单、换模型,觉得只要模型指标够高,项目就成了。事实证明,做出来的东西根本没有可用路径,模型躺在Jupyter Notebook里,既没有评估闭环,也没有部署方案。这种项目和一张实验结果截图差不多。
5.2 更能落地的学习路线
如果你也是从头开始,我会推荐一条“以项目为中心的路线”,而不是“以课程为中心”:
第一步,掌握Python基础和pandas数据清洗能力。不用学得很深,但至少能处理缺失值、拼接表格、做groupby统计。AI工程里大量时间都在跟数据打交道,这部分能力越扎实,后面越轻松。
第二步,选一个简单分类任务,完整走通数据清洗、训练、评估、服务化、监控这一整条链路。不一定要用高大上的模型,逻辑回归、随机森林都可以。关键是理解每个环节会发生什么,尤其是评估结果和线上表现之间的差距从哪里来。
第三步,再回头学模型原理。这时候你已经有了实际项目经验,再去学梯度下降、注意力机制,就会知道这些知识是被什么问题驱动的,吸收效率高得多。
第四步,逐步扩展到生成式任务或更多模态。多模态、大模型这类新东西层出不穷,但工程基本功是通用的:怎么管理数据、怎么评估效果、怎么做灰度上线、怎么处理bad case。底层能力扎实了,换什么模型都是水到渠成的事。
如果只让我总结三条最核心的经验,我会这么说:第一,永远先做基线,哪怕是条规则基线;第二,评估集必须模拟真实分布,否则就是自欺欺人;第三,凡是没上线的模型都是负债,不是资产。这三条,是我在ai-engineering-from-scratch这个项目里用几个月踩坑换来的,也最值得你记下来。