LLM 課程文件
Gradio Blocks 簡介
並獲得增強的文件體驗
開始使用
Gradio Blocks 簡介
在前面的章節中,我們已經使用 `Interface` 類探索並建立了演示。在本節中,我們將介紹我們**新開發的**低階 API,稱為 `gradio.Blocks`。
那麼,`Interface` 和 `Blocks` 有什麼區別呢?
⚡ `Interface`:一個高階 API,允許您透過提供輸入和輸出列表來簡單地建立完整的機器學習演示。
🧱 `Blocks`:一個低階 API,允許您完全控制應用程式的資料流和佈局。您可以使用 `Blocks` 構建非常複雜的多步應用程式(就像“積木”一樣)。
為什麼選擇 Blocks 🧱?
正如我們在前幾節中看到的,`Interface` 類允許您輕鬆地用幾行程式碼建立功能齊全的機器學習演示。`Interface` API 極其易於使用,但缺乏 `Blocks` API 提供的靈活性。例如,您可能希望:
- 將相關的演示分組為單個 Web 應用程式中的多個選項卡。
- 更改演示的佈局,例如指定輸入和輸出的位置。
- 擁有多步介面,其中一個模型的輸出成為下一個模型的輸入,或者通常具有更靈活的資料流。
- 根據使用者輸入更改元件的屬性(例如,下拉列表中的選擇)或其可見性。
我們將在下面探討所有這些概念。
使用 Blocks 建立一個簡單的演示
安裝 Gradio 後,將以下程式碼作為 Python 指令碼、Jupyter Notebook 或 Colab Notebook 執行。
import gradio as gr
def flip_text(x):
return x[::-1]
demo = gr.Blocks()
with demo:
gr.Markdown(
"""
# Flip Text!
Start typing below to see the output.
"""
)
input = gr.Textbox(placeholder="Flip this text")
output = gr.Textbox()
input.change(fn=flip_text, inputs=input, outputs=output)
demo.launch()
上面這個簡單的例子介紹了 Blocks 所依賴的 4 個概念:
透過在 `with gradio.Blocks` 上下文中使用 Python 例項化物件,Blocks 允許您構建結合了 Markdown、HTML、按鈕和互動式元件的 Web 應用程式。
🙋 如果您不熟悉 Python 中的 `with` 語句,我們建議您檢視 Real Python 提供的精彩教程。閱讀完後請回到這裡 🤗您例項化元件的順序很重要,因為每個元素都按照其建立的順序渲染到 Web 應用程式中。(更復雜的佈局將在下面討論)您可以在程式碼中的任何位置定義常規 Python 函式,並使用 `Blocks` 透過使用者輸入執行它們。在我們的示例中,我們有一個簡單的函式來“翻轉”輸入文字,但您可以編寫任何 Python 函式,從簡單的計算到處理機器學習模型的預測。
您可以將事件分配給任何 `Blocks` 元件。當元件被點選、更改等時,這將執行您的函式。當您分配事件時,您需要傳遞三個引數:`fn`:應呼叫的函式,`inputs`:輸入元件(列表),以及 `outputs`:應更新的輸出元件(列表)。
在上面的示例中,當名為 `input` 的 `Textbox` 中的值發生變化時,我們執行 `flip_text()` 函式。該事件讀取 `input` 中的值,將其作為 `name` 引數傳遞給 `flip_text()`,然後返回一個值,該值被分配給我們的第二個名為 `output` 的 `Textbox`。
要檢視每個元件支援的事件列表,請參閱 Gradio 文件。
Blocks 會根據您定義的事件觸發器自動判斷元件是否應具有互動性(接受使用者輸入)。在我們的示例中,第一個文字框是互動式的,因為它的值被 `flip_text()` 函式使用。第二個文字框不具有互動性,因為它的值從不作為輸入使用。在某些情況下,您可能希望覆蓋此行為,您可以透過向元件的 `interactive` 引數傳遞布林值來實現(例如 `gr.Textbox(placeholder="翻轉此文字", interactive=True)`)。
自定義演示佈局
我們如何使用 `Blocks` 來自定義演示的佈局?預設情況下,`Blocks` 會將您建立的元件垂直渲染為一列。您可以透過建立額外的列 `with gradio.Column():` 或行 `with gradio.Row():` 並在這些上下文中建立元件來更改此設定。
您應該記住:在 `Column`(這也是預設設定)下建立的任何元件都將垂直佈局。在 `Row` 下建立的任何元件都將水平佈局,類似於 Web 開發中的 Flexbox 模型。
最後,您還可以透過使用 `with gradio.Tabs()` 上下文管理器為您的演示建立選項卡。在此上下文中,您可以透過指定 `with gradio.TabItem(name_of_tab):` 子級來建立多個選項卡。在 `with gradio.TabItem(name_of_tab):` 上下文中建立的任何元件都將顯示在該選項卡中。
現在,讓我們向演示中新增 `flip_image()` 函式,並新增一個用於翻轉影像的新選項卡。下面是一個包含 2 個選項卡並使用行的示例:
import numpy as np
import gradio as gr
demo = gr.Blocks()
def flip_text(x):
return x[::-1]
def flip_image(x):
return np.fliplr(x)
with demo:
gr.Markdown("Flip text or image files using this demo.")
with gr.Tabs():
with gr.TabItem("Flip Text"):
with gr.Row():
text_input = gr.Textbox()
text_output = gr.Textbox()
text_button = gr.Button("Flip")
with gr.TabItem("Flip Image"):
with gr.Row():
image_input = gr.Image()
image_output = gr.Image()
image_button = gr.Button("Flip")
text_button.click(flip_text, inputs=text_input, outputs=text_output)
image_button.click(flip_image, inputs=image_input, outputs=image_output)
demo.launch()
您會注意到,在此示例中,我們還在每個選項卡中建立了一個 `Button` 元件,併為每個按鈕分配了一個點選事件,這實際上就是執行函式的原因。
探索事件和狀態
正如您可以控制佈局一樣,`Blocks` 允許您精細控制哪些事件觸發函式呼叫。每個元件和許多佈局都支援特定的事件。
例如,`Textbox` 元件有兩個事件:`change()`(當文字框內的值發生變化時)和 `submit()`(當用戶在文字框聚焦時按下回車鍵時)。更復雜的元件可以有更多的事件:例如,`Audio` 元件還有單獨的事件用於音訊檔案播放、清除、暫停等。請參閱文件以瞭解每個元件支援的事件。
您可以將事件觸發器附加到無、一個或多個這些事件。您可以透過將事件名稱作為函式在元件例項上呼叫來建立事件觸發器——例如 `textbox.change(...)` 或 `btn.click(...)`。該函式接受三個引數,如上所述:
- `fn`:要執行的函式
- `inputs`:一個(或多個)元件,其值應作為函式的輸入引數提供。每個元件的值按順序對映到相應的函式引數。如果函式不接受任何引數,則此引數可以為 None。
- `outputs`:一個(或多個)元件,其值應根據函式返回的值進行更新。每個返回值按順序設定相應元件的值。如果函式不返回任何內容,則此引數可以為 None。
您甚至可以使輸入和輸出元件是同一個元件,就像我們在使用 GPT 模型進行文字補全的示例中那樣:
import gradio as gr
api = gr.Interface.load("huggingface/EleutherAI/gpt-j-6B")
def complete_with_gpt(text):
# Use the last 50 characters of the text as context
return text[:-50] + api(text[-50:])
with gr.Blocks() as demo:
textbox = gr.Textbox(placeholder="Type here and press enter...", lines=4)
btn = gr.Button("Generate")
btn.click(complete_with_gpt, textbox, textbox)
demo.launch()
建立多步演示
在某些情況下,您可能需要一個*多步驟演示*,其中您將一個函式的輸出重新用作下一個函式的輸入。使用 `Blocks` 很容易做到這一點,因為您可以將一個元件用作一個事件觸發器的輸入,但作為另一個事件觸發器的輸出。請看下面示例中的文字元件,它的值是語音轉文字模型的結果,但也傳遞給了情感分析模型。
from transformers import pipeline
import gradio as gr
asr = pipeline("automatic-speech-recognition", "facebook/wav2vec2-base-960h")
classifier = pipeline("text-classification")
def speech_to_text(speech):
text = asr(speech)["text"]
return text
def text_to_sentiment(text):
return classifier(text)[0]["label"]
demo = gr.Blocks()
with demo:
audio_file = gr.Audio(type="filepath")
text = gr.Textbox()
label = gr.Label()
b1 = gr.Button("Recognize Speech")
b2 = gr.Button("Classify Sentiment")
b1.click(speech_to_text, inputs=audio_file, outputs=text)
b2.click(text_to_sentiment, inputs=text, outputs=label)
demo.launch()
更新元件屬性
到目前為止,我們已經瞭解瞭如何建立事件來更新另一個元件的值。但是,如果您想更改元件的其他屬性,例如文字框的可見性或單選按鈕組中的選擇,該怎麼辦?您可以透過返回元件類的 `update()` 方法而不是函式中的常規返回值來實現。
這最容易透過一個例子來說明:
import gradio as gr
def change_textbox(choice):
if choice == "short":
return gr.Textbox.update(lines=2, visible=True)
elif choice == "long":
return gr.Textbox.update(lines=8, visible=True)
else:
return gr.Textbox.update(visible=False)
with gr.Blocks() as block:
radio = gr.Radio(
["short", "long", "none"], label="What kind of essay would you like to write?"
)
text = gr.Textbox(lines=2, interactive=True)
radio.change(fn=change_textbox, inputs=radio, outputs=text)
block.launch()
我們剛剛探索了 `Blocks` 的所有核心概念!就像 `Interfaces` 一樣,您可以透過在 `launch()` 方法中使用 `share=True` 或部署到 Hugging Face Spaces 來建立可共享的酷炫演示。
< > 在 GitHub 上更新