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 笔记本或 Colab 笔记本运行。
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 个基本概念
Blocks 允许您构建 Web 应用程序,该应用程序通过在
with gradio.Blocks
上下文中实例化 Python 对象,将 Markdown、HTML、按钮和交互式组件组合在一起。🙋如果您不熟悉 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 个选项卡的示例,并且还使用了 Row
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
组件,并且我们为每个按钮分配了一个 click 事件,这实际上是运行函数的原因。
探索事件和状态
就像您可以控制布局一样,Blocks
使您可以细粒度地控制哪些事件触发函数调用。每个组件和许多布局都有它们支持的特定事件。
例如,Textbox
组件有 2 个事件:change()
(当文本框内的值更改时)和 submit()
(当用户在聚焦在文本框上时按下 Enter 键时)。更复杂的组件可能具有更多事件:例如,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 上来共享。