Gradio 原本去年底我就大致測試完畢, 但最近在測試 DuckDuckGo API 時發現它還有一個好用的 Block 元件, 可以用來自訂 web app 版面, 讓開發者可以更靈活地排列各種 UI 元件, 此外它也提供狀態管理與事件處理功能, 非常適合用來製作 AI 聊天機器人或 Dashboard (儀錶板) 等較複雜的應用程式介面.
本系列文章索引參考 :
十一. 用 Block 元件自訂 web app 版面 :
在之前的 Gradio 測試中, 我們都使用 Interface 類別來建立 web app 的標準網頁介面, 只要用 inputs, outputs, 以及 fn 參數指定輸出入元件與 Submit 按鈕之處理函式即可簡單地建立應用程式介面. 但若要建立結構較複雜的 App, 則 Interface 所提供的簡單且固定的版面就不敷使用了, 這時就需要用到 Blocks 與 Row, Column, Tab, 或 Acordion 等布局元件來自行為介面排版.
Blocks 類別是一個比 Interface 類別還低階的 API, 呼叫其建構式 Blocks() 會建立一個 Blocks 物件 :
>>> import gradio as gr
>>> blocks=gr.Blocks()
>>> type(blocks)
<class 'gradio.blocks.Blocks'>
用 Blocks 布局元件時需要用到 with 語法形成一個語境 (context) 區塊, 然後在此語境內使用 Row, Column, Tab, 或 Acordion 等布局元件為其他 UI 元件進行排版 (也都使用 with 語法) :
with gr.Blocks() as blocks:
# 在此 context 內進行 UI 元件布局
with gr.Row(): # 列布局
# 放置水平排列的 UI 元件 (由左向右)
with gr.Column():
# 放置垂直排列的 UI 元件 (由上而下)
with gr.Tab():
# 放置第一個頁籤內的 UI 元件 (由左向右)
with gr.Tab():
# 放置第二個頁籤內的 UI 元件 (由左向右)
with gr.Acordion():
# 放置手風琴內的 UI 元件 (由左向右)
使用 with 語法的好處是能確保 Blocks 物件在執行完 with 語境後能自動釋放資源, 在語境內部建立的 UI 元件都會被自動加入 Blocks 物件內, 使程式碼更整潔更有可讀性.
最後在語境外呼叫 Blocks 物件的 launch() 方法即可發布 web app :
blocks.launch()
1. 僅使用 Blocks 排版 :
這種排版方式不使用 Row, Column, Tab, 或 Acordion 等布局元件, 直接將 UI 元件放在 Blocks 語境內, 這時 UI 元件會流水式依序由左向右, 由上而下排列, 例如下面將輸入文字轉成大寫的簡單範例中, 我們直接在 blocks 語境內建立了一個 TextBox 輸入與輸出元件, 以及一個 Button 元件 :
>>> with blocks:
in1=gr.Textbox(label="輸入文字")
btn=gr.Button("送出")
out1=gr.Textbox(label="輸出結果")
btn.click(lambda in1: in1.upper(), inputs=in1, outputs=out1)
{'id': 0, 'targets': [(6, 'click')], 'inputs': [5], 'outputs': [7], 'backend_fn': True, 'js': None, 'queue': True, 'api_name': 'lambda', 'scroll_to_output': False, 'show_progress': 'full', 'batch': False, 'max_batch_size': 4, 'cancels': [], 'types': {'generator': False, 'cancel': False}, 'collects_event_data': False, 'trigger_after': None, 'trigger_only_on_success': False, 'trigger_mode': 'once', 'show_api': True, 'zerogpu': False, 'rendered_in': None, 'connection': 'sse', 'time_limit': None, 'stream_every': 0.5, 'like_user_message': False, 'event_specific_args': None}
其中 Button 物件的第一個參數是按鈕事件的處理函式, 並且用關鍵字 inputs 要傳入此函式的輸入元件, 以及用 outputs 指定接收函式傳回值的輸出元件.
接著只要呼叫 Blocks 物件的 launch() 方法發布此 web app :
>>> blocks.launch()
* Running on local URL: http://127.0.0.1:7860
To create a public link, set `share=True` in `launch()`.
結果如下 :
按鈕事件處理函式也可以用 def 來定義, 然後於 click() 方法中以 fn 參數指定 :
import gradio as gr
def handler(text):
return text.upper()
with gr.Blocks() as blocks:
in1=gr.Textbox(label="輸入文字")
btn=gr.Button("送出")
out1=gr.Textbox(label="輸出結果")
btn.click(fn=handler , inputs=in1, outputs=out1)
blocks.launch()
結果是一樣的.
2. 使用 Row 列布局元件排版 :
Row 類別用來將 UI 元件以水平方式 (由左向右) 做橫列排版, 呼叫其建構式 Row() 即可建立一個列布局物件, 與 Blocks 物件用法一樣, 也是使用 with gr.Row() 用法建立一個 Row 物件語境, 然後在其內佈放 UI 物件, 例如 :
import gradio as gr
def handler(text):
return text.upper()
with gr.Blocks() as blocks:
with gr.Row():
in1=gr.Textbox(label="輸入文字")
btn=gr.Button("送出")
out1=gr.Textbox(label="輸出結果")
btn.click(fn=handler , inputs=in1, outputs=out1)
blocks.launch()
此處 in1, btn, 與 out1 三個 UI 元件佈放在 Row 物件的語境內, 它們會被水平排列於版面中, 結果如下 :
可見三個 UI 元件以橫列方式水平排列.
3. 使用 Column 行布局元件排版 :
Column 類別用來將 UI 元件以垂直方式 (由上而下) 做垂直排版, 呼叫其建構式 Column() 即可建立一個行布局物件, 與 Blocks 物件用法一樣, 也是使用 with gr.Column() 用法建立一個 Column 物件語境, 然後在其內佈放 UI 物件, 例如 :
# gradio_blocks_test_3.py
import gradio as gr
def handler(text):
return text.upper()
with gr.Blocks() as blocks:
with gr.Column():
in1=gr.Textbox(label="輸入文字")
btn=gr.Button("送出")
out1=gr.Textbox(label="輸出結果")
btn.click(fn=handler , inputs=in1, outputs=out1)
blocks.launch()
此處 in1, btn, 與 out1 三個 UI 元件佈放在 Column 物件的語境內, 它們會被垂直排列於版面中, 結果如下 :
可見這與上面直接在 Blocks 物件內排版的效果是一樣的.
4. 使用 Tab 頁籤布局元件排版 :
Tab 類別用來將 UI 元件以頁籤的方式排版, 呼叫其建構式 Tab() 並傳入頁籤標題即可建立一個頁籤布局物件, 與 Blocks 物件用法一樣, 也是使用 with gr.Tab() 用法建立一個 Tab 物件語境, 然後在其內佈放 UI 物件, 通常需要建立一個以上的 Tab 語境來各自佈放頁籤內之 UI 元件, 例如 :
# gradio_blocks_test_4.py
import gradio as gr
def upper(text):
return text.upper()
def lower(text):
return text.lower()
with gr.Blocks() as blocks:
with gr.Tab('轉成大寫'):
in1=gr.Textbox(label="輸入文字")
btn1=gr.Button("送出")
out1=gr.Textbox(label="輸出結果")
with gr.Tab('轉成小寫'):
in2=gr.Textbox(label="輸入文字")
btn2=gr.Button("送出")
out2=gr.Textbox(label="輸出結果")
btn1.click(fn=upper, inputs=in1, outputs=out1)
btn2.click(fn=lower, inputs=in2, outputs=out2)
blocks.launch()
此處建立了兩個頁籤物件, 並在各自語境下佈放 UI 元件, 分別達成轉大寫與轉小寫的 web app 功能, 結果如下 :
按頁籤標題即可切換至轉大寫與轉小寫之頁籤.
5. 使用 Accordion 手風琴布局元件排版 :
Accordion 類別用來將 UI 元件以手風琴版面方式排版, 呼叫其建構式 Accordion() 並傳入標題 (第一參數) 即可建立一個手風琴版面物件, 與 Blocks 物件用法一樣, 也是使用 with gr.Accordion() 用法建立一個 Accordion 物件語境, 然後在其內佈放 UI 物件. 手風琴預設是開啟的, 但可以傳入 open=False 將其關閉, 例如 :
# gradio_blocks_test_5.py
import gradio as gr
def upper(text):
return text.upper()
def lower(text):
return text.lower()
with gr.Blocks() as blocks:
with gr.Accordion('轉成大寫'):
in1=gr.Textbox(label="輸入文字")
btn1=gr.Button("送出")
out1=gr.Textbox(label="輸出結果")
with gr.Accordion('轉成小寫', open=False):
in2=gr.Textbox(label="輸入文字")
btn2=gr.Button("送出")
out2=gr.Textbox(label="輸出結果")
btn1.click(fn=upper, inputs=in1, outputs=out1)
btn2.click(fn=lower, inputs=in2, outputs=out2)
blocks.launch()
此例建立了兩個手風琴物件, 分別佈放轉大寫與轉小寫的 UI 元件, 其中轉大寫的預設是開啟, 轉小寫的社為關閉, 初始化時結果如下 :
按手風琴右邊的三角形按鈕可以收合或開啟版面 :
這是關閉轉大寫, 開啟轉小寫版面的效果.
沒有留言:
張貼留言