1. 自定义组件
  2. 关键组件概念

Gradio 组件:关键概念

在本节中,我们讨论了在Gradio中关于组件的一些重要概念。 在开发自己的组件时,理解这些概念非常重要。 否则,你的组件可能会与其他Gradio组件的行为大不相同!

提示: 如果您熟悉Gradio库的内部结构,例如每个组件的预处理和后处理方法,可以跳过此部分。

交互式 vs 静态

Gradio中的每个组件都有一个static变体,大多数组件还有一个interactive版本。 当组件显示一个值,并且用户不能通过与之交互来更改该值时,使用static版本。 当用户能够通过Gradio UI交互来更改值时,使用interactive版本。

让我们看一些例子:

import gradio as gr

with gr.Blocks() as demo:
   gr.Textbox(value="Hello", interactive=True)
   gr.Textbox(value="Hello", interactive=False)

demo.launch()

这将显示两个文本框。 唯一的区别是:你将能够编辑顶部的Gradio组件的值,而你将无法编辑底部的变体(即文本框将被禁用)。

也许一个更有趣的例子是使用 Image 组件:

import gradio as gr

with gr.Blocks() as demo:
   gr.Image(interactive=True)
   gr.Image(interactive=False)

demo.launch()

组件的交互版本要复杂得多——你可以上传图片或从网络摄像头拍摄照片——而静态版本只能用于显示图片。

并非每个组件都有独特的交互版本。例如,gr.AnnotatedImage 仅作为静态版本出现,因为无法交互式地更改注释或图像的值。

你需要记住的内容

  • 如果某个组件被用作任何事件的输入,Gradio将使用该组件的交互版本(如果有);否则,将使用静态版本。

  • 当你设计自定义组件时,你必须在Python类的构造函数中接受布尔类型的交互关键字。在前端,你可以接受interactive属性,这是一个bool类型,表示组件应该是静态的还是交互的。如果你在前端不使用这个属性,组件在交互或静态模式下看起来是一样的。

值及其预处理/后处理方式

组件最重要的属性是它的value。 每个组件都有一个value。 这个值通常由用户在前端设置(如果组件是交互式的)或显示给用户(如果它是静态的)。 当用户触发事件时,这个值也会被发送到后端函数,或者由用户的函数返回,例如在预测结束时。

因此,这个值被传递了很多次,但有时在前端和后端之间需要改变值的格式。 看看这个例子:

import numpy as np
import gradio as gr

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

demo = gr.Interface(sepia, gr.Image(width=200, height=200), "image")
demo.launch()

这将创建一个Gradio应用程序,其中包含一个Image组件作为输入和输出。 在前端,Image组件实际上会将文件上传到服务器并发送文件路径,但在发送到用户函数之前,它会被转换为numpy数组。 相反,当用户从他们的函数返回一个numpy数组时,numpy数组会被转换为文件,以便可以发送到前端并由Image组件显示。

提示: 默认情况下,`Image` 组件将 numpy 数组发送到 python 函数,因为这是机器学习工程师的常见选择,尽管 `Image` 组件也支持使用 `type` 参数的其他格式。阅读 `Image` 文档 [here](https://www.gradio.app/docs/image) 以了解更多信息。

每个组件执行两次转换:

  1. preprocess: 将前端发送的value从格式转换为python函数期望的格式。这通常涉及从适合网络的JSON结构转换为python原生数据结构,如numpy数组或PIL图像。AudioImage组件是preprocess方法的良好示例。

  2. postprocess: 将python函数返回的值转换为前端预期的格式。这通常涉及从python原生数据结构(如PIL图像)转换为JSON结构。

你需要记住的内容

  • 每个组件都必须实现 preprocesspostprocess 方法。在极少数情况下,如果不需要进行任何转换,只需按原样返回值。TextboxNumber 就是这种情况的例子。

  • 作为组件作者,控制着前端显示的数据格式以及使用您组件的人将接收到的数据格式。考虑一个Python开发者会觉得直观的人体工程学数据结构,并通过preprocesspostprocess控制从Web友好的JSON数据结构(反之亦然)的转换。

组件的“示例版本”

Gradio 应用程序支持提供示例输入——这些示例输入在帮助用户开始使用您的 Gradio 应用程序时非常有用。 在 gr.Interface 中,您可以使用 examples 关键字提供示例,而在 Blocks 中,您可以使用特殊的 gr.Examples 组件提供示例。

在此截图的底部,我们展示了一个猎豹的微型示例图像,点击时,将在输入图像组件中填充相同的图像:

img

要启用示例视图,您必须在frontend目录的顶部拥有以下两个文件:

  • Example.svelte: 这对应于你组件的“示例版本”
  • Index.svelte: 这对应于“常规版本”

在后端,通常不需要做任何事情。用户提供的示例value使用前面描述的相同.postprocess()方法进行处理。如果你想以不同的方式处理数据(例如,如果.postprocess()方法计算成本高),那么你可以为你的自定义组件编写自己的.process_example()方法,它将代替使用。

Example.svelte 文件和 process_example() 方法将在专门的 前端后端 指南中分别进行更深入的介绍。

你需要记住的内容

  • 如果您期望您的组件被用作输入,定义一个“示例”视图是很重要的。
  • 如果不这样做,Gradio 将使用默认的,但它不会像它可能的那样信息丰富!

结论

现在你已经了解了关于Gradio组件最重要的部分,你可以开始设计和构建你自己的组件了!