Gradio学习

原创
03/31 09:55
阅读数 698

 HelloWorld

# 导入 Gradio 库,它是一个用于创建 Web 界面的 Python 库
import gradio as gr

# 定义一个问候函数,接受两个参数:
# name: 用户输入的名字
# intensity: 感叹号的数量(从滑块获取)
def greet(name, intensity):
    # 返回问候语,其中感叹号的数量由 intensity 参数决定
    return "Hello, " + name + "!" * int(intensity)

# 创建 Gradio 界面
# fn: 指定要调用的函数
# inputs: 指定输入组件 - 文本框和滑块
# outputs: 指定输出组件 - 文本框
demo = gr.Interface(
    fn=greet,
    inputs=["text", "slider"],
    outputs=["text"],
)

# 启动 Gradio 应用程序,使其在浏览器中可访问
demo.launch()

运行结果

该类Interface有三个核心参数:

  • fn:包装用户界面 (UI) 的函数
  • inputs:用于输入的 Gradio 组件。组件数量应与函数中的参数数量相匹配。
  • outputs:用于输出的 Gradio 组件。组件数量应与函数的返回值数量相匹配。

fn参数非常灵活 - 您可以传递任何想要用 UI 包装的 Python 函数。在上面的示例中,我们看到了一个相对简单的函数,但该函数可以是任何东西,从音乐生成器到税收计算器,再到预训练机器学习模型的预测函数。

inputs和参数outputs接受一个或多个 Gradio 组件。正如我们所见,Gradio 包含 30 多个专为机器学习应用设计的内置组件(例如gr.Textbox()gr.Image()和组件)。gr.HTML()

组件属性

现在我们要调整上面示例组件的一些属性

# 导入 Gradio 库,它是一个用于创建 Web 界面的 Python import gradio as gr

# 定义一个问候函数,接受两个参数:
# name: 用户输入的名字
# intensity: 感叹号的数量(从滑块获取)
def greet(name, intensity):
    # 返回问候语,其中感叹号的数量由 intensity 参数决定
    return "Hello, " + name + "!" * int(intensity)

# 创建 Gradio 界面
# fn: 指定要调用的函数
# inputs: 指定输入组件 - 文本框和滑块
# outputs: 指定输出组件 - 文本框
demo = gr.Interface(
    fn=greet,
    inputs=["text", gr.Slider(value=2, minimum=1, maximum=10, step=1)],
    outputs=[gr.Textbox(label='问候', lines=3)],
)

# 启动 Gradio 应用程序,使其在浏览器中可访问
demo.launch()

运行结果

这里我们将滑块的值调整到从 1 到 10,默认值为 2,并且将输出文本框的标签调整为中文。

多输入、多输出

# 导入 Gradio 库,用于创建交互式 Web 界面
import gradio as gr


# 定义问候函数,接收三个参数:
# name: 用户姓名
# is_morning: 布尔值,表示是早上还是晚上
# temperature: 温度值(华氏度)
def greet(name, is_morning, temperature):
    # 根据时间选择合适的问候语
    salutation = "Good morning" if is_morning else "Good evening"

    # 组合完整的问候语句,包含姓名和温度信息
    greeting = f"{salutation} {name}. It is {temperature} degrees today"

    # 将华氏温度转换为摄氏温度:(°F - 32) * 5/9 = °C
    celsius = (temperature - 32) * 5 / 9

    # 返回两个值:问候语句和转换后的摄氏温度(保留两位小数)
    return greeting, round(celsius, 2)


# 创建 Gradio 界面
demo = gr.Interface(
    # 指定要调用的函数
    fn=greet,
    # 设置输入组件:文本框、复选框和滑块(温度范围 0-100    inputs=["text", "checkbox", gr.Slider(0, 100)],
    # 设置输出组件:文本框(显示问候语)和数字(显示摄氏温度)
    outputs=["text", "number"],
)

# 启动 Gradio 应用程序,在浏览器中呈现界面
demo.launch()

运行结果

正如inputs列表中的每个组件按顺序对应函数的一个参数一样,列表中的每个组件outputs按顺序对应函数的一个返回值。

图像示例

# 导入必要的库
# numpy: 用于进行高效的数组运算
import numpy as np
# gradio: 用于创建交互式 Web 界面
import gradio as gr

# 定义深褐色(sepia)滤镜转换函数
# input_img: 输入的原始图像
def sepia(input_img):
    # 定义 sepia 滤镜的转换矩阵
    # 这个 3x3 的矩阵包含了将 RGB 转换为深褐色的系数
    # 每一行分别对应输出颜色的 RGB 分量
    sepia_filter = np.array([
        [0.393, 0.769, 0.189],  # 红色通道的系数
        [0.349, 0.686, 0.168],  # 绿色通道的系数
        [0.272, 0.534, 0.131]   # 蓝色通道的系数
    ])
    
    # 使用点积运算将原始图像与滤镜矩阵相乘
    # .T 进行矩阵转置,确保维度匹配
    sepia_img = input_img.dot(sepia_filter.T)
    
    # 将图像数值归一化,确保所有像素值都在有效范围内
    # 除以最大值使得所有值都在 0-1 之间
    sepia_img /= sepia_img.max()
    
    # 返回处理后的图像
    return sepia_img

# 创建 Gradio 界面
# sepia: 指定要调用的函数
# gr.Image(): 创建图像输入组件
# "image": 指定输出类型为图像
demo = gr.Interface(sepia, gr.Image(), "image")

# 启动 Gradio 应用程序
demo.launch()

运行结果

当使用Image组件作为输入时,函数将收到一个形状为 的 NumPy 数组(height, width, 3),还将以 NumPy 数组的形式返回图像。Gradio 处理预处理和后处理,将图像转换为 NumPy 数组,反之亦然。

示例输入

# 导入 Gradio 库,用于创建交互式 Web 界面
import gradio as gr

# 定义计算器函数,接收三个参数:
# num1: 第一个数字
# operation: 运算操作(加减乘除)
# num2: 第二个数字
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":
        # 处理除法运算,检查除数是否为零
        if num2 == 0:
            # 如果除数为零,抛出 Gradio 错误提示
            raise gr.Error("Cannot divide by zero!")
        return num1 / num2

# 创建 Gradio 界面
demo = gr.Interface(
    # 指定要调用的函数
    calculator,
    # 设置输入组件:
    [
        "number",  # 第一个数字输入框
        gr.Radio(["add", "subtract", "multiply", "divide"]),  # 运算符选择按钮
        "number"   # 第二个数字输入框
    ],
    # 设置输出组件为数字显示
    "number",
    # 提供示例数据,方便用户理解使用方法
    examples=[
        [45, "add", 3],         # 加法示例:45 + 3
        [3.14, "divide", 2],    # 除法示例:3.14 ÷ 2
        [144, "multiply", 2.5], # 乘法示例:144 × 2.5
        [0, "subtract", 1.2],   # 减法示例:0 - 1.2
    ],
    # 设置应用标题
    title="Toy Calculator",
    # 设置应用描述
    description="Here's a sample toy calculator.",
    article="保留所有者权利",
)

# 启动 Gradio 应用程序
demo.launch()

运行结果

提供示例数据,以便用户轻松加载Interface。这有助于演示模型所需的输入类型,并提供一种结合模型探索数据集的方法。要加载示例数据,您可以为接口构造函数的关键字参数提供一个嵌套列表examples=。外部列表中的每个子列表代表一个数据样本,子列表中的每个元素代表每个输入组件的输入。每个组件的示例数据格式在文档中指定。

我们可以将大型数据集加载到示例中,以便通过 Gradio 浏览并与数据集交互。示例将自动分页(您可以通过examples_per_page的参数进行配置Interface)。

构造函数中有三个参数Interface用于指定内容的存放位置:

  1. title:接受文本,并可以将其显示在界面的最顶部,同时也成为页面的标题。
  2. description:接受文本、markdown 或 HTML 并将其放置在标题下方。
  3. article:它还接受文本、markdown 或 HTML 并将其放置在界面下方。

从目录加载示例

# 导入 Gradio 库,用于创建交互式 Web 界面
import gradio as gr


# 定义计算器函数,接收三个参数:
# num1: 第一个数字
# operation: 运算操作(加减乘除)
# num2: 第二个数字
def calculator(num1, operation, num2):
    # 确保输入的数字是浮点数类型
    try:
        num1 = float(num1)
        num2 = float(num2)
    except ValueError:
        raise gr.Error("输入必须是有效的数字!")

    # 根据不同的运算符执行相应的计算
    if operation == "add":
        return num1 + num2
    elif operation == "subtract":
        return num1 - num2
    elif operation == "multiply":
        return num1 * num2
    elif operation == "divide":
        # 处理除法运算,检查除数是否为零
        if num2 == 0:
            # 如果除数为零,抛出 Gradio 错误提示
            raise gr.Error("Cannot divide by zero!")
        return num1 / num2


# 创建 Gradio 界面
demo = gr.Interface(
    # 指定要调用的函数
    calculator,
    # 设置输入组件:
    [
        "number",  # 第一个数字输入框
        gr.Radio(["add", "subtract", "multiply", "divide"]),  # 运算符选择按钮
        "number"  # 第二个数字输入框
    ],
    # 设置输出组件为数字显示
    "number",
    # 提供示例数据,方便用户理解使用方法
    examples='examples/',
    # 设置应用标题
    title="Toy Calculator",
    # 设置应用描述
    description="Here's a sample toy calculator.",
    article="保留所有者权利",
)

# 启动 Gradio 应用程序
demo.launch()

运行结果

目录结构

在examples文件夹中有一个log.csv,内容如下

num,operation,num2
5,"add",3
4,"divide",2
5,"multiply",3

指定包含示例的目录路径。如果您的界面仅接受单个文件类型输入(例如图像分类器),您只需将目录文件路径传递给examples=参数,然后系统Interface就会将目录中的图像加载为示例。如果有多个输入,此目录必须包含带有示例值的 log.csv 文件。

折叠面板中的其他输入

# 导入 Gradio 库,用于创建交互式 Web 界面
import gradio as gr

# 定义图像生成函数,接收三个参数:
# prompt: 文本提示词
# seed: 随机种子数值
# initial_image: 可选的初始图像
def generate_fake_image(prompt, seed, initial_image=None):
    # 返回两个值:
    # 1. 使用的种子信息(文本格式)
    # 2. 示例图像的URL(这里使用了一个示例图像服务)
    return f"Used seed: {seed}", "https://dummyimage.com/300/09f.png"

# 创建 Gradio 界面
demo = gr.Interface(
    # 指定要调用的函数
    generate_fake_image,
    # 设置主要输入组件:文本框
    inputs=["textbox"],
    # 设置输出组件:文本框和图像显示
    outputs=["textbox", "image"],
    # 设置额外的输入组件:
    additional_inputs=[
        gr.Slider(0, 1000),  # 滑块,范围从 0  1000,用于设置随机种子
        "image"              # 图像输入组件,用于上传初始图像
    ]
)

# 启动 Gradio 应用程序
demo.launch()

运行结果

刚加载时,我们只能看到这样

点击红色部分可以看到第一张图的隐藏部分。 该类Interface采用一个additional_inputs类似的参数,inputs此处包含的任何输入组件默认情况下都不可见。用户必须点击三角符才能显示这些组件。在标准输入之后,其他输入按顺序传递到预测函数中。

全局状态

# 导入 Gradio 库,用于创建交互式 Web 界面
import gradio as gr

# 创建一个全局列表,用于存储所有提交的分数
scores = []


# 定义分数追踪函数
# score: 新提交的分数
def track_score(score):
    # 将新分数添加到列表中
    scores.append(score)

    # 对所有分数进行排序并获取前三名
    # sorted(): 对分数进行排序
    # reverse=True: 降序排序(从高到低)
    # [:3]: 只取前三个分数
    top_scores = sorted(scores, reverse=True)[:3]

    # 返回前三名分数列表
    return top_scores


# 创建 Gradio 界面
demo = gr.Interface(
    # 指定要调用的函数
    track_score,
    # 创建数字输入组件,用于输入分数
    gr.Number(label="Score"),
    # 创建 JSON 输出组件,用于显示前三名分数
    gr.JSON(label="Top Scores")
)

# 启动 Gradio 应用程序
demo.launch()

运行结果

在上面的代码中,scores数组在所有用户之间共享。如果多个用户正在访问此演示,他们的分数将全部添加到同一个列表中,并从此共享引用中收集返回的前 3 个分数。

会话状态

# 导入Gradio库用于创建Web界面
import gradio as gr


def store_message(message: str, history: list[str]):
    """
    存储消息并维护历史记录

    参数:
        message: 当前输入的消息
        history: 历史消息列表

    返回:
        tuple: (输出的JSON对象, 更新后的历史记录)
    """
    output = {
        "Current messages": message,  # 存储当前消息
        "Previous messages": history[::-1]  # 反转并存储历史消息列表
    }
    history.append(message)  # 将当前消息添加到历史记录中
    return output, history


# 创建Gradio界面
demo = gr.Interface(fn=store_message,  # 处理函数
                    inputs=["textbox", gr.State(value=[])],  # 输入组件:文本框和状态存储
                    outputs=["json", gr.State()])  # 输出组件:JSON显示和状态存储

# 启动Web界面
demo.launch()

运行结果

Gradio 支持的另一种数据持久性类型是会话状态,其中数据在页面会话中的多次提交中保持不变。但是,数据不会模型的不同用户之间共享。要将数据存储在会话状态中,需要做三件事:

  1. 将一个额外的参数传入你的函数,它代表接口的状态。
  2. 在函数的最后,将状态的更新值作为额外的返回值返回。
  3. 在创建时添加'state'输入和输出组件'state'Interface

在这里,我们不能将提交历史记录存储在全局变量中,否则提交历史记录会在不同的用户之间混乱。

反应式接口

实时界面

# 导入Gradio库用于创建Web界面
import gradio as gr


def calculator(num1, operation, num2):
    """
    实现基础计算器功能

    参数:
        num1: 第一个数字
        operation: 运算类型(加减乘除)
        num2: 第二个数字

    返回:
        floatstr: 计算结果或错误信息
    """
    if operation == "add":
        return num1 + num2  # 加法运算
    elif operation == "subtract":
        return num1 - num2  # 减法运算
    elif operation == "multiply":
        return num1 * num2  # 乘法运算
    elif operation == "divide":
        try:
            if num2 == 0:
                return "错误:除数不能为0"
            return num1 / num2  # 除法运算
        except ZeroDivisionError:
            return "错误:除数不能为0"


# 创建Gradio界面
demo = gr.Interface(
    calculator,  # 处理函数
    [
        "number",  # 第一个输入:数字输入框
        gr.Radio(["add", "subtract", "multiply", "divide"]),  # 运算符选择器
        "number"  # 第二个输入:数字输入框
    ],
    "number",  # 输出组件:数字显示
    live=True,  # 启用实时计算模式
)

# 启动Web界面
demo.launch()

运行结果

在界面中设置让界面自动刷新live=True,这样只要用户输入发生变化,界面就会重新计算。

四种Gradio接口

除了输入、输出的演示,gradio.Interface实际上可以处理 4 种不同类型的演示:

  1. 标准演示:具有单独的输入和输出(例如图像分类器或语音到文本模型)
  2. 仅输出演示:不接受任何输入但产生输出(例如无条件图像生成模型)
  3. 仅输入演示:不产生任何输出但会接受某种输入(例如,将您上传的图像保存到持久外部数据库的演示)
  4. 统一演示:既有输入组件,也有输出组件,但输入和输出组件相同。这意味着产生的输出将覆盖输入(例如文本自动完成模型)

 根据演示的类型,用户界面(UI)看起来略有不同:

之前的都是标准演示,这里不再重复。

仅输出演示

# 导入所需的库
import time  # 用于模拟处理延迟
import gradio as gr  # 导入Gradio库用于创建Web界面


def fake_gan():
    """
    模拟GAN生成图片的函数

    返回:
        list: 包含预设图片URL的列表
    """
    time.sleep(1)  # 添加1秒延迟,模拟处理时间

    # 预定义的Unsplash图片URL列表
    images = [
        "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80",
        "https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80",
        "https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80",
    ]
    return images


# 创建Gradio界面
demo = gr.Interface(
    fn=fake_gan,  # 处理函数
    inputs=None,  # 无需输入参数
    outputs=gr.Gallery(label="Generated Images",  # 输出组件:图片画廊
                       columns=[2]),  # 设置每行显示2张图片
    title="FD-GAN",  # 应用标题
    description="This is a fake demo of a GAN. In reality, the images are randomly chosen from Unsplash.",  # 应用描述
)

# 启动Web界面
demo.launch()

运行结果

构建这样的演示,只需将Interface中的参数值inputs设置为None。 

仅输入演示

# 导入所需的库
import random  # 用于生成随机字符
import string  # 提供字母字符集
import gradio as gr  # 导入Gradio库用于创建Web界面


def save_image_random_name(image):
    """
    保存图片并生成随机文件名

    参数:
        image: PIL格式的图片对象

    返回:
        None: 函数只进行保存操作,不返回值
    """
    # 生成20位随机字母组成的文件名,并添加.png后缀
    random_string = ''.join(random.choices(string.ascii_letters, k=20)) + '.png'
    # 保存图片
    image.save(random_string)
    # 打印保存确认信息
    print(f"Saved image to {random_string}!")


# 创建Gradio界面
demo = gr.Interface(
    fn=save_image_random_name,  # 处理函数
    inputs=gr.Image(type="pil"),  # 输入组件:PIL格式的图片输入
    outputs=None,  # 无输出组件,因为只进行保存操作
)

# 启动Web界面
demo.launch()

运行结果

* Running on local URL:  http://127.0.0.1:7860

To create a public link, set `share=True` in `launch()`.
Saved image to aqpAktuIunaZyTGEYzcV.png!

创建仅包含输入的演示,将Interface中的参数值outputs设置为None。

统一演示

# 导入必要的库
import gradio as gr  # 用于创建Web界面
from transformers import pipeline  # 用于加载和使用预训练模型

# 初始化文本生成模型
# 使用GPT-2模型创建文本生成pipeline
generator = pipeline('text-generation', model = 'gpt2')

def generate_text(text_prompt):
    """
    使用GPT-2模型生成文本
    参数:
        text_prompt: 用户输入的提示文本
    返回:
        生成的文本字符串
    """
    # 生成文本,设置最大长度为30token,生成5个候选序列
    response = generator(text_prompt, max_length = 30, num_return_sequences=5)
    # 返回第一个生成结果的文本
    return response[0]['generated_text']  

# 创建文本输入框组件
textbox = gr.Textbox()

# 创建Gradio界面
# 输入和输出都使用文本框
demo = gr.Interface(generate_text, textbox, textbox)

# 启动Web界面
demo.launch()

运行结果

单个组件作为输入和输出的演示。只需将inputs和outputs参数的值设置为同一组件即可创建。

块和事件监听器

区块结构

# 导入Gradio库用于创建Web界面
import gradio as gr


def greet(name):
    """
    创建问候语的函数
    参数:
        name: 用户输入的名字
    返回:
        包含问候语的字符串
    """
    return "Hello " + name + "!"


# 使用Blocks创建更灵活的界面布局
with gr.Blocks() as demo:
    # 创建输入文本框组件,用于接收用户名
    name = gr.Textbox(label="Name")
    # 创建输出文本框组件,用于显示问候语
    output = gr.Textbox(label="Output Box")
    # 创建按钮组件
    greet_btn = gr.Button("Greet")
    # 设置按钮点击事件:
    # - fn指定要调用的函数
    # - inputs指定输入组件
    # - outputs指定输出组件
    # - api_name设置API端点名称
    greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")

# 启动Web界面
demo.launch()

运行结果

  1. 首先,请注意该with gr.Blocks() as demo:子句。Blocks 应用程序代码将包含在此子句中。
  2. 接下来是组件。这些组件与Interface 中使用的组件相同。但是,组件不是传递给某个构造函数,而是在with子句中创建时自动添加到块中。
  3. 最后,click()事件监听器。事件监听器定义应用程序内的数据流。在上面的示例中,监听器将两个文本框绑定在一起。文本框name充当方法的输入,文本框output充当方法的输出greet。单击按钮时会触发此数据流greet_btn。与接口一样,事件监听器可以接受多个输入或输出。

使用装饰器附加事件监听器

# 导入Gradio库用于创建Web界面
import gradio as gr

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建输入文本框组件
    name = gr.Textbox(label="Name")
    # 创建输出文本框组件
    output = gr.Textbox(label="Output Box", interactive=True)
    # 创建按钮组件
    greet_btn = gr.Button("Greet")

    # 定义按钮点击事件处理函数
    # inputs参数指定输入组件
    # outputs参数指定输出组件
    @greet_btn.click(inputs=name, outputs=output)
    def greet(name):
        """
        问候函数:返回包含用户名的问候语
        参数:
            name: 用户输入的名字
        返回:
            问候语字符串
        """
        return "Hello " + name + "!"

# 启动Gradio应用
demo.launch()

此处output = gr.Textbox(label="Output Box", interactive=True)让输出组件变的可交互。

事件监听器的类型

# 导入Gradio库,用于创建交互式Web界面
import gradio as gr

# 定义欢迎函数:接收用户名并返回欢迎消息
def welcome(name):
    """
    生成个性化的欢迎消息
    参数:
        name: 用户输入的名字
    返回:
        格式化的欢迎字符串
    """
    return f"Welcome to Gradio, {name}!"

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 添加Markdown标题和说明文字
    gr.Markdown(
    """
    # Hello World!
    Start typing below to see the output.
    """)
    # 创建输入文本框,设置占位符提示文本
    inp = gr.Textbox(placeholder="What is your name?")
    # 创建输出文本框
    out = gr.Textbox()
    # 绑定输入框值改变事件:当输入改变时调用welcome函数
    inp.change(welcome, inp, out)

# 启动Gradio应用
demo.launch()

 运行结果

该功能不是通过点击触发的,而是welcome通过在 Textbox 中键入内容来触发的inp。这是由于change()事件侦听器的原因。不同的组件支持不同的事件侦听器。例如,Video组件支持play()事件侦听器,当用户按下播放按钮时触发。

多个数据流

# 导入Gradio库,用于创建交互式Web界面
import gradio as gr

# 定义数字增加函数
def increase(num):
    """
    将输入数字加1
    参数:
        num: 输入数字
    返回:
        输入数字加1的结果
    """
    return num + 1

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建两个数字输入框组件
    a = gr.Number(label="a")  # 第一个数字输入框
    b = gr.Number(label="b")  # 第二个数字输入框
    
    # 创建两个方向按钮
    atob = gr.Button("a > b")  # ab的操作按钮
    btoa = gr.Button("b > a")  # ba的操作按钮
    
    # 绑定按钮点击事件
    atob.click(increase, a, b)  # 点击时将a的值加1后赋给b
    btoa.click(increase, b, a)  # 点击时将b的值加1后赋给a

# 启动Gradio应用
demo.launch()

运行结果

Blocks 应用程序并不像接口那样局限于单一数据流,请注意num1可以作为 的输入num2,反之亦然!随着您的应用变得越来越复杂,您将拥有许多连接各种组件的数据流。

“多步骤”演示的示例

# transformers库导入pipeline工具
from transformers import pipeline

import gradio as gr

# 初始化语音识别模型
# 使用facebookwav2vec2预训练模型,专门用于语音识别
asr = pipeline("automatic-speech-recognition", "facebook/wav2vec2-base-960h")
# 初始化文本分类模型(情感分析)
classifier = pipeline("text-classification")

# 语音转文本函数
def speech_to_text(speech):
    """
    将语音文件转换为文本
    参数:
        speech: 语音文件路径
    返回:
        识别出的文本内容
    """
    text = asr(speech)["text"]  
    return text

# 文本情感分析函数
def text_to_sentiment(text):
    """
    对文本进行情感分析
    参数:
        text: 输入文本
    返回:
        情感分类标签
    """
    return classifier(text)[0]["label"]  

# 创建Gradio应用实例
demo = gr.Blocks()

# 构建界面
with demo:
    # 创建界面组件
    audio_file = gr.Audio(type="filepath")  # 音频输入组件,接收文件路径
    text = gr.Textbox()  # 文本显示组件,用于显示识别结果
    label = gr.Label()  # 标签组件,用于显示情感分析结果

    # 创建操作按钮
    b1 = gr.Button("Recognize Speech")  # 语音识别按钮
    b2 = gr.Button("Classify Sentiment")  # 情感分析按钮

    # 绑定按钮点击事件
    b1.click(speech_to_text, inputs=audio_file, outputs=text)  # 语音识别处理流程
    b2.click(text_to_sentiment, inputs=text, outputs=label)  # 情感分析处理流程

# 启动Gradio应用
demo.launch()

运行结果

一个模型(语音到文本模型)的输出被输入到下一个模型(情感分类器)

函数输入列表与字典

# 导入Gradio库用于创建Web界面
import gradio as gr

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建两个数字输入组件
    a = gr.Number(label="a")  # 第一个输入数字
    b = gr.Number(label="b")  # 第二个输入数字
    
    # 创建水平行布局,包含两个按钮
    with gr.Row():
        add_btn = gr.Button("Add")      # 加法按钮
        sub_btn = gr.Button("Subtract") # 减法按钮
    
    # 创建结果显示组件
    c = gr.Number(label="sum")

    # 定义加法函数:使用列表形式接收参数
    def add(num1, num2):
        """
        执行加法运算
        参数:
            num1: 第一个数字
            num2: 第二个数字
        返回:
            两数之和
        """
        return num1 + num2
    # 绑定加法按钮事件,使用列表形式传递输入参数
    add_btn.click(add, inputs=[a, b], outputs=c)

    # 定义减法函数:使用字典形式接收参数
    def sub(data):
        """
        执行减法运算
        参数:
            data: 包含输入值的字典
        返回:
            两数之差
        """
        return data[a] - data[b]
    # 绑定减法按钮事件,使用集合形式传递输入参数(将被转换为字典)
    sub_btn.click(sub, inputs={a, b}, outputs=c)

# 启动Gradio应用
demo.launch()

运行结果

多个输入组件将数据传递给函数,则函数有两种方式可以接受输入组件值:

  1. 作为参数列表,或
  2. 作为单个值字典,由组件键入

函数返回列表与字典

以以下方式返回多个输出组件的值:

  1. 值列表,或
  2. 由组件键入的字典
# 导入Gradio库用于创建Web界面
import gradio as gr

with gr.Blocks() as demo:
    food_box = gr.Number(value=10, label="Food Count")
    status_box = gr.Textbox()

    def eat(food):
        if food > 0:
            return food - 1, "full"
        else:
            return 0, "hungry"

    gr.Button("Eat").click(
        fn=eat,
        inputs=food_box,
        outputs=[food_box, status_box]
    )

demo.launch()

运行结果

 上面每个 return 语句分别返回对应于food_box和status_box的两个值。

# 导入Gradio库用于创建Web界面
import gradio as gr

with gr.Blocks() as demo:
    food_box = gr.Number(value=10, label="Food Count")
    status_box = gr.Textbox()

    def eat(food):
        if food > 0:
            return {food_box: food - 1, status_box: "full"}
        else:
            return {status_box: "hungry"}

    gr.Button("Eat").click(
        fn=eat,
        inputs=food_box,
        outputs=[food_box, status_box]
    )

demo.launch()

还可以返回一个字典,其中键对应于输出组件,值作为新值。请注意,当没有食物时,我们只更新status_box元素。我们跳过了更新food_box组件。当事件监听器在返回时影响许多组件,或者有条件地影响输出而不影响其他组件时,字典返回很有用

更新组件配置

import gradio as gr

def change_textbox(choice):
    if choice == "short":
        return gr.Textbox(lines=2, visible=True)
    elif choice == "long":
        return gr.Textbox(lines=8, visible=True, value="Lorem ipsum dolor sit amet")
    else:
        return gr.Textbox(visible=False)

with gr.Blocks() as demo:
    radio = gr.Radio(
        ["short", "long", "none"], label="What kind of essay would you like to write?"
    )
    text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)
    radio.change(fn=change_textbox, inputs=radio, outputs=text)

demo.launch()

运行结果

事件侦听器函数的返回值通常是相应输出组件的更新值。有时我们也想更新组件的配置,例如可见性。在这种情况下,我们返回一个新的组件,设置我们想要更改的属性。该value=参数仍可用于更新值以及组件配置。我们未设置的任何参数都将保留其先前的值。

不改变组件的值

# 导入所需的库
import random  # 用于生成随机数
import gradio as gr  # 用于创建Web界面

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建水平行布局,包含三个控制按钮
    with gr.Row():
        clear_button = gr.Button("Clear")    # 清除按钮
        skip_button = gr.Button("Skip")      # 跳过按钮
        random_button = gr.Button("Random")  # 随机数按钮
    
    # 创建两个数字输入框的列表
    numbers = [gr.Number(), gr.Number()]

    # 绑定清除按钮事件:将两个输入框的值设为None(清空)
    clear_button.click(lambda : (None, None), outputs=numbers)
    
    # 绑定跳过按钮事件:使用gr.skip()保持原值不变
    skip_button.click(lambda : [gr.skip(), gr.skip()], outputs=numbers)
    
    # 绑定随机按钮事件:为两个输入框生成0-100之间的随机数
    random_button.click(lambda : (random.randint(0, 100), random.randint(0, 100)), outputs=numbers)

# 启动Gradio应用
demo.launch()

运行结果

保持组件的值不变。 Gradio 包含一个特殊函数gr.skip(),可以从您的函数返回。返回此函数将保持输出组件(或组件)的值不变。

连续调用

# 导入所需的库
import gradio as gr    # 用于创建Web界面
import random         # 用于随机选择机器人回复
import time          # 用于添加延迟效果

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建聊天界面组件
    chatbot = gr.Chatbot()    # 聊天历史显示组件
    msg = gr.Textbox()        # 用户输入文本框
    clear = gr.Button("Clear") # 清除聊天历史的按钮

    # 处理用户输入的函数
    def user(user_message, history):
        """
        处理用户输入消息
        参数:
            user_message: 用户输入的消息
            history: 聊天历史记录
        返回:
            清空输入框的空字符串
            更新后的历史记录(添加用户消息,机器人回复位置为None
        """
        return "", history + [[user_message, None]]

    # 生成机器人回复的函数
    def bot(history):
        """
        生成机器人的回复
        参数:
            history: 聊天历史记录
        返回:
            更新后的历史记录(包含机器人的回复)
        """
        # 从预设回复中随机选择一个
        bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
        # 添加2秒延迟模拟思考时间
        time.sleep(2)
        # 更新最后一条消息中机器人的回复
        history[-1][1] = bot_message
        return history

    # 设置消息提交事件的处理链
    msg.submit(
        user,                    # 首先处理用户输入
        [msg, chatbot],         # 输入组件:消息框和聊天历史
        [msg, chatbot],         # 输出组件:清空消息框并更新历史
        queue=False             # 禁用队列,立即处理
    ).then(                     # 链式调用
        bot,                    # 然后生成机器人回复
        chatbot,               # 输入:聊天历史
        chatbot                # 输出:更新后的聊天历史
    )
    
    # 设置清除按钮点击事件:清空聊天历史
    clear.click(lambda: None, None, chatbot, queue=False)

# 启动Gradio应用
demo.launch()

 运行结果

可以使用then事件侦听器的方法连续运行事件。这将在前一个事件运行完毕后运行下一个事件。这对于运行分多个步骤更新组件的事件非常有用。

将多个触发器绑定到函数

# 导入Gradioimport gradio as gr

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建界面组件
    name = gr.Textbox(label="Name")           # 姓名输入框
    output = gr.Textbox(label="Output Box")   # 问候输出框
    greet_btn = gr.Button("Greet")           # 问候按钮
    trigger = gr.Textbox(label="Trigger Box") # 触发器信息显示框

    # 问候处理函数
    def greet(name, evt_data: gr.EventData):
        """
        生成问候消息并返回触发事件信息
        参数:
            name: 用户输入的姓名
            evt_data: 事件数据对象,包含触发事件的详细信息
        返回:
            问候消息
            触发组件的类名
        """
        return "Hello " + name + "!", evt_data.target.__class__.__name__

    # 清除姓名输入的函数
    def clear_name(evt_data: gr.EventData):
        """
        清除输入框内容
        参数:
            evt_data: 事件数据对象
        返回:
            空字符串,用于清除输入
        """
        return ""

    # 设置事件处理链
    gr.on(
        # 设置多个触发器:输入框提交和按钮点击都会触发
        triggers=[name.submit, greet_btn.click],
        fn=greet,                    # 处理函数
        inputs=name,                 # 输入组件
        outputs=[output, trigger],   # 输出组件:问候消息和触发器信息
    ).then(                         # 链式处理
        clear_name,                 # 清除函数
        outputs=[name]              # 清除姓名输入框
    )

# 启动Gradio应用
demo.launch()

运行结果

将多个触发器绑定到同一个函数。例如,您可能希望允许用户单击提交按钮,或按 Enter 键提交表单。您可以使用gr.on方法并将触发器列表传递给来执行此操作trigger。

使用装饰器语法

import gradio as gr

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    output = gr.Textbox(label="Output Box")
    greet_btn = gr.Button("Greet")

    @gr.on(triggers=[name.submit, greet_btn.click], inputs=name, outputs=output)
    def greet(name):
        return "Hello " + name + "!"

demo.launch()

以gr.on通过绑定到实现该事件的组件的事件来创建“实时”事件change。如果您未指定任何触发器,该函数将自动绑定到change包含change事件的所有输入组件的所有事件(例如,gr.Textbox有change事件而gr.Button没有事件)。

将组件值直接绑定到其他组件的函数

import gradio as gr

with gr.Blocks() as demo:
  num1 = gr.Number()
  num2 = gr.Number()
  product = gr.Number(lambda a, b: a * b, inputs=[num1, num2])

demo.launch()

 运行结果

将组件的值设置为始终为其他组件的值的函数,则可以使用以上简写方式。

控制布局

子句中的元素with gr.Row将全部水平显示。例如,并排显示两个按钮:

with gr.Blocks() as demo:
    with gr.Row():
        btn1 = gr.Button("Button 1")
        btn2 = gr.Button("Button 2")

可以将 Row 中的每个元素设置为具有相同的高度。使用equal_height参数进行配置。

with gr.Blocks() as demo:
    with gr.Row(equal_height=True):
        textbox = gr.Textbox()
        btn2 = gr.Button("Button 2")

可以通过每个组件中存在的scale和参数的组合来控制行中元素的宽度。min_width

  • scale是一个整数,它定义元素在行中占用的空间大小。如果比例设置为0,元素将不会扩展以占用空间。如果比例设置为1或更大,元素将扩展。一行中的多个元素将按比例扩展。下面,btn2将扩展为 的两倍btn1,而btn0根本不会扩展:
with gr.Blocks() as demo: with gr.Row(): btn0 = gr.Button("Button 0", scale=0) btn1 = gr.Button("Button 1", scale=1) btn2 = gr.Button("Button 2", scale=2)
  • min_width将设置元素的最小宽度。如果没有足够的空间来满足所有min_width值,则 Row 将换行。

 列和嵌套

# 导入Gradioimport gradio as gr

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 第一行:创建包含三个输入组件的水平布局
    with gr.Row():
        text1 = gr.Textbox(label="t1")                    # 文本输入框
        slider2 = gr.Textbox(label="s2")                  # 文本输入框
        # 确保drop3下拉框可用,移除任何disabled属性
        drop3 = gr.Dropdown(["a", "b", "c"], label="d3", interactive=True)  # 下拉选择框

    # 创建一个显示选择结果的文本框
    result = gr.Textbox(label="选择结果", interactive=False)
    
    # 定义处理drop3选择变化的函数
    def on_dropdown_change(value):
        """
        处理下拉框选择变化
        参数:
            value: 选择的值
        返回:
            包含选择信息的字符串
        """
        return f"您选择了: {value}"
    
    # 绑定drop3change事件到处理函数
    drop3.change(fn=on_dropdown_change, inputs=drop3, outputs=result)

    # 第二行:创建两列布局
    with gr.Row():
        # 左列:比例为1,最小宽度300像素
        with gr.Column(scale=1, min_width=300):
            # 创建多个文本输入框和按钮
            text1 = gr.Textbox(label="prompt 1")  # 提示输入框1
            text2 = gr.Textbox(label="prompt 2")  # 提示输入框2
            inbtw = gr.Button("Between")          # 中间按钮
            text4 = gr.Textbox(label="prompt 1")  # 提示输入框3
            text5 = gr.Textbox(label="prompt 2")  # 提示输入框4

        # 右列:比例为2,最小宽度300像素
        with gr.Column(scale=2, min_width=300):
            # 显示图片和按钮
            img1 = gr.Image("images/20250331101812.png")  # 加载并显示图片
            btn = gr.Button("Go")                  # 操作按钮

# 启动Gradio应用
demo.launch()

运行结果

第一列有两个垂直排列的文本框。第二列有一个垂直排列的图像和按钮。注意两列的相对宽度是如何由scale参数设置的。值是该列的两倍,scale宽度也是该列的两倍。 

填充浏览器高度/宽度

import gradio as gr

with gr.Blocks(fill_height=True) as demo:
    gr.Chatbot(scale=1)
    gr.Textbox(scale=0)

# 启动Gradio应用
demo.launch()

运行结果

移除侧边距来让应用占据浏览器的整个宽度,请使用gr.Blocks(fill_width=True)。使顶级组件扩展至占据浏览器的整个高度,请使用fill_height并将比例应用于扩展的组件。

方面

# 导入Gradio库,用于创建Web界面
import gradio as gr

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建图像编辑器组件
    # width="50vw" 表示宽度为浏览器视口宽度的50%
    # vw是视口宽度单位,100vw等于整个视口的宽度
    im = gr.ImageEditor(width="50vw")  # 创建可交互的图像编辑器

# 启动Gradio应用
demo.launch()

运行结果

这些参数可以接受数字(解释为像素)或字符串。使用字符串可以将任何 CSS 单位直接应用于封装的 Block 元素。

标签和折叠面板

# 导入所需的库
import numpy as np    # 用于图像处理
import gradio as gr   # 用于创建Web界面

# 文本翻转函数
def flip_text(x):
    """
    将输入文本反转
    参数:
        x: 输入文本
    返回:
        反转后的文本
    """
    return x[::-1]

# 图像翻转函数
def flip_image(x):
    """
    水平翻转输入图像
    参数:
        x: 输入图像(numpy数组)
    返回:
        水平翻转后的图像
    """
    return np.fliplr(x)

def get_value(x):
    """
    将滑块值转换为适合Markdown显示的字符串
    参数:
        x: 滑块的值(浮点数)
    返回:
        包含滑块值的Markdown字符串
    """
    # 返回格式化的Markdown字符串,而不是直接返回浮点数
    return f"当前值: **{x}**"

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 添加标题说明
    gr.Markdown("Flip text or image files using this demo.")
    
    # 文本翻转标签页
    with gr.Tab("Flip Text"):
        text_input = gr.Textbox()      # 文本输入框
        text_output = gr.Textbox()     # 文本输出框
        text_button = gr.Button("Flip") # 文本翻转按钮
    
    # 图像翻转标签页
    with gr.Tab("Flip Image"):
        # 创建水平布局放置输入输出图像
        with gr.Row():
            image_input = gr.Image()     # 图像输入组件
            image_output = gr.Image()    # 图像输出组件
        image_button = gr.Button("Flip") # 图像翻转按钮

    # 创建折叠面板(默认关闭)
    with gr.Accordion("Open for More!", open=False):
        mk = gr.Markdown("Look at me...")     # 折叠面板内的说明文本
        # 创建滑块组件
        temp_slider = gr.Slider(
            0, 1,                    # 最小值和最大值
            value=0.1,              # 默认值
            step=0.1,               # 步长
            interactive=True,        # 可交互
            label="Slide me",       # 滑块标签
        )

    # 绑定按钮点击事件
    text_button.click(flip_text, inputs=text_input, outputs=text_output)   # 文本翻转功能
    image_button.click(flip_image, inputs=image_input, outputs=image_output) # 图像翻转功能
    temp_slider.change(get_value, inputs=temp_slider, outputs=mk)

# 启动Gradio应用
demo.launch()

运行结果

可以使用子句创建选项卡with gr.Tab('tab_name'):。在上下文中创建的任何组件with gr.Tab('tab_name'):都会出现在该选项卡中。连续的选项卡子句组合在一起,以便一次可以选择一个选项卡,并且只显示该选项卡上下文中的组件。还请注意gr.Accordion('label')本例中的。Accordion 是一种可以切换打开或关闭的布局。与 一样,它是一个可以选择性隐藏或显示内容的布局元素。单击手风琴的切换图标时,Tabs在 内定义的任何组件都将被隐藏或显示。with gr.Accordion('label'):

侧边栏

# 导入所需的库
import gradio as gr    # 用于创建Web界面
import random         # 用于随机选择名字组件

# 宠物名字生成函数
def generate_pet_name(animal_type, personality):
    """
    根据动物类型和性格生成宠物名字
    参数:
        animal_type: 动物类型(猫、狗、鸟、兔子)
        personality: 性格特征(普通、搞笑、高贵)
    返回:
        生成的宠物名字
    """
    # 可爱的名字前缀列表
    cute_prefixes = ["Fluffy", "Ziggy", "Bubbles", "Pickle", "Waffle", "Mochi", "Cookie", "Pepper"]
    
    # 不同动物类型对应的名字后缀
    animal_suffixes = {
        "Cat": ["Whiskers", "Paws", "Mittens", "Purrington"],      # 猫咪后缀
        "Dog": ["Woofles", "Barkington", "Waggins", "Pawsome"],    # 狗狗后缀
        "Bird": ["Feathers", "Wings", "Chirpy", "Tweets"],         # 鸟类后缀
        "Rabbit": ["Hops", "Cottontail", "Bouncy", "Fluff"]        # 兔子后缀
    }

    # 随机选择前缀和对应动物类型的后缀
    prefix = random.choice(cute_prefixes)
    suffix = random.choice(animal_suffixes[animal_type])

    # 根据性格特征调整名字
    if personality == "Silly":  # 搞笑性格:添加头衔
        prefix = random.choice(["Sir", "Lady", "Captain", "Professor"]) + " " + prefix
    elif personality == "Royal":  # 高贵性格:添加尊称
        suffix += " the " + random.choice(["Great", "Magnificent", "Wise", "Brave"])

    # 组合并返回完整的宠物名字
    return f"{prefix} {suffix}"

# 创建Gradio界面块,使用柔和主题
with gr.Blocks(theme=gr.themes.Soft()) as demo:
    # 创建左侧边栏
    with gr.Sidebar(position="left"):
        # 添加标题和说明
        gr.Markdown("# 🐾 Pet Name Generator")
        gr.Markdown("Use the options below to generate a unique pet name!")

        # 创建动物类型下拉选择框
        animal_type = gr.Dropdown(
            choices=["Cat", "Dog", "Bird", "Rabbit"],  # 可选动物类型
            label="Choose your pet type",              # 选择框标签
            value="Cat"                                # 默认值
        )
        
        # 创建性格类型单选按钮组
        personality = gr.Radio(
            choices=["Normal", "Silly", "Royal"],      # 可选性格类型
            label="Personality type",                  # 单选组标签
            value="Normal"                             # 默认值
        )

    # 创建名字输出文本框
    name_output = gr.Textbox(label="Your pet's fancy name:", lines=2)
    # 创建生成按钮,使用主要样式
    generate_btn = gr.Button("Generate Name! 🎲", variant="primary")
    
    # 绑定按钮点击事件
    generate_btn.click(
        fn=generate_pet_name,                    # 处理函数
        inputs=[animal_type, personality],       # 输入组件
        outputs=name_output                      # 输出组件
    )

# 启动Gradio应用
demo.launch()

运行结果

侧边栏是一个可折叠面板,它在屏幕左侧呈现子组件,可以展开或折叠。

能见度

# 导入 Gradio 库用于构建 Web 界面
import gradio as gr

# 创建 Gradio 应用界面
with gr.Blocks() as demo:
    # 创建输入组件
    name_box = gr.Textbox(label="Name")  # 姓名输入框
    age_box = gr.Number(label="Age", minimum=0, maximum=100)  # 年龄输入框(0-100)
    symptoms_box = gr.CheckboxGroup(["Cough", "Fever", "Runny Nose"])  # 症状多选框
    submit_btn = gr.Button("Submit")  # 提交按钮

    # 创建初始隐藏的输出列
    with gr.Column(visible=False) as output_col:
        diagnosis_box = gr.Textbox(label="Diagnosis")  # 诊断结果显示
        patient_summary_box = gr.Textbox(label="Patient Summary")  # 病人信息摘要

    # 处理提交事件的函数
    def submit(name, age, symptoms):
        # 返回更新后的界面状态和诊断结果
        return {
            submit_btn: gr.Button(visible=False),  # 隐藏提交按钮
            output_col: gr.Column(visible=True),   # 显示输出列
            diagnosis_box: "covid" if "Cough" in symptoms else "flu",  # 简单的诊断逻辑
            patient_summary_box: f"{name}, {age} y/o",  # 生成病人摘要
        }

    # 绑定提交按钮点击事件
    submit_btn.click(
        submit,  # 处理函数
        [name_box, age_box, symptoms_box],  # 输入组件列表
        [submit_btn, diagnosis_box, patient_summary_box, output_col],  # 输出组件列表
    )

# 启动 Gradio 应用
demo.launch()

 运行结果

初始

诊断后

组件和布局元素都有一个visible可以初始设置和更新的参数。gr.Column(visible=...)在列上设置可用于显示或隐藏一组组件。

分别定义和渲染组件

# 导入 Gradio 库用于构建 Web 界面
import gradio as gr

input_textbox = gr.Textbox()

with gr.Blocks() as demo:
    gr.Examples(["hello", "bonjour", "merhaba"], input_textbox)
    input_textbox.render()

# 启动 Gradio 应用
demo.launch()

运行结果

在实际将组件呈现到 UI 中之前先定义它们。例如,您可能希望使用gr.Examples相应gr.Textbox输入上方的示例部分来显示。由于gr.Examples需要将输入组件对象作为参数,因此您需要先定义输入组件,然后在定义gr.Examples对象之后再呈现它。 解决这个问题的方法是定义范围gr.Textbox的外部,并在 UI 中想要放置组件的任何位置gr.Blocks()使用该组件的方法.render()。

全局状态

# 导入 Gradio 库用于构建 Web 界面
import gradio as gr

# 定义全局访问计数器变量,在所有用户之间共享
visitor_count = 0

# 计数器增加函数:每次调用时将访问量加1
def increment_counter():
    global visitor_count  # 声明使用全局变量
    visitor_count += 1    # 访问计数加1
    return visitor_count  # 返回最新的访问量

# 创建 Gradio 应用界面
with gr.Blocks() as demo:    
    # 创建文本框显示访问量,初始显示"Counting..."
    number = gr.Textbox(label="Total Visitors", value="Counting...")
    # 绑定页面加载事件:当页面加载时调用 increment_counter 函数,并将结果显示在 number 文本框中
    demo.load(increment_counter, inputs=None, outputs=number)

# 启动 Gradio 应用
demo.launch()

运行结果

Gradio 应用程序中的全局状态非常简单:在函数之外创建的任何变量都在所有用户之间全局共享。 这使得管理全局状态变得非常简单,无需外部服务。例如,在此应用程序中,visitor_count变量在所有用户之间共享。如果不想在用户之间共享某个值,则应在函数内声明它。但如果需要在函数调用之间共享值(例如聊天历史记录),该怎么办?在这种情况下,应该使用后续方法之一来管理状态。 

会话状态

# 导入Gradio库,用于创建Web界面
import gradio as gr

# 创建Gradio界面块
with gr.Blocks() as demo:
    # 创建一个状态变量来存储购物车商品,初始为空列表
    cart = gr.State([])
    # 创建复选框组,显示可选商品列表
    items_to_add = gr.CheckboxGroup(["Cereal", "Milk", "Orange Juice", "Water"])

    # 定义添加商品到购物车的函数
    # new_items: 新选择的商品列表
    # previous_cart: 当前购物车中的商品
    # 返回: 更新后的购物车列表
    def add_items(new_items, previous_cart):
        cart = previous_cart + new_items
        return cart

    # 创建"添加商品"按钮,并绑定点击事件到add_items函数
    gr.Button("Add Items").click(add_items, [items_to_add, cart], cart)

    # 创建数字显示组件,用于显示购物车中的商品数量
    cart_size = gr.Number(label="Cart Size")
    # 当购物车内容变化时,更新显示的商品数量
    cart.change(lambda cart: len(cart), cart, cart_size)

# 启动Gradio应用
demo.launch()

运行结果

Gradio 支持会话状态,即数据在页面会话中的多次提交中保持不变。重申一下,会话数据不会在模型的不同用户之间共享,并且如果用户刷新页面以重新加载 Gradio 应用,则不会保留。要将数据存储在会话状态中,您需要做三件事:

  1. 创建一个gr.State()对象。如果此有状态对象有默认值,则将其传递给构造函数。请注意,gr.State对象必须是可深度复制的,否则您将需要使用如下所述的不同方法。
  2. 在事件监听器中,State根据需要将对象作为输入和输出。
  3. 在事件监听函数中,添加变量作为输入参数和返回值。

注意我们是如何使用状态来实现这一点的:

  1. 我们将购物车商品存储在一个gr.State()对象中,这里将其初始化为一个空列表。
  2. 当将商品添加到购物车时,事件监听器将购物车用作输入和输出 - 它返回包含所有商品的更新后的购物车。
  3. 我们可以将一个.change监听器附加到购物车,它也使用状态变量作为输入。

你可以将其视为gr.State一个不可见的 Gradio 组件,可以存储任何类型的值。在这里,cart它在前端不可见,但用于计算。

.change任何事件侦听器更改状态变量的值后,状态变量的侦听器都会触发。如果状态变量包含一个序列(如、listsetdict,则当其中任何元素发生变化时都会触发更改。如果它包含一个对象或基元,则当值的哈希值发生变化时会触发更改。因此,如果您定义一个自定义类并创建一个gr.State作为该类实例的变量,请确保该类包含合理的__hash__实现。

当用户刷新页面时,会话状态变量的值会被清除。用户关闭标签页后,该值仍会存储在应用后端 60 分钟(可通过delete_cache中的参数进行配置gr.Blocks)。

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部