1. 从零搭建AI工程能力:为什么我劝你别一上来就调包
这两年“AI工程”这个词被说得太多了,多到有点变味。招聘JD上写着“熟悉AI工程化落地”,点进去一看,要求会调三个API、会写Prompt、会用某个框架搭个Demo。说实话,这不叫AI工程,这叫“AI体验官”。真正做过从零到一项目的人心里都清楚,把一个模型从“能跑通”推到“能上线、能扛量、能迭代”,中间隔着的不是一层窗户纸,而是一整套工程体系。
我之所以想聊“ai-engineering-from-scratch”这个主题,是因为过去一年多我参与过几个从零起步的AI项目,有做文本处理的,有做多模态检索的,也有做推理服务部署的。踩过的坑、返工过的模块、半夜被报警叫起来处理的线上问题,加起来能写一本小册子。这些经验里最值钱的部分,恰恰不是“用了什么高级框架”,而是“在什么阶段该做什么决策”。很多新手一上来就冲着最火的框架去,结果连数据怎么流转、显存怎么涨的、延迟卡在哪一段都说不清楚,出了问题只能靠重启大法。
这篇文章想做的事情很明确:把“从零构建AI工程能力”这件事拆开揉碎,讲清楚一个AI项目从需求到上线,每个阶段真正该关注什么、该做什么选择、该避开哪些坑。它适合刚入行的工程师、想从传统后端转AI方向的开发者,也适合带团队做AI产品的技术负责人。我不打算堆砌术语,而是尽量用我实际项目里的场景和数字来说话,让你看完能直接对照自己的项目做检查。
2. 整体设计思路:AI工程到底在工程什么
2.1 先搞清楚AI工程和算法研究的边界
很多人把AI工程和算法研究混为一谈,这是第一个要掰扯清楚的点。算法研究的核心目标是“把指标刷上去”,关注的是模型结构、损失函数、训练策略;而AI工程的核心目标是“把能力稳定地交付出去”,关注的是数据管道、服务架构、资源调度、监控告警、迭代效率。两者有交集,但侧重点完全不同。
我见过不少团队,算法同学把模型训到很好的指标,交给工程同学部署,结果一上线就崩。原因往往不是模型不行,而是工程侧没考虑清楚:输入数据的分布和训练时是否一致?推理时的批处理策略是什么?显存峰值出现在哪个环节?这些问题在实验室里不会暴露,因为实验室的输入是固定的测试集,而线上的输入是千奇百怪的。
所以从零做AI工程,第一件事是建立“交付思维”。你要问自己的不是“这个模型有多强”,而是“这个能力以什么形式、什么延迟、什么成本、什么稳定性交付给用户”。这个思维转变听起来虚,但它直接决定了你后面所有的技术选型。
2.2 分层设计:把系统切成能独立演进的模块
我在实际项目里最常用的思路是分层。一个典型的AI工程系统,我会把它切成这么几层:
- 数据层:负责数据的采集、清洗、标注、版本管理。这一层的产出是“可复现的数据集”。
- 训练层:负责模型训练、微调、评估。产出是“带版本号的模型产物”。
- 推理层:负责模型加载、请求处理、批处理调度。产出是“稳定的推理服务”。
- 应用层:负责业务逻辑编排、结果后处理、对外接口。产出是“用户可用的功能”。
- 观测层:负责日志、指标、追踪、告警。贯穿所有层,产出是“系统可观测性”。
为什么要这么分?因为每一层的演进节奏不一样。数据层可能每天都要更新,训练层可能一周跑一次,推理层可能一个月才动一次配置,应用层可能天天改需求。如果把它们揉在一起,改一个地方就牵一发动全身,迭代效率会低到让人崩溃。
我踩过的一个典型坑是:早期项目里我把数据预处理逻辑直接写在了推理服务里,结果后来数据清洗规则变了,我不得不重新部署整个推理服务,还差点因为逻辑不一致导致线上事故。后来把预处理抽成独立模块,用配置文件驱动,改规则只需要更新配置,推理服务完全不用动。这个教训让我后来所有项目都坚持分层。
2.3 技术选型的三个判断维度
选型是新手最容易纠结的地方。我的经验是,不要看“哪个最火”,而要看三个维度:团队能力匹配度、问题规模匹配度、运维成本可控度。
团队能力匹配度是说,你团队里有没有人能hold住这个技术。如果一个框架很强大但团队没人懂,出了问题没人能修,那就是给自己埋雷。问题规模匹配度是说,不要用杀牛刀去杀鸡。一个日请求量几千的服务,没必要上复杂的分布式推理框架,单机加个队列就够了。运维成本可控度是说,要考虑长期维护。有些方案部署起来很爽,但监控、升级、扩容全是坑,后期会把你拖死。
我一般会做一个简单的决策表,把候选方案在几个维度上打分,然后选综合分最高的。这个表不需要很复杂,但一定要写下来,因为写下来的过程会逼你把模糊的感觉变成明确的判断。
3. 核心细节解析:数据、模型、服务三件套
3.1 数据管道:AI工程里最容易被低估的部分
如果让我给AI工程的各个环节按“重要性”和“被低估程度”排个序,数据管道绝对排第一。模型可以换,框架可以换,但数据管道一旦烂了,整个系统就是建在沙子上。
数据管道的核心任务是把原始数据变成模型能吃的格式,并且保证这个过程可复现、可追溯。我通常会把数据管道拆成几个阶段:
- 采集:从各种来源把原始数据拉过来。这里要注意的是,采集要记录元信息,比如来源、时间、版本,否则后面出了问题根本查不到。
- 清洗:去重、去噪、格式统一。这一步的规则一定要写成代码而不是手动操作,因为手动操作不可复现。
- 标注:如果是监督学习,需要标注。标注的质量控制是个大话题,我后面会单独讲。
- 切分:训练集、验证集、测试集的切分要固定随机种子,并且要记录切分逻辑。
- 版本化:每次数据更新都要有版本号,模型训练时要记录用了哪个版本的数据。
这里有个很实用的技巧:把数据管道的每一步都做成幂等的。也就是说,同样的输入跑两次,结果应该完全一样。这样当你想复现某个模型时,只要指定数据版本和代码版本,就能精确复现。我见过太多团队因为数据管道不可复现,导致模型效果波动时根本找不到原因。
3.2 模型训练:从“能跑”到“可复现”的关键动作
训练环节新手最容易犯的错是“只关注最终指标”。指标当然重要,但工程视角下,更重要的是“这个指标是怎么来的”。
我要求团队里每个训练任务都必须记录这些东西:代码的commit hash、数据版本号、超参数配置、随机种子、硬件环境、训练日志、最终模型文件。这些东西看起来琐碎,但当你想对比两个模型为什么效果不一样时,它们就是救命稻草。
另一个关键动作是评估的标准化。很多团队的评估集是随手划的,今天用这批数据,明天用那批数据,导致指标根本没法横向对比。我的做法是建立一个“黄金评估集”,这个集合一旦确定就冻结,所有模型都用它来评估。同时还会维护一个“动态评估集”,用来观察模型在新数据上的表现。两个集合配合使用,既能保证可比性,又能发现分布漂移。
还有一个容易被忽略的点是模型产物的管理。模型文件、配置文件、预处理逻辑、后处理逻辑,这些东西必须打包在一起,作为一个整体版本来管理。我见过有人只保存了模型权重,结果部署时发现预处理逻辑对不上,只能凭记忆重写,最后效果差了一大截。
3.3 推理服务:延迟、吞吐、成本的三方博弈
推理服务是AI工程里最考验工程能力的地方,因为你要在延迟、吞吐、成本之间做平衡。这三个指标往往是互相矛盾的:想要低延迟,可能就得牺牲吞吐;想要高吞吐,可能就得上更贵的硬件。
我一般会先明确业务的延迟要求。比如一个搜索场景,用户能接受的延迟可能是200毫秒以内;而一个离线批处理任务,延迟可能是小时级别。明确了这个底线,再去设计服务架构。
对于低延迟场景,关键优化点包括:模型量化、算子融合、批处理策略、缓存机制。模型量化是把浮点参数转成低精度表示,能显著减少显存占用和计算量,但可能会损失一点精度,需要评估。算子融合是把多个计算步骤合并成一个,减少内存访问开销。批处理策略是把多个请求攒在一起推理,能提高吞吐,但会增加单个请求的延迟,需要找到平衡点。缓存机制是对重复请求直接返回结果,能极大降低延迟,但要注意缓存的失效策略。
对于高吞吐场景,关键优化点包括:异步处理、队列管理、水平扩展。异步处理是把请求丢进队列后立即返回,由后台worker慢慢处理。队列管理要防止队列积压导致内存溢出。水平扩展是通过增加实例来提升整体吞吐,但要注意负载均衡和状态管理。
这里有个我踩过的坑:早期做推理服务时,我没有做请求的超时控制,结果某个慢请求把整个线程池占满了,导致后续所有请求都超时。后来加了超时控制和熔断机制,才解决了这个问题。所以推理服务一定要有“自我保护”能力,不能让单个异常请求拖垮整个服务。
4. 实操过程:一个文本分类服务的从零搭建
4.1 需求拆解与技术方案确定
假设我们要做一个文本分类服务,输入一段文本,输出它的类别。业务要求是:延迟200毫秒以内,支持每秒100个请求,准确率不低于90%。
基于这些要求,我先做需求拆解:
- 延迟200毫秒意味着模型不能太大,推理时间要控制在100毫秒以内,留出网络和处理的余量。
- 每秒100个请求意味着要考虑并发处理,单实例可能扛不住,需要评估。
- 准确率90%意味着模型要有一定的能力,不能太简单。
技术方案上,我会考虑几个选项:用预训练模型微调、用传统机器学习方法、用规则加模型混合。预训练模型微调通常效果最好,但推理成本高;传统方法成本低但效果可能不够;混合方案灵活但复杂度高。
我的选择是先用预训练模型微调,因为效果有保障,然后通过量化和批处理来优化推理性能。如果性能还是不达标,再考虑蒸馏到小模型。
4.2 数据准备与基线模型训练
数据准备阶段,我会先做数据探查,看看类别分布、文本长度分布、有没有脏数据。然后按照前面说的管道流程,做清洗、切分、版本化。
基线模型训练时,我不会一上来就调参,而是先用默认配置跑一遍,看看基线指标。这个基线很重要,它是后面所有优化的参照点。如果基线就不行,那说明数据有问题,得回去查数据。
训练完成后,我会在黄金评估集上评估,记录指标。同时会做一些错误分析,看看模型在哪些样本上出错,这些信息对后续优化很有价值。
4.3 推理服务搭建与性能压测
推理服务我一般用FastAPI或者类似的框架来搭,因为开发效率高。核心逻辑是:加载模型、接收请求、预处理、推理、后处理、返回结果。
搭建完成后,一定要做性能压测。我通常用locust或者wrk来做压测,模拟真实请求。压测时要关注几个指标:P50延迟、P99延迟、QPS、错误率。P99延迟特别重要,因为它反映了最差情况下的用户体验。
如果压测不达标,就进入优化循环:先看瓶颈在哪,是模型推理慢,还是预处理慢,还是网络慢。定位到瓶颈后,针对性优化。比如模型推理慢,就考虑量化;预处理慢,就考虑优化代码或者加缓存。
4.4 上线部署与监控配置
上线部署时,我会用容器化方案,把服务打包成镜像,方便部署和扩容。部署策略上,先用小流量灰度,观察一段时间没问题再全量。
监控配置是上线前必须做的。我会配置几类监控:服务级别的QPS、延迟、错误率;系统级别的CPU、内存、GPU使用率;业务级别的分类分布、置信度分布。这些监控能帮我在问题发生时快速定位。
告警规则也要设置好,比如错误率超过1%就告警,P99延迟超过500毫秒就告警。告警阈值要根据业务容忍度来定,不能太敏感也不能太迟钝。
5. 常见问题与排查技巧实录
5.1 模型效果突然下降怎么查
模型效果下降是线上最常见的问题之一。我的排查思路是分三步:先确认是不是数据问题,再确认是不是模型问题,最后确认是不是服务问题。
数据问题包括:输入分布变了、数据管道出错了、上游数据源变了。排查方法是看输入数据的统计特征,和训练时的分布对比。如果发现明显偏移,就要追查上游。
模型问题包括:模型文件被覆盖了、加载错了版本、推理逻辑改了。排查方法是检查模型版本和推理代码的变更记录。
服务问题包括:预处理逻辑不一致、后处理逻辑不一致、并发导致的竞态条件。排查方法是看日志,对比线上和离线的处理结果。
5.2 推理延迟毛刺的定位方法
延迟毛刺是指P99延迟远高于P50延迟的情况。这种问题通常由几个原因导致:垃圾回收、锁竞争、批处理策略不当、资源争抢。
定位方法是先看毛刺的时间分布,是周期性的还是随机的。周期性的可能是定时任务导致的,随机的可能是资源争抢。然后用 profiling 工具看热点在哪里。我常用的是py-spy,能直接attach到运行中的进程看调用栈。
如果是批处理导致的,可以调整批处理的最大等待时间,让请求不会等太久。如果是资源争抢,可以考虑隔离资源或者限流。
5.3 显存溢出的常见原因与规避
显存溢出是GPU推理的常见问题。原因通常有几个:批处理太大、模型太大、中间激活值太多、内存泄漏。
规避方法是:先算清楚显存需求,模型参数占多少、激活值占多少、批处理占多少,加起来不能超过显存上限。然后设置合理的批处理大小,留出余量。如果是内存泄漏,要检查代码里有没有持续增长的数据结构。
我一般会在服务启动时做一个显存压力测试,逐步增加批处理大小,找到显存溢出的临界点,然后把批处理大小设在这个临界点的70%左右,留出安全余量。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方向 |
|---|---|---|---|
| 模型效果下降 | 数据分布漂移 | 对比输入统计特征 | 更新训练数据 |
| 模型效果下降 | 模型版本错误 | 检查模型加载日志 | 回滚模型版本 |
| 延迟毛刺 | 垃圾回收 | 看GC日志 | 调整GC参数 |
| 延迟毛刺 | 批处理等待 | 看批处理配置 | 调整等待时间 |
| 显存溢出 | 批处理太大 | 压力测试 | 减小批处理 |
| 显存溢出 | 内存泄漏 | 监控显存增长 | 修复代码 |
| 服务超时 | 慢请求阻塞 | 看请求耗时分布 | 加超时控制 |
| 服务超时 | 资源不足 | 看系统指标 | 扩容或限流 |
6. 迭代与演进:让AI工程能力持续生长
6.1 建立反馈闭环
AI工程和传统软件工程最大的区别是,AI系统的行为会随着数据变化而变化。所以建立一个反馈闭环特别重要。这个闭环包括:线上效果监控、用户反馈收集、bad case分析、数据回流、模型迭代。
我一般会做一个简单的bad case收集机制,把线上置信度低或者用户反馈错误的样本收集起来,定期分析。这些样本是最有价值的训练数据,因为它们反映了模型真实的短板。
6.2 自动化程度的渐进提升
从零开始的AI工程,不要一上来就追求全自动化。我的经验是分阶段来:第一阶段手动为主,把流程跑通;第二阶段半自动化,把重复劳动脚本化;第三阶段全自动化,把整个链路串起来。
每个阶段的提升都要有明确的收益,不能为了自动化而自动化。我见过一些团队花大力气搭了一套自动化平台,结果因为业务变化太快,平台根本跟不上,最后又回到手动操作。
6.3 团队能力建设
AI工程不是一个人的事,需要团队配合。我的经验是,团队里需要有几种角色:懂数据的、懂模型的、懂服务的、懂业务的。不一定要专人专岗,但能力要覆盖到。
另外,文档和知识沉淀特别重要。AI工程里很多经验是隐性的,如果不写下来,人一走就断了。我要求团队里每个项目都要有设计文档、操作手册、问题记录,这些东西平时看着没用,关键时刻能救命。
7. 我踩过的那些坑和给你的建议
说几个我印象最深的坑。第一个是早期做数据管道时,我没有做数据版本管理,结果模型效果波动时根本查不到原因,花了整整一周才定位到是数据源变了。从那以后,我所有项目都强制要求数据版本化。
第二个是推理服务上线时,我没有做超时控制,结果一个慢请求把整个服务拖垮了。后来加了超时和熔断,才稳定下来。这个教训让我明白,AI服务首先是个服务,服务该有的保护机制一个都不能少。
第三个是模型评估时,我一开始没有固定评估集,导致不同模型的指标没法对比,走了很多弯路。后来建立了黄金评估集,才让迭代有了明确的方向。
如果让我给刚入行的朋友一条建议,那就是:不要急着追新框架,先把数据、模型、服务这条链路走通一遍。走通一遍之后,你对整个系统的理解会完全不一样,再去看那些框架,就知道它们解决的是什么问题了。
最后分享一个小技巧:每次上线新模型前,我都会做一个“影子测试”,就是把新模型的推理结果和线上模型的结果都记录下来,但不影响线上返回。跑一段时间后对比两者的差异,确认新模型没有异常再切换。这个做法帮我避免了好几次潜在的事故。