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 上更新