1. 使用 Blocks 构建
  2. 更多 Blocks 功能

更多 Blocks 功能

示例

就像使用 `gr.Interface` 一样,当使用 `gr.Blocks` 时,你也可以为你的函数添加示例。在这种情况下,实例化一个 `gr.Examples`,类似于实例化任何其他组件。`gr.Examples` 的构造函数需要两个必需参数:

  • `examples`:一个嵌套的示例列表,其中外部列表包含示例,每个内部列表包含对应于每个输入组件的输入。
  • `inputs`:当点击示例时应填充的组件或组件列表。

你也可以设置 `cache_examples=True` 或 `cache_examples='lazy'`,类似于 `gr.Interface` 中的缓存 API,在这种情况下必须提供另外两个参数:

  • `outputs`:对应于示例输出的组件或组件列表。
  • `fn`:用于生成对应于示例输出的函数。

下面是一个示例,展示如何在 `gr.Blocks` 应用中使用 `gr.Examples`:

import gradio as gr

def calculator(num1, operation, num2):
    if operation == "add":
        return num1 + num2
    elif operation == "subtract":
        return num1 - num2
    elif operation == "multiply":
        return num1 * num2
    elif operation == "divide":
        return num1 / num2

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            num_1 = gr.Number(value=4)
            operation = gr.Radio(["add", "subtract", "multiply", "divide"])
            num_2 = gr.Number(value=0)
            submit_btn = gr.Button(value="Calculate")
        with gr.Column():
            result = gr.Number()

    submit_btn.click(
        calculator, inputs=[num_1, operation, num_2], outputs=[result], api_visibility="private"
    )
    examples = gr.Examples(
        examples=[
            [5, "add", 3],
            [4, "divide", 2],
            [-4, "multiply", 2.5],
            [0, "subtract", 1.2],
        ],
        inputs=[num_1, operation, num_2],
    )

if __name__ == "__main__":
    demo.launch(footer_links=["gradio"])

注意:当你点击示例时,输入组件的值不仅会更新为示例值,组件的配置也会恢复到你构建组件时的属性。这确保了即使组件的配置已被更改,示例仍与组件兼容。

持续运行事件

你可以使用 `gr.Timer()` 对象在固定的时间表上运行事件。当计时器的 `tick` 事件触发时,它将运行该事件。请参阅下面的代码:

with gr.Blocks as demo:
    timer = gr.Timer(5)
    textbox = gr.Textbox()
    textbox2 = gr.Textbox()
    timer.tick(set_textbox_fn, textbox, textbox2)

如果组件的值是一个函数,这也可以直接与组件的 `every=` 参数一起使用。

with gr.Blocks as demo:
    timer = gr.Timer(5)
    textbox = gr.Textbox()
    textbox2 = gr.Textbox(set_textbox_fn, inputs=[textbox], every=timer)

这是一个演示打印当前时间戳并定期打印随机数字的示例!

import gradio as gr
import random
import time

with gr.Blocks() as demo:
  timer = gr.Timer(1)
  timestamp = gr.Number(label="Time")
  timer.tick(lambda: round(time.time()), outputs=timestamp, api_name="timestamp")

  number = gr.Number(lambda: random.randint(1, 10), every=timer, label="Random Number")
  with gr.Row():
    gr.Button("Start").click(lambda: gr.Timer(active=True), None, timer)
    gr.Button("Stop").click(lambda: gr.Timer(active=False), None, timer)
    gr.Button("Go Fast").click(lambda: 0.2, None, timer)

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

收集事件数据

你可以通过在事件监听函数中将相关的事件数据类作为参数的类型提示,来收集关于特定事件的数据。

例如,`select()` 事件的数据可以通过 `gradio.SelectData` 参数进行类型提示。当用户选择触发组件的某个部分时,会触发此事件,事件数据包含有关用户具体选择内容的信息。例如,如果用户在 `Textbox` 中选择了特定的词语,在 `Image` 中选择了特定的像素,在 `Gallery` 中选择了特定的图像,或者在 `DataFrame` 中选择了特定的单元格,事件数据参数将包含有关特定选择的信息。

`SelectData` 包含被选择的值以及选择发生的索引。一个简单的示例显示了在 `Textbox` 中选择了哪些文本。

import gradio as gr

with gr.Blocks() as demo:
    textbox = gr.Textbox("The quick brown fox jumped.")
    selection = gr.Textbox()

    def get_selection(select_evt: gr.SelectData):
        return select_evt.value

    textbox.select(get_selection, None, selection)

在下面的双人井字棋演示中,用户可以通过选择 `DataFrame` 中的一个单元格来下棋。事件数据参数包含有关所选特定单元格的信息。我们可以首先检查单元格是否为空,然后用用户的棋子更新单元格。

import gradio as gr

with gr.Blocks() as demo:
    turn = gr.Textbox("X", interactive=False, label="Turn")
    board = gr.Dataframe(value=[["", "", ""]] * 3, interactive=False, type="array")

    def place(board: list[list[int]], turn, evt: gr.SelectData):  
        if evt.value:
            return board, turn
        board[evt.index[0]][evt.index[1]] = turn
        turn = "O" if turn == "X" else "X"
        return board, turn

    board.select(place, [board, turn], [board, turn], show_progress="hidden")

demo.launch()

验证

对于某些应用,在使用输入之前对其进行验证非常重要。虽然这可以在主事件函数中完成,但事件也支持一个专用于此任务的 `validator` 函数。

此功能提供了比将此逻辑放入主函数更好的用户体验,原因如下:

  • 输入验证会立即执行,绕过队列,为最终用户提供近乎即时的反馈。
  • 从 `validator` 函数返回的验证错误会在 UI 中以不同的方式显示。
  • 验证器函数允许更大的粒度。你无需引发通用异常,而是可以为每个输入单独返回验证消息和状态。

`validator` kwarg 应该是一个函数,它为每个输入返回一个 `gr.validate` 对象。`gr.validate` 接受两个参数:

  • `is_valid` - 输入是否有效。
  • `message` - 如果验证失败要显示的 message。

在下面的演示中,你可以看到通过为每个输入返回验证状态,我们可以显示给用户更细粒度的信息。

import gradio as gr


def validate_input(age, location):
    return [
        gr.validate(not age or age > 3, "Age must be at least 3"),
        gr.validate("london" not in location.lower(), "Location must not be in London"),
    ]


def process_text(age, location):
    return f"Processed: {age} -- {location.upper()}"


with gr.Blocks() as demo:
    gr.Markdown("# Validator Parameter Test Demo")

    with gr.Row():
        with gr.Column():
            age = gr.Number(
                label="Enter age",
                placeholder="Enter age",
            )
            location = gr.Textbox(
                max_lines=3,
                label="Enter location",
                placeholder="Enter location",
            )

    validate_btn = gr.Button("Process with Validation", variant="primary")

    output_with_validation = gr.Textbox(
        label="Output (with validation)", interactive=False
    )

    validate_btn.click(
        fn=process_text,
        validator=validate_input,
        inputs=[age, location],
        outputs=output_with_validation,
    )


demo.launch()

gradio