
先别急着打开教程或者买课。如果你搜到“ai-engineering”这个词大概率已经发现网上的资料要么讲的是大模型 Prompt 技巧要么直接甩给你一套端到端的 AutoML 平台看完一头雾水。而我这里说的 ai-engineering-from-scratch指的是完全抛开现成 AI 平台的封装从数据、模型、部署、监控这一整条链路亲手把一个 AI 功能做成可用的线上服务的过程。这个标题想表达的核心就一句话“从零开始做 AI 工程”不是“从零开始训练一个模型”而是“从零开始搭建一套能让模型稳定运行的工程系统”。我接下来要写的东西不面向那些只想调用 API 的业务方而是面向打算真正深入 AI 工程化、理解每一个环节、愿意踩坑的开发者。你会看到数据处理怎么从“能用”变成“可信”模型上线之后怎么退化以及为什么一堆人把模型训练出来却永远无法发布——这些才是 AI 工程真正考验人的地方。我把近几年从零搭 AI 服务的完整思路拆成五块每块都是我在实际项目中反复调整过的做法不是教科书式的理想流程而是踩过坑之后保留下来的方案。1. 为什么“AI 工程”和“会跑模型”完全是两码事1.1 一次“Demo 十分钟上线两小时”的真实经历我之前带过一个项目需要做一个面向客服场景的文本分类服务。团队里有个同学模型本身玩得很熟在 Jupyter Notebook 里把 Bert 微调跑得飞起准确率也不错。当时的想法很简单把 Notebook 里的推理代码抽出来写个 HTTP 接口部署到一台 GPU 服务器上完事。结果从“模型跑通”到“线上稳定运行”花了两周。问题一个接一个首先是 Python 环境依赖冲突Notebook 里能跑是因为各种包版本刚好凑在一起但换个干净环境torch 和 transformers 的版本匹配直接让人崩溃然后是模型文件管理训练过程中生成了好几个 checkpoint到最后都不知道线上跑的是哪个版本最离谱的是模型输出的结果在离线评测集上表现很好但上线后前几条真实请求就出现了明显偏差因为线上文本的长度分布和清洗方式跟训练集根本不一致。这件事给我的冲击很大。那个同学的建模能力没有任何问题但他缺少的正是“AI 工程能力”——把模型变成产品能力的一部分并让它持续稳定地工作。1.2 AI 工程AI Engineering到底在做什么如果你去看一些海外团队的岗位定义AI Engineer 往往被描述为负责设计、构建和维护 AI 系统的人这些系统不仅仅是模型还包括数据管线、推理服务、评估体系、监控告警、持续集成等整套基础设施。我的理解更直接一点AI 工程 让模型在真实环境里可靠工作的所有工作。它面对的核心问题不是“模型准不准”而是“模型能不能长期稳定地在生产环境里提供服务”。这跟传统软件工程很像但又有显著差异。传统软件的逻辑是确定的输入 A经过代码逻辑输出 BAI 系统是概率性的输入 A经过模型权重计算输出的是一个概率分布然后我们根据置信度取一个结果。这个概率属性导致三件事特别麻烦输入不可完全约束。用户不会按你训练集的格式来总有脏数据、生僻词、超长文本、恶意输入。错误模式不可枚举。代码 bug 是有限的、可发现的模型错误是无限的你永远无法枚举模型会在哪些输入上犯错误。模型随时间退化。代码只要不修改行为永远一致模型上线后外部数据分布变化会导致效果持续下滑今天测着没问题三个月后可能完全不可用。这套区别决定了 AI 工程不能照搬传统后端的做法必须有自己的方法论。也是为什么“会训练模型”和“会做 AI 工程”相差如此之大。1.3 谁最适合用这套“从零开始”的方式学习如果你已经是软件工程师熟悉 Python、了解基本后端开发但一直没怎么碰过 AI 相关项目——这套思路会让你少走很多弯路。如果你正在做算法研究但你的模型交到别人手里就“活不了”那这篇文章更适合你因为问题可能不在模型本身而在工程链路。我通常不建议真正的初学者一上来就碰“从零”两个字。你需要至少能做到会用 Python 写类、会基本的数据处理pandas 或 numpy、理解简单 API 服务怎么搭。其余的比如训练框架、部署工具、监控体系都可以跟着文章慢慢建起来。2. 从零搭一套 AI 服务的完整链路数据、模型、系统三层“从零开始”最容易让人困惑的是到底从哪开始我的习惯是把整个问题拆成三层——数据层、模型层、系统层。每一层都有自己的工作内容和判定标准层与层之间通过固定的产物文件、接口、指标衔接。2.1 数据层一份可信赖的训练集是怎么来的数据层的工作不是“下载一个公开数据集然后训练”而是把原始数据加工成可靠、可复用、可追溯的训练资源。先说一个最容易翻车的地方文本数据的清洗。很多开源数据集的文本看着干净是因为别人替你清过了。真实业务里的原始文本是什么样乱码、HTML 标签、重复标点、表情符号、简繁体混用、奇怪的换行。如果你不做处理模型确实也能学但学的往往是你不想让它学的东西——比如把“客服回复模板里的固定文案”当成有效特征。我自己的清洗流程大概是统一文本编码统一为 UTF-8去除控制字符和乱码保留中文、英文、数字、有限标点压缩重复标点“”变成“”去除 HTML 标签和 URL除非这些本身是任务目标简繁转换统一用简体然后是人眼抽检——这一步绝对不能省。每清洗 1000 条随机抽 50 条人工看一眼确认清洗规则没有误伤有效信息。接着是更关键的数据切片data slicing。不要只维护一个大的训练集要把数据按场景拆开管理。比如客服文本分类你至少要区分“售前咨询”“售后服务”“投诉建议”几个子场景。模型可能整体准确率很高但在投诉场景一塌糊涂——如果你只有一个混合数据集这个问题完全看不出来。数据层最后要形成的标准化产物是三份文件文件内容用途train.jsonl训练数据带标签训练模型valid.jsonl验证数据与训练分布相近调参、早停test.jsonl更接近线上分布的数据最终评估这里特别说明一下“测试集”的构建态度测试集不能图省事从原数据集随机切一部分。你要模拟线上真实会遇到的情况——加入一些训练过程中没见过的写作风格、长度分布、甚至漏网脏数据。这样测试集评估出来的数字才敢作为“上线能不能过”的判断依据。2.2 模型层选预训练模型还是自己训练在模型层最大的决定不是“用什么模型结构”而是“用别人训练好的还是自己从头训”。这个问题的答案取决于三个变量任务领域、数据规模、算力预算。场景建议方案原因通用任务情感分类、文本摘要、通用语义匹配直接用成熟的预训练模型社区持续维护效果已非常接近上限垂直领域且有独特术语法律、医疗、游戏黑话在预训练模型基础上做微调Fine-tune少量领域数据即可显著提升效果需要极度定制且规模够大比如超大规模类别细分才需要考虑更大规模的定制预训练前两种解决不了的时候再走到这一步我自己的默认做法是直接选用开源预训练模型然后做微调。微调不是玄学但有几件事想清楚学习率不是越大越好。新手最容易犯的错误是把微调时的学习率设置得和从头训练一样。从头训练的学习率通常是 5e-4 到 1e-3 这个级别微调的话全参数微调我一般从 2e-5 起步如果是用 LoRA 之类的高效微调方法可以放宽到 1e-4 到 2e-4。过大学习率的典型表现是训练 loss 下降很快但验证集指标不升反降——模型把预训练学到的通用表示冲掉了。监控两个 loss。训练时不要只看训练集 loss也不要只看验证集 loss要同时看两个曲线的走势。训练 loss 下降、验证 loss 上升是过拟合的经典信号此时应该早停训练 loss 和验证 loss 都下降缓慢甚至抖动可能是学习率太小或者数据存在问题而不是“训练时间不够”。Checkpoint 管理要规范。训练过程中至少留下三个 checkpoint最好的best、最后一个last、训练中途的一个epoch 1/3 处。不要问为什么——线上模型出了问题时这三个 checkpoint 往往能救命。模型文件命名也别用“v1”“v2”这种只有你自己懂的名字建议用“模型名_数据版本_训练时间_验证指标.后缀”这种格式比如“bert_customer_v3_epoch5_f1_0.87.pt”一眼能看出谁是谁。2.3 系统层把模型变成产品要闯的三道关模型训练好了真正的工作才刚刚开始。把模型文件变成一个稳定服务的系统层至少有三道关要闯。第一道关推理服务的接口设计。不要在 Flask 里用原始的 model.predict() 怼上去。你要设计清晰的请求/响应结构把“模型输入/输出”和“API 入参/出参”解耦。举一个最简单的例子——文本分类 API# schemas.py from pydantic import BaseModel, Field class ClassifyRequest(BaseModel): text: str Field(..., description待分类文本) topk: int Field(default1, ge1, le5, description返回前 k 个类别) class ClassifyResponse(BaseModel): label: str score: float all_scores: dict[str, float]为什么一定要用 Schema 做一层约束因为线上什么请求都可能来空的 text、超长的 text、二进制垃圾。让 Schema 层先过滤掉非法请求模型服务只处理语义合理的输入你的系统会稳得多。第二道关模型服务的封装与依赖锁定。这一关的另一个名字叫“让模型可复现”。你的训练环境是 Jupyter你的线上环境是 Docker两者 Python 包版本必须一致。最稳的做法是把推理环境做成镜像锁死所有依赖版本然后用这个镜像同时跑“离线评估”和“线上服务”——保证线上线下代码路径一致而不是线上单独写一套推理逻辑。FROM python:3.10-slim WORKDIR /app # 先装依赖再拷代码利用 Docker 缓存加速构建 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . # 模型文件单独拷贝或通过外部挂载 COPY models/ /app/models/ CMD [uvicorn, api.main:app, --host, 0.0.0.0, --port, 8000]这里多提一个坑模型文件不要打进 Docker 镜像里除非你的模型很小。模型文件动辄几百 MB 甚至几个 GB每次镜像构建都要重传一遍而且模型经常要更新镜像也会越积越重。正确做法是让模型文件跑在磁盘挂载或对象存储上镜像只负责代码和依赖启动时再拉取模型文件。第三道关推理性能与批量策略。很多人上线第一版模型服务时都会遇到一个尴尬单次请求几十毫秒的模型推理只是理论值实际延迟可能高 10 倍。为什么因为 GPU 推理有显存开销、有框架启动预热而且 CPU 与 GPU 之间的数据拷贝比计算本身更耗时。性能优化我的经验是按顺序做这几件事批量推理batching把并发的多个请求拼成一个 batch一次性喂给模型。GPU 处理 32 条文本的时间和处理 1 条差别不大吞吐量直接翻几倍。模型预热warm-up服务启动后先跑两三条“假请求”把 CUDA kernel 和模型加载全部触发完再对外开始接收流量。显存优化加载模型时设置torch.cuda.empty_cache()PyTorch 场景并选择合适的torch.dtype。对大多数推理场景float16甚至int8量化带来的精度损失在可接受范围内但显存占用和推理速度显著改善。3. 落地中最容易被轻视的三个环节评估基线、漂移监控、版本回滚模型训练完、服务部署好项目似乎就“完成”了恰恰相反真正的工程工作从这一刻才开始。我见过太多的 AI 项目在上线初期效果惊艳然后在一个月内迅速退化而没人察觉直到用户投诉大量涌入。下面这三个环节是最容易被忽略、却决定了一个 AI 系统能否长期存活的。3.1 评估基线没有对比就没有“改进”可言AI 项目的评估难难在它没有一个客观的“标准答案”。模型说“这个文本是投诉”到底对不对谁来判定所以你要做的第一件事是确立一个独立于开发过程的评估基线。什么叫独立就是整个开发过程中所有人都不能看测试集。训练时调参用验证集上线前最终用测试集两拨数据严格分开。我见过不少人偷懒把测试集并入验证集一起用结果模型“看着”准确率越来越高上线后立刻现原形——因为模型在开发过程中已经“见过”了那些测试样本它的高分是背题背出来的不是真正学出来的。评估指标的选择也要克制。不要只盯着准确率accuracy一个数字。在绝大多数真实场景里类别都是不均衡的——“正常咨询”可能有 80%“投诉”只有 2%。“准确率”会给你一个虚高的假象30 条投诉全被分错但在 10000 条数据里只有 3 个百分点的影响。你要真正关注的是每个类别的精确率precision、召回率recall、F1尤其是那些“低频但重要”的类别。更重要的是评估时要把人工抽检加进去每次跑完测试集随机抽 20 条人工看一遍确认模型不是靠某种巧合比如所有短文本都分到同一个类别刷出来的高分。3.2 漂移监控模型上线的第一天就开始退化一篇经典的判断是模型一经训练其质量就开始下降。原因在于生产环境永远是动态的——用户的表达方式在变、业务政策在变、输入数据的分布无时无刻不在漂移。我建议至少从两个维度做监控。第一个维度特征分布漂移检测PSIPopulation Stability Index。这是一种衡量两个分布差异的指标。把模型训练时的输入数据分布基准分布和线上最近的输入数据分布做一个对比计算出一个 PSI 值。经验阈值是这样的PSI 0.1分布基本稳定放心PSI ∈ [0.1, 0.25]轻微漂移需要关注PSI 0.25显著漂移必须排查根因举一个实例。某个客服分类模型的 PSI 在某个周一突然冲到 0.48一查发现产品刚刚上线了一个“自助退款”功能大量用户用手机端发消息时自带了一段固定的功能提示短语导致输入文本的整体分布完全变了。如果没有漂移监控你根本不知道这一周模型准确率为什么会暴跌。第二个维度置信度与决策阈值监控。线上每次推理都会产出一个置信度分数。你可以统计每天的平均置信度、最低置信度、以及被模型判定为“低置信度”的比例。如果平均置信度持续下滑通常意味着输入数据分布和训练时不一致。这里有个实操技巧把每天的置信度分位数比如 5%、50%、95%记录下来画成折线图比只看平均值能更早发现问题。3.3 版本管理与快速回滚模型文件也是代码团队里做传统软件开发的同事经常提醒我们代码要能回滚。但 AI 项目比传统软件多一层难度模型文件本身也要版本管理而且模型的回滚比代码回滚更复杂——因为代码的逻辑是确定的回滚到旧代码就能恢复到旧行为而模型是权重的黑盒你必须保留权重文件、对应的评测记录、数据版本才能完整回到某个历史状态。我在实践中建立了一套简单的模型登记表字段示例模型 IDcls-bert-v207训练数据版本dvc://datasets/cust_v5权重文件路径s3://models/bert_cust_v5_epoch5_f1_0.87.pt验证集指标acc 0.92 / f1 0.87测试集指标acc 0.90 / f1 0.85部署时间2025-03-12 10:00每次部署新模型之前先建立一个“当前线上模型 A”的完整快照包括权重、指标、日志。一旦新模型 B 出问题比如某个类别突然崩了传统后端可以直接 git revert 代码但 AI 项目必须把“代码切换到 A 的版本”和“模型文件恢复到 A 的权重”两个动作同时完成缺一不可。如果没有这套登记机制时间一久你根本不知道旧模型对应哪一份数据训练出来的、哪个 checkpoint回滚也无从谈起。4. 零基础入门的实践路径一套我反复调整过的学习顺序最后这部分送给真正想“从零开始”动手的人。我不建议去学一大堆理论再看书比较高效的方式是按阶段做小项目每个项目练熟一两个关键能力。4.1 第一阶段跳过深度学习先做“传统模型 完整工程链路”很多人一上来就想用大模型我觉得这是路线错误。第一阶段的目标不是“追求最好效果”而是“把整套工程链路打通”。我的建议是做一个最简单的文本情感分类项目用 scikit-learn 的 TF-IDF Logistic Regression 或朴素贝叶斯效果够用就行。工作重点是写一个完整的数据清洗脚本把原始数据变干净写训练脚本输出保存模型文件和评估报告用 FastAPI 写一个推理 API用 Docker 打包部署到一台服务器用 curl 或 Postman 调用 API并记录请求日志这五步走完你对“AI 工程”这个概念的实际体感就建立起来了。你会亲眼看到数据质量对结果的影响、模型文件怎么加载、API 部署有哪些坑、怎么判断服务在线。这一阶段不需要 GPU不需要深度学习框架一台普通笔记本足够。4.2 第二阶段升级到预训练模型加入推理性能优化第二个阶段的目标是把原来的模型替换成一个预训练模型比如一个小的中文 BERT 或者更轻量的文本向量模型并继续保持整个工程链路运行。这时你会遇到几件新事模型文件变大了几百倍部署时的模型加载时间明显变长GPU 参与推理后API 延迟第一次有变化需要处理更复杂的依赖关系torch、transformers、tokenizers 的版本匹配第一次接触“模型微调”和“checkpoint 保存与加载”这个阶段做完你基本具备了独立做 AI 项目的能力。更重要的是你会意识到模型只是整个产品的一个组件工程体系决定了这个组件的实际价值。我建议第二阶段结束时你可以尝试为模型增加一个简单的监控指标比如记录每次请求的输入长度、置信度自己动手做一个可视化看板用任何你顺手的绘图工具都行看到模型在真实使用中的数据。4.3 第三阶段把 CI/CD 引入 AI 项目第三阶段其实就是回到我前面说的那套完整体系自动化测试集评估、模型注册、漂移监控、A/B 测试。这是 AI 工程化进阶的体现。把这个阶段做好有一个关键的思维转变把模型当成软件代码一样对待建立流程管起来。比如你训练出一个新模型后不要直接上线而是先经过一条自动化的流水线跑测试集 → 输出指标报告 → 与当前线上版本对比 → 如果关键指标提升且没有严重回退才允许部署。这个过程可以做得非常简单哪怕一开始就是一个 Python 脚本也好过“人肉决定上线”。5. 我踩过的几个坑以及现在的“默认动作”到了最后分享几个实际踩过的坑和对应的策略希望能让你少走弯路。坑一过于信任公开数据集。公开数据集往往已经过清洗和标注它们只能作为“练习用”不代表真实业务情况。真实线上数据永远更脏、更偏斜。现在的默认动作是拿到任何数据集第一件事是写一个数据探查脚本统计空值、异常值、类别分布、文本长度分布而不是直接开始训练。坑二测试集上的指标提升不等于线上效果提升。我见过有人在测试集上把准确率从 87% 调到 92%上线后发现用户反馈完全没变好。原因之一就是离线测试分布和线上分布不同。现在的默认动作是每次上线新模型前先用旧模型跑一遍最近一周的真实线上日志把线上样本加进测试集重新评估离线指标和线上效果的关系才会清晰。坑三没人负责“上线之后”。很多 AI 项目做完就结束了没有监控、没有版本记录、没有回滚方案。等到模型出了问题所有人都在“回忆”之前到底部署了哪个模型。现在我的团队做任何模型上线都必须同时提交模型登记表、监控指标清单、回滚流程操作文档。这是硬性要求不完成就视为没有上线。坑四一开始就追求全自动和复杂架构。如果你刚接触 AI 工程不要一上来就搭 Airflow、Kubernetes、MLflow 全家桶。这些工具是为规模化准备的但你连一个模型服务的生命周期都没完整经历过时工具只会变成负担。先把最简单的方式跑通再在真实需求驱动下一个工具一个工具地加。如果你决定开始我给你的第一个任务是找一个文本数据哪怕是你自己收集的朋友圈评论本周内做出一个能通过 API 调用的情感分类服务。不需要深度模型不需要 GPU只要能稳定跑起来。然后你再回到这篇文章看看第二层、第三层的内容你会比任何人给你的直接答案都更清楚下一步该做什么。