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( r=8, # 低秩矩阵的秩,一般4-16 lora_alpha=32, # 缩放系数,一般是r的2-4倍 target_modules=["q_proj", "v_proj"], # 要微调的模块 lora_dropout=0.1, bias="none", task_type="CAUSAL_LM" )这里r和lora_alpha是两个关键参数。r越大,能学习的参数越多,效果可能更好但更容易过拟合。lora_alpha控制新参数对原模型的影响程度。我的经验是r=8、alpha=32是个不错的起点,大部分场景够用。
提示:微调前一定要先跑通推理,确认基座模型本身能正常工作。我遇到过好几次微调效果差,最后发现是基座模型加载就有问题。
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), timeout=5.0 ) return {"result": result} except asyncio.TimeoutError: raise HTTPException(status_code=504, 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_embeddings=True) return embeddings # 批量处理,避免一次性加载太多 batch_size = 256 all_embeddings = [] for i in range(0, len(questions), batch_size): batch = questions[i:i+batch_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_k=1): pairs = [[query, c] for c in candidates] with torch.no_grad(): inputs = rerank_tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512) scores = rerank_model(**inputs).logits.view(-1) # 按分数排序 ranked = sorted(zip(candidates, scores.tolist()), key=lambda x: x[1], reverse=True) 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+ |
| 合并数据转换 | 120 | +140% | 350ms |
| GPU重排 | 180 | +50% | 320ms |
| 加缓存 | 200+ | +11% | 300ms |
这个表是我当时记录的大致数据,具体数字可能有出入,但趋势是准确的。每一步优化都有明确的收益,不是瞎调。
5. 常见问题与排查技巧实录:那些文档里不会写的东西
5.1 模型加载与显存问题排查
显存不够是AI工程里最常见的问题之一。症状一般是程序崩溃,报CUDA out of memory。排查思路是先用nvidia-smi看显存占用,确认是模型本身太大还是中间激活值太大。如果是模型太大,可以考虑量化、用更小的模型、或者用CPU卸载。如果是激活值太大,减小batch size通常能解决。
我遇到过一个比较隐蔽的问题:模型加载时显存够,但推理时爆显存。原因是推理时中间激活值占用了额外显存,而加载时只算了模型参数的显存。解决办法是预留足够的显存余量,一般建议至少留20%的余量。
还有一个坑是显存碎片化。长时间运行的服务,反复分配释放显存会导致碎片化,最后明明总显存够但分配不出来。解决办法是设置PYTORCH_CUDA_ALLOC_CONF=expandable_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服务很烧钱,如果不控制成本,再好的效果也撑不住。从选型到部署到运维,每一步都要考虑成本。我一般会把成本作为一个核心指标来监控,和效果、延迟同等重要。
这个领域变化很快,新模型、新框架、新工具层出不穷。但底层的工程思维是不变的:理解需求、选对方案、做好实现、持续迭代。把这套思维建立起来,具体的技术栈怎么变都能应对。