前面 15 天,我一直在處理同一件事情:
怎麼讓 AI 在 Edge Device 上真正跑起來。
從一開始的 Person Detection,到 QCS6490 NPU、GStreamer、Streaming、Geofence,最後把 Detection 變成 Event。
到這裡,PoC 基本上已經可以 Demo 了。
但開始整理成產品之後,我又遇到一個問題:
好好的程式,為什麼還要包成 Container?
老實說,一開始我也覺得不一定需要。
如果只有一台 ECU-2200,其實很簡單。
ECU-2200
│
├── Frontend
├── Backend
├── AI Runtime
├── GStreamer
└── Model
把環境裝好,程式啟動。
有問題?
ssh
docker logs
restart
甚至連 Docker 都不一定需要。
如果只是做 PoC,這樣完全可以。
但產品開始往下走,我們開始遇到另一個問題。
假設今天不是一台,而是 50 台 Edge Device。
每台都要裝:
Python
Node.js
GStreamer
QNN
AI Runtime
Backend
Frontend
Model
然後每一台的環境可能還不太一樣。
可能變成:
ECU-001
Python 3.10
Backend 1.0
ECU-002
Python 3.11
Backend 1.0
ECU-003
Python 3.10
Backend 1.1
這時候問題就開始出現了。
明明是同一個 Application:
為什麼這台可以跑,那台不行?
工程師最後可能花很多時間在處理:
「環境到底差在哪裡?」
而不是處理 AI 本身。
Container 對我們來說,最直接的價值不是「AI 一定要用 Docker」。
而是:
把 Application 需要的環境一起打包,讓它到不同 Edge Device 時,至少 Application 本身可以用比較一致的方式交付。
例如:
Frontend
↓
Frontend Container
Backend
↓
Backend Container
AI Runtime
↓
AI Container
每個元件都有自己的環境。
我們的 Edge AI Application 根本不只有一個 Container。
例如現在可能長這樣:
Unmanned Area AI Application
│
├── Frontend Container
├── Backend Container
└── AI Runtime Container
那我要怎麼把它們一起啟動?
總不能:
docker run frontend
docker run backend
docker run ai-runtime
每台機器都自己打一遍吧?
所以這時候 Docker Compose 就開始有用了。
例如:
services:
frontend:
image: advantech/edge-ai-frontend:1.2
depends_on:
- backend
backend:
image: advantech/edge-ai-backend:1.5
depends_on:
- ai-runtime
ai-runtime:
image: advantech/edge-ai-runtime:1.0
這時候我們管理的就不再是:
Container A
Container B
Container C
而是:
Edge AI Application
│
├── Frontend
├── Backend
└── AI Runtime
這個差別其實滿重要的。
這是我做到這裡才慢慢比較清楚的一件事情。
對 RD 來說:
Container 很重要。
但對客戶來說,他不會在意你到底有幾個 Container。
他看到的是:
Unmanned Area AI
Version 1.5
Status: Running
他不會想知道:
frontend container = running
backend container = running
runtime container = running
所以我們開始需要一個更高一層的概念:
Application。
這點在 Edge AI 特別重要。
因為我們不是單純跑一個 Web Application。
底下還有:
Camera
↓
Video Driver
↓
GStreamer
↓
QNN
↓
HTP / NPU
↓
AI Application
這些東西還是會碰到:
所以不是把所有東西塞進 Docker,就什麼問題都沒有。
比較接近實際情況的是:
ECU-2200
│
├── Host OS
│ ├── Kernel
│ ├── Driver
│ ├── BSP
│ └── Hardware
│
└── Container
├── Frontend
├── Backend
└── AI Runtime
Container 管 Application Environment,Host 還是負責 Hardware。
這個界線要先搞清楚。
Application 可以 Container 化。
Frontend 有版本。
Backend 有版本。
AI Runtime 也有版本。
但是:
Model 呢?
假設今天:
Frontend 1.2
Backend 1.5
AI Runtime 1.0
Person Model 2.1
過兩個禮拜,Person Model 改成:
Person Model 2.2
難道我要:
Model 2.2
↓
重新 Build Docker Image
↓
重新測試 Application
↓
重新部署
嗎?
如果只有一台,也許還可以。
但如果有 100 台呢?
這時候我開始發現:
Application、Container、Model,其實是三種不同的東西。
它們的版本,也不一定應該綁在一起。
EdgeHub
│
┌────────────┼────────────┐
↓ ↓ ↓
Device Application Model
Management Management Management
│ │
↓ ↓
Docker/Compose Registry
│
┌────────┼────────┐
↓ ↓ ↓
Frontend Backend AI Runtime
這時候幾個東西的責任就比較清楚:
| 東西 | 負責什麼 |
|---|---|
| Docker Image | 把一個 Application 元件包起來 |
| Docker Compose | 定義多個 Container 怎麼一起跑 |
| Harbor | 管理 Docker Image |
| Model Registry | 管理 AI Model |
| EdgeHub | 管理 Device、Application、Deployment |
原本我以為 Model Registry 就是:
「找個地方把 Model 放起來。」
做到這裡才發現,好像完全不是這麼簡單。
如果 Model 會獨立更新,那我們至少需要知道:
Person Detection
│
├── v1.0
├── v2.0
└── v2.1
而且還要知道:
v2.1
│
├── 支援 QCS6490?
├── 支援 HTP?
├── 需要哪個 Runtime?
├── Input 是什麼?
├── Output 是什麼?
├── 有沒有經過 Validation?
└── 現在哪些 Device 正在使用?
這時候 Model Registry 就不再只是「放檔案」。
而是開始變成:
Model 的管理中心。
一開始我們只是想:
把 AI 做出來。
後來變成:
把 AI 放進 Container。
再後來才發現:
Container 不是最終目的。
真正要管理的是:
Device
↓
Application
↓
Container
↓
Model
而每一層都有自己的生命週期。
所以到了這裡,我下一個問題反而變得很明確:
如果 Model 可以獨立於 Application 更新,那我們到底要怎麼管理 Model?
這就是我接下來開始研究 Model Registry 的原因。