年前有个朋友转岗做AI落地,开口第一句话就问:“我会调模型、也刷过不少开源项目,为什么一到自己从零搭系统就发怵?”这个问题我太熟了。太多人手里的能力是“点状”的:会用某个库、能跑通某个notebook,但把AI真正当成一套工程系统来设计、迭代、排查,往往没经历过。项目标题“ai-engineering-from-scratch”要解决的,恰恰就是这个断层:从零开始,把AI当成一项系统工程来做。
这篇内容适合三类人:一是准备入行AI工程、不想只当“调包侠”的同学;二是已经在做算法、但总觉得线上问题一团乱麻的研究型工程师;三是想系统带团队落地AI项目的技术负责人。我会从技能坐标、工程主线、阶梯项目、真实排障四个层面展开,全程用我自己做过、踩过、改过的例子来讲述,尽量让你看完就能照着规划自己的从零到一路线。
1. 项目起底:"ai-engineering-from-scratch"到底在解决什么问题
1.1 我理解中的"从零开始"包含两层含义
很多教程把“from scratch”理解成“零基础入门”,但我个人更倾向于把它读成两层意思。
第一层,是你面前没有现成AI组件可抄的时候,能否自己设计出一个小而完整的系统。举个例子,很多人用过HuggingFace的pipeline,调用三行代码就能跑一个文本分类,但这种使用方式其实掩盖了大量工程细节:输入数据怎么校验,请求量上来怎么扛,模型版本怎么管理,线上效果下降怎么发现。当你需要抛开这些封装、从数据文件和一沓源码开始重新搭一套服务时,才是真正考验工程能力的时候。
第二层,是职业能力的重建。很多人都不是科班出身,半路接触AI,最初的经验来自无数碎片:刷过几节课、抄过几个项目、用过几个平台的API。这些东西不是没用,而是太碎,形不成“系统感”。从零开始重新组织自己的知识结构,把工程通用能力、机器学习基础、数据能力、服务化能力按主次排布清楚,这才是项目名最想传达的主张。
我见过太多人“明明什么都会一点,但什么都落不了地”,核心原因就是没有经历过一次完整的从零搭建。那种被数据、模型、服务、监控一起夹击的体验,才是AI工程师真正成长的时刻。
1.2 AI工程不是"会训练模型",它和算法研究是两种思维模式
我经常用一个表格来区分算法型工作和工程型工作,这个区分非常重要:
| 对比维度 | 算法/研究倾向 | 工程倾向 |
|---|---|---|
| 核心目标 | 提升离线指标、验证新方法 | 稳定交付、可复现、可排查 |
| 完成标准 | 实验结论能写清楚即可 | 线上全链路可观测、可回滚 |
| 时间节奏 | 以实验周期为单位,不确定性高 | 按迭代节奏交付,有明确排期 |
| 对失败的态度 | 失败是一个研究结论 | 失败是需要尽快恢复的事故 |
| 数据视角 | 使用固定数据集做评测 | 持续面对新数据、脏数据、分布变化 |
把这两种思维搞混,是很多AI项目烂尾的根源。研究岗可以花两周调一个模型结构,工程岗不行——你面对的是一个真实系统:流量在涨、数据在变、上游字段经常缺,甚至模型还没上线业务就要你保证响应时间。
从零搭建一次AI系统,会强迫你同时切换这两种思维。你要像研究者一样理解模型为什么会失效,也要像工程师一样设计监控和回滚方案。这种“随时切换视角”的能力,恰恰是“ai-engineering”这个复合词的精髓。
1.3 一个实用主义AI工程师的技能坐标
如果让我给“从零开始”画一张当前尺度下的技能地图,我不会按“数学、机器学习、深度学习”这种教科书维度去画,而是按“能不能支撑系统运转”来画。
第一块是软件工程通用能力。包括Python工程素养、Git协作、代码组织、测试、Docker、CI/CD。这块经常被轻视,但线上事故多半死在这里。第二块是机器学习基础与实验能力。不要求手推所有公式,但要清楚损失函数在做什么、评估指标有什么盲区、过拟合和数据泄漏长什么样。第三块是数据和数据处理能力。SQL、数据校验、特征分析、异常检测,这些是AI系统里最脏最累、也最决定成败的部分。第四块是服务化与运维能力。怎么把模型封装成接口、怎么做批处理、怎么加缓存、怎么监控延迟和效果衰减。
这四块之间不是线性关系,而是像一个四面体,支撑起任何一个生产可用的AI系统。后面我所有建议,都会按这个坐标系展开。
2. 入行前的四个关键准备:环境、代码、数学与数据
2.1 先把环境做到"可复现",再从环境里解放出来
很多从零开始的教程一上来就讲算法,但以我的经验,真正拖垮新人的不是算法,而是环境。依赖冲突、版本不一致、本地能跑上线就挂,这类问题能消耗掉你三分之一的心力。既然要从零开始,不如第一步就把环境能力练扎实。
我建议新手直接采用这套起步组合:Python 3.11+,用uv管理虚拟环境和依赖。uv是目前我用过最省心的Python包管理工具,速度比pip快一个量级,uv venv建环境、uv pip install装包,体验非常顺。当然用venv加requirements.txt也完全没问题,关键是必须习惯给每个项目一个独立环境,并且把依赖固定住。
等项目跑到一定阶段,至少要把Docker用起来。我贴一个最简Dockerfile作参考:
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]这段内容不长,但把“环境即代码”的核心理念展示出来了:任何环境差异都被镜像固定住。为什么这件事对AI工程特别重要?因为AI依赖的库底层有大量C扩展(numpy、torch这类),不同操作系统、不同Python版本、不同CUDA版本,都可能让同一份代码运行出不同结果。如果环境不可复现,你连“这个bug是我改出来的还是环境导致的”都判断不了,后续所有排查都会变成猜谜。
2.2 代码功底由"能跑"升级为"能改、能查、能量"
第二项准备是代码工程习惯。这里我不谈花哨的架构设计,只说三个对AI项目最要命的点。
一是模块边界要清晰。把数据读取、特征处理、模型训练、评估、推理拆分到不同函数或类里,不要全堆在一个300行的脚本里。这样做的原因很实际:当模型效果不好时,你需要快速单独验证“是数据问题还是模型问题”,如果代码耦合在一起,你根本没法做隔离实验。
二是加类型标注和日志。很多AI代码是动态类型泛滥的重灾区,函数参数是DataFrame还是list,不查上下文根本不知道。我习惯在新项目里给关键函数加上类型提示,并统一用logging输出关键步骤,比如“加载数据完成,共10000条,其中缺失值200条”。这些日志看着不起眼,线上排查时就是救命稻草。
三是做参数化实验配置。把学习率、批次大小、模型名称这些参数从硬编码里抽出来。我早期跑实验经常改一处参数要全局搜替换,后来统一改成配置文件(YAML或简单Python字典)加命令行覆盖,实验效率翻了好几倍。硬编码是实验复现的头号杀手,这句话值得反复默念。
2.3 数学和统计不必啃完高数,但"关键四件套"必须补
聊到数学很多新人直接头大。我的观点很明确:AI工程实践中,你不需要成为数学专家,但必须懂几个关键概念,否则“调参”就永远是玄学。
这“关键四件套”我按优先级排:线性变换(矩阵乘法、向量点积)、概率分布(均值、方差、正态分布)、梯度与优化(链式法则的直觉理解、学习率的意义)、评估指标(准确率、精确率、召回率、AUC各自的偏科)。这些东西用什么方式补?我推荐一个特别实战的路径——用numpy去手写一次线性回归和一次简单神经网络的前向传播,不用任何深度学习框架。这个过程不复杂,但能把“梯度下降到底在更新什么”“损失函数和参数的关系”彻底搞明白。
另一个容易被忽视的是数据统计直觉。你要习惯拿到一列特征先看一眼分布:均值、中位数、缺失比例、异常值范围。很多线上效果崩掉,根子并不在模型,而是输入分布早就变了,没人发现。拥有这种直觉,是工程型AI选手区别于纯调包选手的重要标志。
2.4 数据基本功:SQL和"脏数据耐受力"
最后一项准备是数据能力。SQL必须熟练,因为绝大多数真实AI系统的数据源头在数据库和数据仓库里,你不可能指望别人给你整理好一份“干净”的CSV。
但比SQL更重要的是“脏数据耐受力”。真实数据里什么都有:字段缺失、类型错乱、重复记录、时间格式五花八门、标签和特征错位。我见过最离谱的一次,一个看似正常的用户画像表里,年龄字段混进了几十种“未填写”的写法,相当于这个特征完全不可用。你要做的不是抱怨数据脏,而是建立一套数据校验流程:读取后立刻检查字段数量、类型、空值率、唯一值数量,写进脚本里,每次跑数据都自动执行一遍。这套习惯会让你在团队里迅速变成“靠谱”的代名词。
3. 我拆解AI系统工程常用的一条主线:数据→模型→服务→监控
3.1 数据环节:比模型更容易决定生死的一个阶段
到了正式做AI系统的环节,我强烈建议按一条主线来思考和拆解:数据 → 模型 → 服务 → 监控。这条主线不算新颖,但它把“AI工程”真正拆成了可以逐项迭代的子系统。
数据环节最容易被新手跳过。很多人从开源数据集起步,数据是别人清洗好的、标签是完整的,于是产生了“数据集本来就应该长这样”的错觉。一旦进入真实项目,数据全要靠自己搞定,就傻眼了。我的建议是先把一半的时间花在数据上。收集原始数据只是第一步,后面是三个动作:验证、清洗、切分。
验证就是检查数据是否可以用于训练,字段含义是否和文档一致。清洗是对缺失值、异常值、重复值做处理。切分则是要非常谨慎地按业务时间来划分训练集和验证集。比如做推荐系统,如果你随机切分数据,模型会“偷看”到未来信息,离线指标虚高,上线立刻打回原形。数据切分这件事,直接影响你对模型效果的所有判断。
这里我放一个通用的数据校验清单:
- 表结构检查:字段名、字段数是否与预期一致
- 类型检查:数字列是否都是数字、日期列能否统一解析
- 空值检查:每列空值率是否异常偏高
- 重复检查:是否存在主键重复或整行重复
- 分布检查:关键特征的分布是否处于合理范围
- 时间一致性:最新数据时间是否和预期接近,是否存在乱序
这套检查在深度学习时代尤其重要。模型会无条件“信任”你给的数据,数据里的错误它会照单全收并放大给你看。
3.2 模型选择与训练:从基线开始,而不是从最新论文开始
模型环节的核心工程原则是:先从最简单最笨的基线开始,再一步步增加复杂度。
太多人一上来就上预训练大模型或结构复杂的模型,结果就是:系统出了问题,你根本分不清是数据问题还是模型结构问题。我自己的习惯是先跑一个逻辑回归或者浅层模型做基线,把这个基线的离线指标、训练时间、推理延迟全部记录下来。这至少能告诉你两件事:这个任务用简单方法能做到什么程度、后续花力气引入复杂模型值不值。
训练过程中的工程控制,我主要看三点。第一,实验记录。每次实验的模型配置、数据版本、超参数、指标结果,必须落到一个可追溯的表格里。我习惯用一张简单的CSV加一个命名规范来实现:模型类型、数据批次、特征版本、日期时间组合成实验名。别嫌土,线上出问题回溯时,这套记录能直接救你的命。
第二,评估集设计要固定且多样化。固定是指同一个验证集不能随便变,否则指标不可比;多样化是指至少包含一个“有点难”的评估子集。我见过很多团队把验证集做得太简单,模型看起来优秀,一上真实场景就现原形。
第三,训练过程要留痕。每个epoch的损失、验证指标都要输出和保存,形成一个可绘制的曲线。不要只在最后打印一个最终数字,那样永远看不到“模型先升后降”的过拟合过程。曲线是诊断工具,不是给领导看的装饰品。
3.3 服务化:AI工程和算法实验的分水岭
模型训练完只是开始,AI工程真正与实验不同的地方在服务化。所谓服务化,就是把模型包装成可以被外部系统调用的接口,并保证它在真实请求压力下稳定工作。
我习惯用FastAPI作为推理服务的框架,它上手极快且自带OpenAPI文档,调试方便。一个最小推理服务大致长这样:
from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class PredictRequest(BaseModel): text: str class PredictResponse(BaseModel): label: str confidence: float @app.post("/predict", response_model=PredictResponse) def predict(req: PredictRequest): label, confidence = model.predict(req.text) return PredictResponse(label=label, confidence=confidence)这段代码本身不复杂,但工程上要堵的洞有很多:请求里text为空或超长怎么办?模型推理异常了返回什么?并发量高了要不要加缓存?这些才是服务化真正的考点。我的经验里,有两个点最重要。
一是请求校验。永远不要信上游,输入不合法要在入口就拦掉,否则脏数据会直达模型,产生你无法解释的推理结果。二是加缓存。对重复性高的请求,用LRU缓存可以极大降低模型压力。特别是生成式模型,同样的输入反复算一次,浪费的都是真金白银的GPU时间。这个优化对“AI工程”的性价比极高。
3.4 监控与迭代:模型上线不是终点,而是运营的开始
最后一条是监控。很多人把模型上线当成项目结束,其实这才是AI项目的真正开始。模型和传统软件不一样,传统软件的逻辑是写死的,行为稳定;模型的行为会跟着输入分布漂移而变差,而且这种变差往往是缓慢的、隐蔽的。
我建议至少盯三方面。一是系统指标:请求量、响应延迟、错误率。这部分和普通后端监控一致,用Prometheus加Grafana这类工具就能做得很好。二是输入分布指标:关键特征的均值、方差、缺失率有没有发生偏移。这部分是对付数据漂移的关键。三是业务效果指标:比如推荐系统的点击率、风控模型的拦截率。没有人关心你的模型离线AUC是多少,大家只看业务指标有没有涨。
监控发现问题后,要能快速迭代。迭代的前提是前面的工作都没有偷懒:实验可复现、数据版本清晰、服务支持新模型一键切换。我特别强调一下回滚能力。每次上线新模型,必须保留旧模型的部署能力,以便在效果下跌时秒级回退。没有回滚方案就上线,等于把系统当赌桌,而AI工程师不该赌。
4. 给新手抄作业:三个从零到一的阶梯项目
4.1 项目一:不碰机器学习的规则系统,先练"工程骨架"
这是我最推荐的新手第一个项目,很多人不理解:为什么学AI先从非AI项目开始?因为你要练的“工程骨架”——输入、处理、输出、测试、部署——和用什么模型毫无关系。如果连一个规则系统都做得不清不楚,加上机器学习只会更乱。
具体做法:做一个简单的垃圾评论过滤器。不用机器学习,就用关键词列表加评分机制:命中敏感词加分,超过阈值就拦截。虽然这是一个玩具级系统,但它完整包含了工程主线的所有环节:接收请求、清洗文本、规则匹配、输出决策、记录日志、暴露监控接口。
在这个项目里你要刻意训练四件事。第一,把处理逻辑封装成独立模块,留出后续替换成机器学习模型的位置。第二,给关键函数写单元测试,比如“包含敏感词的评论必须被拦截”。第三,把服务用Docker部署起来,至少在本机体验一次容器化运行。第四,加结构化日志,知道每条请求从进入到返回花了多久、命中哪条规则。这个项目花一到两周做完,你的工程手感会完全不同。
4.2 项目二:超小模型全链路——训练、导出、服务
第二个项目开始接触机器学习,但控制规模。用scikit-learn做一个文本分类模型,或者用PyTorch训练一个极小的MLP,类别可以就三四个。关键目标不是模型多强,而是走通“训练→导出→加载→服务”的全链路。
我在这个阶段特别想让新手体验一次“训练和服务的分离”。训练环境和推理环境经常不是一套:训练代码用重型框架,推理服务要轻量快速。所以要把模型导出成统一格式(比如joblib或torch.jit),在推理服务里只加载模型,不跑完整训练框架。
这个项目建议加上评估环节。把数据集切分好,算出精确率、召回率、F1,然后故意在服务里输入一些训练时没见过的“边界样本”,观察模型如何犯错。这一步会让“离线指标代表不了线上表现”从一句空话变成亲身体验。当你能完整解释“为什么这个样本预测错了、哪里出了问题”时,这个项目就过关了。
4.3 项目三:做一个带检索的RAG问答系统
第三个项目就是当前很热的RAG问答系统,但我把它当工程系统来做,不只是调库。RAG的链路长,足够让你体会AI工程中“组合复杂度”的挑战。
整个项目拆成五块来实现:文档加载与切分、向量化、索引存储、检索、问答生成。每一块你都要能单独测试。文档切分是第一个坑:切太碎语义断裂,切太长检索不精准。我建议从固定长度加重叠窗口开始,再根据检索效果调参。向量化这里选择embedding模型时要记录两个指标:向量维度与单条延迟,它们直接影响存储成本和场景响应速度。
索引存储我推荐先用FAISS或纯内存方案把链路跑通,之后再上真正的向量数据库。原因很简单:别让基础设施分散你对主链路问题的注意力。检索环节要调的是“召回数量”,太多会带噪声,太少会漏答案。问答生成则是把检索到的片段和用户问题拼给大模型,这里要处理的关键工程问题是上下文长度控制和大模型的幻觉。RAG项目会让你的视角从“单个模型”彻底跃升为“多个组件组成的系统”,这才是“ai-engineering”最核心的体验。
5. 会发酵的坑:真实调试经历和我的排查习惯
5.1 环境与依赖的“午夜凶铃”
环境坑是每个AI工程师都会反复撞的。碰到最典型的是这样的:周一提交代码时还能跑,周四别人pull下来直接崩。查了半天,原来某依赖库在自己本地静默升级了一个小版本,行为变了。从那以后我养成两个习惯。
第一,所有项目必须锁定依赖版本,不只是主版本,小版本和哈希也要锁。Python项目用requirements.txt加--no-cache-dir安装是底线,进一步可以用带锁文件的工具,如uv。第二,环境变更必须通过代码审查和CI。不要一个人默默给项目加了新库却没有任何记录,等别人跑挂了才在群里说“哦我装了个包”。这不是技术水平问题,是工程协作素养问题。
5.2 线上效果比离线差的三个隐藏原因
排名第一的原因几乎都是数据分布偏移。真实业务的数据和训练集存在肉眼可见或不可见的差异,模型从没见过这种分布,表现自然崩。第二个原因是特征不一致,训练时你处理的字段和服务线上时拿到的字段不一致,比如上游接口悄悄改了个字段名,程序没报错,但模型输入变了。第三个原因是集成系统的不变量被破坏,比如缓存串了用户、特征拼接顺序错误,这类Bug不会让程序崩溃,但会在无声中毁掉所有指标。
排查时我的固定套路是“找不变量”:选定一个样本,从请求入口到模型输出逐步追踪,验证每个环节的值是否符合预期。比如缓存命中是否真的返回了同一命中的结果、特征拼接是否和训练时完全一致。AI系统看起来复杂,但只要把一个请求从入口到尾端走一遍,大多数隐藏问题会暴露得明明白白。
5.3 我的排查习惯和给新手的建议
养成这些习惯后,我个人的排查流程一般是这样:先确认最近一次“正常”是什么时候,回滚观察是否恢复;再把出问题的环节锁定到数据、模型、服务哪一段;最后做最小复现。最小复现特别重要,一条能稳定复现的请求,比一万行日志都有价值。如果能在本地用一条样本复现线上异常,问题基本就解决一半了。
最后给新手一个建议:从零开始做AI工程,请刻意保持“小步慢跑”的节奏。不要一上来就追求大模型、大系统,先把最小的闭环做得坚固。每做一个项目,就去补一块短板:做规则系统补工程,做分类模型补实验,做RAG补系统组合。这个节奏看起来慢,其实是最省时间的路径。
我个人的体会是:AI工程这个行当,最大的门槛不是算法,而是你能不能把一个请求从头到尾追踪得明明白白,把一个系统拆成能独立验证的模块,把一次失败复盘成可复用的经验。这些能力没有捷径,只能靠一次次从零搭建来换取。“ai-engineering-from-scratch”这个名字看起来是一句宣言,做下来更像是一句实话:AI工程的根基,从来都是工程本身。