从零搭建AI工程能力:为什么我劝你别一上来就调包
发布时间:2026/9/29 19:31:06来源:尧图网络
1. 从零搭建AI工程能力为什么我劝你别一上来就调包这两年“AI工程”这个词被说得太多了多到有点变味。招聘JD上写着“熟悉AI工程化落地”培训班广告里喊着“三个月转型AI工程师”打开技术社区满屏都是“大模型应用开发实战”。但真到了要自己动手做一个能跑起来、能上线、能维护的AI项目时很多人会发现自己卡在一个很尴尬的位置模型原理大概懂一点调包也能跑通demo可一旦要处理真实数据、要控制成本、要保证服务稳定就完全不知道从哪下手了。ai-engineering-from-scratch这个标题说的就是从零开始建立AI工程能力这件事。它不是教你推导反向传播公式也不是带你刷Kaggle排行榜而是解决一个更实际的问题当你手里有一个AI相关的需求时怎么把它从“能跑通”变成“能交付”。适合谁看我觉得有三类人最需要一是刚转行做AI应用开发、还在靠复制粘贴代码过日子的新手二是有算法背景但没怎么碰过工程化的同学三是做传统软件开发、现在被要求接手AI模块的老手。这三类人的痛点不一样但缺的东西是共通的——一套从环境搭建到上线运维的完整工程思维。我自己在这个领域摸爬滚打了几年踩过的坑比写过的代码还多。最开始我也觉得AI工程不就是调个API、跑个推理嘛能有多难。后来才发现真正难的不是模型本身而是围绕模型的那一整套工程体系。这篇文章我会把从零搭建AI工程能力的完整路径拆开讲包括整体设计思路、核心环节的实操要点、完整的落地流程以及我在实际项目中遇到过的典型问题和排查方法。内容会比较长但都是实打实的经验不是那种看完就忘的科普。2. 整体设计与思路拆解AI工程到底在工程什么2.1 先搞清楚AI工程和算法研究的边界很多人对AI工程的误解是把“训模型”当成了核心工作。实际上在绝大多数实际项目里训练模型只占整个工作量的很小一部分。我做过一个粗略的统计一个完整的AI应用项目数据准备和清洗大概占40%的时间工程架构和接口开发占25%模型选型和微调占20%剩下的15%是部署、监控和迭代。这个比例因项目而异但大方向是没错的——AI工程的重心在“工程”两个字上不在“AI”上。算法研究关心的是模型在benchmark上的指标能不能再高一个点AI工程关心的是这个模型在真实流量下延迟能不能控制在200毫秒以内、成本能不能压到每千次调用五毛钱以下、出错了能不能自动降级。这两个方向的评价标准完全不同。我见过不少算法很强的同学转做工程时特别不适应因为他们习惯了用准确率说话但工程场景下“准确率”只是众多指标中的一个甚至不是最重要的那个。所以从零开始搭建AI工程能力第一步要调整的就是心态不要追求用最先进的模型要用最合适的方案。一个7B参数的小模型经过好的工程优化在特定场景下完全可能比一个70B的大模型表现更好因为前者延迟低、成本低、可控性强。这个判断在真实项目中反复被验证。2.2 技术选型的核心原则从场景倒推不从技术正推技术选型是AI工程里最容易走弯路的环节。我见过太多项目一上来就说“我们要用最新的那个模型”“我们要上向量数据库”“我们要做Agent架构”结果做出来的东西根本没人用。正确的思路应该是反过来的先明确场景需求再倒推技术方案。具体来说我会问自己四个问题。第一这个任务的输入输出是什么是文本分类、信息抽取、还是生成式问答不同任务对模型能力的要求完全不同。第二延迟要求是多少如果是面向C端的实时交互那延迟必须控制在几百毫秒级别大模型直接调用可能就不合适。第三预算是多少这决定了你能用多大的模型、能不能做微调、要不要上缓存。第四数据敏感度如何如果数据不能出内网那很多云端API方案就直接排除了。把这四个问题回答清楚技术选型的方向基本就定了。我一般会做一个简单的决策表来辅助判断场景特征推荐方案理由低延迟、高并发、任务简单小模型本地部署或轻量API成本可控延迟稳定复杂推理、低频调用大模型API效果好按量付费数据敏感、不能出内网开源模型本地部署数据安全可控任务固定、数据充足微调小模型效果好且成本低任务多变、快速验证大模型API加提示工程灵活迭代快这个表不是绝对的但能帮你快速缩小选择范围。我自己的经验是80%的场景用“小模型加好的工程优化”就能解决剩下20%才需要上大模型。很多团队一上来就all in大模型结果成本失控、延迟爆炸最后又灰溜溜地换回小模型。2.3 架构设计的三个关键决策点AI应用的架构设计和传统后端架构有相似之处但多了几个特有的决策点。第一个是推理服务的部署形态是每个请求独立调用还是做批处理是同步返回还是异步加回调这个决策直接影响用户体验和资源利用率。我的建议是如果延迟要求不苛刻尽量做微批处理把短时间内的多个请求合并成一个batch送给模型吞吐量能提升好几倍。第二个决策点是缓存策略。AI推理很贵但很多请求其实是重复的或者高度相似的。我一般会做两层缓存精确匹配缓存和语义相似缓存。精确匹配就是请求内容完全一样时直接返回缓存结果这个用Redis就能做。语义相似缓存稍微复杂一点需要把请求向量化后做相似度检索超过阈值就复用结果。实测下来好的缓存策略能减少30%到50%的推理调用量成本直接砍半。第三个决策点是降级方案。AI服务不可能100%可用模型可能超时、API可能限流、网络可能抖动。这时候必须有降级策略比如返回兜底话术、切换到更小的备用模型、或者直接走规则引擎。我见过一个线上事故就是因为没有降级方案大模型API一挂整个功能全不可用用户投诉爆了。后来加了一个简单的规则兜底虽然效果差一些但至少服务不中断。3. 核心细节解析与实操要点从环境到代码的完整链路3.1 开发环境搭建别小看这一步环境搭建听起来很简单但实际上是新手最容易卡住的地方。我建议从零开始的话按这个顺序来先装Python环境管理工具再配虚拟环境然后装核心依赖最后验证GPU可用性。Python版本我推荐3.10或3.11这两个版本在AI生态里兼容性最好。太新的版本有些库还没适配太老的版本又缺少一些新特性。环境管理工具用conda或者uv都行我个人现在更倾向uv速度快很多。虚拟环境一定要用不要图省事直接装在系统Python里否则后面依赖冲突会让你痛不欲生。核心依赖这块根据你的方向不同会有差异。如果做深度学习PyTorch是绕不开的装的时候注意CUDA版本要和你显卡驱动匹配。我踩过好几次坑都是CUDA版本对不上导致GPU用不了。验证GPU是否可用很简单跑一行代码就行import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))如果输出True和你的显卡型号说明环境没问题。如果输出False大概率是CUDA版本不匹配需要重新装对应版本的PyTorch。注意不要盲目追求最新版本的CUDA和PyTorch生产环境建议用经过验证的稳定组合。我一般会查PyTorch官网的版本对照表选一个发布半年以上的版本。3.2 数据处理AI工程里最脏最累的活数据处理是AI工程里最不起眼但最重要的一环。我敢说一个AI项目最终效果好不好70%取决于数据质量30%才取决于模型选择。但很多团队在数据上花的时间远远不够随便清洗一下就开始训模型结果效果不行就怪模型不好。数据处理的完整流程包括数据采集、数据清洗、数据标注、数据增强、数据划分。每一步都有讲究。数据采集要注意来源的多样性和代表性不能只从一个渠道拿数据否则模型会有偏差。数据清洗要处理缺失值、异常值、重复值还要做格式统一。这一步我一般会写一个checklist逐项过一遍缺失值比例是否超过阈值超过的话是删除还是填充异常值是否合理是真实异常还是录入错误重复数据是否去重去重标准是什么文本编码是否统一有没有乱码标签分布是否均衡不均衡的话怎么处理数据标注是个体力活但也有很多技巧。我建议先标一小批做验证确认标注标准没问题再大规模铺开。标注标准要写得足够细最好有正例和反例。我见过太多项目因为标注标准模糊导致标注质量参差不齐最后模型学了一堆噪声。数据划分这块训练集、验证集、测试集的划分要随机且分层。如果数据有时间属性还要考虑时间上的划分不能用未来数据预测过去。这个细节很多人会忽略但在实际业务中特别重要。3.3 模型选型与微调合适比先进更重要模型选型我前面已经讲了原则这里补充一些实操细节。开源模型现在选择很多从1B到70B都有。我的建议是先用小模型快速验证pipeline能不能跑通确认没问题再换大模型。不要一上来就搞最大的调试起来又慢又贵。微调这块现在主流的方法是LoRA和QLoRA能在消费级显卡上微调不小的模型。LoRA的核心思想是不改原模型参数只训练一小部分低秩矩阵这样显存占用和训练时间都大幅降低。QLoRA更进一步把原模型量化到4bit再微调显存需求更低。我实测下来一张24G显存的卡用QLoRA能微调7B到13B的模型效果和全量微调差距不大。微调数据的格式很关键。一般用instruction-input-output的三元组格式instruction是任务描述input是输入output是期望输出。数据量的话几百到几千条就能看到明显效果但质量比数量重要。我一般会准备500条左右的高质量数据先跑一轮看效果再决定要不要加数据。# LoRA微调的核心配置示例 from peft import LoraConfig, get_peft_model lora_config LoraConfig( r8, # 低秩矩阵的秩一般4-16 lora_alpha32, # 缩放系数一般是r的2-4倍 target_modules[q_proj, v_proj], # 要微调的模块 lora_dropout0.1, biasnone, task_typeCAUSAL_LM )这里r和lora_alpha是两个关键参数。r越大能学习的参数越多效果可能更好但更容易过拟合。lora_alpha控制新参数对原模型的影响程度。我的经验是r8、alpha32是个不错的起点大部分场景够用。提示微调前一定要先跑通推理确认基座模型本身能正常工作。我遇到过好几次微调效果差最后发现是基座模型加载就有问题。3.4 推理服务化把模型变成能用的接口模型训好了只是第一步要让它能被业务调用还需要做服务化。最简单的做法是用FastAPI包一层把模型加载到内存暴露一个HTTP接口。但生产环境要考虑的东西多得多并发处理、批处理、超时控制、限流、监控。并发处理这块Python有GIL限制多线程对CPU密集型任务效果不好。但AI推理主要是GPU计算GIL的影响相对小一些。我一般用FastAPI加uvicorn配合异步IO来处理并发请求。如果QPS很高可以考虑用Triton Inference Server或者vLLM这类专门的推理框架它们对批处理和并发做了深度优化。批处理是提升吞吐量的关键。核心思路是把短时间内到达的多个请求合并成一个batch送给模型这样GPU利用率更高。vLLM在这方面做得很好它有一个叫continuous batching的机制能动态地把新请求加入正在处理的batch里。实测下来同样的硬件用vLLM比朴素实现吞吐量能高5到10倍。超时控制和限流是保证服务稳定的必要手段。我一般会设置三层超时单次推理超时、单请求总超时、服务级熔断。限流用令牌桶或者漏桶算法控制单位时间内的请求数。这些在FastAPI里都有现成的中间件可以用。# 简单的推理服务示例 from fastapi import FastAPI, HTTPException from pydantic import BaseModel import asyncio app FastAPI() class Request(BaseModel): text: str max_length: int 512 app.post(/predict) async def predict(req: Request): try: result await asyncio.wait_for( model_inference(req.text, req.max_length), timeout5.0 ) return {result: result} except asyncio.TimeoutError: raise HTTPException(status_code504, detail推理超时)这个例子很简单但展示了核心思路异步处理加超时控制。实际项目中还要加日志、监控、鉴权等。4. 实操过程与核心环节实现一个完整项目的落地记录4.1 项目背景与需求拆解我拿一个实际做过的项目来串一遍完整流程。需求是给一个客服系统做智能问答用户提问后自动匹配知识库里的答案匹配不到就转人工。核心指标有三个准确率要超过85%响应时间要在500毫秒以内每天处理量大概10万次。拿到需求后我先做拆解。这是一个典型的检索加生成的混合任务不是纯粹的生成式问答。因为客服场景对准确性要求很高不能让模型自由发挥必须基于知识库回答。所以架构上我选择了“向量检索加小模型重排”的方案而不是直接上大模型生成。为什么这么选第一知识库里的问答对是固定的检索能保证答案的准确性。第二检索加小模型的延迟远低于大模型生成能满足500毫秒的要求。第三成本可控向量检索和小模型推理都很便宜。如果直接上大模型10万次每天的调用成本会很高而且延迟也难保证。4.2 数据准备与向量化知识库里有大概2万条问答对格式是问题和标准答案。第一步是把所有问题向量化存到向量数据库里。向量化模型我选了BGE系列的中文模型在中文语义相似度任务上表现不错而且模型不大推理速度快。向量化的过程很简单但有几个细节要注意。第一问题文本要做预处理去掉特殊字符和多余空格。第二如果问题比较长要考虑截断或者分段。第三向量要归一化这样用余弦相似度检索时可以直接用内积计算速度快很多。from sentence_transformers import SentenceTransformer import numpy as np model SentenceTransformer(BAAI/bge-base-zh-v1.5) def encode_questions(questions): # 预处理 cleaned [q.strip().replace(\n, ) for q in questions] # 向量化 embeddings model.encode(cleaned, normalize_embeddingsTrue) return embeddings # 批量处理避免一次性加载太多 batch_size 256 all_embeddings [] for i in range(0, len(questions), batch_size): batch questions[i:ibatch_size] emb encode_questions(batch) all_embeddings.append(emb) all_embeddings np.vstack(all_embeddings)向量数据库我选了FAISS轻量、快、够用。2万条数据的索引构建只要几秒钟检索延迟在毫秒级别。如果数据量到百万级可以考虑Milvus或者Qdrant但2万条用FAISS完全足够。4.3 检索加重排的完整实现检索的流程是用户问题向量化在FAISS里找Top-K个最相似的问题然后对这K个候选做重排选出最匹配的一个。K一般取10到20太小可能漏掉正确答案太大重排开销高。重排我用了一个小的交叉编码器模型它会把用户问题和候选问题拼在一起输入模型输出一个匹配分数。交叉编码器比向量相似度更准但计算量大所以只对Top-K个候选做。这个“先粗排再精排”的两阶段架构是检索系统的经典设计兼顾了速度和准确性。from transformers import AutoTokenizer, AutoModelForSequenceClassification import torch rerank_model AutoModelForSequenceClassification.from_pretrained(BAAI/bge-reranker-base) rerank_tokenizer AutoTokenizer.from_pretrained(BAAI/bge-reranker-base) def rerank(query, candidates, top_k1): pairs [[query, c] for c in candidates] with torch.no_grad(): inputs rerank_tokenizer(pairs, paddingTrue, truncationTrue, return_tensorspt, max_length512) scores rerank_model(**inputs).logits.view(-1) # 按分数排序 ranked sorted(zip(candidates, scores.tolist()), keylambda x: x[1], reverseTrue) return ranked[:top_k]这里有个细节重排模型的输入长度限制是512个token如果问题很长会被截断。客服场景的问题一般不长所以问题不大。但如果你的场景问题很长要考虑分段或者换用支持更长输入的模型。4.4 阈值判断与兜底策略检索加重排之后会得到一个匹配分数。这个分数不能直接用来判断是否匹配因为不同问题的分数分布不一样。我一般会设一个阈值分数高于阈值就返回答案低于阈值就转人工。阈值的设定需要根据验证集来调目标是让准确率和覆盖率之间达到平衡。我当时的做法是在验证集上跑一遍画出准确率随阈值变化的曲线选一个准确率满足要求85%以上且覆盖率尽可能高的点。最终选的阈值让覆盖率大概在70%左右也就是说30%的问题会转人工。这个比例业务方可以接受因为人工客服本来就有冗余。兜底策略除了转人工还可以加一层规则匹配。比如用户问“退货怎么操作”如果检索没匹配到可以用关键词规则直接返回退货流程。规则匹配虽然笨但在特定场景下很有效而且零延迟零成本。注意阈值不要设得太高否则覆盖率太低用户体验差也不要设得太低否则准确率不达标用户更不满意。这个平衡点需要和业务方一起定。4.5 性能优化与压测上线前一定要做压测。我用locust模拟了不同并发下的请求观察延迟和吞吐量的变化。第一次压测结果不太理想QPS到50的时候延迟就超过500毫秒了。排查后发现瓶颈在向量检索和重排之间的数据传递上每次都要做一次Python对象到numpy数组的转换开销不小。优化方法很简单把检索和重排合并到一个函数里减少中间的数据转换。另外把重排模型也放到GPU上和向量化模型共享显存。优化后QPS到200时延迟还在300毫秒以内满足了需求。还有一个优化点是缓存。我把高频问题的检索结果缓存起来用LRU策略管理。客服场景下问题重复率很高缓存命中率能到40%左右大大减轻了后端压力。优化项优化前QPS优化后QPS延迟变化初始版本50-500ms合并数据转换120140%350msGPU重排18050%320ms加缓存20011%300ms这个表是我当时记录的大致数据具体数字可能有出入但趋势是准确的。每一步优化都有明确的收益不是瞎调。5. 常见问题与排查技巧实录那些文档里不会写的东西5.1 模型加载与显存问题排查显存不够是AI工程里最常见的问题之一。症状一般是程序崩溃报CUDA out of memory。排查思路是先用nvidia-smi看显存占用确认是模型本身太大还是中间激活值太大。如果是模型太大可以考虑量化、用更小的模型、或者用CPU卸载。如果是激活值太大减小batch size通常能解决。我遇到过一个比较隐蔽的问题模型加载时显存够但推理时爆显存。原因是推理时中间激活值占用了额外显存而加载时只算了模型参数的显存。解决办法是预留足够的显存余量一般建议至少留20%的余量。还有一个坑是显存碎片化。长时间运行的服务反复分配释放显存会导致碎片化最后明明总显存够但分配不出来。解决办法是设置PYTORCH_CUDA_ALLOC_CONFexpandable_segments:True让PyTorch用可扩展的显存段。5.2 推理结果不稳定的排查推理结果不稳定表现为同样的输入有时候输出不一样。如果用了采样策略比如temperature大于0那输出不一样是正常的。但如果temperature设为0还是不稳定那就有问题了。常见原因有几个。第一模型没有设成eval模式dropout还在起作用。这个用model.eval()就能解决。第二输入没有做确定性处理比如字典遍历顺序不确定导致输入顺序变化。第三多GPU推理时数据分发有问题。第四浮点数计算的非确定性这个比较难完全消除但影响通常很小。我一般会写一个确定性测试同样的输入跑100次看输出是否完全一致。如果不一致就逐项排查上面的原因。5.3 服务上线后的监控与告警服务上线不是终点而是起点。没有监控的AI服务就像盲人开车出了问题都不知道。我一般会监控这几个指标请求量、延迟分布P50、P95、P99、错误率、缓存命中率、GPU利用率、显存占用。延迟分布比平均延迟更重要。平均延迟可能很好看但P99延迟很高说明有少量请求体验很差。我一般会设P99延迟的告警阈值超过就触发告警。错误率要区分不同类型的错误。超时、限流、模型报错、数据格式错误处理方式都不一样。我一般会按错误类型分别统计方便快速定位问题。监控指标告警阈值排查方向P99延迟1s检查GPU利用率、批处理配置错误率1%查看错误日志、区分错误类型缓存命中率20%检查缓存策略、请求分布GPU利用率30%检查批处理、并发配置显存占用90%检查内存泄漏、模型大小这个表是我在实际项目中总结的不同场景阈值可能不同但排查方向是通用的。5.4 成本控制的几个实用技巧AI服务的成本主要来自GPU资源和API调用。控制成本有几个立竿见影的技巧。第一能用量化就用量化4bit量化能让显存需求降到原来的四分之一效果损失很小。第二能缓存就缓存前面讲过了缓存能减少30%到50%的调用。第三能批处理就批处理批处理能大幅提升GPU利用率。第四监控token消耗很多API是按token计费的控制输入输出长度能直接省钱。我做过一个对比同样的服务不做任何优化的话每月成本大概5000块做了量化和缓存之后降到1500块左右降幅70%。这个投入产出比非常高值得花时间做。提示成本优化不要牺牲太多效果。我一般会设一个效果底线比如准确率不能低于某个值在这个前提下尽量降成本。如果降成本导致效果明显下降那就得不偿失了。5.5 版本管理与回滚AI服务的版本管理比传统软件复杂因为涉及模型版本、代码版本、配置版本三个维度。我一般会用模型注册表来管理模型版本每次训练产出的模型都注册进去记录训练数据、超参数、评估指标。代码用Git管理配置用配置文件或者配置中心管理。回滚策略要提前准备好。模型效果不好、服务出故障、成本超预期都可能需要回滚。回滚要能做到一键切换不能临时改代码。我一般会保留最近三个版本的模型随时可以切回去。上线新模型时我一般会做灰度发布。先切10%的流量到新模型观察一段时间没问题再逐步扩大比例。这样即使新模型有问题影响范围也可控。6. 从能跑到能交付AI工程能力的进阶路径6.1 新手最容易忽略的三个工程习惯第一个是写日志。AI服务的日志比传统服务更重要因为出问题时需要知道输入是什么、输出是什么、中间经过了哪些步骤。我一般会在关键节点打日志包括请求进入、向量化完成、检索完成、重排完成、返回结果。日志要结构化方便后续分析。第二个是写测试。AI服务的测试比传统服务难写因为输出不是确定的。但至少可以写冒烟测试确认服务能正常响应、延迟在合理范围、不报错。还可以写回归测试用一批固定输入跑一遍看输出有没有明显变化。第三个是写文档。AI项目的文档特别重要因为涉及模型、数据、配置等多个方面不写文档过两个月自己都忘了。文档至少包括架构说明、接口文档、模型说明、部署步骤、常见问题。这三个习惯看起来简单但坚持做的人不多。我见过太多项目因为没日志、没测试、没文档维护起来极其痛苦。6.2 从单模型到多模型编排当项目变复杂时单个模型往往不够用需要多个模型配合。比如一个问答系统可能需要意图识别模型、实体抽取模型、检索模型、生成模型。这时候就需要做模型编排。编排的核心是定义好每个模型的输入输出以及它们之间的依赖关系。我一般会用DAG来描述这个流程每个节点是一个模型调用边是数据流。编排引擎负责按顺序执行处理错误和重试。编排的难点在于错误处理。某个模型调用失败时是重试、跳过、还是整个流程失败这取决于业务逻辑。我一般会给每个节点设重试次数和超时时间超过就触发降级。6.3 持续迭代数据飞轮怎么转起来AI服务上线后最重要的迭代方向是数据飞轮。简单说就是用户使用产生数据数据用来改进模型改进后的模型提供更好的服务吸引更多用户使用。这个循环转起来效果会越来越好。数据飞轮的关键是收集高质量的反馈数据。用户的点击、点赞、纠错都是宝贵的反馈。我一般会在产品里设计反馈入口鼓励用户标注。收集到的数据经过清洗和标注后加入训练集定期重新训练模型。迭代频率取决于业务需求和数据积累速度。我一般会每月做一次小迭代每季度做一次大迭代。小迭代主要是调参和加数据大迭代可能涉及换模型或改架构。6.4 我个人的一些经验体会做了这么多AI工程项目我最大的体会是工程能力比算法能力更稀缺。算法知识可以学网上教程一大堆但工程能力需要在真实项目中摸爬滚打才能积累。很多团队算法很强但工程很弱做出来的东西demo很惊艳但一上线就崩。另一个体会是不要追求完美要追求可用。我见过太多项目因为追求最先进的模型、最优雅的架构结果迟迟上不了线。实际上一个能跑起来的简单方案远比一个跑不起来的完美方案有价值。先上线再迭代这是AI工程的正道。最后一个体会是成本意识要贯穿始终。AI服务很烧钱如果不控制成本再好的效果也撑不住。从选型到部署到运维每一步都要考虑成本。我一般会把成本作为一个核心指标来监控和效果、延迟同等重要。这个领域变化很快新模型、新框架、新工具层出不穷。但底层的工程思维是不变的理解需求、选对方案、做好实现、持续迭代。把这套思维建立起来具体的技术栈怎么变都能应对。
网站建设高端定制企业官网