尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

从零构建AI工程:数据、部署、监控与成本控制全指南

发布时间:2026/9/30 0:12:31

资讯中心
01
ARTICLE

从零构建AI工程:数据、部署、监控与成本控制全指南

从零构建AI工程:数据、部署、监控与成本控制全指南
1. 先想清楚什么是 AI 工程别急着写代码我见过太多人把AI 工程和AI 编程划等号。学了几个框架跑通了一个开源模型就觉得已经入了门。结果一到真实业务里连第一个需求都扛不住——模型在笔记本上跑得好好的上了服务器就崩离线评测分数很高上线后被业务方喷得体无完肤。问题出在哪出在工程两个字上。AI 工程真正要解决的不是模型怎么训练而是模型怎么稳定地在业务里产生价值。它至少包含三块模型开发、系统接入、持续运营。模型开发只是地基里的第一铲土后面还有数据管线、服务部署、监控告警、成本控制、迭代机制——每一块都得从零开始搭。这个项目叫 ai-engineering-from-scratch我理解它的本意就是不依赖任何现成的 AI 平台不回避底层细节一个人把整套体系从无到有建起来。这一篇我就用自己折腾出来的完整路径来讲中间有不少踩坑后的修正。适合谁看两类人一是刚入行的算法工程师想搞明白模型之外还有什么二是后端开发者想系统性补上 AI 工程能力。无论你是哪一类看完能少走至少三个月的弯路。1.1 AI 工程为什么容易被人低估很多人低估 AI 工程是因为他们看到的只是模型推理这个单点。但在真实项目里模型推理只占整个系统的一小部分。我做过一个内容风控项目最终上线的代码里模型相关部分不到 20%剩下 80% 是特征处理、规则融合、异步任务、缓存策略、人工复审流程、报表统计。这个比例一点也不夸张。你想想一个模型要真正服务业务它得先有干净可靠的数据输入得有稳定的服务框架托底得有阈值策略应对不同置信度得有兜底规则防止模型抽风还得有完整的链路追踪让问题能被定位。每一环都是工程问题。另一个原因是 AI 项目的不确定性比其他软件项目高得多。传统软件开发需求明确后工期估算基本靠谱。AI 项目不是这样——模型效果可能因为数据分布变化突然崩掉第三方依赖可能因为版本升级带来行为变化同一个 prompt 换个标点符号结果就不同。这种不确定性只能用工程手段去对冲灰度发布、A/B 测试、评测回归、持续监控。没有这些项目就是在裸奔。所以我的第一个建议是从零开始做 AI 工程先别急着跑模型先把工程两个字吃透。你接下来做的每一个技术选型、每一段代码组织、每一次部署策略都是在为不确定性上保险。1.2 从零开始需要建立的三个思维我总结了三个最重要的思维方式它们比任何具体技术都关键。第一个是数据思维。模型是数据的浓缩数据质量决定了模型效果的上限。很多新人花大量时间调模型参数却不愿意花时间去看原始数据长什么样。我见过最夸张的例子有人用爬虫抓了 10 万条文本训练分类模型后来发现其中 30% 都是重复的还有 15% 的标签标错了。效果能好吗肯定不能。第二个是评测思维。永远先定义什么叫做好再动手做模型。没有评测标准你就是在茫茫大海里游泳永远不知道方向对不对。我自己的习惯是任何项目开工第一天先写评测脚本和第一批评估样本哪怕用的是最简单的规则。第三个是成本思维。GPU 很贵人工审核很贵数据标注很贵甚至 prompt 里的 token 也是钱。方案设计阶段不考虑成本上线后一定会被现实毒打。有一个项目最开始设计的是 streaming 方式流式返回效果好但 GPU 占用极高后来改成批量异步处理 缓存复用成本直降 70%。有了这三个思维打底下面讲具体的技术路径才有意义。2. 地基怎么打环境、数据、代码三位一体从零开始第一个要解决的就是环境问题。Python 环境依赖、CUDA 版本、不同的框架之间的冲突这些能消耗掉一个新手一整个星期而且毫无成就感。我自己的方案经历了三次迭代最后稳定在用 conda 管环境、用 Docker 管部署的双轨制。2.1 环境管理为什么是 conda Docker 双轨制先说开发环境。我强烈建议用 conda不管是 Miniconda 还是 Anaconda。理由很简单conda 不仅管 Python 包还能管 CUDA、cuDNN 这些底层库。你用 pip 装 PyTorch GPU 版它默认给你装一套 CUDA 运行时但你系统里可能已经有一版 CUDA两套互相之间经常出幺蛾子。conda 能把 CUDA toolkit 和 Python 包放在同一个虚拟环境里互不干扰。我每个项目的环境创建命令大概是这样的conda create -n ai-eng python3.10 conda activate ai-eng conda install cudatoolkit11.8 cudnn8.6 -c conda-forge pip install torch2.0.1这里有个小技巧conda install cudatoolkit和pip install torch分开装。如果你直接用 pip 装 torch它会下拉 NVIDIA 的预编译 CUDA 库虽然也能跑但当你需要编译自定义算子时经常和系统 CUDA 对不上版本。分开装的好处是你能精确控制 CUDA 版本编译不依赖运行时。这个坑我踩过两次浪费了整整一天。再说部署环境。开发环境是 conda部署环境必须 Docker。为什么因为你要保证在我机器上能跑变成在任何机器上都能跑。我写过一份还不能公开的 Dockerfile核心思路是基础镜像用nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04然后创建一个非 root 用户运行服务。这个细节特别重要——很多人在 Docker 里用 root 跑模型服务一旦容器被攻破宿主机就裸奔了。开发环境和部署环境之间的衔接也是一门学问。我的做法是在 requirements.txt 里固定所有直接依赖的版本号用 pip-tools 生成完整的锁定版本然后在 Docker build 里按照锁定版本安装。这样开发环境即使用 conda依赖却是完全一致的。2.2 数据先行数据版本管理和数据质量检查代码有 Git 管版本数据怎么办很多人训练完模型后数据文件散落在各个磁盘路径别人问起你这个模型的训练数据是哪个版本没人说得清。这就是数据版本管理缺失的典型症状。我在项目里试过 DVCData Version Control它能像 Git 管理代码一样管理数据。第一次建模时一个完整的档案在 DVC 里就是这样的流程初始化仓库、把远程存储挂上、把数据添加进去、打 tag。到后面每次数据更新就提交数据变更记录。不过说实话DVC 的体验一般特别是对不熟悉命令行的新人来说门槛略高。后来我换成了一个更务实的方案用文件命名和清单文件组合。数据目录结构长这样data/ ├── raw/ # 原始数据只读永不修改 │ └── 2024-06-01_crawled_posts.json ├── processed/ # 清洗后的数据 │ └── 2024-06-05_news_classification_all.jsonl ├── splits/ # 划分好的训练/验证/测试集 │ ├── 2024-06-05_train.jsonl │ ├── 2024-06-05_dev.jsonl │ └── 2024-06-05_test.jsonl └── manifest.csv # 数据文件清单manifest.csv 里记录每个文件的生成时间、来源、行了、hash 值谁生成了它、用了什么脚本。这样任何时候回溯都能找到一份数据的完整血缘。虽然不是最花哨的方案但它简单可靠。数据质量检查是更关键的一环。我在每个项目的第一周都会写一个data_quality.py脚本跑一遍基础的统计检查重复率、空值率、标签分布、数据来源分布、文本长度分布。这些指标在后续每次训练前都要跑一遍防止数据集在某个环节被无声地污染。2.3 代码结构一个能成长的骨架代码结构直接决定了这个项目能走多远。我见过很多 AI 项目的代码只有一个大 notebook或者一个几百行的 main.py里面什么都有数据加载、模型定义、训练循环、评测、可视化。这种代码在第 1 个迭代还能用到第 10 个迭代就是灾难。我的标准结构是这样划分的ai-engineering-from-scratch/ ├── configs/ # 所有配置YAML 格式 │ ├── data.yaml │ ├── model.yaml │ └── train.yaml ├── data/ # 数据目录见上一节 ├── src/ # 核心代码 │ ├── data/ # 数据处理相关 │ │ ├── loader.py │ │ ├── preprocess.py │ │ └── quality_check.py │ ├── models/ # 模型架构定义 │ │ └── classifier.py │ ├── train/ # 训练相关 │ │ ├── trainer.py │ │ ├── loss.py │ │ └── optimizer.py │ ├── evaluate/ # 评测相关 │ │ └── metrics.py │ └── serving/ # 服务相关 │ ├── api.py │ └── inference.py ├── scripts/ # 入口脚本尽量薄 │ ├── run_train.py │ ├── run_evaluate.py │ └── run_serve.py ├── tests/ # 单元测试别偷懒 ├── notebooks/ # 探索性分析不参与主流程 └── pyproject.toml这个结构最核心的原则是配置与代码分离、入口脚本保持薄、每个模块只做一件事。我见过太多人把超参写死在代码里每次调参都要改代码重启改着改着就忘了基准版本用的什么参数。配置文件 实验记录可以完美解决这个问题。讲句不好听的代码结构这件事大多数教程都不会认真教你但它在真实项目里比模型结构重要得多。我现在的习惯是项目开工第一天就把骨架搭好哪怕是一个空壳先架起来再往里面填。3. 第一个实战从文案质检到多标签分类地基打完了该上真家伙了。我拿自己做过的电商文案质量评估项目作为示例完整走一遍从零到一的流程。这个任务的背景是电商平台上每天产生大量商品描述文案运营团队需要从中找出低质量、可能误导用户的文案进行整改。以前靠人工抽查一天只能看 200 条漏检率极高。这个任务天然的边界是需求听起来很模糊——什么是低质量文案不把这个定义清晰化后面所有工作都没法展开。3.1 把模糊需求拆成可量化的任务定义我和运营团队开了一次需求对齐会把他们平时审核文案时关注的点全部列出来归纳出了五个维度虚假宣传使用了顶级最好100%有效等绝对化用语信息缺失缺少规格参数、材质、产地等关键属性词不达意文案与商品实际不符比如明明是食品却写帮助提升工作效率语病错别字存在明显语法错误或错别字违规导流包含微信、QQ 等联系方式或外链引导。每个维度的判定标准写成了带正反例的文档然后让运营团队一份一份地标注。这样任务从判断文案是否低质变成了对文案做五个维度的多标签分类。多标签和单标签有个重要区别——一个文案可以同时命中多个问题所以最终输出是五个维度的概率分布而不是单一标签。这一步是整个项目最重要的决策。如果你把模糊需求直接丢给模型帮我判断文案好还是不好模型的输出你没法解释运营团队也不敢信。拆解成维度后模型的每个输出都有明确含义人机还可以协同——低置信度的案例进人工复审队列高置信度的自动处理。3.2 基线与评估指标先行任务定义清楚后我在动手写任何模型代码之前先定义了两个基线第一个是规则基线。五个维度里违规导流和虚假宣传实际上可以用正则表达式做得很准。导流特征无非是微信、QQ、手机号模式绝对化用语有一份相当完整的词表。我写了一个规则引擎跑了初版数据效果已经不错。这个规则基线的意义在于——如果模型连规则都打不过那它没有上线价值。第二个是简单模型基线。用 TF-IDF 逻辑回归做一轮快速实验不追求最好效果只求建立模型路线的起点。评估指标上五个维度都采用主要看 F1精确率和召回率调和平均的宏平均其中虚假宣传维度单独看精确率因为这个维度误伤运营的信任成本极高。同时因为类别存在不平衡语病错别字远少于其他维度我还记录了每个维度的样本数和各自的 F1。评估集是用一周的运营标注结果构建的一共 1500 条1000 条训练、250 条验证、250 条测试。在还没开始深度学习之前我已经能回答这个模型算不算好这个问题。3.3 快速构建和验证流程规则基线效果非常好违规导流F1 达到 0.94虚假宣传达到 0.90总耗时不到一个下午。TF-IDF 逻辑回归的总 F1 是 0.78明显不如规则。这时候团队里有人提议那直接用规则算了别搞模型了。我没有同意。原因是规则的覆盖面有天花板新话术、变种写法、复杂的语句结构规则都没办法泛化。但我也没有说规则没用——最终方案是混排规则层把确定性能处理掉的案例直接处理掉剩下的模糊案例交给模型判断。接着上深度学习模型。当时试了三个方案TextCNN轻量快速、BERT base 微调、以及后来很流行的向量嵌入加分类头方案。预实验结果显示BERT base 微调的总 F1 达到了 0.86比逻辑回归高 8 个点其中词不达意维度提升了 15 个百分点。其实到这一步我已经积累了一套可以复用的公式先规则快速兜底再用模型提升泛化最后接人工复核流程。很多 AI 项目翻车是因为要么只做规则太死板要么只做模型不收约束。这里再补充一个实际经验微调 BERT 时千万要固定随机种子并且跑两到三次取平均。因为 BERT 的微调过程对随机性相当敏感好几次实验结果差异只来自随机种子不同却差点让我误判两个超参的性能优劣。4. 把模型放进真实业务链路中的关键细节模型在离线评测里拿到了 F1 0.86 的成绩是不是就可以上线了差得远。从离线跑得好到线上用得稳中间还要穿过一整片丛林。这一节讲我认为最容易被忽视的四个技术细节。4.1 服务层选型FastAPI 真够用别过度设计我用 FastAPI不用 Flask也不上 LangChain 之类的重型框架。理由很直接FastAPI 自带 OpenAPI 文档、输入输出校验、异步支持对模型服务这种 IO 密集型场景正好合适。Flask 的同步 WSGI 在模型推理时容易被阻塞撑不住并发请求。模型服务的核心代码比很多人想得要薄# serving/api.py核心结构示意 from fastapi import FastAPI from pydantic import BaseModel, Field class EvalRequest(BaseModel): text: str Field(..., min_length1, max_length2000) dimensions: list[str] [misleading, missing_info, irrelevant, typo, diversion] class EvalResponse(BaseModel): results: dict[str, float] rule_hit: dict[str, bool] model_used: str app FastAPI(titleTextQualityEval) app.post(/v1/evaluate, response_modelEvalResponse) async def evaluate(req: EvalRequest): # 1. 先跑规则层 rule_result rule_engine.check(req.text) # 2. 规则未覆盖的维度送进模型 model_dims [d for d in req.dimensions if d not in rule_result or rule_result[d] is None] model_result {} if model_dims: model_result model_service.predict(req.text, model_dims) # 3. 合并结果返回带解释的数据结构 return compose_response(rule_result, model_result)这个规则先行、模型兜底的接口设计带来的好处是响应时间大幅下降——约 35% 的请求根本不会走到模型层规则在十几毫秒内就返回了。只有当规则不能确定时才进入模型推理平均延迟从 800ms 降到了 500ms 左右。响应结构里我刻意把rule_hit和model_used都传回去这是为了方便排查问题——当你怀疑线上结果不对时能直接看出到底是规则的功劳还是模型的判断而不是两眼一抹黑。4.2 上下文管理与结构化输出稳定性的基本盘这一小节看起来基础但却是线上踩坑最多的一环。先说上下文管理。如果你的应用是对话式、多轮式的场景上下文长度是一个必须仔细管理的东西。很多真实故障都源于上下文无限累积用户每轮都带完整历史进去token 数很快飙升然后触发长度限制或者直接报错。我的做法是固定窗口大小并且有一个定点清理机制比如最多保留最近 8 轮对话超过的自动截断每条内容按时间衰减权重权重低于阈值的先裁剪必要时用摘要模型把旧文压缩成 100 字以内的提要再添回去。这一步起码能省 40% 的 token还不影响关键信息。再说结构化输出。模型直接输出自由文本解析起来非常痛苦prompt 里写了用 JSON 返回还是经常输出 Markdown 代码块或者多了一个逗号的 JSON。我的兜底方案是两步走第一步prompt 里明确输出格式并且附上一个极其简单的示例。不做复杂系统提示词越简单越不容易出幺蛾子。第二步解析时用先抽提取 JSON 段落、再校验、最后再修的思路。直接用json.loads会是脆弱的高危操作很容易被一个注释或尾随逗号搞崩。那些看起来像 JSON 但又不严格是的内容我会写一个小的清洗函数。如果业务上对输出的合法性和稳定性要求特别高建议采用 constrained decoding 或者用函数调用机制来约束输出内容而不是靠 prompt 碰运气。4.3 监控、灰度与回滚模型上线是一场手术模型上线最忌讳的是一把梭。我的标准动作是先拉一个影子环境把线上真实流量同时发给旧模型和新模型新模型的输出只在日志里记录、不真正生效对比一段时间后让新模型接管 5% 的流量没有异常再逐步提升到 50%、100%。整个过程建议用配置中心控制不改代码、不重新发版。监控指标我通常分三层系统层响应时间、请求量、GPU 利用率、显存占用模型层预测置信度分布、规则命中率、模型拒绝率业务层用户反馈率、平均处理时长、复审率变化。业务层指标最容易被忽略但却是最重要的——它直接反映模型对业务目标有没有帮助。我见过太多 AI 项目上线后系统层指标一切正常业务指标却不降反升就是因为没有监控业务层。回滚机制方面有一套设计的核心是旧模型不能删。我一般会保留最近两个版本的服务镜像在配置中心切一个开关就能回到旧版本。如果新模型线上效果严重翻车回滚应该在 5 分钟内完成而不是花两小时重新部署。5. 从能跑到好用的分水岭评测、迭代与成本模型上了线只是万里长征走完了前半程。后面真正考验工程能力的是持续迭代阶段。这一节讲三个分水岭问题。5.1 评测集不能一劳永逸我见过不少团队一个测试集用了一年模型迭代了好几版所有版本都在同一个测试集上刷分。这带来的问题是灾难性的模型过拟合测试集分数虚高真实场景效果却越来越差。测试集本身也会过期——业务的数据分布一直在变化新的文案类型、新的违规手段旧测试集根本覆盖不到。我迭代评测集的方法是月度重建测试集 滚动补充案例库。每次新模型上线后从线上请求中随机抽取样本加入测试集这个样本要保留真实的业务 label。人工审核流里发现的模型误判案例也定期回流成测试样本。这样测试集数量持续增长覆盖范围越来越接近真实分布。这里还有一个细节评测集必须和训练集严格互斥。如果有人误把训练数据混进测试集评测结果就会严重失真。我在数据管线里加了 hash 级别的去重检查从源头堵住这个隐患。5.2 迭代离线和上线之间的差距如何弥合每次模型迭代光看离线 F1 涨了多少没有意义。我坚持在离线评测之外加一组合格性冒烟测试把最近两周线上真实请求样本灌进新模型看输出有没有异常值、会不会崩溃、延迟能不能接受。然后重点来了对比新旧模型在线上同一样本上的输出差异。我把这种对比行为称为差异分析——如果新模型和旧模型在 90% 的样本上输出完全一致那说明这次迭代没有实质变化不值得上线如果差异集中在某几类样本上那就得仔细看这些差异是好是坏。有时候新模型 F1 更高但高出来的收益只集中在 20% 的样本上另外 80% 的输出其实跟旧模型差不多。这种局部优势是否值得承担整体风险需要业务方一起判断。5.3 成本控制AI 工程的隐性考核指标最后聊成本但它可能是整个项目存亡的关键因素。还是以文案质量评估为例。BERT base 微调模型的单次推理成本大约是每 1000 条 0.15 元按当时算力价格估算。平台上每天产生约 10 万条新文案光推理成本一天就是 15 元一个月 450 元左右。确实不算多。但如果你把这个模型换成 GPT-4 API每 1000 条可能要几十块钱一个月下来可能几万块。同一个任务成本可以差三个数量级。我的成本优化三板斧是规则前置过滤便宜的先上、模型蒸馏大模型教小模型小模型上线、动态降级高峰期走高质量模型低峰期或非关键链路用轻量模型。还有 token 级优化压缩 prompt 长度、用缓存复用历史计算的结果、批量推理减少重复加载。我算过一个长文本任务把 prompt 模板精简掉无用的背景说明后token 量减少一半成本直接跟着降一半效果几乎不受影响。在 AI 工程里抠 token 就是抠成本而且是纯利。6. 我踩过的几个大坑以及最后的建议写了这么多技术细节最后想快速说说踩坑记录都是一些看起来不起眼、但就能耗掉你一整天的问题。第一个坑Python 依赖冲突。有个周五我升级了一个数据预处理库的小版本结果把 numpy 的版本也一起升级了然后模型推理出现过一次难以解释的错误。查了半天才发现是 numpy 的兼容性问题。从那以后我养成了两个习惯依赖全部锁定精确版本、升级任何库之前先看它的依赖树影响。这也回到了第二节讲的环境管理。第二个坑GPU 显存泄漏。上线初期服务跑一个周末显存就被占满服务直接 OOM 挂掉。排查半天发现是推理代码里有个 Python list 在循环中不断追加张量历史结果一直没释放。后来专门做了显存追踪把每次推理前后的显存差值打日志才定位到问题。这个教训告诉我线上服务一定要有显存监控告警不能等服务自己崩了才反应。第三个坑回滚机制没有前置验证。曾经出现过一次模型上线后效果不达标需要回滚结果因为旧镜像的配置文件过旧回滚后反而起不来服务。那次事故之后我把回滚演练列入了上线 checklist——每次新版本发布前先在测试环境演练一遍回滚流程确保 5 分钟内能切回任意旧版本。另外一个很容易被忽略的点prompt 里的标点符号和措辞风格对模型稳定性影响比想象中要大。在同样的任务上一个用句号、一个用感叹号的 prompt产出质量差异可能达到 5% 以上。这个差异在评测集上不容易看出来但在线上真实流量里会被放大。所以 prompt 一旦定稿就要做版本管理不要随意改动措辞。回看从零搭建 AI 工程的整个过程最深的一个体会是AI 项目的成功率不取决于你用了多强的模型而取决于你把多少精力花在模型之外的事情上。数据质量、任务定义、评测体系、服务稳定性、成本控制每一件看起来都不那么性感但它们才是项目能落地、能持续产生价值的真正支撑。我在实际项目里摸索出来的这套方法不敢说放之四海皆准但至少从一个零基础的状态走到现在被证明是走得通的。希望这篇长文能帮你跳过那些我已经替你们踩过的坑。如果只能记住一句话那就是先定义清楚问题和评估标准再动手写代码最后才轮到模型。别反着来。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。