Gradio 学习
Gradio 做一些展示页面真的非常方便,非常有必要学习的一个库!!!以此记录
Quickstrat
先决条件 及 下载
python3.8.0
及以上
pip install gradio -i https://pypi.tuna.tsinghua.edu.cn/simple
一个快速开始的例子
import gradio as gr
def gradio_welcome(name):
return f"我是Gradio, 欢迎你:{name}!"
app = gr.Interface(
fn=gradio_welcome,
inputs=['text'],
outputs=['text']
)
app.launch()
当然对上面的控件,是简写方式
app = gr.Interface(
fn=gradio_welcome,
inputs=[gr.Textbox(label='请输入您的名字', value='张三')],
outputs=[gr.Textbox(label='输出')]
)
1. Interface
a.介绍
第一部分都是围绕着Interface这个高级抽象类展开的,利用Interface这个抽象类建立一个页面,初始化Interface需要三个必要参数fn
,inputs
, outputs
。
fn: 对Interface(UI)的绑定
inputs: 输入,输入的数量要取决于绑定函数的形参数量
outputs: 输出,输出的数量要取决于绑定函数的返回数量
官方对此的描述: The gr.Interface
class is a high-level abstraction in Gradio that allows you to quickly create a demo for any Python function simply by specifying the input types and the output types. Revisiting our first demo:
b.输入,输出
输入也是多元的,TextBox
的字符串,CheckBox
的布尔值,Slider
的数字
输出可以输出 不仅是输出TextBox
文字 Image
, DataFrame
, Video
,Html
,Markdown
一个输入图片,加一层黄色蒙版的案例
import numpy as np
import gradio as gr
def sepia(input_img):
sepia_filter = np.array([
[0.393, 0.769, 0.189],
[0.349, 0.686, 0.168],
[0.272, 0.534, 0.131]
])
sepia_img = input_img.dot(sepia_filter.T)
sepia_img /= sepia_img.max()
return sepia_img
demo = gr.Interface(sepia, gr.Image(), "image")
demo.launch()
c. 其他参数
import gradio as gr
def calculator(name, cls):
return name + '是' + cls
demo = gr.Interface(
calculator,
[
"text",
gr.Radio(["一班", "二班", "三班"]),
],
"text",
examples=[
['张三', '三班'],
['李四', '二班'],
],
title="班级表格",
description="这是一个班级表格参照",
)
demo.launch()
必要3个参数,不在此再次赘述了
title: app的一个标题
label: 输入输出空间都有次属性,一个空间的标签
description:进一步说明
examples:列子 也可以传入csv文件examples='/demo/calculator/examples' 确保目录下有csv文件
cache_examples:为True则对例子进行缓存,即使数据更新了,也不会进行更新了,只能用开启新的launch重新加载。也可以为lazy开启懒加载,启动程序不会进行缓存,当第一个用户访问用到时才会开始缓存。相对于前者启动Gradio的速度会更快
d. Interface的四种情况
Standard Demo:有输入有输出
Outputs-only Demo: 没有输入仅仅只有输出
Inputs-only Demo: 只有输入没有输出
Unified demos: 拥有输入和输出,但是输入和输出都是通一控件,输出覆盖掉输出。比如翻译模型,输入你好,输出hello 覆盖你好
e. Interface State
1.Globla
在全局创建一个变量,保存历史过来的数据,进行显示。如果是多用户使用,这个方案则会导致所有用户都会出现不属于他们的输出,引用官方的一个案例
import gradio as gr
scores = []
def track_score(score):
scores.append(score)
top_scores = sorted(scores, reverse=True)[:3]
return top_scores
demo = gr.Interface(
track_score,
gr.Number(label="Score"),
gr.JSON(label="Top Scores")
)
demo.launch()
2.Session
利用session可以区分用户,解决了globla带来的串联问题。我自己的一个案例,模拟下载输出进度。
import time
import gradio as gr
def store_message(file: str, history: list[str]):
for i in range(1, 101):
time.sleep(0.01)
history.append(f'{file}文件正在下载,进度[{i}%]')
print(history)
yield '\n'.join(history), history
history.append(f'{file}文件下载完成')
return '\n'.join(history), history
demo = gr.Interface(
fn=store_message,
inputs=["textbox", gr.State(value=[])],
outputs=[gr.Textbox(max_lines=5, autoscroll=True, show_copy_button=True, label='日志输出'), gr.State()]
)
demo.launch()
f. Live 和 Streaming
live : 布尔值,如果为True,则自动监听,输入参数输入完成后,无需点击按钮,自动在输出控件显示输出结果
streaming: 流式传输,摄像头,或者麦克风之类的需要一直传输的
先跳过,后面在学习,暂时没有这个需求
2. Blocks
类似于组件的开发,一个最直观的例子
上面说的Interface四种情况,都是单数据量,而Blocks则不限制
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")
@greet_btn.click(inputs=name, outputs=output)
def greet(name):
return "Hello " + name + "!"
demo.launch()
import gradio as gr
def greet(name):
return "Hello " + name + "!"
with gr.Blocks() as demo:
name = gr.Textbox(label="Name")
output = gr.Textbox(label="Output Box")
greet_btn = gr.Button("Greet")
greet_btn.click(fn=greet, inputs=name, outputs=output, api_name="greet")
demo.launch()
a. 时间监听和交互 (Event Listeners and Interactivity)
interactivity: 其中Textbox当作为输出时是不能交互的, 通过此参数输出控件也变得可被交互,当然有输出内容的时候交互输入的内容就会被覆盖掉
output = gr.Textbox(label="Output Box", interactive=True)
b. 多个输入,字典或列表
上面的案例都是一个控件的输入,此案例是两个输入控件的传递,分别用字典和列表
import gradio as gr
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):
return num1 + num2
add_btn.click(add, inputs=[a, b], outputs=c)
def sub(data):
return data[a] - data[b]
sub_btn.click(sub, inputs={a, b}, outputs=c)
demo.launch()
c. 输出 retrun 字典或列表
之前默认案例的return都是用的列表,输出两个,当其中一个不用的时候,也要用0或者None占位。
而字典可以允许跳过某些控件的更新。但是传递的时候key必须是控件名称
列表
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]
)
字典
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]
)