[Day 29] 使用 Python Flask 架设 API 吧!

使用 Python Flask 架设 API 吧!

今日学习目标

  • API 观念讲解
    • 什麽是 API?
    • RESTful API
    • HTTP Request 方法
  • 手把手实作一个花朵分类器 API
    • 透过 Python Flask 建置一个後端预测模型 API

前言

当模型训练完以後下一个步骤就是应用与落地。我们可以设计一个嵌入式系统与使用者互动,例如树莓派、Jetson Nano、NeuroPilot...等硬体来协助 AI 模型的边缘运算。或是设计一个手机 APP 以及网页应用。很多人可能会有疑问模型训练好然後下一个步骤该怎做?最常见的做法就是将训练好的模型储存起来并建立一个 API 部署在後端服务器中,接着任何的终端设备都可以透过这一个 API 进行资料的存取与模型预测。下图是一个简单的模型落地的应用情境,我们可以在後端服务器部署模型并建立一个 API 的接口与前端使用者互动。前端网页的使用者透过 HTTP 的协定与後端服务器进行通讯与资料交换,最终模型的预测结果会回传到前端使用者并将结果选染在网页上。我们延续昨天的内容 [Day 28] 储存训练好的模型,目前已经成功的输出模型。今天就来教各位如何透过 Python Flask 架设一个鸢尾花朵分类器的 API 吧!

https://ithelp.ithome.com.tw/upload/images/20211011/201072477uMsu8TsW3.png

什麽是 API?

所谓的 API 中文全名为应用程序介面 (Application Programming Interface) 是属於客户端与伺服端的沟通桥梁,它提供一个端口能够进行资料交换。简单来说是一个前端与後端的一个沟通介面。

https://ithelp.ithome.com.tw/upload/images/20211011/20107247ppUsK2iKwl.png

另外大家可能听过一个名词叫做 RESTful API。所谓的 REST 为 Representational State Transfer 的缩写是一种网路架构风格,近几年来 REST 的概念已经被实作在大型网路系统中,而在 Web 服务中使用 REST 概念被实作出来的 API 就简称为 RESTful API 他是使用 HTTP 的协定完整定义 Web 服务在 HTTP Request 的各种流程。

https://ithelp.ithome.com.tw/upload/images/20211011/20107247dj3hviG2Vm.png

HTTP Request 方法

透过网路协定 HTTP Request 不同的方法,可以实现不同的资料交换请求方式。HTTP 本身就是 REST 的实作,所谓的 HTTP Request 定义了八种请求方法分别为:

  • GET:此方法只能向指定的资源要求取得资料,并不会更动到内部资源。
  • HEAD:HEAD 跟 GET 方法类似只差别在它并不会回传你所请求的资源在 body 上,只回传 HTTP header。
  • POST:向指定的资源提交资料。
  • PUT:向指定资源位置提交更新内容。
  • DELETE:向指定资源位置请求删除内容。
  • CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
  • OPTIONS:此方法可使服务器传回该资源所支持的所有 HTTP 请求方法。
  • TRACE:回显服务器收到的请求,主要用於测试或诊断。

[程序实作] 鸢尾花朵分类器 API

建立 Python Flask API

Flask 是一个使用 Python 语言编写的轻量级 Web 应用框架。在今日的文章中我们将延续昨天所储存的鸢尾花朵分类器模型,建立一个花朵分类预测的 API。使用者可以透过 POST 协定从前端网页发送四个数值分别为花萼的长与宽以及花瓣的长与宽。後端程序收到数值後送给事先打包好的模型,并将模型预测结果透过 JSON 格式回传到前端使用者。以下为程序整个树状结构,其中在最外层资料夹有三个档案分别有将模型封装成函式的 model.py 与 Flask 主程序 run.py 以及负责管理专案套件的 requirements.txt。另外在 model 资料夹中负责储存训练好的模型压缩档。

.
├── model
│   └── xgboost-iris.pgz
├── model.py
├── requirements.txt
└── run.py

封装预测模型 (model.py)

首先建立一个 model.py 档案,在这个档案中我们要载入事先训练好的模型并将它封装成一个 function 或是 class。在本范例程序中我们是建立一个 predict() 的函式并且允许接收一个 Numpy 的阵列,其中里面允许夹带四个花朵特徵的数值。最後将模型预测结果存放在 pred 变数中,并将预测的类别回传。

# -*- coding: UTF-8 -*-
import pickle
import gzip

# 载入模型
with gzip.open('./model/xgboost-iris.pgz', 'rb') as f:
    xgboostModel = pickle.load(f)

# 将模型预测写成一个 function 
def predict(input):
    pred=xgboostModel.predict(input)[0]
    return pred

建立 Flask API (run.py)

接着我们要透过 Flask 建立一个 API,首先要设定开放跨网域 CORS 权限。所谓的跨来源资源共享 (Cross-Origin Resource Sharing, CORS) 是一种使用额外 HTTP 标头来让目前浏览网站的使用者能访问不同来源网域的服务器。当使用者请求一个来自於不同网域、通讯协定或通讯埠的资源时,会建立一个跨来源 HTTP 请求。所以在撰写程序的时候必须透过 flask_cors 里面所提供的 CORS 添加跨来源资源共享。这样前端使用者在不同网域利用 ajax 或 fetch 存取 API 时就会有读取权限。

# -*- coding: UTF-8 -*-
import numpy as np
import model

from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

接着我们先示范建立一个 GET 的路由 @app.route('/'),单引号内的内容即代表使用者在呼叫 API 的路径位置 / 代表是 root 的意思。在这一个测试的路由中我们直接回传一个 hello!! 的字串。稍後将会教各位如何透过 Postman 这个软件来测试 API。另外第二个路由是负责接收花朵四个数值,并将这四个数值放到 Numpy 阵列中送到稍早以封装好的 mpdel.py 中的 predict() 方法。并将预测的结果透过 JSON 格式回应给前端使用者。值得注意的是这一个路由我们是设定他的路径为 /predict 以及 HTTP Requesst 的方法指定 methods=['POST']

@app.route('/')
def index():
    return 'hello!!'

@app.route('/predict', methods=['POST'])
def postInput():
    # 取得前端传过来的数值
    insertValues = request.get_json()
    x1=insertValues['sepalLengthCm']
    x2=insertValues['sepalWidthCm']
    x3=insertValues['petalLengthCm']
    x4=insertValues['petalWidthCm']
    input = np.array([[x1, x2, x3, x4]])

    result = model.predict(input)

    return jsonify({'return': str(result)})

最後我们透过 app.run() 将此 API 部署在服务器的 3000 PORT 当中。host='0.0.0.0' 表示预设路由将会自动帮你取得目前服务器的固定 IP 位置。由於我们目前在本机开发等等测试时可以直接使用 http://localhost:3000 进行测试。另外参数 debug 设定为 True 即表示 API 被启动时会自动监听程序是否有变动,如果有更新内容即会立刻重新启动 API。此设定适合在开发时候使用,而真正上线时再调成 False。

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=3000, debug=True)

管理套件版本 (requirements.txt)

requirements.txt 这一支档案是负记录了当前专案资料夹下程序所有依赖的套件及相对应的版本。下列五个是在本实作中将会使用到的套件,若套件後面没有特别指定版本号,安装时将会自动安装最新的版本。

Flask
Flask-Cors
numpy
scikit-learn
xgboost

假设程序在另一台电脑上执行时,要一个一个安装套件很麻烦。因此可以直接透过 requirements.txt 纪录专案中依赖的套件。并且输入以下指令即可一次安装所有指定的套件。

pip install -r requirements.txt

执行 API

在本机或开发环境中测试执行 API 的方式很简单。只要开启终端机并输入以下指令即可:

python run.py

https://ithelp.ithome.com.tw/upload/images/20211011/20107247z5GVgYO4uW.png

程序真正上线时建议使用 gunicorn 或 Waitress 来产生 WSGI 服务,并於背景运行

还记得我们有写一个 GET 方法的测试路由吗?这时候大家可以开启电脑中的浏览器并在网址列输入 http://localhost:3000 即可立即看到 API 在指定的路径下所回应的内容。如果出现以下画面即代表 API 已经正常的被运行罗。

https://ithelp.ithome.com.tw/upload/images/20211011/20107247xZk0axmnFf.png

那你可能会问我该怎麽测试另一个 POST 方法呢?由於 GET 方法比较好处理,我们直接在浏览器输入路径就能立即观看结果。那当我们要测试 POST、PUT、DELETE 等方法时就必须依靠第三方软件 Postman 来协助模拟 HTTP Request 完成 API 测试。

测试 API 的好工具 Postman

当你写好一支 API 时要马上测试看看你写的程序逻辑是否正确,就可以使用 Postman 这个软件来做 API 测试。Postman 他是一个能够模拟 HTTP Request 的工具能够让你简单快速的测试你的 API,并且内建包含许多 HTTP 的请求方式,例如常见的 GET(取得)、POST(新增)、PUT(修改)、DELETE(删除)。首先大家可以到官网下载与安装。

https://ithelp.ithome.com.tw/upload/images/20211011/20107247XzwgTeF0mD.png

安装好之後可以打开程序并点选 POST 并贴上 API 网址。由於我们现在要测试另一个预测的路径 predict,因此在网址列贴上 http://localhost:3000/predict。点选 Body-> raw -> JSON 并将花朵的四个参数以 JSON 格式进行描述。

{
    "sepalLengthCm": 5.9,
    "sepalWidthCm": 3,
    "petalLengthCm": 5.1,
    "petalWidthCm": 1.8
}

点选 Send 後即可将模拟的四个数值透过 JSON 格式使用 POST 方法传送到後端 API 中的 predict 路径。该 API 透过 POST 接收到前端使用者所发送的讯息後,解析这四个数值并依序放在阵列中并进行模型预测。最终预测结果会将花的种类以 JSON 格式回传到前端使用者。此时前端的网页设计师就可以将拿到的预测结果进行前端的画面渲染与更新。

https://ithelp.ithome.com.tw/upload/images/20211011/20107247TOY1A80ErT.png

本系列教学内容及范例程序都可以从我的 GitHub 取得!


<<:  [Day 26] Edge Impulse + BLE Sense也能感受彩色的人生

>>:  Day-27 : Model 一对多

[Day20] NLP会用到的模型(四)-LSTM实现POS

一. 资料准备 此资料与[Day9]的资料一样为conllu档,都是作为POS任务 架构如下,每个词...

[Day8]训练集与验证集

今天开始处理训练集和验证集的问题 开始前先安装yahoo finance的package pip i...

[Day14] Flutter with GetX animated_text_kit

animated_text_kit 文字特殊效果的第三方,可以参考文档的样式作选择 使用起来类似是F...

[Day22] JavaScript - Fetch API

第18篇有提到过Fetch的用法(连结),这篇要实际使用Fetch来做简单的Api串接。 首先介绍一...

[Lesson14] Retrofit

在 gradle (Module) 层级的 dependencies 中内加入: implement...