直接用tf.keras.models.load_model搭配fastapi+uvicorn比tf serving更易上手调试;tf serving单模型验证复杂度高,目录结构、权限、启动参数要求严,rest接口不稳定,本地验证运维负担重。

直接用 tf.keras.models.load_model 加 FastAPI + uvicorn,比 TF Serving 更快上手、更易调试;高并发瓶颈不在框架选型,而在模型加载方式、设备绑定和推理上下文管理。
为什么别一上来就跑 TF Serving?
TF Serving 对单模型验证反而增加复杂度:要严格匹配目录结构(my_model/1/)、权限(chmod -R a+r)、启动参数(--rest_api_port=8501 --enable_batching=true),且 REST 接口是实验性功能,/healthz 不可用、/ 返回 404 是常态。本地快速验证时,它带来的运维负担远超收益。
- 常见错误现象:
curl http://localhost:8501返回 404,但日志没报错——其实是路径不对,必须用/v1/models/my_model - 真正卡点不是性能,而是调试成本:改一行预处理代码,就得重新导出 SavedModel、重启服务、再测
- 如果你只部署一个模型、QPS FastAPI + load_model 启动时间更短、日志更直观、断点更可控
FastAPI 启动时必须做这三件事
否则并发一上来就内存暴涨或 GPU 显存不释放:
- 全局加载模型:
model = tf.keras.models.load_model("my_model")放在app.py顶层,**绝不能**写在@app.post("/predict")函数里 - 显式指定设备并固定计算图:
model = model.compile() # 确保已编译,若用 GPU,加model = model.to('cuda')(PyTorch)或确保 TensorFlow 已识别 GPU(tf.config.list_physical_devices('GPU')) - 每次推理必须包裹
with tf.device('/CPU:0'):或with tf.device('/GPU:0'):,避免不同请求混用设备导致张量类型错配
图像输入的预处理别踩这些坑
很多线上报错源于输入格式不一致,而非模型本身:
- 用
PIL.Image.open()读图后,必须转np.array()再tf.image.resize(..., [224, 224]),别用cv2.resize—— 插值方式不同会导致预测结果漂移 - 补 batch 维度必须用
tf.expand_dims(img_array, 0),不是np.expand_dims,否则后续model.predict()可能静默失败 - 如果模型输入要求
float32,务必显式img_tensor = tf.cast(img_tensor, tf.float32),TensorFlow 不会自动提升类型
并发高了显存爆了?先看这行代码有没有
现象是首次请求成功、第二次开始返回 ResourceExhaustedError 或 nvidia-smi 显示显存占用持续上涨——问题几乎总出在推理上下文没清理:
- 必须在预测函数内加
with tf.device('/GPU:0'), tf.name_scope('inference'):,并确保所有中间变量(如 resize 后的 tensor)作用域明确 - 返回前加
del predictions和tf.keras.backend.clear_session()(仅限 CPU 场景;GPU 下慎用,可能触发 CUDA 上下文重置) - 更稳妥的做法是:用
tf.function包装预测逻辑,例如@tf.function(input_signature=[...]) def predict_fn(x): return model(x),能强制图模式执行、避免 eager 模式缓存
真正的高并发瓶颈往往不在 HTTP 层,而在于模型是否被正确固化为图、输入 pipeline 是否可复用、以及 GPU 上下文是否被多个 worker 共享。别急着换框架,先确认 model.save 导出的是 save_format='tf',再检查 uvicorn 启动时是否用了 --workers 2 而不是默认的单进程。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











