Blocks 是 Gradio 库中的一个用来自定义构建交互式 web app 的模块。它相较于 Interface 而言,更加底层,能够用来构建更复杂的应用。ChatInterface 可用来便捷构建聊天机器人交互页面。
1. 基本使用
import gradio as gr def test(): with gr.Blocks(title='我的应用', theme=gr.themes.Ocean()) as app: # 创建所需控件 num1 = gr.Number() num2 = gr.Number() button = gr.Button('提交') # 绑定点击事件 # 方式一 def response(num): return num + 100 button.click(fn=response, inputs=num1, outputs=num2) # 方式二 # @button.click(inputs=num1, outputs=num2) # def response(num): # return num + 100 app.launch() if __name__ == '__main__': test()
2. 事件处理
如何将多个事件便捷绑定到同一个处理函数上,以及如何连续处理事件。
import gradio as gr # 1. gr.on 多个事件绑定到同一个函数 def test01(): with gr.Blocks() as app: num1 = gr.Number() num2 = gr.Number() button = gr.Button() # 将多个事件绑定到同一个事件处理函数上 def my_submit(num): return num + 100 # 1. 分别绑定 num1.submit(my_submit, inputs=num1, outputs=num2) button.click(my_submit, inputs=num1, outputs=num2) # 2. 使用 gr.on # gr.on(triggers=[button.click, num1.submit], fn=my_submit, inputs=num1, outputs=num2) @gr.on(triggers=[button.click, num1.submit], inputs=num1, outputs=num2) def my_submit(num): return num + 100 app.launch() # 2. 连续事件 then 和 success def test02(): with gr.Blocks() as app: num1 = gr.Number() num2 = gr.Number(interactive=True) num3 = gr.Number(interactive=True) btn1 = gr.Button('提交') btn2 = gr.Button('提交') # then:无论上一个事件是否抛出异常,下一个事件都会执行 def then_submit1(num): # raise gr.Error('错误发生') return num + 10 def then_submit2(num): return num + 100 btn1.click(fn=then_submit1, inputs=num1, outputs=num2).then(then_submit2, inputs=num2, outputs=num3) # success:只有上一个事件没有抛出异常,下一个事件才会执行 def success_submit1(num): # raise gr.Error('错误发生') return num + 10 def success_submit2(num): return num + 100 btn2.click(fn=success_submit1, inputs=num1, outputs=num2).success(fn=success_submit2, inputs=num2, outputs=num3) app.launch() if __name__ == '__main__': test02()
3. 布局控制
主要四种常见布局:gradio.Row、gradio.Column、gradio.Tab、gradio.Accordion
import gradio as gr def test(): with gr.Blocks(fill_width=True, fill_height=True) as app: with gr.Row(): # 控件在一行水平排列 with gr.Row(): # scale 调整控件占比 gr.Textbox(label='text1', scale=1) gr.Textbox(label='text2', scale=2) gr.Image('http://mengbaoliang.cn/wp-content/uploads/2023/12/a40e7875913e8d5.png', scale=3) # 控件在一列垂直排列 with gr.Column(): gr.TextArea(label='area1') gr.TextArea(label='area2') with gr.Tab('标签页1'): with gr.Row(): gr.Textbox(label='text1') gr.Textbox(label='text2') with gr.Tab('标签页2'): with gr.Column(): gr.TextArea(label='area1') gr.TextArea(label='area2') with gr.Accordion('折叠/展开', open=False): with gr.Column(): gr.TextArea(label='area1') gr.TextArea(label='area2') app.launch() if __name__ == '__main__': test()
4. 动态渲染
import gradio as gr # 1. 通过输入数字创建控件 def test01(): with gr.Blocks() as app: gr.Markdown('# 动态创建控件') numnber = gr.Number(label='控件数量') @gr.render(inputs=numnber, triggers=[numnber.submit,]) def add_components(number): for i in range(number): gr.Number() app.launch() # 2. 通过点击按钮创建控件 def test02(): with gr.Blocks() as app: gr.Markdown('# 动态创建控件') with gr.Row(): state = gr.State(0) btn1 = gr.Button('增加') btn2 = gr.Button('减少') # 改变 state 的值 btn1.click(lambda x : x + 1, state, state) btn2.click(lambda x : x - 1, state, state) @gr.render(inputs=state, triggers=[state.change,]) def change_components(number): for i in range(number): with gr.Row(): num1 = gr.Number(key=f'in{i}') num2 = gr.Number(key=f'out{i}') num1.submit(fn=lambda x : x + 100, inputs=num1, outputs=num2) app.launch() if __name__ == '__main__': test02()
5. 修改属性
import gradio as gr def test(): with gr.Blocks() as app: choice = gr.Radio(choices=['1', '3', '5', '7']) output = gr.Textbox(label="输出") @choice.change(inputs=choice, outputs=output) def process_function(value): if value == '1': return gr.update(lines=1, value="一行") if value == '3': return gr.update(lines=3, value="三行") if value == '5': return gr.update(lines=5, value="五行") if value == '7': return gr.update(lines=7, value="七行") app.launch() if __name__ == '__main__': test()