相信不少朋友第一次看到“ai-engineering-from-scratch”这个标题,心里可能会犯嘀咕:这不就是又一份AI学习路线图吗?网上类似的内容实在太多了,从Python语法到TensorFlow入门,从吴恩达的课程到各种大模型微调教程,随手一搜就是一大堆。
但真正在AI领域待过几年的人,看到"from scratch"这几个字,想的往往不是“从零学Python”,而是一个更棘手的问题:在2025年这个时间节点,AI工程早就不再是“调包训练模型”那么简单了。
我自己带过不少想转行做AI工程的朋友,也包括团队里刚毕业的新人。最普遍的现象是:大家能跑通一个开源项目的README,能在Colab上训练一个手写数字识别模型,但如果要做一个真正能上线、能扛住用户请求、能持续迭代的AI系统,却完全不知道从哪里下手。这不怪任何人,因为“工程”二字的分量,从来不在模型本身,而在模型之外那一大圈“看不见的骨架”。
这篇文章,我想用我自己从零搭建AI工程体系的完整经历,聊聊这条路上真正重要的几个转折点。它覆盖的不仅仅是“学什么”,更核心的是“怎么串起来”和“工程思维是怎么养成的”。适合这样几类人看:刚入门但不想只停留在调包层面的新手;已经能做点小Demo、但想把系统做得更扎实的开发者;以及带团队做AI落地项目、需要梳理技术路线的人。
1. 从零开始之前:先搞清楚“AI工程”到底在解决什么问题
在看任何教程、选任何框架之前,我建议你先想清楚一个问题:你要成为的到底是“AI算法工程师”还是“AI工程化工程师”?这两个角色的日常可以说是天差地别。
算法工程师的核心场景是“在离线环境里折腾数据、特征和模型结构”,他们的产出物往往是实验报告、模型权重文件、效果评测指标。而AI工程化工程师的核心场景是“把算法产出的东西变成一个稳定运行的在线服务,并且让它能够被监控、被迭代、被扩展”。他们要考虑的是:模型推理延迟如何压到100毫秒以内?GPU资源如何分配才经济?特征数据从哪里来、怎么保证线上和训练时一致?模型出了问题如何快速回滚?
很多人从零开始学AI,目标其实是后者,但网上的教程几乎都在教前者。这就造成了一个很尴尬的局面:学完了深度学习的全部理论,最后还是不会部署一个模型服务。
我自己对“AI工程”的粗浅定义是:用一套可靠的系统方法,把AI模型嵌入到真实业务流程中,并让这套系统具备可维护性、可观测性和持续演进能力。这句话听起来绕,但拆开看就三点:能上线、能监控、能迭代。
如果你也是抱着这样的目标来的,那么下面的经验或许对你真的有用。我把这条路上最容易被忽略、也是最关键的几个环节,按我自己踩坑的深度逐个展开讲。
2. 第一道分水岭:从“能跑通Demo”到“能交付服务”
几乎所有自学AI的人都会经历一个爽点阶段:照着教程敲完代码,模型在测试集上跑出98%的准确率,那一刻觉得自己已经天下无敌了。但接下来要做的事情,才是真正的AI工程分水岭——怎么把这个在Notebook里活得好好的代码,变成一个别人通过浏览器就能访问、稳定响应、异常可查的线上服务。
2.1 用Flask可能不够:模型服务为什么需要专用的推理框架
最早我犯过很多新手都会犯的错误:训练好模型之后,直接用Flask包了一个HTTP接口,草草上线了事。在低并发、无压力的情况下,这个方案跑得还挺欢。但用户量稍微一上来,麻烦就接踵而至:请求排队、线程炸掉、内存泄漏,更麻烦的是模型推理占用的GPU显存无法释放,一连串问题搞得我焦头烂额。
后来我才意识到,模型推理场景和普通Web请求有本质区别——它是计算密集型,而且模型在前向传播过程中要连续占据显存和CPU算力。普通的Web框架没有为这种长耗时计算任务做任何优化。
业界推荐的方案是使用专门为模型推理设计的服务框架。在实践中,我个人的选择优先级是这样的:
- TorchServe:PyTorch官方出品,和模型生态绑定最紧密,开箱即用支持模型版本管理和监控指标。如果团队主要栈是PyTorch,这个优先尝试。
- Triton Inference Server:NVIDIA出品,主打多模型并发调度、动态batch、GPU资源利用率的极致优化。当系统规模变大、需要管理多个模型时,它几乎是绕不开的选择。
- Kubernetes + KServe:部署层的终极形态,适合已经在云原生方向深耕的团队,模型可以像微服务一样弹性伸缩。
提示:新人最容易陷入的误区是,把大量时间花在反复对比框架特性上。我的经验是,先选最顺手的一个(比如TorchServe)完整跑通一遍“模型打包 → 启动服务 → 调用接口”的流程,远比纠结选型要重要得多。选型这件事,在业务量起来之后有的是机会换。
2.2 一个完整的模型上线流程,到底长什么样
我后来整理出了一套固定的“服务化五步走”,团队里每个新人我都会让他们按这个流程走一遍。别嫌步骤繁琐,每一步都在排掉后面线上环境的雷:
- 模型导出:把训练好的PyTorch模型转换成TorchScript或ONNX格式。这一步会去掉训练专用的梯度信息,把计算图固化,模型体积更小,推理速度也会有一定提升。
- 镜像打包:写一个干净的Dockerfile,里面只装运行时依赖,不装任何训练相关的库。这一步能大幅减少镜像体积——我自己见过有人把整个conda环境塞进镜像,结果镜像体积7GB,随意一个漏洞扫描就慢得让人崩溃。
- 本地预检:在本地容器里发起模拟请求,验证模型的输入输出结构、响应时间、显存占用。这里有句经验之谈:线上90%的问题,都能在“本地完整跑流程”这个环节暴露出来,但偏偏很多人懒于做这一步。
- 部署上线:放到测试环境、再到生产环境。这个阶段推荐先灰度、后全量,尤其是模型这类表现不太稳定的出入口,保守点没坏处。
- 接口链路巡检:确认监控指标正常上报,日志能查到,报警规则挂好。到此,这个服务才算“真正交付”了,而不是把接口暴露出去就算交付。
2.3 数据验证:最容易忽略的线上拦路虎
在我做AI工程化之后,最常遇到的一类线上事故就是“线上输入数据和训练时长得不一样”。训练时图片都是干净的、尺寸整齐的;线上来的图片五花八门,有些甚至只有半张脸。文本也是,训练集的文本经过清洗,线上的用户输入却带着各种格式错乱的字符。
所以我在服务入口处强制加了一道“数据验证层”。这层不用做得特别复杂,但至少要有三个检查项:
- 完整性检查:必填字段是否存在,类型是否正确
- 值域检查:数值是否有合理上下限,文本长度是否在模型可接受范围内
- 兼容性检查:图片尺寸是否需要缩放/裁剪,文本是否需要统一编码
大部分问题卡在这层,就可以直接返回一个友好的错误提示,而不是让用户等到模型推理完再莫名其妙地收到一个失败的请求。这个习惯让我后续省下的排查时间,远超当时实现它花费的精力。
3. 管理AI资产:从“自己看得懂”到“系统和团队都用得明白”
写代码的人都知道版本管理的重要性,Git就是为此而生的。但到了AI工程这个领域,“版本管理”这个词的含义被大大拓宽了——我不光要管代码,我还要管数据、模型、参数配置、实验记录。如果这几样东西得不到统一管理,你会发现一个神奇的现状:团队里每个人跑出来的模型效果都对不上,但谁也说不清差异出在哪。
3.1 模型不是“文件”而是“产物”,需要一套完整生命周期管理
在正式做工程化之前,我的模型管理方式是什么呢?一个文件夹,起名“model_final_v3.8_真的不改了.pth”。相信很多同行看到这里会心一笑。模型文件的后缀和文件夹的命名,根本没法承载训练日期、训练数据版本、超参数、评估指标这些信息。
后来我将方案切换为“模型注册中心”的模式。这个思路类似于软件工程里的制品库——每一次训练产出的模型,连同它的元数据一起注册进去,拥有一个唯一标识。我再通过这个标识去部署服务、去追溯效果、去做模型对比。整个流程就清晰了很多。
我常用的一套结构是这样的:
- 模型仓库:存放模型文件本身,例如对象存储(如S3或MinIO)
- 元数据库:记录每个模型的训练时间、数据集版本、超参数、评估指标、负责人
- 版本状态机:一个模型要经历“实验 → 候选 → 已发布 → 已下线”这样的状态流转,禁止任何人绕过状态直接上线
这套体系最直接的价值体现在“线上模型要回滚”的时刻。没有这套体系时,回滚靠拍脑袋翻文件夹;有了之后,一条命令把服务指针指回上一个已验证的版本,整个过程五分钟不到就能完成。
3.2 特征和数据集的版本化:比模型版本化更容易翻车的地方
模型文件丢了可以重新训练,数据集一旦发生悄悄改动,你可能训练出一个“看似差不多但实际长歪了”的模型,而且这种偏差很难察觉。我亲身经历过这样一个坑:一个不老实的同学在公共数据集文件夹里更新了一版数据文件,文件名保持不变,内容却多了几百条新的标注。结果就是,全组人的评估报告对不上,折腾了一周时间才定位到是数据集悄悄变了。
所以我现在对数据集的管理有一条铁律:数据文件一旦被某个实验引用,就立刻赋予一个不可变的版本号,任何修改都必须生成新版本,旧版本永远保留。实践中我一般用DVC(Data Version Control)来管理,它跟Git的体验非常一致,甚至可以直接依赖Git仓库存储元数据,而数据本体扔在对象存储里。
3.3 环境依赖:让实验可以稳定复现的隐形支柱
Git管住了代码,DVC管住了数据,那Python包的版本呢?我见过很多项目,跑在A机器上没问题,跑到B机器上就爆粗口——原因往往就是某个包版本不一致。
真正可复现的实验环境,应该把Python版本、CUDA版本、pip包清单这三样全部锁定。工具层面我推荐用Poetry或Pipenv维护依赖树,用conda管理底层环境,再用Docker把整套环境固化成镜像。把它们组合起来的效果是:任何人拿到我的仓库和交付说明,一条命令就能还原出和我完全相同的运行环境。这不是什么高深技术,但它的确决定了你的实验能不能赢得团队信任。
4. 为AI系统装上“仪表盘”:可观测性与持续监控
传统后端服务的可观测性三板斧是日志、指标、链路追踪。到了AI系统里,这三样依然存在,但它们的语义发生了变化,而且多了一个全新的维度——“模型质量和数据分布”的监控。
为什么会多出这个维度?因为传统软件的故障往往是“功能不符合预期”,而AI系统的故障往往是“模型在特定情况下输出了非预期的结果”,这通常不是一个二进制的“是/否”问题,而是一个连续的质量退化过程。等到用户投诉才知道效果变差了,那就已经晚了。
4.1 在线监控到底要盯哪些指标
我给自己部署的AI服务设计了这样一个监控仪表盘,主要分四层来看:
- 系统层:推理延迟、GPU利用率、内存占用、请求错误率。这是最基础的一层,系统“活着”还是“死了”全靠它判断。
- 业务层:请求量、输入数据的分布变化、业务反馈指标(如点赞率、转化率)。这一层告诉你“系统活得好不好”。
- 数据漂移层:输入特征分布与训练集分布的差异程度。用一个简单的不等式或PSI(群体稳定性指数)来量化。当分布发生显著变化时,哪怕用户还没投诉,你也应该收到预警。
- 效果层:抽检标注和模型预测的一致性、用户显式反馈(点踩、举报)的比率。
综合来看,我最看重的是“数据漂移”这个指标。它最大的价值在于能够提前预警——AI系统的衰退通常先体现在输入分布的变化上,然后才传导到业务效果上。等你发现业务效果下降的时候,其实系统的有效寿命已经快到头了。
4.2 模型推理日志和普通日志为什么不能一样
普通的后端日志结构大概是“时间、用户、请求路径、状态码、耗时”,足够排错了。AI推理日志必须更细:输入的内容摘要、模型的原始输出、推测的置信度分数、命中了哪些推理分支、耗时与资源消耗。
为什么需要这些?因为AI的事故排查往往需要复现“模型当时看到了什么”。记得有一次线上的垃圾分类模型突然频出低级错误,我翻日志才发现,用户上传了大量训练集中从未出现的异形物品照片,模型的输出置信度已经低到和随机猜测差不多了。如果没有记录输入样本和置信度,这个问题的定位会跟大海捞针一样难。
落地形式上,推荐把推理日志输出成结构化的JSON,一份随时可查的实时流,一份归档到便宜的对象存储里用于回溯分析。日志的保留周期建议至少一个月,方便做版本对比和长期效果分析。
4.3 告警规则怎么设,才能既不吵死人又不漏报
告警设置是个微妙的平衡。规则太敏感,每天被蜂鸣声淹没,慢慢就会形成“狼来了”的心态,真正出事时没人理会。规则太粗糙,故障一路蔓延到不可挽回才被发现。
我自己设置告警时,会遵循“三不在”原则:
- 不告警于单个异常点:用滑动窗口(例如5分钟)内的平均表现来判断,避免偶发的网络抖动触发惊吓
- 不告警于可自愈问题:例如某一次超时重试成功,这种直接过滤掉
- 不只告警于系统指标:数据的漂移预警,跟系统的宕机告警同等重要,需要给足权重
实操中,我习惯设置两级告警:P1级是系统不可用、请求大面积失败,立刻通过电话渠道通知;P2级是性能劣化、数据漂移超过阈值,发到群里让相关同学处理。别嫌这设置啰嗦,经历过一次半夜只看手机就快速定位线上问题之后,你会感谢这个规则。
5. 从零开始的实战路径:亲手搭一个带反馈闭环的智能问答服务
说了这么多抽象概念,我以一个我反复带新人练手的项目为例,把整个从零开始到工程化的过程串一遍。这个项目就是“搭建一个带用户反馈闭环的文档智能问答服务”。它不涉及特别复杂的模型训练,但完整覆盖了AI工程的每一个核心环节。
选择“智能问答”作为起点,是因为它几乎涵盖了AI工程的所有典型场景:数据预处理、模型调用或微调、向量检索、服务封装、用户反馈回收、持续效果评估。麻雀虽小五脏俱全。
5.1 项目的整体架构与数据流向
整条链路大致是这样的:
- 数据准备:收集一批中文技术文档,做清洗、分块、向量化,存入向量数据库
- 问答引擎:接收用户问题 → 从向量库检索相关文档片段 → 把片段和问题一起提交给大模型 → 生成回答
- 反馈闭环:用户在页面点“有帮助/没帮助”,反馈数据回流到存储,成为后续评估和微调的数据基础
- 监控与评估:记录每次问答的输入输出,定期抽检模型回答质量,监控检索命中率和用户反馈率
这个链路里,向量检索节点是最关键的工程节点。它决定了模型能不能找到正确的上下文。我用的是比较常见的Embedding模型生成向量,检索用余弦相似度。
5.2 每一个环节的具体工程落地
数据清洗与分块。文档首先要转成纯文本,去掉页眉页脚、图表噪声。然后按段落或标题结构切分成块。分块大小直接影响检索准确率:块太小,语义不完整;块太大,噪声太多。我的经验是,中文技术文档块大小控制在500~800字之间,重叠200字,效果相对稳妥。这个数值不用纠结到极致,多试几次就能找到感觉。
向量化与检索。向量化直接用开源的Embedding模型,比如BAAI的bge系列,中文效果实测不错。向量数据库我用过Milvus和单机版的Chroma,工程化推荐Metor后者的部署更轻。检索时除了向量相似度,我还加了一层关键词过滤,当用户问题包含明确的文档编号或专有名词时,先做一次倒排索引召回,再和向量召回结果取并集。这能明显改善某些边缘场景的命中率。
大模型接入与提示词。我用的方式是“检索增强生成(RAG)”,即把检索到的文档片段作为参考资料,提示词明确要求模型只能依据这些资料回答,若资料内没有答案,必须直接说“未找到相关信息”。这比让模型自由发挥要稳妥得多,大大降低了“一本正经地胡说八道”的概率。
用户反馈回收机制。设计上我保留了很轻量的交互:回答下方放两个按钮——“有帮助”和“没帮助”。反馈数据被记入数据库,每个反馈样本都会关联当时的提问、检索片段和模型回答。这套数据在后续做效果分析和模型微调时,是金矿级别的资源,比什么测试集都贴近线上真实分布。
5.3 如何对这类系统做效果评估
智能问答系统的评估,不能只看“模型回答的文字是否漂亮”。我拆成三层来评估:
- 检索质量:召回的相关片段里有多少是真正相关的,可以用“命中率”简单衡量——即返回的Top5里是否包含标准答案所在的片段
- 生成质量:回答是否忠实于检索片段,是否有幻觉内容。这部分我采用“抽检+人工打分”的方式
- 业务反馈:用户的点赞率、负面反馈率、问题是否被有效解决
我在整个项目里建议你重点盯“检索质量”,因为它是决定体验的上限。检索要是捞偏了,模型回答再流畅也是白搭。依我个人的测试经验,当检索命中率低于70%的时候,用户对问答系统的不满意率会呈指数级上升。
6. 这条路上反复出现的坑,和我现在会怎么避
最后这部分,聊聊我自己从零走到现在,踩过的那些可以写进“案底”的坑。每一条都是真金白银买来的教训。
6.1 环境依赖带来的“薛定谔的复现”
先说最痛的一个:环境复现。有一阵子我换了一台新机器,业绩需要复现半年前的一个实验,结果不是缺库就是版本不匹配,甚至同一段代码在两个CUDA版本下跑出了完全不同的结果。我花了将近一周时间才把环境勉强搭回来,那种无力感至今记忆犹新。
现在我给所有项目立了一条规矩:任何实验记录,必须同时提交一份完整的依赖清单和Docker镜像描述。环境搞不定,再漂亮的实验结果都等于零。这条规矩没有例外。
6.2 评估集比模型更重要,但几乎没人认真做
另一件我后来才彻底想明白的事是:评估集才是项目真正的资产,模型只是资产的临时表现形式。数据是会变的,模型是要迭代的,但你精心标注的、覆盖各种边界情况的评估集,却是你判断“这个新模型到底有没有变好”的金标准。
很多团队火急火燎地训练新模型,但评估集却只是随手拿一批数据跑一下。这带来的后果是:模型发布后在线效果“感觉差不多”,但你根本不知道它到底是更好还是更差。所以我的习惯是,在项目早期就投入精力建设固定的评估集,并且在每次模型更新时,强制跑同一套评估集对比。这件事的程序相当枯燥,但它是工程化精进的重要标志。
6.3 防止“微调迷恋症”:什么时候该用RAG,什么时候该微调
最后聊一个战略层面的决策问题。很多刚接触大模型的朋友,一上来就想着微调一个自己的模型,觉得这样才有“技术含量”。但微调其实成本和风险都不低,它需要高质量的数据集、充足的算力,而且缺乏可解释性。
我在大多数应用场景里,推荐的第一选择是“提示词工程 + RAG”。只有当出现以下情况时,才考虑微调:
- 需要模型学会特定领域专有的表达风格或固定输出格式
- RAG检索到的知识不足以覆盖某些频率很高、要求很稳定的任务
- 需要在模型推理时降低延迟、减少输入的上下文长度,而这需要模型“内化”一部分知识
让RAG和技术方案并行,而不是一上来就梭哈微调,是很多工程化项目能够低成本跑通的一个重要原因。等你验证了业务本身确实有长期稳定的需求,再投入微调的预算,那时候的决策依据也充分得多。
最后的几句大实话
一路走过来,我最大的感受是,AI工程的核心其实不是“AI”,而是“工程”——它考验的是你如何在一个充满不确定性的系统里,持续做出相对确定的行为。框架和模型日新月异,今天的热门工具可能半年后就被替代,但那套关于数据管理、版本控制、可观测性、效果评估、灰度发布的思维方式,才是真正能够随你走得很远、并且不断复用的底层能力。
如果你也是从零开始走这条路,我能给出的最实用的建议是:不要受困于“学完再动手”的惯性,尽早把一个小而完整的项目跑通,哪怕它在技术上并不惊艳。因为只有亲手经历过那个“从Notebook到线上服务”的完整链路,你才会真正理解,AI工程师这个头衔里,“工程师”三个字的分量。
后续等你把这条链路跑通了,再回来看数据漂移、特征平台、模型A/B测试这些更高阶的话题,你会发现一切都自然顺理成章。共勉。