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

AI工程实战:从数据清洗到模型部署的完整链路

发布时间:2026/9/29 18:59:05

资讯中心
01
ARTICLE

AI工程实战:从数据清洗到模型部署的完整链路

AI工程实战:从数据清洗到模型部署的完整链路
写在前面这不是一篇教你数学原理的文章我见过太多人收藏了一堆“从入门到精通”的教程报名了好几个训练营最后却连一个能稳定跑起来的AI项目都拿不出来。原因不是他们笨而是大多数教程都在讲模型内部怎么工作很少有人讲“AI工程”本身该怎么落地。我说的AI工程不是调一次API、跑通一段notebook而是从数据准备、模型选型、微调实验、评估上线到日常维护的完整链路。这个项目的名字很长——ai-engineering-from-scratch翻译过来就是“从零开始搞AI工程”。它是我自己维护的一套实战笔记和代码骨架目标很简单让一个只有基础Python能力的人也能按步骤搭出一套可运行、可迭代、可评估的AI系统而不是停留在“跑通demo就结束”的阶段。如果你是从传统软件开发转过来或者已经在用大模型API、但想往前再走一步这篇文章会非常适合你。下面我会把这条链路里的关键节点、我踩过的坑、以及我认为最值得投入的方向按实战顺序完整讲一遍。1. 为什么想写“ai-engineering-from-scratch”这个项目1.1 网络上教程的断层大家都在讲架构没人讲搬砖你随便搜一下“大模型入门”出来的内容基本都是Transformer结构、注意力机制、损失函数推导。这些东西重不重要重要。但对于一个想真正动手做项目的人来说它们不是第一步。真正的第一步是什么是拿到一台干净的机器把Python环境装好把模型权重下载下来把一份训练数据整理成模型能吃的格式然后跑通一个最小的训练流程。这个过程看起来一点不“高级”但它决定了你后面所有工作能不能顺利进行。我见过不少朋友在Kaggle或GitHub上找到一个不错的项目兴奋地clone下来结果卡在环境依赖上两天最后不了了之。教程断层就在这里——几乎没有人认真讲“如何让一个AI项目可复现、可维护”而这恰恰是工程的核心。1.2 AI工程和传统软件工程最本质的区别不确定性管理我在写这个项目之前有将近十年的后端开发经验。传统软件工程里代码行为是确定的输入A走完逻辑输出B。你可以写单元测试可以精确控制流程。AI系统完全不是这样。同一个Prompt同一个模型温度调到0它偶尔还会给你不同的答案。数据一更新模型精度可能突然掉了几个点。上周测得好好的功能这周用户反馈变了个说法效果立刻变差。所以AI工程的核心不是“实现功能”而是“管理不确定性”。我们要做的所有工作——数据版本化、评估集设计、灰度发布、监控告警——本质上都是在把不可控的因素逐步关进笼子里。这是我写这个项目时最重要的一条主线想明白了这一点后面每一步你都知道自己为什么要做。1.3 这个项目到底适合谁来学先说结论适合三类人。第一类是从传统开发转过来的工程师。你已经具备代码能力缺的是AI工程里数据怎么管、模型怎么选、部署形态怎么定这些“非模型知识”。第二类是在用API但想深入一步的产品或自学爱好者。你已经知道Prompt怎么写但还想搞清楚微调是怎么一回事、什么时候该微调、什么时候不该微调。第三类是刚入行的学生学校教了理论但你需要一个可落地的最小闭环来建立体感。不适合谁呢如果你想从零推导数学公式那出门左转去看论文。我这里只讲怎么把东西做出来、怎么让它稳定跑下去不搞学术。2. 环境与基建先让项目达到“克隆即运行”2.1 为什么我放弃conda和pip选了uv做环境管理先说一个现实问题Python环境管理是AI项目里最烦人的事情之一。早期我习惯用conda但conda装包慢、环境大而且依赖解析经常撞车。后来项目多了我彻底转到了uv这套工具上。uv是一个用Rust写的Python包管理器兼容pip和requirements.txt但速度快得多。实测下来一个常见的transformers环境uv安装速度能比pip快五到十倍锁文件清晰还能自动管理Python版本。最关键的是它支持pyproject.toml——项目依赖写在声明文件里任何人clone下来后只需要两条命令uv sync uv run python scripts/train_lora.py这基本实现了“克隆即运行”。我强烈建议所有新项目都从uv init开始而不是继续手工维护那份容易过期的requirements.txt。提示如果是在国内网络环境下安装uv可以用cargo install uv或者直接下载发布包速度都还不错。Python官方源如果太慢记得把pip或者uv的index换到国内镜像这点后面很多操作都会受益。2.2 一个最小AI项目骨架长什么样很多初学者拿到一个AI项目后第一反应是“代码在哪个文件”。但工程化之后项目结构比代码本身更能决定你的效率。我现在的标准骨架大致是这样的ai-engineering-from-scratch/ ├── pyproject.toml ├── Makefile ├── src/ │ └── app/ │ ├── data/ │ │ ├── load.py │ │ ├── clean.py │ │ └── versions.py │ ├── model/ │ │ ├── infer.py │ │ └── train_lora.py │ └── eval/ │ └── run_eval.py ├── scripts/ │ ├── download_weights.sh │ └── run_web.sh ├── tests/ │ ├── test_data.py │ └── test_infer.py ├── data/ │ ├── raw/ │ ├── processed/ │ └── versions/ └── artifacts/ ├── checkpoints/ └── eval_results/几个关键模块我解释一下。pyproject.toml是项目声明的核心依赖、元数据、运行命令统统记在里面。Makefile则是给“记不住命令的人”准备的入口。比如我会把常用操作写成BIN : uv run train: $(BIN) python scripts/train_lora.py eval: $(BIN) python scripts/run_eval.py serve: $(BIN) python -m app.web.server这样你不需要记住去哪看命令行只用make train、make eval就完事了。data/raw和data/processed分开存放很重要——原始数据永不改动任何清洗都生成新文件放到processed。这个习惯让我避免了很多“数据被覆盖后追不回来”的悲剧。2.3 模型权重下载Hugging Face CLI与镜像加速环境搞定后第一步就是下载底座模型。很多人卡在Hugging Face下载太慢其实解法很简单只用一行环境变量切到镜像站点。export HF_ENDPOINThttps://hf-mirror.com然后命令行登录一次huggingface-cli login输入你的Access Token即可。有些模型比如Llama系列需要先接受使用许可用CLI下载时如果遇到401或403先去Hugging Face官网的模型页面点击同意协议再回来重试。之后下载权重就非常直接了huggingface-cli download Qwen/Qwen2.5-7B-Instruct --local-dir models/Qwen2.5-7B-Instruct提示--local-dir而不是--cache-dir的好处是权重文件会以一个清晰明了的目录结构存在项目的models/下不会被Hugging Face默认的缓存目录打散成一堆哈希文件夹。做工程目录可读性比省几GB磁盘重要得多。2.4 实验追踪为什么用MLflow而不是TensorBoard刚开始做微调实验的时候我只是把loss打到终端日志里结果第二天就忘了哪个参数组跑出了最好的结果。后来换成了MLflow做实验追踪。选择MLflow而不是TensorBoard最大理由是它的Tracking模块能同时记录参数、指标和产物而且支持本地方案不依赖云服务。我用一个最简单的初始化就能开跑import mlflow mlflow.set_experiment(qwen2.5-sft-v1) with mlflow.start_run(): mlflow.log_param(lora_r, 16) mlflow.log_param(lora_alpha, 32) mlflow.log_param(learning_rate, 2e-4) mlflow.log_metric(eval_f1, 0.83) mlflow.log_artifact(artifacts/checkpoints/best_model, artifact_pathcheckpoints)记录完之后浏览器打开http://localhost:5000就能看到每次实验的参数和指标对比。这一步看起来简单但长期价值非常大——你以后做模型迭代时能一眼看出上一次成功的配置是什么不用再靠猜。3. 数据工程真正的护城河3.1 为什么数据工程要放在模型前面微调过模型的人都知道一个体会模型效果不好90%的情况不是模型不强而是数据不行。脏数据、不均衡数据、错误标注这些问题会直接反映到最终行为上。你想靠调参挽回数据问题基本是徒劳。所以我写这个项目时把数据工程放到了所有模型操作的优先级前三位。这不是说模型不重要而是模型已经是公开的商品化的能力你对效果的控制权其实绝大部分来自数据。3.2 数据清洗的具体规则我用的清洗流程大概分为五步每一步都很朴素但不做不行。去重用text的哈希值做主键去掉完全重复的样本再用模糊相似度例如rapidfuzz的token set ratio去掉语义重复的样本阈值一般定在85分以上。去污染如果样本里包含改写过的Prompt痕迹、或者候选答案本身就是从某大模型生成的这类数据对微调有潜在风险。我一般会做一个规则过滤去掉含有“作为AI助手”“我不能帮助”这类标志性短语的样本。去除低质量内容按长度过滤过短样本去掉过长样本截断到目标上下文长度的1.5倍再保留。统一编码为UTF-8去掉不可见字符和控制符号。个人信息脱敏手机号、邮箱、身份证号这类信息用正则替换成占位符别指望模型为你保密训练数据里不应出现真实隐私信息。最后人工抽检清洗完后随机抽100条人工过目确认过滤规则没有误伤正常数据。这个抽检比例不高但能拦住八成规则拍脑袋写错的情况。3.3 标注策略先用弱监督再用人工校验做监督微调SFT必须要标签但AI项目里数据量大、标注成本高是永远的痛点。我的策略是“弱监督规则标注 人工抽样校验”。比如做一个客服意图分类的数据集我先写一批简单规则def weak_label(text: str) - str: if any(kw in text for kw in [退货, 退款, 换货]): return after_sales if any(kw in text for kw in [密码, 登录, 账号]): return account_issue if 多少钱 in text or 价格 in text: return price_query return other先用这类规则给大量未标注数据打粗标签然后人工抽300条做准确率评估。如果某个类别准确率低于80%我就加规则或人工重标那一类。这样能花比较少的钱得到一份质量可控的训练集。注意弱监督规则不能只标“对”的样本。很多新手会忽略“负样本”和“拒答样本”比如用户表达感谢、闲聊时应该引导模型给出恰当回应而不是硬塞到业务分类里。训练数据里如果没有这类样本模型上线后很容易把无关对话也强行归类。3.4 数据版本化别再用文件名记版本了刚开始做项目时我处理数据的习惯是train_v2.csv、train_final_final.csv后来自己都分不清哪个是哪个。现在我用一套非常轻量的版本化方案。核心思路是每次生成新数据集时同时生成一份dataset_card.json记录来源、清洗规则、样本数、时间戳和hash值。{ name: helpdesk_intent_v3, source: customer_logs_20250201, clean_rules: [dedup, personally_identifiable_information_masking, length_filter_8_1024], num_samples: 12580, created_at: 2025-02-05T10:00:00Z, sha256: a3f2c8e1b9... }真正训练的时候直接在配置里写数据集版本的路径模型训练完也把对应的dataset_card.json记录到实验追踪系统里。这样任何一个效果变差的问题都能反过来追溯是数据变了还是模型变了还是代码变了。这一招在后续迭代里帮了我大忙。4. 模型选型与微调用决策树代替盲目试错4.1 先算账再选模型很多人选模型只看排行榜谁分高用谁。但工程必须看约束条件。我的选型计算从三件事开始显存、延迟、许可证。显存估算有个非常实用的公式加载FP16格式的模型大约需要参数量 × 2字节。一个7B模型大概需要14GB显存才能跑推理13B需要26GB34B需要68GB。如果做推理服务还需要加上KV Cache实际占用量会比这个基础值再高一些。我做了一张常用的估算表供参考模型规模参数量FP16推理显存估算微调建议7B/8B约70~80亿14~16GB单张24GB卡可跑QLoRA13B/14B约130~140亿26~28GB单张48GB卡或双卡分布式34B/72B340亿以上68GB以上多卡或托管API然后算延迟。同样一个请求7B模型在单张A10上大约几十毫秒到几百毫秒72B模型即使有A100延迟也可能翻几倍。你的业务场景如果要求首字延迟低于200毫秒那72B可能一开始就不该进候选名单。最后看许可证。不同模型的商用条款差异很大比如部分模型仅限研究使用部分允许商用但要求履行额外披露义务。选型之前把许可证条款和法务过一遍别等上线了再发现不能用。4.2 Base模型与Chat模型的差别Hugging Face上同一个系列通常会出两种版本Base版和Instruct/Chat版。新手经常搞混是不是微调就应该从Base开始我的建议是绝大多数业务场景直接用Chat/Instruct版继续做LoRA不要从Base重新训。原因很简单。Chat版在发布前就已经做过大规模的监督微调和偏好对齐它知道怎么回答问题、怎么拒绝不合适的请求。你的领域任务是在这个良好基础上做“风格和内容迁移”而不是从零教它说话。从Base开始意味着你得自己准备大量通用对话数据成本极高而且很容易训出“能说领域话、但整体对话能力下降”的模型。4.3 LoRA实操一套能直接抄的配置选完底座微调本身我建议从LoRA入手不要上来就全参数微调。LoRA的优势是显存占用低、训练快、一个底座可以同时挂多个任务适配器切换部署非常方便。我更进一步的实践是直接用QLoRA把底座量化到4bit再挂LoRA适配器一张24GB的卡就能训7B模型。参考配置model_name: Qwen/Qwen2.5-7B-Instruct lora_r: 16 lora_alpha: 32 target_modules: - q_proj - k_proj - v_proj - o_proj - gate_proj - up_proj - down_proj lr: 2e-4 batch_size: 4 gradient_accumulation_steps: 4 num_epochs: 1 warmup_ratio: 0.03 max_seq_len: 1024这些参数的相对关系比绝对值重要。lora_alpha一般设成lora_r的2倍学习率在1e-4到5e-4之间比较稳。训练一个epoch就够了SFT阶段真不需要多轮训练轮数多了模型很容易在训练集上过拟合导致通用能力下降。训练时我还会固定住一个关键开关use_chat_template必须开启。Chat模型的训练数据要按它的对话角色格式组织如果丢给模型一段裸文本它会非常困惑。数据格式大致是|im_start|user 如何查询我的订单状态|im_end| |im_start|assistant 您好请提供您的订单号我帮您查看。|im_end|每一行都要严格走这个模板。用transformers自带的apply_chat_template方法生成千万别手写拼接手写必错。5. 评估体系别让“感觉变聪明了”骗了你5.1 为什么训练loss下降不代表效果变好这个问题我踩过很大的坑。有一次我微调完一个模型训练loss从2.1降到了0.8当时觉得稳了。结果一上测试集意图识别的准确率反而掉了3个百分点。原因后来分析清楚了loss下降只能说明模型在训练数据上的拟合度提高不代表它学会了“泛化”。尤其是生成任务里模型经常会把答案背下来而不是理解规律。所以评估必须用独立于训练集的、贴近真实分布的评测集绝不能只看训练曲线。5.2 离线评估Golden Set怎么设计我的做法是维护一个“黄金评测集”目标是覆盖真实业务中最重要的场景和已知的模型弱点。这个评测集不大通常几百到一千条但每条都经过人工复核标注。设计Golden Set时我坚持三条原则。第一贴近真实分布。用线上日志样本的抽样和标注结果做了100多条真实用户问题其余再手工补充边界情况。不要用模型自己生成的数据评估自己那会高估效果。第二包含已知弱点。比如我发现模型经常把“改地址”的意图误判成“物流查询”就往评测集里专门加一批这类难样本防止以后迭代时这类问题悄悄复发。第三定期更新。每次上线的新功能、每收到一批典型badcase都要补充进评测集。Golden Set需要跟着业务长不是做一次就放那吃灰。对于生成任务我倾向用“规则化指标 关键要素匹配”。例如客服回答质量我预先定义3到5个必须覆盖的要素订单号、解决方案、致歉检查模型输出是否包含这些要素。这种方法比直接让大模型打分更稳定也更容易定位问题。5.3 在线评估和灰度发布离线评估过完线上依然要有护栏。不要让你的模型一上线就面对100%流量。我第一次上线时直接全量切过去结果半天后收到用户投诉“回答像换了一个人”。虽然离线指标都是好的但线上用户有些固定表达方式Golden Set没有覆盖到。从此以后我坚持灰度流程先切5%流量观察一小时没有明显异常报错率、用户差评率再逐步扩大到30%、100%。同时把每一次线上应答日志回流到数据池作为下一轮微调的数据来源。这个循环一旦跑起来你的系统就像有了“自我进化”的能力每个月的效果都会往上走。6. 从实验到生产部署形态、失效边界与成本权衡6.1 三种部署形态各有什么代价模型训好了部署方式的选择会直接影响体验和账单。我见过团队把一个7B模型用CPU服务结果单次推理响应时间冲到几十秒用户自然留不住。部署不能拿“能跑”当唯一标准必须在延迟、成本、数据隐私这几个维度之间做权衡。我整理了三种常见形态供对照部署方式优点缺点适合场景托管API如OpenAI、国内大模型API上手最快效果强无需GPU管理单次调用费累积快数据要出域定制能力弱快速验证、并发低、数据不敏感自托管开源模型vLLM/TGI推理成本可控数据不出域可挂LoRA适配器需要GPU机器运维复杂度高有稳定流量、需要定制模型CPU/边缘小模型成本极低、无GPU依赖延迟高能力有限内部工具、离线批处理、强环境约束场景如果你的业务已经过了验证期我通常建议走“自托管适配器”的路线。GPU用按需租用单张A10或L20起步先把吞吐指标跑出来再决定要不要长期包机。6.2 失效边界设计超时、重试、缓存、降级模型服务和普通API不一样它不是每次都能给出正确格式。你的工程一定要预设“如果模型罢工了系统怎么兜底”。超时首字返回超过10秒直接断开重新走降级逻辑。不要无限等待那会拖垮整个调用链路。重试重试策略要有上限而且要在指数退避基础上加随机抖动避免重试风暴。对生成任务相同输入重试结果可能不同所以重试时可以考虑把温度调低提高稳定输出的概率。缓存对高频且可复现的查询做结果缓存。比如“客服入口在哪”“退货政策是什么”这类问题的答案基本固定直接打缓存能省大量推理资源。我用Redis做LRU缓存缓存命中率一度超过30%等于白赚了三分之一的机器预算。降级当模型服务异常、或结果无法通过校验时回退到模板话术或人工介入。你要的不是“永远不失败”而是“失败了用户也不至于滞留”。另外解析模型输出时不要只祈盼JSON格式完美。真实场景里大模型给出的JSON基本都会掺杂多余文本、换行或注释符。不要无脑重试而是要写一个鲁棒解析函数先用正则抽取最外层的{...}再做二次解析失败后才进入重试流程。6.3 成本账单一次真实的估算很多读者会问自托管模型到底要花多少钱我按一个小场景算给你看。假设你有10个并发用户每个用户平均每天20次请求每次请求约300个输入token、200个输出token。用7B模型自托管单张A10 24GB显卡大概能把吞吐跑到10~20请求/秒足够覆盖这种并发需求。按租用价每小时10元来算全天跑满也就240元一天。托管API按每百万token大约5元的价格同样请求量一天可能要花50到80元。看起来API更便宜别忘了还有调用频率上去了、数据出域、以及无法使用自定义LoRA的隐性成本。如果每天请求量再翻十倍托管API的费用会线性增长而自托管只要把显卡从1张加到3张单位成本反而下降。这就是为什么流量稳定后我普遍建议迁移到自托管的原因固定成本你付得起边际成本你压得下。6.4 监控和维护模型上线只是开始模型上线后维护工作其实比训练更多。我每天会看四类监控指标延迟分位数P50/P95关注长尾而不是平均、输入分布漂移用户的话术模式突变要及时识别、结果拒绝率格式解析失败的占比上升说明模型行为在漂移、以及用户反馈信号点赞、点踩、人工介入率。这些指标一旦触发阈值我不会直接盲目重训模型而是先回看对应的badcase确认是不是数据分布变了。如果是把最近的新样本补充进Golden Set先线上微调规则或Prompt缓解攒够一批数据后再做下一轮LoRA微调。这整套“监控→回流→重训→灰度”的循环才是一个AI系统真正可持续的形态。提示内容安全过滤不要放在模型之后才做最好在请求进来时、模型输出后都做一遍关键词和分类器检查。这是底线工程宁可误伤不可漏过。最后再分享一个我个人的习惯这个项目做到现在我最深的体会是AI工程最大的敌人不是“模型效果不够好”而是“你搞不清楚哪儿出了问题”。数据版本化、实验追踪、Golden Set、灰度发布这套流程看起来不酷但它们才是让AI项目从“能用”走向“可信赖”的真正杠杆。如果你刚准备起步我建议你从一份真实的数据集开始先把“数据清洗→微调→评估→部署”的最小闭环跑通不要一开始就追求72B大模型和复杂分布式训练。先把小模型的全链路摸透再慢慢往上加规模。这条路我已经替你们踩过一遍了按这个顺序走你能少绕很多弯路。
02
RELATED NEWS

相关资讯

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

03
WHY YAOTU

想打造同款高转化官网?

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

◈

场景化定制

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

◐

营销型架构

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

▲

全周期服务

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

免费获取你的建站方案

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