Gradio 月活用户达到 100 万的旅程!
阅读更多Gradio 月活用户达到 100 万的旅程!
阅读更多本指南将涵盖你实现自定义组件的后端处理所需了解的一切内容。
所有组件都继承自 Component
、FormComponent
或 BlockContext
这三个类之一。你需要继承其中一个,以便你的组件的行为与其他所有 Gradio 组件一样。当你使用 gradio cc create --template
从模板开始时,你无需担心选择哪个,因为模板会使用正确的那个。为了完整性,以及在你需要从头开始创建自己的组件的情况下,我们解释了每个类的用途。
FormComponent
:当你想将你的组件与其他 FormComponents
一起分组在同一个 Form
布局中时,请使用它。Slider
、Textbox
和 Number
组件都是 FormComponents
。BlockContext
:当你想将其他组件“放置”在你的组件“内部”时,请使用它。这将启用 with MyComponent() as component:
语法。Component
:在所有其他情况下使用它。提示: 如果你的组件支持流式输出,请从 `StreamingOutput` 类继承。
提示: 如果你从 `BlockContext` 继承,你还需要将元类设置为 `ComponentMeta`。请参见下面的示例。
from gradio.blocks import BlockContext
from gradio.component_meta import ComponentMeta
@document()
class Row(BlockContext, metaclass=ComponentMeta):
pass
当你从这些类中的任何一个继承时,必须实现以下方法。否则,当你实例化你的组件时,Python 解释器将引发错误!
preprocess
和 postprocess
在关键概念指南中解释。它们处理从前端发送的数据到 Python 函数预期格式的转换。
def preprocess(self, x: Any) -> Any:
"""
Convert from the web-friendly (typically JSON) value in the frontend to the format expected by the python function.
"""
return x
def postprocess(self, y):
"""
Convert from the data returned by the python function to the web-friendly (typically JSON) value expected by the frontend.
"""
return y
process_example
接受原始 Python 值,并返回应在应用中的示例预览中显示的修改后的值。如果未提供,则改用 .postprocess()
方法。让我们看一下 SimpleDropdown
组件的以下示例。
def process_example(self, input_data):
return next((c[0] for c in self.choices if c[1] == input_data), None)
由于 self.choices
是对应于(display_name
,value
)的元组列表,因此这会将用户提供的值转换为显示值(或者如果该值不存在于 self.choices
中,则将其转换为 None
)。
api_info
preprocess
期望的值的 JSON 模式表示。这为通过 Gradio 客户端的 API 使用提供支持。如果你的组件指定了 data_model
,你不需要自己实现此方法。请参阅以下部分中的 data_model
。
def api_info(self) -> dict[str, list[str]]:
"""
A JSON-schema representation of the value that the `preprocess` expects and the `postprocess` returns.
"""
pass
example_payload
你的组件的示例有效负载,例如可以传递到组件的 .preprocess()
方法中的内容。示例输入显示在使用你的自定义组件的 Gradio 应用的 View API
页面中。必须是 JSON 可序列化的。如果你的组件需要文件,最好使用公开可访问的 URL。
def example_payload(self) -> Any:
"""
The example inputs for this component for API usage. Must be JSON-serializable.
"""
pass
example_value
组件的示例值,例如,可以传递到组件的 .postprocess()
方法中的值。这用作自定义组件开发中创建的默认应用程序中的示例值。
def example_payload(self) -> Any:
"""
The example inputs for this component for API usage. Must be JSON-serializable.
"""
pass
flag
将组件的值写入可以存储在用于标记的 csv
或 json
文件中的格式。如果您的组件指定了 data_model
,则您不需要自己实现此操作。 data_model
在以下部分中介绍。
def flag(self, x: Any | GradioDataModel, flag_dir: str | Path = "") -> str:
pass
read_from_flag
从用于标记的 csv
或 json
文件中存储的格式转换为组件的 python value
。如果您的组件指定了 data_model
,则您不需要自己实现此操作。 data_model
在以下部分中介绍。
def read_from_flag(
self,
x: Any,
) -> GradioDataModel | Any:
"""
Convert the data from the csv or jsonl file into the component state.
"""
return x
data_model
data_model
是您定义组件的值将存储在前端的预期数据格式的方式。它指定了您的 preprocess
方法期望的数据格式以及 postprocess
方法返回的格式。为您的组件定义 data_model
不是必需的,但它极大地简化了创建自定义组件的过程。如果您定义了自定义组件,您只需要实现四个方法 - preprocess
、postprocess
、example_payload
和 example_value
!
您可以通过定义一个继承自 GradioModel
或 GradioRootModel
的 pydantic 模型 来定义 data_model
。
最好通过一个示例来解释这一点。让我们看一下核心 Video
组件,它将视频数据存储为 JSON 对象,其中包含两个键 video
和 subtitles
,它们指向单独的文件。
from gradio.data_classes import FileData, GradioModel
class VideoData(GradioModel):
video: FileData
subtitles: Optional[FileData] = None
class Video(Component):
data_model = VideoData
通过添加这四行代码,您的组件将自动实现 API 使用、标记方法和示例缓存方法所需的方法!它还具有自文档化代码的额外好处。任何阅读您的组件代码的人都将确切地知道它期望的数据。
提示: 如果您的组件期望从前端上传文件,则您必须使用 FileData
模型!这将在以下部分中解释。
提示: 在[此处](https://docs.pydantic.org.cn/latest/concepts/models/#basic-model-usage)阅读 pydantic 文档。
GradioModel
和 GradioRootModel
之间的区别在于 RootModel
不会将数据序列化为字典。例如,Names
模型会将数据序列化为 {'names': ['freddy', 'pete']}
,而 NamesRoot
模型会将其序列化为 ['freddy', 'pete']
。
from typing import List
class Names(GradioModel):
names: List[str]
class NamesRoot(GradioRootModel):
root: List[str]
即使您的组件不期望“复杂”的 JSON 数据结构,定义 GradioRootModel
也是有益的,这样您就不必担心实现 API 和标记方法。
提示: 使用 Python typing 库中的类来键入您的模型。例如,使用 `List` 而不是 `list`。
如果您的组件期望上传文件作为输入,或将保存的文件返回到前端,则您必须使用 FileData
来键入 data_model
中的文件。
当您使用 FileData
时
Gradio 知道它应该允许将此文件提供给前端。 Gradio 自动阻止服务任意计算机中服务器上文件的请求。
Gradio 会自动将文件放置在缓存中,以便不保存文件的重复副本。
客户端库将自动知道它们应该在发送请求之前上传输入文件。它们还将自动下载文件。
如果您不使用 FileData
,您的组件将无法按预期工作!
您的组件的事件触发器在 EVENTS
类属性中定义。这是一个列表,其中包含事件的字符串名称。将事件添加到此列表将自动向您的组件添加具有相同名称的方法!
您可以从 gradio.events
导入 Events
枚举,以访问核心 gradio 组件中常用的事件。
例如,以下代码将在 MyComponent
类中定义 text_submit
、file_upload
和 change
方法。
from gradio.events import Events
from gradio.components import FormComponent
class MyComponent(FormComponent):
EVENTS = [
"text_submit",
"file_upload",
Events.change
]
提示: 不要忘记在 JavaScript 代码中也处理这些事件!