ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI工程从零搭建:数据管道、模型服务与监控告警实战指南

AI工程从零搭建:数据管道、模型服务与监控告警实战指南 “AI Engineering from Scratch”这个标题看着就很硬核。它不是那种教你调个 API、套个 LangChain 模板的速成课而是把 AI 应用的工程底座一块块拆给你看。最近“ai-engineering”相关的讨论越来越多很多同学从模型 API 调用入手最后都卡在工程化落地上推理性能怎么优化、数据管道怎么搭、评估怎么做、上线之后怎么监控。如果你正处在这个阶段或者想从一开始就建立完整的 AI 工程认知这篇文章的内容应该对你有用。我会从全局设计、核心模块拆解、一条可落地的实操路径到常见问题排障完整走一遍。1. 全局设计先搞清楚“从零开始”到底要搭什么很多人在看到“from scratch”的时候第一反应是“我要从线性代数开始推导 Transformer”或者“我要自己写一个深度学习框架”。这种理解不能说错但太狭隘了。在真实的工作环境中“from scratch”的含义更接近在不依赖全套托管服务的前提下自己动手搭建一个能跑、能维护、能迭代的 AI 应用系统级工程。也就是说这个“零”的起点不是“不懂数学”而是“没有现成的 AI 基础设施”。要解决的问题是当你没有现成的 ML 平台、没有现成的特征存储、没有现成的模型服务框架时你该如何用最基础的工具组合出一个生产可用的 AI 系统。1.1 核心需求解析不只是训练模型而是交付系统我们把标题拆开看AI Engineering 包含两大层面AI 层面涉及模型选型、数据处理、训练或微调、评估这些和算法强相关的环节。Engineering 层面涉及系统架构、服务部署、性能优化、监控告警、CI/CD、成本控制这些和软件工程强相关的环节。很多人以为 AI 工程化就是“训练一个模型然后封装成 API”但实际落地时你会发现训练只占整个工程量的一小部分。我见过太多团队花两个月调模型最后上线时才发现推理延迟压不下来、数据分布一变模型就崩、监控面板上全是报警却不知道先处理哪个。这些问题都不是“模型”层面的问题而是“工程”层面的问题。1.2 设计原则以终为始反推架构我在自己动手搭建这套系统时遵循了一个核心原则从“上线形态”反推技术选型。先问自己几个问题这个系统的调用方式是什么在线 API、离线批量还是嵌入到现有服务里预期的 QPS每秒请求数和延迟要求是多少数据更新频率是小时级、天级还是实时团队里有几个人维护大家的技能栈是什么这四个问题的答案直接决定了架构的复杂度。比如你现在只是个人项目或小团队就别一开始就上 Kubernetes一个 Docker Compose 就能解决很多问题。但如果你知道半年后要支持多租户高并发那服务层的设计从一开始就要考虑水平扩展。这种“以终为始”的思路贯穿整个 from scratch 过程。它帮你避免两个极端一个是堆砌大而全的组件导致过度设计另一个是图省事全部用 Notepad 写脚本导致后期完全没法维护。2. 核心模块拆解一个最小可用 AI 系统的完整构成一个可投入生产的 AI 工程系统从上到下大致包含数据层、训练层、模型服务层、评估与监控层、运维层。每一层都有自己独立的技术栈和坑点。2.1 数据层特征管道与数据版本管理的底层逻辑数据处理往往是被新手最轻视的环节。很多人用 Pandas 处理完一份 CSV 就开始训练完全不考虑数据质量、特征一致性和版本回溯问题。但真实生产环境里数据和模型是同步演进的如果数据和模型没有做版本绑定三个月后你连“这个模型当时是用什么数据训出来的”都无法复现。从工程角度看数据层必须解决数据获取批量导入还是实时流、数据校验格式、分布、缺失率、特征加工标准化、归一化、编码、数据版本管理。我的建议从一开始就引入你的数据版本控制工具。它的思路和 Git 类似但针对的是数据集和特征文件。每一次训练任务都记录下用到的数据版本这样模型文件和数据集就建立了关联关系出问题时能精确回溯。特征管道我推荐用标准化流程加工作流调度工具。很多团队觉得 Airflow 太重确实它适合那种有复杂依赖的周期性任务。如果你只是每天定时拉数据、清洗、落库直接用一个简单的 Python 脚本配合调度器调度就够了。关键不在于工具多强大而在于任务有明确的状态管理、日志输出和失败重试。2.2 模型服务层的技术选型与性能优化模型训练完成后如何把这个模型变成可以被外部系统调用的服务是整个工程链路里最影响体验的一环。先说选型。如果你训练的是深度学习模型PyTorch 生态目前最常见的服务化方案就是用专门的生产级推理服务器把模型导出为对应格式然后加载并提供接口。如果你用的是机器学习库Sklearn / XGBoost可以直接用工具对模型先做序列化保存再用网络框架包一层 HTTP 接口。我在初版架构时踩过一个坑模型文件用默认方式保存后直接加载到服务进程里做推理。结果请求一多GIL 锁导致 CPU 无法多线程并行性能完全发挥不出来。后来我改用独立推理服务进程才把 CPU 利用率和吞吐拉上去。推理性能优化有几个关键手段按优先级排序模型量化把 FP32 权重压缩到 FP16 或 INT8推理速度能提升 2 到 4 倍显存占用也大幅降低。批处理把并发的请求攒到一个小队列里凑够一批再跑一次前向计算。对于 GPU 推理尤其有效吞吐能提升一个量级。缓存对相同输入直接返回缓存结果。这个在 LLM 应用里尤其常见因为很多 Prompt 场景下的问题本质上是重复的。2.3 评估与监控没有度量就没有优化模型上线后的评估逻辑和离线训练时是完全不同的。离线评估你可以慢慢算准确率、召回率但线上系统需要的是实时监控数据漂移、推理延迟、异常输入占比并且能自动或半自动地触发模型重训。评估体系我建议分层设计模型质量层算指标例如准确率、均方误差、F1 值对应的是“模型本身好不好用”。系统性能层算延迟百分位P50/P95/P99、吞吐量、错误率对应的是“服务稳不稳定”。业务指标层算点击率、转化率、留存率对应的是“AI 到底给业务创造了什么价值”。这三个层级的监控缺一不可。只做第一层模型调得再好线上也可能表现不佳只做第三层出了故障你也无法定位是模型问题还是系统问题。监控落地的技术栈我推荐从最朴素的方案起步服务日志统一收集到集中式日志系统里配合现成的仪表盘工具做可视化。先别急着上复杂的 APM 工具把日志打全、打好比什么监控工具都强。3. 实操路径从零到一搭建一个可运行的 AI 推理服务这一节我直接给出一条经过验证的从零到一实操路径。我会以一个文本分类服务的搭建为例完整展示从数据处理到服务上线的过程并给出可复制的设计思路。3.1 第一周搭数据管道固定数据版本我习惯先搭数据管道而不是先写模型代码。因为模型训练可以反复迭代但数据管道一旦铺下去后面所有环节都会依赖它。首先是原始数据收集。用一个脚本从数据源拉取原始文件落到一个原始数据目录里按日期归档例如data/raw/20240101/。这一步的作用是保留最原始的信息为后续的数据清洗留退路。然后是清洗与加工。写一个独立的 Python 脚本针对这份数据处理以下事项缺失值填充、标签编码、文本截断、训练集和测试集划分。脚本的输出在数据集文件夹下生成全新的数据集文件。保存时注意带上版本号例如train_v001.parquet。为什么要用 Parquet 而不是 CSV因为 CSV 没有 Schema 概念几千列的时候读写效率很差而且大文件加载很占内存。Parquet 是列式存储读取指定列会快很多而且自带压缩磁盘占用也更小。这个选择在数据量大了之后差距非常明显。最后初始化数据版本管理工具把原始数据和加工后的数据都纳入版本管理。记录之后你就具备了回溯能力。3.2 第二周模型训练与实验记录数据处理完了就进入到模型训练阶段。平时做实验时很多人都有一个坏习惯模型参数、训练日志、指标结果全部散落在不同的文件夹里过两周就忘了哪个文件对应哪个结果。要解决这个问题我建议引入实验跟踪工具如 MLflow、Weights Biases 等任选其一即可。不用把所有实验都记录得特别详细但至少要固定这样几项数据版本、代码版本、超参数、最终指标、模型产物地址。这五个信息完整记录后你的每次训练就有了“指纹”任何一次实验结果都能追溯到完整的上下文。即使你只是一个人维护这套系统这个习惯也能让你在三个月后快速定位到“当时那个最好的模型是哪个”。训练代码本身我会固定成一个标准的模式读取数据、预处理、定义模型、交叉验证、评估、保存模型产物。不要在一个 Notebook 里跑完整流程因为 Notebook 天然难以复用和维护。3.3 第三周服务化封装与性能压测模型训完后开始把它封装成一个 API 服务。我做服务化的标准结构是四层接口层负责接收 HTTP 请求、参数校验、返回格式化。业务逻辑层负责调用模型进行预测以及一些前后处理逻辑。模型加载层负责加载模型权重、初始化推理引擎。基础设施层负责日志、监控指标暴露、健康检查即对外提供探活接口。如果用 Python 生态最简单的方案就是用一些轻量级 Web 框架写一个应用文件把模型加载写到全局初始化阶段然后对外暴露一个预测接口和一个健康检查接口。为什么模型加载必须放全局初始化因为模型加载是一个 IO 密集且耗时的操作。如果每个请求进来都重新加载一次模型服务基本没法用。全局初始化只在进程启动时执行一次之后所有请求都复用已经驻留内存的模型实例。服务写完之后立刻做压测。很多人上线前不压测上线后一看 P99 延迟 5 秒才发现问题。我在压测时常用的工具是并发测试工具先以 1 并发起步逐渐增加压力记录不同并发下的延迟分布和错误率。压测的重点不是看最大吞吐而是看瓶颈出现的拐点——在那个拐点之前的负载区间才是你能安全承诺的容量范围。如果压测发现性能不足优先检查模型推理有没有做批处理有没有做量化服务启动了几个 Worker数据库有没有成为瓶颈3.4 第四周监控告警与迭代闭环服务稳定跑起来之后立刻补监控和告警。我个人经验是没有告警的服务等同于裸奔。监控部署至少包含三条线服务日志记录每天全量请求和响应存留足够周期。业务指标日志把预测结果分布、置信度分布记下来用于识别线上数据漂移。系统指标CPU、内存、GPU 利用率、请求耗时、错误码。这些指标记录好之后在可视化面板里配置几个核心面板请求量趋势、延迟趋势、错误率趋势、资源使用率。告警规则我建议从最简单的开始延迟超过阈值、错误率超过百分之一、突然零请求。先保证“出事知道”再慢慢优化“怎么提前发现出事”。迭代闭环的核心是定期从线上日志里抽取新增样本沉淀为新训练数据重新训练后灰度上线。这个闭环一旦转起来模型才真正开始“越用越准”。4. 遇到的几个典型故障与排查思路这条路走下来踩过的坑远比顺利的时刻多。这里挑几个典型的故障复盘一下希望能帮你少走弯路。4.1 推理延迟高居不下问题出在数据预处理一次模型服务压测时我注意到单次推理延迟只有 20 毫秒但接口整体 P95 延迟却高达 800 毫秒。一开始怀疑是网络框架的问题排查很久才发现瓶颈出在预处理函数里文本转 ID 的操作循环里包含冗余的对象创建和重复计算每次请求都要执行一遍。排查方式其实很直接在代码里分阶段打点计时把“预处理耗时”“模型推理耗时”“后处理耗时”分别记录下来一看就明白时间花在哪了。从那之后我把所有不依赖输入数据的预处理步骤全部抽到启动阶段完成并把依赖输入的部分向量化重写。优化后整体 P99 延迟降到了 100 毫秒以内。4.2 线上模型效果变差不是模型退化了是数据变了跑了一段时间后业务方反馈模型准确率明显下降。检查模型文件没变代码也没改动但效果就是变差了。后来对比了线上预测结果分布和训练集的标注分布发现输入数据的文本风格发生了明显的偏移导致模型输出置信度整体偏低。这就触发了我前面提到的业务指标监控的价值只盯着系统性能指标是不够的业务指标预测分布的漂移才是模型失效的前兆。解决办法是收集最近一段时间的线上数据补充标注后增量训练重新发布。4.3 缓存失效风暴加缓存后出现大面积错误为了降低重复请求的延迟我引入了一个简单的内存缓存模块结果上线后反而出现大量超时错误。查了半天发现是缓存并发写的问题高并发场景下多个线程同时写入同一个 Key 的缓存导致数据竞争部分线程拿到半初始化状态的数据。这个问题的教训是任何中间件级的优化都要先想想并发安全。后来我换成了线程安全的缓存方案并且增加了缓存击穿保护单飞模式即同一时间只有一个请求去查源数据其他请求等待结果问题才彻底解决。4.4 新手上路最容易忽略的五个问题结合我自己带人的经验给刚入门的同学五个提醒固定随机种子不固定随机种子你的实验结果就永远无法复现也就谈不上迭代了。数据处理、模型初始化、训练过程都要固定。统一 Python 环境用虚拟环境固定依赖版本不然今天能跑明天崩多半是某个依赖被升级了。日志不要只打一句“成功”要打清楚“哪个环节成功、耗时多久、输入输出的关键信息是什么”才能定位问题。日志就是服务的黑匣子越详细越好。别急着追求并行先确认单线程逻辑正确再去做多线程多进程。并行引入了复杂度先把复杂度本身搞定再说。模型文件和代码要一起走版本管理模型和代码脱节会让生产环境完全不可复现。在机器学习平台类工具出现之前我们用的办法是在代码仓库的 Release 里附带模型文件的哈希值靠这个把代码和模型绑定在一起。5. 从“能跑”到“好用”的关键横跳前四周的搭建能让你有一个“能跑”的系统但要达到“好用”的程度还有一些工程习惯上的关键转变。5.1 从手动运行到自动化流水线最初你可能习惯手动跑脚本——手动处理数据、手动跑训练、手动启动服务。这在 Demo 阶段没什么问题但一旦进入长期迭代就必须把这些操作全部自动化。用工作流调度工具把“数据更新 - 模型训练 - 评估 - 部署”串成一条流水线。任何一个环节失败时流水线自动重试或告警而不是依赖人工盯着屏幕。这一步是我认为 from scratch 过程中价值最高的一步。自动化的意义不只是省人力它让整个系统的迭代节奏从“有灵感才更新”变成“按节奏持续进化”。5.2 从无测试到关键链路测试AI 系统的测试不像传统软件那样容易覆盖。但至少有几个关键链路必须测试数据处理函数的输入输出是否符合预期、模型推理服务的接口是否正确、模型在新数据上的表现是否触发下降预警。我在项目里会在代码提交前跑一个轻量级的冒烟测试Smoke Test确保最基本的流程没有中断。更进一步的话可以引入数据质量测试每次数据管道更新时自动计算数据分布指标和上一个版本对比如果偏移超过阈值就阻断后续流程。这个机制能极大避免“数据早就导错了跑到训练完才发现”的尴尬局面。越早发现问题修复成本越低。5.3 从独享到共享的模型仓库项目推进到多模型并存阶段时一定要建立统一的模型仓库。所有模型产物统一命名规则、统一打包格式、统一上传到同一个存储位置并附带元信息训练时间、数据版本、指标、作者。这个习惯初期看不出效果但在模型超过五个之后你会发现“找模型”“对比模型”“回滚版本”这些操作变得异常顺手。这其实就是一个轻量级的模型管理方案远期再平滑过渡到正式模型管理平台也不难。6. 后续可以怎么继续扩展这套系统这套系统稳定运行之后还有很多方向可以继续演进。一个方向是从分析型模型走向生成式模型。当你开始接入大语言模型时前面搭的这套工程底座基本可以平移过去。你需要额外补充的是Prompt 版本管理、上下文管理、答案评估大模型打分或者人工反馈闭环以及成本控制Token 用量追踪。另一个方向是引入更高级的部署形态。从 Docker Compose 过渡到容器集群管理平台再到服务网格每一步的动机都应该来自真实的瓶颈而不是追逐技术潮流。我在生产环境里见过太多过度工程化的案例——一个日请求量只有几千的服务搞了三套中间件和四套监控系统。这种复杂度只会拖垮迭代速度。还有一块容易被忽视的是安全加固。模型服务上线公网后接口鉴权、限流、敏感信息过滤这些都得补上。尤其是模型可能输出敏感内容必须要有内容审核机制兜底。这部分能力虽然是后加的但应该在架构设计时预留位置不然等到需要时再接会非常痛苦。最后分享一点个人体会AI Engineering from Scratch 这个项目真正难的不是某一块硬核技术而是把模型、数据、服务、监控、自动化这些环节像齿轮一样咬合在一起的能力。如果你也正在走这条路建议不要一上来就追求复杂架构先把最小闭环跑通再一层层加厚。把一个简单的系统打磨到极致比搭建一个复杂但处处都是坑的系统有价值得多。如果你有具体场景想聊的欢迎在评论区说说你现在卡在哪一步是数据处理、模型服务化还是线上监控我们可以就具体环节再展开细聊。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进