从外包到甲方:一个老广程序员的机器学习部署实战血泪史
大家好,我是阿强,广州西关长大的土著,干了三年Java外包,去年十月终于跳槽进了甲方——一家做智能零售的本地科技公司。月薪从15k涨到了22k,房租还是3500(多亏了爸妈的老房子),但肩上的担子可重多了。今天想跟大家聊聊我最近踩过的一个大坑:机器学习模型怎么从“能跑”变成“能用”。
一、那个让我失眠的周五晚上
事情得从上周五晚上说起。那天快下班,产品总监老陈突然在钉钉上@我:“阿强,明天上线前,算法那边的推荐模型要部署到生产环境,你配合一下。”
我当场懵了。我?一个写Spring Boot写了五年的Java仔,连pandas都没装过,现在要搞ML部署?我弱弱地问:“陈总,这不应该是算法工程师的事吗?”
老陈回得飞快:“他们只负责训练和调参,部署是你们后端的事。再说了,你不是会Python吗?”
我心想:我会个锤子Python!顶多写过几个Flask小脚本,连virtualenv都配不明白。但话到嘴边,只能咽下去——毕竟刚进甲方,谁敢说“不会”?
那晚我翻来覆去睡不着,老婆看我刷手机刷到凌晨两点,问我:“又加班?”
我说:“不是,我在B站看‘十分钟部署PyTorch模型’。”
她叹了口气:“你不是说进了甲方就轻松点吗?”
我苦笑:“轻松?甲方才是修罗场啊。”
二、从“Hello World”到“Hello Production”
第二天一早,我硬着头皮去找算法组的小李。他递给我一个.pkl文件,说:“模型在这,用sklearn保存的,加载后直接调predict()就行。”
我问:“API接口呢?输入格式?性能要求?监控指标?”
他耸耸肩:“这些你们定吧,反正我们本地测试准确率92%。”
那一刻,我真正明白了什么叫“算法与工程的鸿沟”。
回到工位,我开始动手。最简单的方案:用Flask写个Web服务,加载模型,暴露REST接口。代码半小时搞定,本地测试OK。但一想到要上生产,冷汗就下来了:
- 并发怎么办? Flask单线程,10个请求就卡死。
- 内存泄漏? 模型加载一次吃掉2G内存,服务挂了咋办?
- 版本管理? 下次算法更新模型,怎么无缝替换?
- 日志监控? 用户点了推荐结果,转化率多少?模型有没有漂移?
这些问题,外包时期根本不用考虑——客户只要Demo能跑就行。但在甲方,产品要的是稳定、可维护、可度量的服务。
三、实战经验:从“能跑”到“能扛”
我花了三天时间,把最初的“玩具服务”改造成一个勉强能上生产的系统。这里分享几点血泪换来的实战经验:
1. 别用Flask裸奔,上FastAPI + Uvicorn
Flask虽然简单,但异步支持弱,性能差。我换成FastAPI,配合Uvicorn,吞吐量直接翻了3倍。而且自动生成OpenAPI文档,产品和前端都能直接看接口定义,沟通成本大降。
from fastapi import FastAPI
import joblib
app = FastAPI()
model = joblib.load("model.pkl")
@app.post("/predict")
def predict(payload: dict):
result = model.predict([payload["features"]])
return {"prediction": result[0]}
2. 模型加载必须“懒加载”+“单例”
一开始我把模型加载放在全局,服务启动就加载。结果每次重启都要等半分钟,运维骂我。后来改成首次请求时加载,并加锁保证单例:
_model = None
_lock = threading.Lock()
def get_model():
global _model
if _model is None:
with _lock:
if _model is None:
_model = joblib.load("model.pkl")
return _model
3. 用Docker封装,别让环境背锅
算法给的requirements.txt里有torch==1.12.0+cu113,但我司服务器没GPU。折腾半天才发现,他们本地用的是CUDA版,而生产环境只能用CPU。最后统一用Docker镜像隔离环境,算法提供Dockerfile,我负责构建和部署,各司其职。
4. 监控不能少:Prometheus + 自定义指标
光看QPS不够,我加了三个关键指标:
model_prediction_count:预测次数model_latency_seconds:单次推理耗时model_version:当前模型版本
这样产品问“推荐效果怎么样”,我就能甩出图表,而不是拍脑袋说“应该还行”。
5. 灰度发布:先放10%流量
上线那天,我没敢全量。用Nginx分流,先放10%用户走新模型,对比旧规则引擎的点击率。三天后数据稳定,才切全量。事实证明,新模型CTR提升了7%,老板笑开了花。
四、从“工具人”到“桥梁”的转变
这件事让我意识到,在甲方,程序员不能只是写CRUD的码农。你得懂业务,懂算法,懂运维,甚至懂一点产品思维。
以前在外包,需求是“做一个登录页面”,做完就完事。现在的需求是“提升用户复购率”,而机器学习只是手段之一。我开始主动约产品开会,问清楚指标定义;找算法聊特征工程,理解为什么选这个模型;跟运维对齐日志规范,确保问题可追溯。
这种转变很累,但很值。上周团建,老陈拍我肩膀说:“阿强,你比很多纯算法的人更懂怎么让模型落地。” 那一刻,我觉得22k的工资,值了。
五、给兄弟们的建议
如果你也像我一样,从传统开发转向AI工程化,记住三点:
- 别怕Python。Java人总觉得Python“不严谨”,但它的生态(NumPy、Pandas、Scikit-learn)就是为数据科学而生。学点基础语法,够用就行。
- 关注“交付”而非“技术”。产品不在乎你用TensorFlow还是PyTorch,只在乎推荐准不准、服务稳不稳。
- 建立协作机制。和算法约定好:模型必须带版本号、输入输出Schema、性能基准。写成文档,双方签字——别笑,真的有用!
六、写在最后
从外包到甲方,我最大的感悟是:技术没有高低贵贱,只有是否解决问题。
三年外包教会我快速交付,甲方教会我深度思考。现在,我既能在Java里写优雅的领域模型,也能在Python里调试模型推理瓶颈。这种“跨界”能力,或许就是我们普通程序员的护城河。
下个月,公司要上实时个性化推荐,要用到Flink + TensorFlow Serving。我又开始熬夜看文档了。但这次,我不慌了——因为我知道,只要一步步来,再难的问题,也能拆解成一行行代码。
共勉。
(完)
—— 阿强,广州程序员,现居荔湾,梦想是写出既跑得快又跑得稳的代码。

评论 0