← M09 MLOps 與部署 M09 MLOps 與部署

M09.04|模型服務化:讓 AI 模型變成可呼叫的服務

訓練好的模型如果沒辦法被其他系統使用,它就只是一個孤立的 .pkl 檔

L2-系統部署-模型服務化與 API 設計 L2-AI技術應用-推論系統設計
模型服務化 REST API gRPC 批次推論 即時推論 FastAPI TensorFlow Serving 推論延遲 吞吐量
📋

本講學習重點

REST API 和 gRPC 怎麼選?
批次推論和即時推論各適合什麼場景?
如何提升模型推論的效能?
FastAPI 和 TensorFlow Serving 的差別?
什麼是 SLA,模型服務要怎麼設定?

REST API = JSON over HTTP,通用但相對慢;gRPC = Protobuf,高效能但複雜

即時推論 = 收到請求立刻回應(毫秒級);批次推論 = 積累後批量處理(分鐘到小時)

效能優化:模型量化(FP32→INT8)、模型蒸餾、ONNX 加速、批次請求合併

FastAPI 適合快速原型;TF Serving/Triton 適合生產高吞吐量

SLA 常見指標:p99 延遲 < 200ms、可用性 99.9%(每月停機 < 43 分鐘)

BentoML 和 Seldon Core 是高層次抽象,簡化模型部署複雜度

模型版本 A/B 測試可以在服務層實現,不需要改動業務邏輯

📌 模型服務化是讓訓練好的模型能被外部系統呼叫的過程,核心選擇是 REST vs gRPC 通訊協定、即時 vs 批次推論模式。選擇合適的服務框架(FastAPI、TensorFlow Serving、BentoML)並設定清晰的 SLA,是讓 AI 在生產環境中穩定運作的基礎。
模型服務化:讓 AI 模型變成可呼叫的服務

🎙️ Podcast(中文)

0:00 / 0:00

一句話搞懂

模型服務化就是把訓練好的機器學習模型「包裝」成一個可以接受請求、回傳預測結果的服務——就像餐廳廚師(模型)和用餐客人(呼叫方)之間,需要服務生(API 服務層)來傳遞點單和上菜,讓模型能夠被外部系統以標準化的方式呼叫,而不是直接把模型原始碼複製到每個用到它的地方。


白話解說

為什麼需要「服務化」?

想像你訓練好了一個銷售預測模型,存成了一個 model.pkl 檔案。現在業務系統要使用這個預測——問題來了:

業務系統是 Java 寫的,你的模型是 Python 訓練的。Java 不能直接載入 Python 的 pickle 檔。就算語言一樣,直接把模型嵌入業務系統也是很糟糕的設計:每次模型更新都要重新部署業務系統,訓練環境的 Python 套件版本衝突問題會讓你頭痛不已,而且模型沒辦法被多個系統同時使用。

解決方案是把模型獨立包裝成一個服務(Service):這個服務運行在獨立的環境裡,對外暴露一個標準化的介面(API),任何人只要發送正確格式的請求,就能拿到預測結果。模型更新時,只需要更新這個服務,不需要動到呼叫它的所有系統。

這就是微服務架構的精神:把模型從一個靜態檔案,變成一個可以獨立擴展、獨立更新、被多方呼叫的動態服務。

REST API vs gRPC:兩種通訊語言

模型服務最常使用兩種通訊協定:

REST API(RESTful HTTP API):使用你熟悉的 HTTP 協定,資料格式是 JSON(純文字)。呼叫方式就像瀏覽網頁:發一個 POST 請求到特定 URL,附帶 JSON 格式的輸入資料,收到 JSON 格式的預測結果。

# REST API 呼叫範例
curl -X POST http://model-service/predict \
  -H "Content-Type: application/json" \
  -d '{"age": 35, "income": 80000, "tenure_months": 24}'

# 回傳
{"churn_probability": 0.23, "prediction": "low_risk"}

優點:所有程式語言都能呼叫,除錯容易(可以直接在瀏覽器測試),生態系成熟。 缺點:JSON 序列化/反序列化有開銷,HTTP/1.1 每次請求都有額外的 header 資料,高頻呼叫時效能相對差。

gRPC(Google Remote Procedure Call):Google 開發的高效能 RPC 框架,使用 Protobuf(Protocol Buffers)作為資料序列化格式。Protobuf 是二進位格式,比 JSON 更緊湊(同樣資料量小 3-10 倍),解析速度更快。gRPC 還支援雙向串流,可以同時傳送和接收資料流。

優點:效能顯著優於 REST(延遲更低、吞吐量更高)、支援串流傳輸、強型別定義(API schema 明確)。 缺點:設定相對複雜,需要生成客戶端代碼,在瀏覽器中使用需要額外的 proxy,debug 比 JSON 麻煩。

選擇準則:如果是面向終端用戶的 API,或者需要第三方集成,用 REST。如果是微服務之間的內部通訊,高頻呼叫(每秒超過幾千次),用 gRPC。

即時推論 vs 批次推論:根據業務需求選擇

即時推論(Online/Real-time Inference):用戶或系統發送請求,模型在幾毫秒到幾百毫秒內回傳結果。這是最直觀的模式,適合:

  • 推薦系統(用戶打開 App,立刻看到個人化推薦)
  • 詐騙偵測(每筆交易發生時,即時判斷是否異常)
  • 客服聊天機器人(用戶輸入問題,立刻得到回應)
  • 醫療輔助診斷(醫生上傳影像,幾秒內得到初步判讀)

挑戰:需要低延遲的模型(複雜模型需要優化)、服務要能應對流量波峰(需要自動擴展)、SLA 要求高(99.9% 可用性)。

批次推論(Batch Inference):積累一批請求後,一次性批量處理,結果寫入資料庫供後續使用。適合:

  • 每日信用評分更新(每天凌晨批量計算所有客戶的信用分數)
  • 推薦清單預計算(提前計算每個用戶的推薦清單,存入快取)
  • 報表生成(每週計算銷售預測報表)
  • 大量影像/文件的離線處理

優點:可以充分利用 GPU 的批次計算效率,不需要低延遲服務,成本通常更低。 缺點:結果有延遲(不是即時的),對突發的即時需求無法回應。

混合模式:很多系統同時使用兩者。例如推薦系統:預先批次計算每個用戶的基礎推薦清單存入快取(批次),當用戶真正打開 App 時,用即時推論根據當下情境微調推薦(即時)。

主流的模型服務框架

FastAPI(快速原型與中小規模):基於 Python 的現代 Web 框架,能在幾十行程式碼內把模型包裝成 REST API:

from fastapi import FastAPI
import joblib

app = FastAPI()
model = joblib.load("model.pkl")

@app.post("/predict")
def predict(data: dict):
    features = [[data["age"], data["income"], data["tenure"]]]
    prediction = model.predict_proba(features)[0][1]
    return {"churn_probability": float(prediction)}

優點:開發速度快,Python 生態系直接使用,自動生成 API 文件(Swagger UI)。 缺點:單進程 Python 服務的吞吐量有限,不內建模型版本管理。

TensorFlow Serving / TorchServe:分別是 TensorFlow 和 PyTorch 官方的生產級服務框架。支援模型熱更新(不停機更新模型)、多版本並存、gRPC 和 REST 兩種介面、GPU 加速。適合大規模生產部署。

NVIDIA Triton Inference Server:NVIDIA 開發的高效能推論伺服器,支援幾乎所有模型格式(TensorFlow、PyTorch、ONNX、TensorRT),能自動合併多個請求進行批次處理(Dynamic Batching),最大化 GPU 使用率。

BentoML:高層次的模型服務抽象,讓你專注在模型邏輯,它幫你處理 API 框架、容器化、部署的細節。適合不想深入底層但需要生產級部署的場景。

推論效能優化:讓模型跑得更快

當模型服務成為系統瓶頸,以下是常用的優化手段:

模型量化(Quantization):把模型參數從 32 位元浮點數(FP32)轉換成 16 位元(FP16)或 8 位元整數(INT8)。這能讓模型大小縮小 2-4 倍,推論速度提升 2-4 倍,準確率只有微小損失(通常 < 1%)。是最常用的加速手段。

ONNX 轉換:ONNX(Open Neural Network Exchange)是跨框架的模型格式。把 PyTorch 或 TensorFlow 模型轉成 ONNX 格式,再用 ONNX Runtime 做推論,通常能提升 1.5-3 倍的速度,且不依賴原本的訓練框架。

動態批次(Dynamic Batching):把在短時間內到達的多個請求合併成一個批次,一起送進 GPU 計算。GPU 最擅長的就是並行計算,單個請求的 GPU 使用率可能只有 5%,合成批次後可以提升到 80% 以上。

快取(Caching):對相同或高度相似的輸入,直接返回快取的結果,不需要重跑模型。適合推薦系統、分類結果等輸出相對穩定的場景。


應用場景

場景 推論模式 通訊協定 推薦框架 關鍵 SLA
電商即時推薦 即時 REST FastAPI / BentoML p99 延遲 < 100ms
金融詐騙偵測 即時 gRPC TensorFlow Serving p99 延遲 < 50ms
夜間批次信用評分 批次 N/A(直接寫 DB) 自訂 Python 腳本 在營業前完成
醫療影像分析 即時 REST Triton Inference Server p99 延遲 < 2000ms
NLP 客服機器人 即時 REST/WebSocket FastAPI + GPT API p99 延遲 < 500ms
工廠影像品管 即時(邊緣) gRPC Triton(TensorRT) p99 延遲 < 20ms
廣告點擊率預測 即時(超高QPS) gRPC TorchServe + 量化 p99 延遲 < 30ms

常見誤區

誤區 1:「直接把模型嵌入業務程式碼就好,不需要獨立服務」

這個做法在概念驗證(PoC)階段可以接受,但一旦要進入生產環境,問題就會接踵而來。

首先是依賴衝突:ML 模型常常有特定版本的 Python 套件需求(例如 scikit-learn 1.2.3、numpy 1.24.0),這些可能和業務系統的需求衝突,導致難以解決的版本地獄。

其次是更新問題:模型需要定期更新,如果嵌入業務程式碼,每次更新模型都要重新部署整個業務系統,增加了風險和工作量。

第三是資源競爭:模型推論(尤其是深度學習模型)消耗大量 CPU 和記憶體。把它嵌入業務服務會讓業務服務的資源不可預期地被佔用,影響正常業務的穩定性。

把模型獨立成服務,才能讓模型和業務系統各自獨立擴展、各自部署、各自優化。

誤區 2:「只要模型準確率高,推論速度不重要」

推論延遲(inference latency)直接影響用戶體驗,進而影響業務指標。Google 的研究顯示,網頁載入時間每增加 100ms,轉換率下降 7%。電商推薦如果要花 2 秒才能給出結果,很多用戶早就放棄等待了。

SLA(Service Level Agreement,服務等級協議)需要根據業務場景明確定義:互動式 UI 的回應時間通常要求在 200ms 以內,後端微服務之間的呼叫可以允許稍長。「p99 延遲」(第 99 百分位延遲)是更重要的指標——它代表 99% 的請求都在這個時間內完成,那 1% 的慢請求可能讓用戶感到失望。

當模型的推論速度不夠快,需要系統性地尋找瓶頸:是模型本身太複雜(考慮量化或蒸餾)、是資料前處理太慢(考慮 C++ 實作或向量化)、是 I/O 瓶頸(考慮快取或非同步處理),而不是一味堆更多機器。

誤區 3:「批次推論比即時推論簡單,不需要特別設計」

這個誤解低估了批次推論的複雜性。一個生產級的批次推論系統需要考慮:

容錯機制:處理幾百萬筆資料的批次任務,中途可能因為任何原因中斷(機器重啟、記憶體不足、資料格式錯誤)。沒有斷點續傳機制,每次失敗都要從頭開始,浪費大量計算資源。

資源調度:批次任務通常在離峰時段(深夜)執行,但執行時間不可預測。如果批次任務沒在規定時間前完成(例如信用評分要在隔天開盤前完成),業務就會出問題。需要合理的資源規劃和超時告警。

資料一致性:批次推論通常從資料庫讀取大量資料,但資料庫在批次執行期間可能有新的寫入。要確認批次任務用的是哪個時間點的快照,避免「看了一半的資料」。


小練習

練習 1:設計模型服務 API

你的團隊訓練了一個「商品評論情感分析模型」,輸入是評論文字,輸出是情感標籤(正面/中性/負面)和信心分數。請設計這個服務的 REST API:

  • 設計 POST /analyze 的請求和回應 JSON 格式
  • 設計 GET /health 的健康檢查回應
  • 考慮:需要支援批次請求嗎?(一次送入多筆評論)
  • 定義合理的 SLA(延遲要求、可用性要求)

練習 2:選擇服務架構

以下兩個場景,請分別設計合適的服務架構:

A. 電商平台的商品圖片分類服務:賣家上傳圖片時,自動判斷商品類別(書籍、3C、衣物等),準確率要高,但每次只有一張圖,允許 2 秒的延遲。

B. 銀行的每日風險評估系統:每天凌晨需要對 500 萬筆帳戶計算風險分數,在早上 8 點前全部完成並寫入資料庫,供信貸人員查詢。

查看答案 **練習 1 API 設計** ```json // POST /analyze 請求格式 { "reviews": [ { "review_id": "R001", "text": "這個商品品質很好,非常滿意!" }, { "review_id": "R002", "text": "運送太慢了,而且包裝破損" } ] } // POST /analyze 回應格式 { "results": [ { "review_id": "R001", "sentiment": "positive", "confidence": 0.92, "scores": { "positive": 0.92, "neutral": 0.06, "negative": 0.02 } }, { "review_id": "R002", "sentiment": "negative", "confidence": 0.88, "scores": { "positive": 0.04, "neutral": 0.08, "negative": 0.88 } } ], "model_version": "v2.1.3", "processing_time_ms": 45 } // GET /health 回應 { "status": "healthy", "model_loaded": true, "model_version": "v2.1.3", "uptime_seconds": 86400 } ``` **支援批次請求**:是的,因為評論分析常見的使用情境是批量處理(例如每天新增的評論一起分析),支援批次可以大幅提升吞吐量。 **SLA 建議**: - p99 延遲 ≤ 500ms(單筆)、≤ 2000ms(批次 100 筆以內) - 可用性 ≥ 99.9%(每月停機 < 43 分鐘) - 批次大小限制:單次請求最多 100 筆(超過要分批) --- **練習 2 架構設計** **A. 商品圖片分類服務** 推薦架構:**即時推論 + FastAPI/BentoML + REST API** 理由: - 只需支援單張圖片,延遲要求 2 秒很寬鬆 - 使用 FastAPI 包裝 PyTorch 或 TensorFlow 模型 - 用 ONNX 轉換提升推論速度(確保 < 2 秒) - 無需 GPU(除非模型特別大),CPU 推論即可 流程:賣家上傳圖片 → 前端呼叫 `/classify` API → 模型服務回傳類別 → 商品系統寫入資料庫 **B. 銀行每日風險評估** 推薦架構:**批次推論 + Apache Spark 或 Ray + 分散式計算** 理由: - 500 萬筆資料,要在 8 小時內完成(凌晨 12 點 → 早上 8 點) - 每秒要處理約 175 筆(500萬/28800秒),單機夠用,但要有容錯機制 - 使用 Spark ML 或 Ray 做分散式推論,充分利用多核心 - 每批次推論結果直接寫入目標資料庫(分批寫入,不是全部完成才寫) 流程:凌晨 12:00 批次任務啟動 → 從 DB 讀取所有帳戶特徵 → 分批推論(每批 10,000 筆)→ 結果寫入 DB → 早上 7:30 完成 → 8:00 準時供信貸人員查詢 關鍵設計:要有進度監控(預計完成時間)和異常告警(如果進度落後,提前通知),確保不會在 8 點還沒跑完。

關鍵字自我檢核

✅ 模型服務化 model serving ✅ REST API ✅ gRPC ✅ 批次推論 batch inference ✅ 即時推論 online inference ✅ FastAPI ✅ TensorFlow Serving ✅ Triton Inference Server ✅ BentoML ✅ 推論延遲 inference latency ✅ 吞吐量 throughput ✅ SLA 服務等級協議 ✅ 模型壓縮 model compression ✅ ONNX