在 Web API 開發中,完善的 API 檔案至關重要。Swagger(OpenAPI)是廣泛使用的 API 檔案標準,能清晰描述 API 的端點、引數、傳回值等資訊,並提供可互動介面進行測試。本文將逐步示範如何使用 Swagger 檔案化 Flask Web API,並探討如何使用 ONNX 格式儲存模型並建立 REST API。首先,我們會安裝 Flasgger 函式庫,接著在 Flask 應用中組態 Swagger,並為每個 API 端點(例如:產品、購物車、結帳)新增 Swagger 檔案,使用 YAML 檔案定義 API 結構。最後,我們將示範如何執行 Flask 應用並測試 API 檔案,以及如何將模型轉換為 ONNX 格式,並在 JavaScript 中使用 ONNX Runtime 載入和執行模型,最後建立一個 REST API 來提供模型預測服務。

使用 Swagger 檔案化 API

在開發 Web API 的過程中,良好的檔案對於維護和擴充套件至關重要。Swagger(現稱為 OpenAPI)是一種廣泛使用的 API 檔案標準,能夠清晰地描述 API 的端點、引數、傳回值等資訊,並提供一個可互動的介面來測試 API。

步驟 1:安裝 Flasgger

首先,我們需要安裝 Flasgger 這個函式庫,它能夠將 Swagger 整合到 Flask 應用中。執行以下命令進行安裝:

pip install flasgger

步驟 2:組態 Swagger

接下來,我們需要在 Flask 應用中組態 Swagger。首先,匯入必要的模組並建立 Swagger 物件:

from flasgger import Swagger

app = Flask(__name__)
swagger = Swagger(app)

步驟 3:定義 API 端點

我們為每個 API 端點新增 Swagger 檔案。首先,看一下 /products 端點的定義:

@app.route('/products', methods=['GET'])
@swag_from('swagger/products.yml')
def products():
    products = db.get_products()
    return jsonify(products)

這裡,@swag_from 裝飾器用於指定該端點的 Swagger 檔案位置。

products.yml

---
tags:
  - products
responses:
  200:
    description: A list of products
    schema:
      type: array
      items:
        type: object
        properties:
          id:
            type: integer
          name:
            type: string
          price:
            type: number

這個 YAML 檔案描述了 /products 端點的傳回值結構。

步驟 4:其他端點的檔案

類別似地,我們為購物車相關的端點新增檔案:

cart.yml

---
tags:
  - cart
responses:
  200:
    description: A list of items in the cart
    schema:
      type: array
      items:
        type: object
        properties:
          id:
            type: integer
          product_id:
            type: integer
          quantity:
            type: integer

add_to_cart.yml

---
tags:
  - cart
parameters:
  - in: body
    name: body
    required: true
    schema:
      type: object
      properties:
        productId:
          type: integer
        quantity:
          type: integer
responses:
  200:
    description: Added to cart

checkout.yml

---
tags:
  - checkout
parameters:
  - in: body
    name: body
    required: true
    schema:
      type: object
      properties:
        cartId:
          type: integer
responses:
  200:
    description: Checkout successful

#### 內容解密:

  1. Swagger 組態:透過 Swagger(app) 初始化 Swagger,自動生成 API 檔案介面。
  2. 端點檔案:使用 @swag_from 指定每個端點的檔案檔案,如 products.yml
  3. YAML 檔案結構:每個 YAML 檔案定義了對應端點的引數、傳回值及型別資訊。

步驟 5:執行並測試 API 檔案

執行 Flask 應用後,存取 http://localhost:5000/apidocs/ 可以看到 Swagger UI 介面。在此介面中,可以瀏覽 API 端點、測試請求並檢視傳回結果。

指派作業:擴充套件 API 功能

為了進一步提升 API 的功能,可以考慮以下任務:

  • 新增取得單一產品資訊的端點。
  • 新增從購物車移除產品的端點。
  • 新增更新購物車中產品數量的端點。

解題思路:

將上述任務以提示的形式輸入到 Copilot Chat 中,它將生成相應的程式碼和檔案。預期結果包括更新後的程式碼和相應的 Swagger 檔案。

使用 AI 服務增強 Web 應用程式

簡介

有多種方法可以利用 AI 服務來增強 Web 應用程式:您可以利用現有的 Web API 或自行建置並呼叫模型。 新增 AI 至應用程式的主要目的是使其變得更聰明,不僅是為了聰明而聰明,而是為了讓它對使用者更有用。例如,如果您有一個允許使用者搜尋產品的 Web 應用程式,您可以新增一個功能,根據使用者的購買記錄推薦產品。事實上,為什麼只侷限於之前的購買記錄?為什麼不根據使用者的搜尋記錄推薦產品?或者,如果使用者可以拍攝產品照片並讓應用程式推薦類別似的產品呢?

商業領域:電子商務

我們繼續在電子商務領域工作,但我們的業務重點是評級。好的或壞的評級可以影響特定產品的銷量。該邏輯域由以下部分組成:

  • 產品:被評級的產品
  • 評級:實際評級和元資訊,如評論、日期等

問題與資料領域

需要解決的問題是如何利用這些評級資料並從中學習。

  • 見解:例如,我們可以獲得應該開始/停止銷售某種產品的見解。可能還有其他見解,例如某些產品在世界的某些地區銷售良好。
  • 技術問題:技術方面是如何攝取資料、訓練模型,然後找出 Web 應用程式如何利用該模型。

特徵分解

從特徵角度來看,我們需要將其視為由三個主要部分組成。

  1. 資料攝取和訓練:這需要一個單獨的介面,也許它是在沒有使用者介面的情況下完成的,只是靜態資料被輸入到能夠訓練模型的程式碼中。有了這種理解,我們可以概述步驟如下:

    • 載入資料
    • 清理資料
    • 建立特徵
    • 訓練模型
    • 評估模型
    • 執行預測
  2. 使用模型:一旦模型被訓練出來,就需要將其公開,最好是透過 Web 端點。為此,我們認為需要以下步驟:

    • 將模型轉換為合適的格式(如有需要)
    • 建立 Web API
    • 透過 Web API 公開模型
    • 佈署模型,需要將 API 上線
  3. 預測:對於預測部分,這是一種為「後台」設計的功能,而不是導向客戶的功能。

    • 建立使用者介面以執行預測
    • 建立底層程式碼,與 Web API 通訊以進行預測

建立模型

假設我們正在處理 sales_rating.csv 檔案中的資料,這是合併兩個資料集的結果,一個包含銷售資料,另一個包含評級資料。資料如下所示:

| product_id | avg_rating | sold | |



-|



-|


| | 1 | 2.5 | 100 | | 2 | 3.7 | 200 | | … | … | … |

我們的理論是,產品的平均評級與銷量相關。透過建立模型,我們可以更接近於確定我們的假設是否正確。

擬定計劃

我們可以向 Copilot 請教建立模型的步驟。我們輸入以下提示作為註解:

# 銷售評級資料範例
import pandas as pd

# 載入資料
df = pd.read_csv("sales_rating.csv")

# 檢視前幾行
print(df.head())

載入必要的函式庫

首先,讓我們在 VS Code 中建立一個新的筆記本,命名為 sales.ipynb

# 安裝 pandas 和 scikit-learn
!pip install pandas scikit-learn

# 載入 pandas 和 scikit-learn
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

#### 內容解密:
1. `!pip install pandas scikit-learn`:在 Jupyter Notebook 中安裝必要的 Python 套件
2. `import pandas as pd`:載入 pandas 套件用於資料處理和分析
3. `from sklearn.linear_model import LinearRegression`:從 scikit-learn 套件中載入線性迴歸模型用於建立預測模型
4. `from sklearn.model_selection import train_test_split`:用於將資料分割為訓練集和測試集

讀取 CSV 檔案

# 讀取 CSV 檔案
df = pd.read_csv("sales_rating.csv")

# 檢視前幾行資料
print(df.head())

#### 內容解密:
1. `df = pd.read_csv("sales_rating.csv")`:使用 pandas 的 `read_csv` 方法讀取名為 `sales_rating.csv` 的 CSV 檔案並將其儲存到 DataFrame `df`
2. `print(df.head())`:顯示 DataFrame 的前幾行以檢查資料是否正確載入

使用 AI 服務增強 Web 應用程式

建立測試和訓練資料集

在機器學習中,我們通常會將資料分成測試和訓練資料集。訓練資料集用於訓練模型,而測試資料集用於測試模型。我們可以使用 Copilot 來幫助我們完成這項任務。

程式碼實作

test_size = 0.2
test = df.sample(frac=test_size)
training = df.drop(test.index)

內容解密:

  1. test_size = 0.2:設定測試資料集的大小為 20%。
  2. test = df.sample(frac=test_size):從原始資料集中隨機抽取 20% 的資料作為測試資料集。
  3. training = df.drop(test.index):將剩餘的 80% 資料作為訓練資料集。

建立模型

建立模型涉及選擇我們想要使用的演算法,然後訓練模型。讓我們使用 LinearRegression 演算法來建立模型。

程式碼實作

model = sklearn.linear_model.LinearRegression()
model.fit(training[["avg_rating"]], training[["sold"]])

內容解密:

  1. model = sklearn.linear_model.LinearRegression():建立一個線性迴歸模型。
  2. model.fit(training[["avg_rating"]], training[["sold"]]):使用訓練資料集訓練模型,其中 avg_rating 是輸入特徵,sold 是輸出目標。

評估模型

我們需要評估模型的表現。讓我們使用 Copilot 來幫助我們完成這項任務。

程式碼實作

score = model.score(test[["avg_rating"]], test[["sold"]])

內容解密:

  1. score = model.score(test[["avg_rating"]], test[["sold"]]):計算模型在測試資料集上的 R^2 分數,評估模型的預測能力。

預測

讓我們使用模型進行預測。

程式碼實作

predictions = model.predict(test[["avg_rating"]])

內容解密:

  1. predictions = model.predict(test[["avg_rating"]]):使用模型對測試資料集進行預測。

視覺化預測結果

讓我們將預測結果與實際值進行比較。

程式碼實作

import matplotlib.pyplot as plt
plt.scatter(test[["avg_rating"]], test[["sold"]], color='black')
plt.plot(test[["avg_rating"]], predictions, color='blue', linewidth=3)

內容解密:

  1. plt.scatter(test[["avg_rating"]], test[["sold"]], color='black'):繪製實際值的散點圖。
  2. plt.plot(test[["avg_rating"]], predictions, color='blue', linewidth=3):繪製預測值的線圖。

儲存模型

讓我們將模型儲存到一個 .pkl 檔案中。

程式碼實作

import pickle
pickle.dump(model, open("model.pkl", "wb"))

內容解密:

  1. pickle.dump(model, open("model.pkl", "wb")):將模型儲存到一個名為 model.pkl 的檔案中。

建立 REST API

讓我們使用 Python 建立一個 REST API,以公開我們的模型。

程式碼實作

import pickle
import flask
# 載入模型
model = pickle.load(open("model.pkl", "rb"))
# 建立 Flask 應用程式
app = flask.Flask(__name__)
# 定義路由
@app.route('/', methods=['GET', 'POST'])
def predict():
    if flask.request.method == 'GET':
        # 處理 GET 請求
        pass

內容解密:

  1. model = pickle.load(open("model.pkl", "rb")):載入儲存的模型。
  2. app = flask.Flask(__name__):建立一個 Flask 應用程式。
  3. @app.route('/', methods=['GET', 'POST']):定義一個路由,處理 GET 和 POST 請求。

將模型轉換為ONNX格式並建立REST API

在前面的章節中,我們探討瞭如何使用Pickle來儲存模型並在Python中載入。然而,Pickle有一些缺點,包括它是Python特有的。另一方面,ONNX是一種不受限於Python的格式,可以在其他語言中使用。接下來,我們將探討如何使用ONNX格式來處理我們的模型。

將模型轉換為ONNX格式

要將模型轉換為ONNX格式,我們需要進行以下步驟:

  1. 安裝必要的依賴套件。
  2. 匯入必要的函式庫。
  3. 將模型轉換為ONNX格式。

安裝ONNX依賴套件

首先,我們需要安裝skl2onnx套件。可以使用以下命令進行安裝:

! pip install skl2onnx

將模型轉換為ONNX格式

接下來,我們需要匯入必要的函式庫並將模型轉換為ONNX格式。以下是範例程式碼:

import skl2onnx

# 將模型轉換為ONNX格式
skl2onnx.to_onnx(model, train[["avg_rating"]].astype("float32"), "model.onnx")

內容解密:

  1. import skl2onnx:匯入skl2onnx函式庫,該函式庫用於將Scikit-learn模型轉換為ONNX格式。
  2. skl2onnx.to_onnx(model, train[["avg_rating"]].astype("float32"), "model.onnx"):將模型轉換為ONNX格式並儲存為model.onnx檔案。其中,model是我們訓練好的Scikit-learn模型,train[["avg_rating"]].astype("float32")指定了模型的輸入資料型態,"model.onnx"是輸出檔案的名稱。

在JavaScript中載入ONNX模型

現在,我們已經將模型轉換為ONNX格式,接下來需要在JavaScript中載入該模型。可以使用onnxruntime函式庫來實作這一點。

安裝onnxruntime

首先,需要安裝onnxruntime套件。可以使用以下命令進行安裝:

npm install onnxruntime

載入ONNX模型

以下是載入ONNX模型的範例程式碼:

const rt = require("onnxruntime");

// 從ONNX檔案載入模型
const model = await rt.InferenceSession.create("model.onnx");

// 進行預測
const inputName = model.inputNames[0];
const outputName = model.outputNames[0];
const feeds = { [inputName]: [[4.5]] };
const results = await model.run(feeds);
console.log(results[outputName]);

內容解密:

  1. const rt = require("onnxruntime");:匯入onnxruntime函式庫。
  2. const model = await rt.InferenceSession.create("model.onnx");:從model.onnx檔案載入模型。
  3. const inputName = model.inputNames[0];const outputName = model.outputNames[0];:取得模型的輸入和輸出名稱。
  4. const feeds = { [inputName]: [[4.5]] };:準備輸入資料。
  5. const results = await model.run(feeds);:進行預測。
  6. console.log(results[outputName]);:輸出預測結果。

建立使用ONNX模型的REST API

最後,我們需要建立一個REST API來提供模型的預測服務。可以使用Express框架來實作這一點。

建立REST API

以下是建立REST API的範例程式碼:

const express = require("express");
const rt = require("onnxruntime");

const app = express();
app.use(express.json());

// 從ONNX檔案載入模型
const model = await rt.InferenceSession.create("model.onnx");

app.post("/predict", async (req, res) => {
    try {
        const inputName = model.inputNames[0];
        const outputName = model.outputNames[0];
        const feeds = { [inputName]: [[req.body.avg_rating]] };
        const results = await model.run(feeds);
        res.json({ prediction: results[outputName] });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.listen(3000, () => {
    console.log("Server listening on port 3000");
});

內容解密:

  1. const app = express();:建立Express應用程式。
  2. app.use(express.json());:啟用JSON解析中介軟體。
  3. app.post("/predict", async (req, res) => { ... });:定義/predict路由,處理POST請求。
  4. 在路由處理函式中,取得輸入資料,進行預測,並傳回預測結果。