Gradio Agents & MCP 黑客松
获奖者Gradio Agents & MCP 黑客松
获奖者本指南将涵盖实现自定义组件后端处理所需的一切知识。
所有组件都继承自三个类之一:Component
、FormComponent
或 BlockContext
。你需要继承其中一个,以便你的组件能像所有其他 Gradio 组件一样运行。当你使用 gradio cc create --template
从模板开始时,你无需担心选择哪个,因为模板会使用正确的那个。为了完整性,以及在你需要从零开始创建自己的组件时,我们解释了每个类的用途。
FormComponent
:当你希望你的组件与其他 FormComponent
组件一起分组在同一个 Form
布局中时,请使用此项。Slider
、Textbox
和 Number
组件都是 FormComponent
。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-schema 表示。这通过 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` 模型来定义文件类型!这将在下一节中解释。
提示: 阅读 pydantic 文档 [此处](https://docs.pydantic.org.cn/latest/concepts/models/#basic-model-usage)。
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`。
如果你的组件期望上传文件作为输入,或者向前端返回已保存的文件,则你必须在 data_model
中使用 FileData
来定义文件类型。
当你使用 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 代码中处理这些事件!