# 【vMaker Edge AI專欄 #24】 如何使用 Gradio 快速搭建人工智慧應用圖形化人機界面 作者:Jack OmniXRI, 2024/12/15 ![vMaker_EdgeAI_24_Fig00](https://hackmd.io/_uploads/By1_KFMNJg.jpg) 相信很多朋友都是使用 Python 及 Jupyter Notebook 環境在開發人工智慧應用程式,不論是影像辨識、分類,還是大語言模型、影音生成應用。當只能使用命令列(Command Line)模式操作而沒有圖形化人機界面(Gaphical User Interface, GUI),那麼使用上就會變得非常不直覺且不方便。 傳統上要開發 Python GUI 大概會想到使用 Tkinter, PySide, PyQT 等工具,但這些工具比較適合開發桌機或手機版的應用,並不容易和 Jupyter Notebook 這類網頁版程式整合,包含 Google Colab, Intel OpenVINO Notebooks, Hugging Face 等。所以這裡要幫大家介紹另一項常見的 GUI 開源工具「**Gradio**」。[1] Gradio 提供了很便捷的網頁型式的各種輸入和輸出模組,如下所示。[2] * 應用界面:Interface(簡單應用)、Blocks(客製化應用) * 輸出輸入:文字框(Textbox)、資料框(DataFrame)、影像(Image)、下拉盒(Dropdown)、數字(Number)、文字說明(Markdown)、檔案(File) * 控制元件:按鍵(Button) * 版面佈局:標籤頁(Tab)、列佈局(Row)、行佈局(Column) 以上內容除了可直接顯示在 Jupyter Notebook 欄位上,還可透過獨立網頁顯示,包括裝置端(本地端)網址(http://localhost:7860),或公開(雲端)網址(https://xxxx.gradio.live),方便分享結果給其它人使用。 接下來就依序介紹幾個常用模組的使用方式給大家參考。完整範例可點擊下列連結直接於 Google Colab 上啟動。 [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/OmniXRI/Hello_World_Gradio/blob/main/Hello_World_Gradio.ipynb) 建議開啟後,先點擊選單「檔案」─「在雲端硬碟中儲存複本」,方便之後可以修改及測試程式。接著點擊選單「執行階段」─「全部執行」可一口氣把所有範例都執行一遍。 ![vMaker_EdgeAI_24_Fig01](https://hackmd.io/_uploads/ByzUGcGEkx.jpg) Fig. 1 Google Colab 工作及執行畫面。(OmniXRI整理製作, 2024/12/15) ## 1. 安裝 Gradio 及必要函式庫 在 Colab 中通常已預安裝好很多 Python 常用套件,如TensorFlow, PyTorch, OpenCV等,這裡只需安裝最重要的 gradio 即可,另外由於後面會下載一些配套檔案,所以另外多安裝一些必要的函式庫,如 requests, numpy 等。 ```python= !pip install -q gradio !pip install requests !pip install numpy #!pip install opencv-pytho # Colab 預設已安裝,本地端可依需要開啟安裝 import gradio as gr # 導入 gradio 函式庫並令別名為 gr import numpy as np # 導入 numpy 函式庫並令別名為 np #import cv2 # 導入 opencv 函式庫 ``` ## 2. 基本文字/數字輸出入 ### 2.1. 簡單應用界面一(簡單型) Gradio 使用上非常簡單,只需定義一個處理函式 fn,接著就可呼叫界面 Interface() 函式 ,指定輸出入格式後,再呼叫執行函式 launch() 函式即可秀出一個漂亮的輸出入界面。 以下範例運行後,左半邊為文字輸入,左半邊為輸出結果。當輸入一個「名字」(字串),按下「Submit」即可在右半邊顯示「Hello 名字!!」,而其內容就是經過 greet1() 組合出來的。當按下「Clear」時可清除輸出入內容。 運行後,除了在 Jupyter Notebook 欄位中出現界面,另外會提供一個公開網址,點擊後會出現一個新網頁,顯示一樣的內容。這個網址就可分享給其它人,享受你設計出的應用。 **註:共享連結只保留72小時,如需免費永久托管,需在終端機模式運行「gradio deploy」部署到 Hugging Face Spaces。** ```python= #import gradio as gr # 導入 gradio 函式庫並令別名為 gr # 定義 Gradio 輸出入處理函式 greet1() # 輸入文字: name(字串) # 輸出結果: "Hello name!!"(字串) def greet1(name): return "Hello " + name + "!!" # 建立輸人及輸出簡單應用界面 # fn: 界面函數名稱, inputs: 輸人格式, outputs: 輸出格式 demo = gr.Interface(fn=greet1, inputs="text", outputs="text") # 執行顯示界面 demo.launch() ``` ![vMaker_EdgeAI_24_Fig02](https://hackmd.io/_uploads/SkP5YFGN1l.jpg) Fig. 2 簡單文字輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15) ### 2.2. 簡單應用界面二(自定義型) 上一個範例,只有簡單的顯示界面。在這個範例可指定較複雜的設定,具有多個輸入和輸出,同時也自定義了輸出入的標籤,方便使用者辨識用途。 當在 name 欄位輸入「名字」,點選或解除「是早上」複選盒,拉動滑桿或直接輸入華氏溫度數值並按下「Submit」鍵,就會產生處理函式的輸出文字內容及溫度。當按下「Clear」鍵可清除輸入及輸出結果。 在處理函式 greet2() 引入三個變數,分別為 name(字串), is_morning(布林值)及temperature(數值),而回返值為二組字串 greeting 及四捨五入取小數點二位的攝氏溫度值。 在界面函式 Interface(), 分別使用 inputs, outputs 來定義每個輸出入值的更進一步外觀。如果想了解更多各元件用法可參考 [2]。 ```python= #import gradio as gr # 導入 gradio 函式庫並令別名為 gr # 定義 Gradio 輸出入處理函式 greet2() # 輸入: name(字串)、is_morning(布林值)、temperature(數值) # 輸出: "Good morning name, It is xx.x ℉ today"(字串)、攝氏溫度(數值) def greet2(name, is_morning, temperature): salutation = "Good morning" if is_morning else "Good evening" # 若複選盒有勾選則輸出 "Good morning", 否則輸出 "Good evening" greeting = f"{salutation} {name}. It is {temperature} ℉ today" # 組合輸出用字串 celsius = (temperature - 32) * 5 / 9 # 將華氏溫度轉成攝氏 return greeting, round(celsius, 2) # 建立輸人及輸出簡單應用界面 # fn: 界面函數名稱 # inputs: 輸人格式, 名字(標籤:名字)、是早上(複選盒)、華氏溫度(標籤:華氏(℉),滑桿,最小值0,最大值100,預設值50) # outputs: 輸出格式,結果字串(標籤:輸出)、結果溫度(標籤:攝氏(℃)) demo = gr.Interface( fn=greet2, inputs=[gr.Textbox(placeholder="請輸入姓名", label="姓名"), "checkbox", gr.Slider(0, 100, value=50, label="華氏(℉)") ], outputs=[gr.Textbox(label="輸出"), gr.Textbox(label="攝氏(℃)") ], ) # 執行顯示界面 demo.launch() ``` ![vMaker_EdgeAI_24_Fig03](https://hackmd.io/_uploads/Skj9YKfVJx.jpg) Fig. 3 自定義文字輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15) ### 2.3. 執行預設計 GUI (*.py) 對於常用的網頁表單格式,在不托管情況下也可以把相關內容預編成一個 Python 模組 (*.py)。 假設想要把上一步驟的 GUI 變成可引用之函式,可將後半段程式變成名為 launch_demo 的函式,再將程式儲存成 gradio_test.py 的程式,放在同一路徑下即可,如 Fig. 4所示。 ```python= # gradio_test.py import gradio as gr # 導入 Gradio 函式庫並令別名為 gr # 定義 Gradio 輸出入處理函式 greet2() # 輸入: name(字串)、is_morning(布林值)、temperature(數值) # 輸出: "Good morning name, It is xx.x ℉ today"(字串)、攝氏溫度(數值) def greet2(name, is_morning, temperature): salutation = "Good morning" if is_morning else "Good evening" # 若複選盒有勾選則輸出 "Good morning", 否則輸出 "Good evening" greeting = f"{salutation} {name}. It is {temperature} ℉ today" # 組合輸出用字串 celsius = (temperature - 32) * 5 / 9 # 將華氏溫度轉成攝氏 return greeting, round(celsius, 2) def launch_demo(): # 建立輸人及輸出簡單應用界面 # fn: 界面函數名稱 # inputs: 輸人格式, 名字(字串)、是早上(複選盒)、華氏溫度(滑桿,最小值0,最大值100,預設值50) # outputs: 輸出格式,結果字串(標籤 Reslut)、結果溫度(標籤 攝氏(℃)) demo = gr.Interface( fn=greet2, inputs=[gr.Textbox(placeholder="請輸入姓名", label="姓名"), "checkbox", gr.Slider(0, 100, value=50, label="華氏(℉)")], outputs=[gr.Textbox(label="輸出"), gr.Textbox(label="攝氏(℃)")], ) # 執行顯示界面 demo.launch() ``` 若想在 Colab 上運行上述模組時,需先自行下載到 Colab 提供的臨時雲端硬碟,預設使用者根目錄路徑為 content。亦可自行手動上傳。 由於執行路徑並不包含此路徑,所以還需使用 sys.path.append() 將路徑加入才能正確引用。若在本地端執行則不用增加該目錄。 ```python= import requests from pathlib import Path import sys # 從 Github 下載 gradio_test.py 並存於使用者根目錄 r = requests.get( url="https://raw.githubusercontent.com/OmniXRI/Hello_World_Gradio/main/gradio_test.py", ) open("gradio_test.py", "w").write(r.text) sys.path.append('./') # 在 Colab 使用者根目錄 ./ 預設在 /content,將其加入方便開啟下載之檔案 from gradio_test import launch_demo launch_demo() # 執行預設 GUI ``` ![vMaker_EdgeAI_24_Fig04](https://hackmd.io/_uploads/H15BJ9fNyg.jpg) Fig. 4 以 Python 模組方式引用,完成文字輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15) ## 3. 基本影像輸出入 ### 3.1. 使用 numpy 格式影像 當執行後,可支持三種影像輸入方式,直接上傳(支持從電腦檔案夾點擊或直接拖拉置放)、從網路攝影機直接拍照取像及貼上已剪貼簿中的影像。 上傳影像後,按下「Submit」鍵,即可呼叫影像處理函式 sepia(),這裡會令原始影像變成棕色影像顯示在輸出。 ```python= #import gradio as gr # 導入 Gradio 函式庫並令別名為 gr #import numpy as np # 導入 numpy 函式庫並令別名為 np # 定義影像處理函式 sepia() # 輸入: imput_image(影像) # 輸出: sepia_img(影像) def sepia(input_img): sepia_filter = np.array([ [0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131] ]) sepia_img = input_img.dot(sepia_filter.T) # 將影像點乘使其變成棕色 sepia_img /= sepia_img.max() # 進行影像正規化 return sepia_img # 建立輸人及輸出簡單應用界面 # fn: 界面函數名稱, inputs: 輸人影像格式, outputs: 輸出影像 demo = gr.Interface(sepia, gr.Image(), "image") # 執行顯示界面 demo.launch() ``` ![vMaker_EdgeAI_24_Fig05](https://hackmd.io/_uploads/ByIqsiM4ye.jpg) Fig. 5 影像輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15) ### 3.2. 使用 OpenCV 格式影像 如果想要使用 OpenCV 影像格式進行影像處理,在界面函式輸人部份需加上 type="filepath" ,而處理函式部份則需加上 input_img = cv2.imread(input_img) 才能順利工作。 ```python= #import gradio as gr # 導入 Gradio 函式庫並令別名為 gr #import numpy as np # 導入 numpy 函式庫並令別名為 np import cv2 # Colab 預設已安裝 opencv-python # 定義影像處理函式 sepia() # 輸入: imput_image(影像) # 輸出: sepia_img(影像) def sepia(input_img): input_img = cv2.imread(input_img) # 從使用者根目錄讀取影像 sepia_filter = np.array([ [0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131] ]) sepia_img = input_img.dot(sepia_filter.T) # 將影像點乘使其變成棕色 sepia_img /= sepia_img.max() # 進行影像正規化 return sepia_img # 建立輸人及輸出簡單應用界面 # fn: 界面函數名稱, inputs: 輸人影像格式, outputs: 輸出影像 demo = gr.Interface(sepia, gr.Image(type="filepath"), "image") # 執行顯示界面 demo.launch() ``` ![vMaker_EdgeAI_24_Fig06](https://hackmd.io/_uploads/HklPk9MNkg.jpg) Fig. 6 使用 numpy 和 OpenCV 影像格式程式比較。(OmniXRI整理製作, 2024/12/15) ## 4. 基本影音輸出入 為方便測試,會先下載兩個影音檔「Jack_OmniXRI.mp4」、「good_weather.wav」作為 Examples 。 另外為豐富人機界面另外加上四個項目: * title = 標題 * description = 描述 * examples = [ [樣本1影片, 樣本1聲音], [樣本2影片, 樣本2聲音] ] * article = 表單最後註腳,可使用 Markdown 語法 當按下 Examples 中文字時會自動載入影音檔到輸入欄位,若不想使用範例影音,亦可自行拖拉影音檔到輸入區。 這裡的影音處理函式 av_identity 為空的,直接輸出原影音檔,若有需要可在此處增加所需程式。 當按下「Submit」鍵後,會把輸入區之影音複製一份到輸出區。 ```python= #import requests #from pathlib import Path #import sys # 從 Github 下載測試用影音檔並存於使用者根目錄 r = requests.get( url="https://github.com/OmniXRI/Hello_World_Gradio/raw/refs/heads/main/Jack_OmniXRI.mp4", ) with open("Jack_OmniXRI.mp4", "wb") as f: f.write(r.content) r = requests.get( url="https://github.com/OmniXRI/Hello_World_Gradio/raw/refs/heads/main/good_weather_ZH.wav", ) with open("good_weather_ZH.wav", "wb") as f: f.write(r.content) #sys.path.append('./') # 在 Colab 使用者根目錄 ./ 預設在 /content,將其加入方便開啟下載之檔案 #import gradio as gr # 導入 Gradio 函式庫並令別名為 gr # 定義影音處理函式(空處理) # 輸入: video(影片)、audio(聲音) # 輸出: video(影片)、audio(聲音) def av_identity(video, audio): return video, audio # 建立輸人及輸出簡單應用界面 # fn: 界面函數名稱, inputs: 輸人影像格式, outputs: 輸出影像 demo = gr.Interface( fn = av_identity, inputs = [gr.Video(), gr.Audio()], outputs = ["video", "audio"], title = "影音測試", description = "操作說明:上傳影音檔或點擊 Examples 取得影音檔,再點擊 Submit 即可", examples = [["Jack_OmniXRI.mp4", "good_weather_ZH.wav"]], article = "更多資訊可參考 [OmniXRI Github](https://github.com/OmniXRI/Hello_World_Gradio)" ) # 執行顯示界面 demo.launch() ``` ![vMaker_EdgeAI_24_Fig07](https://hackmd.io/_uploads/rkrP1qzVkx.jpg) Fig. 7 自定義影音輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15) ## 小結 透過以上的介紹,相信大家已經對 Gradio 有了一些基本認識,只要透過更複雜的排列組合,就能讓大家更容易創建出屬於自己需求的應用。目前已有很多 AI 相關應用都是使用這項工具,包括大型語言模型對話,影音生成等,在 Hugging Face 上也有許多範例,後續有機會再為大家介紹更進階的應用。 ## 參考文獻 [1] Gradio, Home Page & Github https://www.gradio.app/ https://github.com/gradio-app/gradio [2] Gradio, Documentation - interface https://www.gradio.app/docs/gradio/interface ## 延伸閱讀 [A] Hugging Face, Gradio 塊簡介(NLP Coures) https://huggingface.co/learn/nlp-course/zh-TW/chapter9/7 **本文同步發表在[【台灣自造者 vMaker】](https://vmaker.tw/archives/category/%e5%b0%88%e6%ac%84/jack-omnixri)** --- OmniXRI 整理製作,歡迎點贊、收藏、訂閱、留言、分享 ###### tags: `vMaker` `Edge AI`