在 Jupyterhub 上用十分鐘建立 Server 來跑模型

Abby Yeh
Taiwan AI Academy
Published in
6 min readSep 3, 2019

Build an AI App — 0: use Ngrok and Flask to build a server for ai model

Photo by Jordan Harrison on Unsplash

想要用 web service 來展示你的 model 的時後,只有 Jupyterhub 怎麼辦呢? 不想租 AWS、GCE,想用自己的本機的跑 server 的時候,又要怎麼辦呢? 用這次要介紹的 ngrok 就可以讓你輕鬆地在任何機器上建立讓別人可以連線的 server。

— 環境架設 —

首先,需要一個有裝 flask、你需要的套件 (e.g. Tensorflow, Pytorch) 和 GPU 的 hub 就可以囉!

首先從 Ngrok 的官網 下載需要的作業系統的 zip file (在這裡我是下載 32-bits Linux 的檔案),解壓縮和認證後就可以直接使用它啦!

$ unzip /path/to/ngrok.zip
$ ./ngrok authtoken <your Ngrok id>

最簡單的使用方法就是執行以下指令:

$ ./ngrok http 80

這樣就可以建立一個 HTTP 的連線到 80 這個 port,用紅筐內的網址連到你的 server 了。只可惜要升級帳號才能有固定的 ip,所以比較適合拿來開發或demo用。

— 建立 Flask Server —

Flask 是一個非常容易使用的 web server 框架,所以就用他來建立範例 server吧。首先,建立一個 hello world server 來測試 Ngrok 是首有成功連到server。創建一個新檔 app/main.py,在裡面寫:

from flask import Flask, request, send_fileapp = Flask(__name__)@app.route("/")
def hello():
return "Hello World!"

在 Terminal 執行:

export FLASK_APP=app/main.py
python -m flask run

Flask 預設的 port 是 5000,所以執行 Ngrok的時候就得要 bind 到 5000。

$ ./ngrok http 5000

打開瀏覽器前往 “http://xxxx.ngrok:5000/”,有出現 “Hello World!” 就是成功了!

safari 成功畫面

— 建立 API —

接著就可以來寫 API 啦!不過在開始前,先看一下範例 server 所使用的 model 的使用方法吧!這是一個 image transfer 的 model,需要 input 一張圖片和你要 transfer 過去的風格。

def transform(image, style):

...

return output_image

首先,先建立一個 API

用 @app.route(URL, methods) 建立一個 api,因為要傳圖片到 server,所以 method 要選 POST。 另外,為了讓使用者決定要要轉到哪種風格,用角括號加入在網址加入 style 變數 :

@app.route('/sync_transform/<style>', methods=['POST'])
def sync_transform(style):

如果使用者 post 到 “sync_transform/style1”,那麼 sync_transform 函式就會收到 “style1” 字串作為 input。

然後要從 request 夾帶的檔案得到 Image 物件。

  1. 先檢查使用者是否有夾帶檔案,沒有檔案則回傳 error_message 和 status_code。
if 'file' not in request.files:
return 'No file part', 500

2. 再檢查有沒有檔名,因為如果傳來的是空的 file part 過來,會沒有檔名。

file = request.files['file']
if file.filename == '':
return 'No selected file', 500

3. 用 pillow 將檔案轉成 Image 物件。

image = Image.open(file.stream).convert("RGB")

記得要先 import pillow 這個 package:

from PIL import Image

接下來就是可以執行 model 了,這個範例 model 會回傳一個 Pillow Image 物件:

image = sync_transform(image, style)

最後,回傳前必須轉成 file bytes:

# 轉成指定副檔名的 bytes,要產生jpg的話,format要給 jpeg
image_bytes = io.BytesIO()
image.save(image_bytes, format='JPEG')
# 把讀取位置調回最開始
image_bytes.seek(0)

用 Flask 的 send_file 回傳到 client 端:

return send_file(image_bytes, attachment_filename='result.jpg', mimetype='image/jpg')

完整 function 如下:

— 執行 —

分別在不同分頁 執行 Ngrok 和 Flask server 就可以接收 requests 了。

— Request 測試 —

最後用 request 套件來測試 Server 是否有成功。建立一個 test.py:

執行完後,test_recieved_from_jupyter.jpg 可以正常顯示就代表成功了!

— 完整程式碼 —

https://github.com/leafinity/cartoon_server/tree/jupyter-sync-server

— 參考資料 —

[1] Flask Document Quickstart

[2] Flask Upload Files

[2] Install both python 3.6 and 3.7

[3] Celery Broken with Latest Python

[4] First Steps with Celery

--

--