抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Gradio

Gradio是一个基于Python的Web UI框架,常用于AI demo搭建,SD的webui就使用的Gradio

Gradio采用函数式编程,由组件和函数组成,声明组件即可绘制UI,为组件绑定函数可以修改组件内容

可以在Gradio Playground中预览体验

基本语法

Blocks

我不太喜欢 Interface

相较于Interface,Blocks可以使用gr.Row()等排版方式,更灵活

Gradio可以渲染一个markdown、html文本,可以将一些大段文字写在资源里,运行时读资源文本

在某个层级声明一个组件(比如Button)就会渲染一个按钮,可以用循环等方式批量生成

组件可以绑定事件,事件由函数+输入+输出组成

import gradio as gr
import shutil
from pathlib import Path
import zipfile

with gr.Blocks() as demo: # MARK!
# 声明一个Markdown标题
gr.Markdown('# Hello Title')
# 声明一个Upload button
u = gr.UploadButton("Upload a file", file_count="single", file_types=[".zip"])
# 下面的几个组件在一行
with gr.Row():
file_name_text = gr.Textbox(lines=1, label="File name")
file_count_text = gr.Textbox(lines=1, label="File count")
# 为Upload button绑定事件,输入是button本身,输出是两个Textbox
u.upload(process_upload_file, inputs=u, outputs=[file_name_text, file_count_text])

if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860) # 端口,尤其是要将服务暴露出去时
demo.queue(concurrency_count=3)

TabbedInterface

可以将多个Blocks和在一起,通过左上角的页签切换显示的Blocks,很适合多个平行功能的开发

with gr.Blocks() as demo:
...
with gr.Blocks() as demo2:
...

app = gr.TabbedInterface([demo, demo2], ['Demo Name', 'Demo2 Name'])
app.launch(server_name="0.0.0.0", server_port=7861)

函数

我感觉gradio的函数写法很神奇,你在函数外只能声明组件,不能拿到组件的值,不能修改组件,想做1+1也要使用函数

为组件绑定函数时,inputs和outputs均为组件(或组件数组),但函数的输入和输出是组件的值,而非组件本身,比如你为一个函数绑定了输出为一个Textbox,你只需要返回一个字符串就行

# 这个函数的输入是一个upload button对应的内容
def process_upload_file(file):
upload_dir = Path("./uploads")
upload_dir.mkdir(parents=True, exist_ok=True) # Create the directory if it doesn't exist
file_path = upload_dir / Path(file.name)
shutil.copy(file, upload_dir)
unzip_folder = upload_dir / Path(file).stem
with zipfile.ZipFile(file_path, 'r') as zip_ref:
zip_ref.extractall(unzip_folder)
# 输出是两个字符串
return Path(file).stem, len(zip_ref.namelist())

全局变量

在外部定义一个全局变量,在函数中可以访问

stop_animation = False

def play_animation(file_name, current_frame, file_count, frame_rate):
global stop_animation
stop_animation = False
for i in range(int(current_frame), int(file_count)):
if stop_animation:
break
time.sleep(1/float(frame_rate))
progress = (i+1)/int(file_count)
with open(f'uploads/{file_name}/{i}.svg', 'r') as f:
svg_content = f.read()
# 这里的yield是stream用法
yield svg_content, i, progress
def stop_animation():
global stop_animation # MARK!
stop_animation = True

with gr.Blocks() as demo:
...
html = gr.HTML()
with gr.Row():
btn = gr.Button("Start")
stop_btn = gr.Button("Stop")
btn.click(play_animation, inputs=[file_name_text, frame_index, file_count_text, frame_rate], outputs=[html, frame_index, sl])
stop_btn.click(stop_animation)

组件

示例

可以给一些输入组件提供示例,点一下自动填充

input_image = gr.Image(type="filepath")
gr.Examples(
examples=[
[osp.join(example_portrait_dir, "hal.jpeg")],
[osp.join(example_portrait_dir, "s7.jpg")],
],
inputs=[input_image],
cache_examples=False,
)

其他

网络连接bug

https://github.com/gradio-app/gradio/issues/4332

评论