1. 自定义组件
  2. 记录自定义组件

记录自定义组件

在4.15版本中,我们在Gradio CLI中添加了一个新的gradio cc docs命令,用于为您的自定义组件生成丰富的文档。此命令将自动为用户生成文档,但要充分利用它,您需要做一些事情。

如何使用它?

文档将在运行gradio cc build时生成。你可以传递--no-generate-docs参数来关闭此行为。

还有一个独立的docs命令,允许更大的自定义。如果你手动运行这个命令,应该在pyproject.toml中的version被提升之后但在构建组件之前运行。

所有参数都是可选的。

gradio cc docs
  path # The directory of the custom component.
  --demo-dir # Path to the demo directory.
  --demo-name # Name of the demo file
  --space-url # URL of the Hugging Face Space to link to
  --generate-space # create a documentation space.
  --no-generate-space # do not create a documentation space
  --readme-path # Path to the README.md file.
  --generate-readme # create a REAMDE.md file
  --no-generate-readme # do not create a README.md file
  --suppress-demo-check # suppress validation checks and warnings

生成了什么?

gradio cc docs 命令将生成一个交互式的 Gradio 应用程序和一个包含各种功能的静态 README 文件。你可以在这里看到一个示例:

README.md 和 space 都具有以下特点:

  • Description.
  • Installation instructions.
  • A fully functional code snippet.
  • 可选的链接到 PyPi、GitHub 和 Hugging Face Spaces。
  • API文档包括:
    • 组件初始化的参数表,显示类型、默认值和描述。
    • 描述组件如何影响用户的预测函数。
    • 事件及其描述的表。
    • 在初始化或预处理器或后处理器中可能使用的任何其他接口或类。

此外,Gradio 还包括:

  • 一个实时演示。
  • 参数表的更丰富、交互式版本。
  • More beautiful styles!

我需要做什么?

文档生成器使用现有标准来提取必要的信息,即类型提示和文档字符串。没有特定于Gradio的API用于文档生成,因此遵循最佳实践通常会得到最佳结果。

如果您已经在组件源代码中使用类型提示和文档字符串,那么您不需要做太多工作就可以从这个功能中受益,但有一些细节您应该注意。

Python 版本

为了获得最佳的文档体验,生成文档时需要使用 Python 3.10 或更高版本。这是因为用于生成文档的一些内省功能仅在 3.10 中添加。

类型提示

Python 类型提示被广泛用于为用户提供有用的信息。

What are type hints?

如果你需要更熟悉Python中的类型提示,它们是一种简单的方式来表达函数和方法的参数和返回值预期的Python类型。它们提供了有用的编辑器内体验,有助于维护,并与各种其他工具集成。这些类型可以是简单的原始类型,如list str bool;它们也可以是更复杂的类型,如list[str]str | Nonetuple[str, float | int];或者它们可以是使用实用类如TypedDict的更复杂类型。

阅读更多关于Python中的类型提示。

我需要为哪些内容添加提示?

你不需要为代码的每个部分添加类型提示。为了使文档正常工作,你需要为以下组件方法添加类型提示:

  • __init__ 参数应该被类型化。
  • postprocess 参数和返回值应该被类型化。
  • preprocess 参数和返回值应该被类型化。

如果您正在使用gradio cc create,这些类型应该已经存在,但您可能需要根据所做的任何更改进行调整。

__init__

在这里,您只需要输入参数。如果您已经使用gradio cc create`克隆了一个模板,这些应该已经设置好了。您只需要为您添加或更改的内容添加新的提示:

def __init__(
  self,
  value: str | None = None,
  *,
  sources: Literal["upload", "microphone"] = "upload,
  every: Timer | float | None = None,
  ...
):
  ...
preprocesspostprocess

preprocesspostprocess 方法决定了传递给用户函数的值以及需要返回的值。

即使你的组件设计主要是作为输入或输出,也值得为输入参数和返回值添加类型提示,因为Gradio无法限制组件的使用方式。

在这种情况下,我们特别关心:

  • preprocess的返回类型。
  • postprocess的输入类型。
def preprocess(
  self, payload: FileData | None # input is optional
) -> tuple[int, str] | str | None:

# user function input  is the preprocess return ▲
# user function output is the postprocess input ▼

def postprocess(
  self, value: tuple[int, str] | None
) -> FileData | bytes | None: # return is optional
  ...

文档字符串

Docstrings 也被广泛用于提取 API 中某些部分的更有意义、人类可读的描述。

What are docstrings?

如果您需要更熟悉Python中的文档字符串(docstrings),它们是一种用人类可读的决策和解释来注释代码部分的方式。它们提供了丰富的编辑器内体验,如类型提示,但与类型提示不同,它们没有任何特定的语法要求。它们是简单的字符串,几乎可以采取任何形式。唯一的要求是它们出现的位置。文档字符串应该是“出现在模块、函数、类或方法定义中的第一个语句的字符串字面量”。

阅读更多关于Python文档字符串的内容。

虽然文档字符串没有任何语法要求,但出于文档目的,我们需要一个特定的结构。

与类型提示一样,我们关心的具体信息如下:

  • __init__ 参数文档字符串。
  • preprocess 返回文档字符串。
  • postprocess 输入参数的文档字符串。

其他所有内容都是可选的。

文档字符串应始终采用此格式以便文档生成器识别:

"""
A description of the class.

This can span multiple lines and can _contain_ *markdown*.
"""

方法和函数

这些描述中的Markdown将不会转换为格式化文本。

"""
Parameters:
    param_one: A description for this parameter.
    param_two: A description for this parameter.
Returns:
    A description for this return value.
"""

事件

在自定义组件中,事件表示为存储在组件类的events字段上的列表。虽然我们不需要事件类型,但我们确实需要一个人类可读的描述,以便用户能够理解事件的行为。

为了促进这一点,我们必须以特定的方式创建事件。

有两种方法可以向自定义组件添加事件。

内置事件

Gradio 提供了多种内置事件,这些事件可能足以满足您的组件需求。如果您使用的是内置事件,您不需要做任何事情,因为它们已经有我们可以提取的描述:

from gradio.events import Events

class ParamViewer(Component):
  ...

  EVENTS = [
    Events.change,
    Events.upload,
  ]

自定义事件

如果内置事件不适合您的使用场景,您可以定义一个自定义事件。这是一个简单的过程,但您必须以这种方式创建事件,以便文档字符串能够正常工作:

from gradio.events import Events, EventListener

class ParamViewer(Component):
  ...

  EVENTS = [
    Events.change,
    EventListener(
        "bingbong",
        doc="This listener is triggered when the user does a bingbong."
      )
  ]

演示

demo/app.py,通常用于开发组件,生成实时演示和代码片段。这里唯一的严格规则是demo.launch()命令必须包含在__name__ == "__main__"条件中,如下所示:

if __name__ == "__main__":
  demo.launch()

文档生成器将扫描此类条款,如果缺失则会报错。如果您没有demo/app.py中启动演示,那么您可以传递--suppress-demo-check来关闭此检查。

演示推荐

虽然没有额外的规则,但为了从文档生成器获得最佳体验,您应该记住一些最佳实践。

这些只是指导原则,每种情况都是独特的,但它们是值得记住的合理原则。

保持演示简洁

简洁的演示看起来更好,并且使用户更容易理解演示的功能。尽量移除尽可能多的无关UI元素,以集中用户的注意力在核心用例上。

有时,为文档创建一个demo/app.py,并为测试目的创建一个更复杂的应用程序可能是有意义的。您还可以创建其他空间,展示更复杂的示例,并从主类文档字符串或pyproject.toml描述中链接到它们。

保持代码简洁

'入门'代码片段使用了演示代码,应尽可能简短,以保持用户的参与度并避免混淆。

示例代码片段的目的不是展示整个API;这个代码片段应该是新用户成功的最短路径。它应该易于输入或复制粘贴,并且易于理解。解释性评论应该简洁明了。

避免外部依赖

如上所述,用户应该能够复制粘贴一个代码片段并拥有一个完全可用的应用程序。尽量避免第三方库依赖,以便于实现这一点。

你应该仔细考虑任何示例;避免需要额外文件或对环境做出假设的示例通常是一个好主意。

确保demo目录是自包含的

在某些情况下,只有demo目录会被上传到Hugging Face空间,因为如果可能的话,组件将通过PyPi安装。确保该目录是自包含的,并且包含正确运行演示所需的任何文件是至关重要的。

附加网址

文档生成器将生成一些按钮,为用户提供有用的信息和链接。在某些情况下,它们是自动获取的,但有些需要明确包含在pyproject.yaml中。

  • PyPi 版本和链接 - 这是自动生成的。
  • GitHub 仓库 - 这是通过 pyproject.tomlproject.urls.repository 填充的。
  • Hugging Face Space - 这是通过pyproject.tomlproject.urls.space填充的。

一个示例 pyproject.toml 的 urls 部分可能如下所示:

[project.urls]
repository = "https://github.com/user/repo-name"
space = "https://huggingface.co/spaces/user/space-name"