Gradio 工具

一、基础概念

  1. Gradio 允许用户使用 Python 为任何机器学习模型构建、自定义、共享 web-based 演示(demo )。

    安装:pip install gradio

  2. 简单用法:

  1. launch 方法:默认情况下,launch() 方法将在 Web server 中启动演示并在本地运行。 如果你在JupyterColab notebook 中运行代码,那么 Gradio 会将演示 GUI 嵌入到 notebook 中。也可以通过不同的参数自定义 launch() 的行为:

    • inline:是否在 Python notebook 中内嵌地展示 interface

    • inbrowser:是否在默认浏览器中自动地打开一个新 tablaunch interface

    • share:是否为 interface 从你的电脑上创建一个公开可分享的链接。

  2. 包含预测模型:首先,我们定义一个接受文本提示并返回文本完成的预测函数:

    然后我们创建和启动一个接口:

  3. Interface类: Interface 类有3 个必需参数:

    其中:

    • fn:由 Gradio 接口包装的预测函数。 该函数可以接受一个或多个参数并返回一个或多个值。

    • inputs:输入组件类型。 Gradio 提供了许多预构建的组件,例如 "image""mic"

    • outputs:输出组件类型。 同样,Gradio 提供了许多预构建的组件。

    有关组件的完整列表,请参考 https://gradio.app/docs 。 每个预构建的组件都可以通过实例化该组件对应的类来定制。

    为了给演示添加额外的内容,Interface 类支持一些可选参数:

    • title:演示标题,它出现在输入组件和输出组件的上方。

    • description:界面描述(文本、MarkdownHTML ),显示在输入组件和输出组件的上方、标题下方。

    • article:扩展文章(文本、MarkdownHTML)用于解释界面。如果提供,它会出现在输入组件和输出组件的下方。

    • theme:界面主题。可以为 default, huggingface, grass, peach 等之一。也可以添加 dark- 前缀从而得到深色主题。

    • examples:可以为函数提供一些示例的输入。它们可以出现在 UI 组件下方。

    • live:如果 live=True,那么每次当输入更改时,模型都会重新运行。

    例如:

  4. 处理多个输入和多个输出:

  5. 分享:有两种方式可以分享你的演示:

    • 临时分享:通过在 launch() 方法中设置 share=True 来实现:

      这会生成一个公开的、可分享的链接。其它用户可以在该用户的浏览器中使用你的模型长达 72 个小时。所有模型计算都发生在你的设备上。注意,由于这些链接是公开可访问的,这意味着任何人都可以用你的模型进行预测。

      如果设置 share=False(默认行为),则仅创建本地链接。

    • Hugging Face Spaces 上托管(永久分享):Hugging Face Spaces 提供了在互联网上永久地、免费地托管Gradio 模型的基础设施。

  6. Hugging Face Hub 集成:Gradio 可以直接与 Hugging Face HubHugging Face Spaces 集成,仅用一行代码从 HubSpace 加载演示。

二、高级功能

  1. 使用状态保存数据:Gradio 支持 ”会话状态“,其中数据在页面加载中的多次提交中持续存在。会话状态对于构建演示很有用,例如,聊天机器人需要保留历史会话数据。请注意, 会话状态不会在模型的不同用户之间共享数据。

    要将数据存储在会话状态中,你需要做三件事:

    • 向函数中传递一个额外的参数,该参数表示 Interface 的状态。

    • 在函数结束时, 将状态的更新后的值以额外的返回值来返回

    • 在创建Interface时添加 state input 组件和 state output 组件。

    例如下面的聊天机器人的例子:

    注意:可以给 state 参数(即, history 变量)传入一个默认值,作为 state 的初始值。

  2. 为输出结果提供解释:大多数机器学习模型都是黑盒子,函数的内部逻辑对终端用户是隐藏的。为了提高透明度,我们通过简单地将 Interface 类中的 interpretation 关键字设置为默认值,使得向模型添加解释变得非常容易。这允许你的用户理解输入的哪些部分负责输出。

    示例:

    通过提交一个输入,然后单击输出组件下的 Interpret 来测试解释功能。

    除了 Gradio 提供的 default 解释方法之外,你还可以为 interpretation 参数指定 shap,并设置 num_shap 参数。这使用基于Shapley 的解释。最后,还可以将自己的解释函数传入 interpretation 参数。

  3. BlocksBlocks 是底层的 API,它和 Interface 的区别在于:

    • Interface:高级 API,让你只需提供 inputoutput 组件,即可创建完整的机器学习演示。

    • Block :低级 API,它允许你完全控制你的应用程序的数据流和布局。

    为什么要用 Block ?虽然 Interface API 非常易于使用,但是缺乏 Blocks API 提供的灵活性。例如:

    • 将一组演示整合成 web application 中的多个选项卡。

    • 更改 demo 的布局,例如,指定 input 组件和 output 组件的位置。

    • 具有 multi-step 的接口,其中一个模型的输出作为下一个模型的输入,或者通常具有更灵活的数据流。

    • 根据用户输入来调整组件的属性(如下拉列表的选项)、或可见性。

    简单的示例:

    上述简单示例介绍了 block4 个基本概念:

    • block 允许你允许你构建结合了 markdownHTMLbutton、以及交互组件的 web 应用程序,只需实例化这些组件。

      实例化组件的顺序很重要,因为每个元素都按照创建的顺序呈现到 web 应用程序中。更复杂的布局将在接下来讨论。

    • 你可以在代码中的任何位置定义常规 Python 函数, 并使用block在用户输入的情况下运行它们。如示例中的 flip_text 函数。你可以编写任何 Python 函数, 从简单的计算到处理机器学习模型预测。

    • 你可以将事件指定给任何block组件。这将在组件被单击、被修改等情况下运行函数。当你分配一个事件时,你传入三个参数:

      • fn:事件发生时,应该被调用的函数。

      • inputs:被调用的输入组件(及其列表)

      • outputs:被调用的输出组件(及其列表)

      在上面的示例中,当名为 inputTextbox 中的值发生变化时,我们运行 flip_text() 函数。该事件读取input 组件中的值,将其作为参数传递给 flip_text(),然后该函数返回一个值从而被传递给名为 outputTextbox

    • block 会根据你定义的事件触发器自动确定组件是否应该是交互式的(接受用户输入)。在我们的示例中:

      • 第一个文本框是交互式的,因为它的值由 flip_text() 函数使用。

      • 第二个文本框不是交互式的,因为它的值从不用作输入。

      在某些情况下,你可能想要覆盖它。此时,你可以通过传递一个布尔值给组件的interactive参数。例如 gr.Textbox(placeholder="Flip this text", interactive=True)

  4. 自定义布局:默认情况下,block 在单列中垂直呈现创建的组件。你可以通过使用 with gradio.Column(): 创建其他列或使用 with gradio.Row(): 创建其他行,从而在这些上下文中创建组件来改变这一点。注意:在 Column 下创建的任何组件都将垂直布局(这也是默认设置);在 Row 下创建的任何组件都将水平布局。

    最后,你还可以使用 with gradio.Tabs() 上下文管理器为你的 demo 创建选项卡。在此上下文中,你可以通过使用 gradio.TabItem(name_of_tab): 指定来创建选项卡的多个选项。在 gradio.TabItem(name_of_tab): 中创建的任何组件都会出现在该选项卡中。

    示例:

  5. 探索事件和状态:正如你可以控制布局一样, block 可以让你对触发函数调用的事件进行细粒度控制。每个组件和许多布局都有它们支持的特定事件。例如。 Textbox 组件有两个事件:

    • change() :当文本框内的值发生变化时,该事件发生。

    • submit() :当用户焦点在文本框时且按下 enter 键,则该事件发生。

    更复杂的组件可以有更多的事件。例如,Audio组件也有单独的事件,用于播放、清除、暂停音频文件等。

    你可以将事件触发器附加到这些事件中的一个或多个。你可以通过在组件实例中调用事件名称作为函数来创建一个事件触发器。例如 textbox.change(...)btn.click(...)。如前所述, 该函数接受三个参数:

    • fn:当该事件发生时需要回调的函数。

    • inputs:组件(及其列表), 其值应作为 fn 函数的输入参数提供。每个组件的值按顺序映射到相应的函数参数。如果 fn 函数不带任何参数,则此参数可以为 None

    • outputs:应根据函数返回的值更新其值的组件(及其列表)。每个返回值按顺序设置相应组件的值。如果 fn 函数不返回任何内容,则此参数可以为 None

    你甚至可以使输入和输出组件成为同一个组件,如:

  6. 创建多步骤的演示:在某些情况下, 您可能需要一个多步骤的演示,其中复用一个函数的输出作为下一个函数的输入。使用 block 很容易做到这一点,因为你可以使用某个组件作为一个事件触发器的输入,但作为另一个事件触发器的输出。

    例如:一个文本组件,它的值是语音到文本模型的结果,但也被传递到情感分析模型中:

  7. 更新组件的属性:到目前为止,我们已经了解了如何创建事件来更新另一个组件的值。但是,如果你想更改组件的其他属性(例如文本框的可见性) ,那么你可以通过返回组件类的 update() 方法而不是返回常规的返回值来做到这一点。

    示例:

     

三、示例

  1. 音频示例:我们将使用 Audio 组件作为输入。 使用 Audio 组件时,你可以指定希望音频的 source 是用户上传的文件、还是用户录制声音的麦克风。 在这个例子中,我们将其设置为麦克风。

    此外,我们希望将音频作为 numpy 数组来接收,以便后续处理。 所以我们将 "type" 设置为 "numpy",它会传递输入 data 作为 (sample_rate, data) 的元组进入我们的函数。

    我们还将使用 Audio 输出组件,它可以自动将(sample_rate, data) 元组渲染为可播放的音频文件。 在这种情况下,我们不需要进行任何自定义,因此我们将使用字符串快捷方式 "audio"

  2. 语音识别:我们将使用 Transformers 中的 pipeline() 函数加载我们的语音识别模型。接下来,我们将实现一个 transcribe_audio() 函数来处理音频并返回转录文本。 最后,我们将把这个函数包装在一个 Interface 中,其中 Audio 组件用于输入,只有文本用于输出。

    注意这里通过将 optional 参数设为 True,从而允许用户提供麦克风或音频文件(或两者都不提供,但这会返回错误消息)。