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 转换为深褐色的系数 # 每一行分别对应输出颜色的 R、G、B 分量 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
用于指定内容的存放位置:
title
:接受文本,并可以将其显示在界面的最顶部,同时也成为页面的标题。description
:接受文本、markdown 或 HTML 并将其放置在标题下方。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 支持的另一种数据持久性类型是会话状态,其中数据在页面会话中的多次提交中保持不变。但是,数据不会在模型的不同用户之间共享。要将数据存储在会话状态中,需要做三件事:
- 将一个额外的参数传入你的函数,它代表接口的状态。
- 在函数的最后,将状态的更新值作为额外的返回值返回。
- 在创建时添加
'state'
输入和输出组件'state'
Interface
在这里,我们不能将提交历史记录存储在全局变量中,否则提交历史记录会在不同的用户之间混乱。
反应式接口
实时界面
# 导入Gradio库用于创建Web界面 import gradio as gr def calculator(num1, operation, num2): """ 实现基础计算器功能 参数: num1: 第一个数字 operation: 运算类型(加减乘除) num2: 第二个数字 返回: float或str: 计算结果或错误信息 """ 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 种不同类型的演示:
- 标准演示:具有单独的输入和输出(例如图像分类器或语音到文本模型)
- 仅输出演示:不接受任何输入但产生输出(例如无条件图像生成模型)
- 仅输入演示:不产生任何输出但会接受某种输入(例如,将您上传的图像保存到持久外部数据库的演示)
- 统一演示:既有输入组件,也有输出组件,但输入和输出组件相同。这意味着产生的输出将覆盖输入(例如文本自动完成模型)
根据演示的类型,用户界面(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: 用户输入的提示文本 返回: 生成的文本字符串 """ # 生成文本,设置最大长度为30个token,生成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()
运行结果
- 首先,请注意该
with gr.Blocks() as demo:
子句。Blocks 应用程序代码将包含在此子句中。 - 接下来是组件。这些组件与
Interface
中使用的组件相同。但是,组件不是传递给某个构造函数,而是在with
子句中创建时自动添加到块中。 - 最后,
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") # 从a到b的操作按钮 btoa = gr.Button("b > a") # 从b到a的操作按钮 # 绑定按钮点击事件 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 # 初始化语音识别模型 # 使用facebook的wav2vec2预训练模型,专门用于语音识别 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()
运行结果
多个输入组件将数据传递给函数,则函数有两种方式可以接受输入组件值:
- 作为参数列表,或
- 作为单个值字典,由组件键入
函数返回列表与字典
以以下方式返回多个输出组件的值:
- 值列表,或
- 由组件键入的字典
# 导入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事件侦听器的方法连续运行事件。这将在前一个事件运行完毕后运行下一个事件。这对于运行分多个步骤更新组件的事件非常有用。
将多个触发器绑定到函数
# 导入Gradio库 import 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 将换行。
列和嵌套
# 导入Gradio库 import 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}" # 绑定drop3的change事件到处理函数 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 应用,则不会保留。要将数据存储在会话状态中,您需要做三件事:
- 创建一个
gr.State()
对象。如果此有状态对象有默认值,则将其传递给构造函数。请注意,gr.State
对象必须是可深度复制的,否则您将需要使用如下所述的不同方法。 - 在事件监听器中,
State
根据需要将对象作为输入和输出。 - 在事件监听函数中,添加变量作为输入参数和返回值。
注意我们是如何使用状态来实现这一点的:
- 我们将购物车商品存储在一个
gr.State()
对象中,这里将其初始化为一个空列表。 - 当将商品添加到购物车时,事件监听器将购物车用作输入和输出 - 它返回包含所有商品的更新后的购物车。
- 我们可以将一个
.change
监听器附加到购物车,它也使用状态变量作为输入。
你可以将其视为gr.State
一个不可见的 Gradio 组件,可以存储任何类型的值。在这里,cart
它在前端不可见,但用于计算。
.change
任何事件侦听器更改状态变量的值后,状态变量的侦听器都会触发。如果状态变量包含一个序列(如、list
或set
)dict
,则当其中任何元素发生变化时都会触发更改。如果它包含一个对象或基元,则当值的哈希值发生变化时会触发更改。因此,如果您定义一个自定义类并创建一个gr.State
作为该类实例的变量,请确保该类包含合理的__hash__
实现。
当用户刷新页面时,会话状态变量的值会被清除。用户关闭标签页后,该值仍会存储在应用后端 60 分钟(可通过delete_cache
中的参数进行配置gr.Blocks
)。