欢迎你,未来的Gradio大师!接下来的旅程,我们将从完全0基础起步,手把手教你掌握Gradio这个强大的工具。学完这份文档,你不仅能快速搭建AI演示,更能开发出复杂的、可用于生产的Web应用。我们的目标是:让复杂变简单,让想法立刻变成可交互的现实。
第一阶段:入门篇 - 3分钟创建第一个App
1.1 Gradio是什么?
Gradio是一个开源的Python库,它让你无需HTML、CSS或JavaScript知识,就能为你的机器学习模型、API或任何Python函数快速构建一个漂亮的Web演示或应用。你写几行Python代码,它就自动生成一个可以拖拽、上传文件、点击按钮的网页界面。
1.2 环境安装
在开始之前,确保你的电脑上已经安装了Python(3.8及以上版本,推荐3.10+)。打开你的终端(Mac/Linux)或命令提示符(Windows),输入以下命令:
基础安装:
pip install gradio
国内用户加速安装(推荐):
pip install gradio -i https://pypi.tuna.tsinghua.edu.cn/simple
验证安装:
python -c "import gradio as gr; print(gr.__version__)"
💡 小贴士:建议在虚拟环境中进行安装,以避免与其他项目依赖产生冲突。
- Conda环境:
conda create -n gradio python=3.10 && conda activate gradio - venv环境:
python -m venv gradio_env && source gradio_env/bin/activate(Mac/Linux) 或gradio_env\Scripts\activate(Windows)
1.3 第一个程序:“你好,世界!”
让我们用最经典的例子开启旅程。创建一个新的Python文件,比如 app.py,输入以下代码:
import gradio as gr
# 1. 定义你的核心业务逻辑函数(这是最关键的!)
def greet(name):
return f"你好, {name}!欢迎进入Gradio的世界!"
# 2. 创建Gradio界面
demo = gr.Interface(
fn=greet, # 要包装的函数
inputs="text", # 输入组件类型(文本框)
outputs="text" # 输出组件类型(文本框)
)
# 3. 启动应用
demo.launch()
运行这个文件:python app.py。你会看到类似这样的输出:
Running on local URL: http://127.0.0.1:7860
在浏览器中打开这个地址,你的第一个Web应用就诞生了!在文本框输入你的名字,点击提交,看看发生了什么?
1.4 核心概念:Interface
上面的例子中,我们用到了Gradio最核心的高级类 gr.Interface。它就像一个万能胶水,把三个核心参数粘在一起:
fn:你想要包装的函数。这是你应用的大脑,可以是任何Python函数——从简单的字符串操作到复杂的深度学习模型推理。inputs:一个或多个输入组件。告诉Gradio,你的函数需要什么样的输入。可以是组件名称的字符串(如"text"),也可以是组件类的实例(如gr.Textbox())。outputs:一个或多个输出组件。告诉Gradio,你的函数返回什么样的结果。
1.5 让你的App更好看:添加标题和描述
我们还可以给应用增加一些样式,让它看起来更专业。
import gradio as gr
def greet(name, intensity):
return f"你好, {name}!" + "!" * int(intensity)
demo = gr.Interface(
fn=greet,
inputs=[
gr.Textbox(label="你的名字", placeholder="在这里输入...", lines=1),
gr.Slider(label="热情程度", minimum=1, maximum=5, value=3, step=1)
],
outputs=gr.Textbox(label="问候结果"),
title="🌟 我的第一个Gradio应用",
description="这是一个简单的问候应用,展示了Gradio的基本功能。",
theme="soft", # 内置主题:soft, default, monochrome
flagging_mode="never", # 禁用标记功能
examples=[["张三", 3], ["李四", 5]] # 添加示例,方便用户快速体验
)
demo.launch()
1.6 一键分享:把你的App发给全世界
Gradio提供了最简单的分享方式。只需在 launch() 函数中添加一个参数 share=True。
demo.launch(share=True)
运行后,你会看到一个公网链接(例如 https://xxxxx.gradio.live)。把这个链接发给任何人,他们就能通过浏览器访问你电脑上正在运行的应用了!
⚠️ 重要提示:
- 这个链接是临时且通过frp代理转发的,有效期72小时
- 适合快速演示,代码仍在你本地运行
- 生产环境部署建议使用Hugging Face Spaces或自有服务器
第二阶段:基础篇 - 玩转Gradio组件
2.1 丰富的输入/输出组件
Gradio内置了30多种组件,几乎覆盖了所有AI应用场景。我们来看几个最常用的。
| 组件类型 | 描述 | 常用场景 | 关键参数 |
|---|---|---|---|
gr.Textbox() | 文本输入/输出框 | 文本生成、翻译、问答 | lines, placeholder, max_lines |
gr.Number() | 数字输入/输出 | 数值计算、参数调节 | minimum, maximum, step |
gr.Slider() | 滑动条 | 调节模型参数 | minimum, maximum, step, interactive |
gr.Image() | 图片上传/显示 | 图像分类、目标检测、生成 | type, image_mode, sources |
gr.Audio() | 音频上传/播放 | 语音识别、音乐生成 | type, source, format |
gr.Video() | 视频上传/播放 | 视频分析、动作识别 | format, sources |
gr.File() | 文件上传/下载 | 文档处理、批量预测 | file_types, file_count |
gr.Dataframe() | 数据表格 | 数据分析、表格预测 | headers, row_count, col_count |
gr.Dropdown() | 下拉菜单 | 选择模型版本、预设选项 | choices, value, multiselect |
gr.Radio() | 单选按钮 | 二选一或多选一 | choices, value |
gr.Checkbox() | 复选框 | 是否启用某功能 | label, value |
gr.CheckboxGroup() | 复选框组 | 多选功能 | choices, value |
gr.Chatbot() | 聊天机器人显示框 | 对话式AI | value, height, avatar_images |
gr.Markdown() | Markdown文本 | 标题、说明、文章 | value, visible |
gr.HTML() | 自定义HTML | 嵌入富文本内容 | value, visible |
gr.JSON() | JSON数据显示 | 展示结构化数据 | value, height |
gr.ColorPicker() | 颜色选择器 | 颜色相关应用 | value, label |
gr.Gallery() | 图片画廊 | 展示多张图片 | value, columns, height |
2.2 多输入和多输出
实际应用中,函数往往需要多个输入,也可能返回多个结果。Gradio处理起来同样简单。
import gradio as gr
import numpy as np
def process_text(text, num, check):
"""一个处理文本和数字的函数"""
if check:
processed_text = text.upper()
else:
processed_text = text.lower()
processed_num = num * 2
status = "✅ 处理成功" if processed_text else "⚠️ 处理失败"
return processed_text, processed_num, status
demo = gr.Interface(
fn=process_text,
inputs=[
gr.Textbox(label="输入文本", lines=2),
gr.Number(label="输入数字", value=10),
gr.Checkbox(label="转换为大写", value=True)
],
outputs=[
gr.Textbox(label="处理后的文本"),
gr.Number(label="数字×2"),
gr.Textbox(label="状态")
],
title="多输入多输出演示"
)
demo.launch()
2.3 案例实战1:简单的图像分类器
让我们把理论应用到实际中,结合Hugging Face的 transformers 库,创建一个图像分类应用。
import gradio as gr
from transformers import pipeline
import torch
# 检查是否有GPU可用
device = 0 if torch.cuda.is_available() else -1
# 加载一个预训练的图像分类模型
print("正在加载模型,首次运行会下载模型文件...")
classifier = pipeline(
"image-classification",
model="google/vit-base-patch16-224",
device=device
)
def classify_image(image):
"""接收PIL图像,返回预测结果字典"""
try:
predictions = classifier(image)
return {p['label']: p['score'] for p in predictions}
except Exception as e:
return {"错误": f"处理失败: {str(e)}"}
# 创建界面
demo = gr.Interface(
fn=classify_image,
inputs=gr.Image(type="pil", label="上传图片"), # 输入图像,类型为PIL
outputs=gr.Label(num_top_classes=3, label="识别结果"), # 显示前3个最可能的类别
title="🖼️ 智能图像分类器",
description="上传一张图片,AI会告诉你图片中可能是什么!支持动物、物体、场景等识别。",
examples=[["cat.jpg"], ["dog.jpg"], ["car.jpg"]], # 需要准备示例图片
cache_examples=True, # 缓存示例结果,加快加载速度
theme="soft"
)
print("应用启动成功!访问 http://localhost:7860")
demo.launch()
2.4 案例实战2:文本情感分析
创建一个情感分析工具,实时判断文本的情感倾向。
import gradio as gr
from transformers import pipeline
# 加载情感分析模型
sentiment_analyzer = pipeline(
"sentiment-analysis",
model="distilbert-base-uncased-finetuned-sst-2-english"
)
def analyze_sentiment(text):
"""分析文本情感"""
if not text.strip():
return {"等待输入...": 0}
result = sentiment_analyzer(text)[0]
label = result['label']
score = result['score']
# 转换为中文标签
label_cn = "正面 😊" if label == "POSITIVE" else "负面 😔"
return {label_cn: score}
demo = gr.Interface(
fn=analyze_sentiment,
inputs=gr.Textbox(
label="输入文本",
placeholder="例如:I love this movie! 或 This product is terrible...",
lines=3
),
outputs=gr.Label(label="情感分析结果"),
title="📊 实时情感分析器",
description="输入一段英文文本,AI会实时分析其情感倾向。",
theme="soft",
live=True # 实时分析,无需点击提交
)
demo.launch()
第三阶段:进阶篇 - 掌握Blocks构建复杂应用
3.1 为什么需要Blocks?
gr.Interface 简单易用,但不够灵活。当我们需要更复杂的布局(如将组件放在同一行)、更精细的事件控制(如点击按钮后执行某个函数)、或者需要管理多个数据流时,gr.Blocks 就派上了用场。
gr.Blocks 是一个低级API,它允许你像搭积木一样自由地构建Web应用。核心优势:
- ✅ 完全自定义布局:任意排列组件
- ✅ 精细事件控制:可以给任意组件绑定任意事件
- ✅ 复杂数据流:支持多个函数之间的数据传递
- ✅ 状态管理:轻松管理会话状态
3.2 你的第一个Blocks应用
用 gr.Blocks 重写之前的问候应用。
import gradio as gr
# 定义一个构建应用的函数,这是一个好习惯
def build_greet_app():
with gr.Blocks(title="Blocks版问候应用", theme="soft") as demo:
gr.Markdown("""
# 🌟 欢迎使用Blocks
这是使用 `gr.Blocks` 构建的应用,布局更加灵活!
""")
with gr.Row():
# 左侧:输入区域
with gr.Column(scale=1):
name = gr.Textbox(
label="你的名字",
placeholder="例如:张三",
info="输入你的名字,我会热情地问候你"
)
greet_btn = gr.Button("🎯 点击问候", variant="primary")
# 右侧:输出区域
with gr.Column(scale=1):
output = gr.Textbox(
label="问候结果",
interactive=False
)
# 添加一个清空按钮
clear_btn = gr.Button("🗑️ 清空")
# 定义按钮的点击事件
greet_btn.click(
fn=lambda name: f"你好,{name}!欢迎使用Blocks!",
inputs=name,
outputs=output
)
# 清空按钮事件
clear_btn.click(
fn=lambda: ("", ""), # 返回两个值,分别更新两个组件
inputs=[],
outputs=[name, output]
)
# 添加示例
gr.Examples(
examples=[["张三"], ["李四"], ["王五"]],
inputs=name,
outputs=output,
fn=lambda name: f"你好,{name}!"
)
return demo
demo = build_greet_app()
demo.launch()
3.3 布局:Row, Column, Tabs
Blocks 的强大之处在于布局控制。以下是一个完整的布局示例:
import gradio as gr
import numpy as np
from PIL import Image
import io
def build_layout_demo():
with gr.Blocks(title="高级布局演示", theme="soft") as demo:
gr.Markdown("# 🎨 Gradio高级布局指南")
gr.Markdown("本节展示如何使用 `Row`, `Column`, `Tab` 创建专业级界面")
# 1. 多列布局示例
gr.Markdown("## 1. 多列布局")
with gr.Row():
with gr.Column(scale=1, min_width=200):
gr.Markdown("### 左侧面板")
text_input = gr.Textbox(label="输入文本", lines=3)
btn_upper = gr.Button("转换为大写")
with gr.Column(scale=2, min_width=400):
gr.Markdown("### 中间面板(主工作区)")
text_output = gr.Textbox(label="处理结果", lines=5)
with gr.Column(scale=1, min_width=200):
gr.Markdown("### 右侧面板")
status = gr.Label(label="状态")
clear_btn = gr.Button("清空所有")
# 2. 选项卡布局
gr.Markdown("## 2. 选项卡布局")
with gr.Tabs():
with gr.TabItem("📷 图像处理"):
with gr.Row():
with gr.Column():
image_input = gr.Image(label="上传图片", type="pil")
process_img_btn = gr.Button("处理图片", variant="primary")
with gr.Column():
image_output = gr.Image(label="处理后图片")
with gr.TabItem("🎵 音频处理"):
with gr.Row():
audio_input = gr.Audio(label="上传音频", type="numpy")
audio_output = gr.Audio(label="处理后音频")
with gr.TabItem("📊 数据分析"):
with gr.Row():
data_input = gr.Dataframe(
label="输入数据",
headers=["A", "B", "C"],
row_count=5,
col_count=3
)
data_output = gr.JSON(label="分析结果")
# 3. 手风琴折叠面板
gr.Markdown("## 3. 折叠面板")
with gr.Accordion("高级设置 (点击展开)", open=False):
gr.Markdown("这些是高级选项,一般用户不需要修改")
with gr.Row():
temperature = gr.Slider(label="温度", minimum=0, maximum=1, value=0.7)
max_length = gr.Slider(label="最大长度", minimum=10, maximum=500, value=100)
with gr.Row():
use_gpu = gr.Checkbox(label="使用GPU", value=True)
model_dropdown = gr.Dropdown(
label="选择模型",
choices=["GPT-3.5", "GPT-4", "Claude"],
value="GPT-3.5"
)
# 定义事件处理函数
def process_text(text):
if text:
return text.upper(), "✅ 处理成功"
return "", "⚠️ 请输入文本"
def clear_all():
return "", "", {"等待输入": 0}
# 绑定事件
btn_upper.click(
fn=process_text,
inputs=text_input,
outputs=[text_output, status]
)
clear_btn.click(
fn=clear_all,
inputs=[],
outputs=[text_input, text_output, status]
)
# 简单的图像处理函数
def process_image(img):
if img is None:
return None
# 转换为灰度图
return img.convert('L')
process_img_btn.click(
fn=process_image,
inputs=image_input,
outputs=image_output
)
return demo
demo = build_layout_demo()
demo.launch()
3.4 状态管理:State
在复杂的交互中,我们需要在多次请求之间记住一些信息(例如聊天历史、计数器等)。Gradio提供了 gr.State 来实现这一点,它就像一个存储在服务器端的、不显示在界面上的变量。
import gradio as gr
import random
import time
def build_state_demo():
with gr.Blocks(title="状态管理演示", theme="soft") as demo:
gr.Markdown("# 🔄 状态管理 (State)")
gr.Markdown("`gr.State` 可以在多次交互中保持数据,而不显示在界面上")
# 初始化状态
counter = gr.State(value=0) # 计数器
history = gr.State(value=[]) # 历史记录
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### 计数器示例")
current_count = gr.Number(label="当前计数", value=0, interactive=False)
with gr.Row():
increment_btn = gr.Button("➕ 增加")
decrement_btn = gr.Button("➖ 减少")
reset_btn = gr.Button("🔄 重置")
with gr.Column(scale=2):
gr.Markdown("### 历史记录")
history_display = gr.JSON(label="操作历史")
# 分隔线
gr.Markdown("---")
# 猜数字游戏示例
gr.Markdown("### 🎮 猜数字游戏")
gr.Markdown("系统随机生成1-100之间的数字,你来猜!")
# 游戏状态
secret_number = gr.State(value=random.randint(1, 100))
attempts = gr.State(value=0)
game_over = gr.State(value=False)
with gr.Row():
guess_input = gr.Number(label="输入你的猜测", minimum=1, maximum=100)
guess_btn = gr.Button("提交猜测", variant="primary")
new_game_btn = gr.Button("新游戏")
game_feedback = gr.Textbox(label="提示", interactive=False)
attempts_display = gr.Number(label="尝试次数", value=0, interactive=False)
# 计数器函数
def increment(counter_val, history_val):
counter_val += 1
history_val.append(f"增加操作 at {time.strftime('%H:%M:%S')}")
return counter_val, counter_val, history_val, history_val
def decrement(counter_val, history_val):
counter_val -= 1
history_val.append(f"减少操作 at {time.strftime('%H:%M:%S')}")
return counter_val, counter_val, history_val, history_val
def reset_counter():
return 0, 0, [], []
# 猜数字游戏函数
def check_guess(guess, secret, attempts_count, game_over_flag):
if game_over_flag:
return "游戏已结束,请点击'新游戏'重新开始", attempts_count, game_over_flag, secret
if guess is None:
return "请输入一个数字!", attempts_count, game_over_flag, secret
attempts_count += 1
if guess < secret:
feedback = f"猜小了!再试试(第{attempts_count}次)"
elif guess > secret:
feedback = f"猜大了!再试试(第{attempts_count}次)"
else:
feedback = f"🎉 恭喜!猜对了!数字就是{secret},用了{attempts_count}次"
game_over_flag = True
return feedback, attempts_count, game_over_flag, secret
def new_game():
new_secret = random.randint(1, 100)
return "新游戏开始!输入你的第一个猜测", 0, False, new_secret
# 绑定计数器事件
increment_btn.click(
fn=increment,
inputs=[counter, history],
outputs=[counter, current_count, history, history_display]
)
decrement_btn.click(
fn=decrement,
inputs=[counter, history],
outputs=[counter, current_count, history, history_display]
)
reset_btn.click(
fn=reset_counter,
inputs=[],
outputs=[counter, current_count, history, history_display]
)
# 绑定游戏事件
guess_btn.click(
fn=check_guess,
inputs=[guess_input, secret_number, attempts, game_over],
outputs=[game_feedback, attempts_display, game_over, secret_number]
)
new_game_btn.click(
fn=new_game,
inputs=[],
outputs=[game_feedback, attempts_display, game_over, secret_number]
)
# 自动清空guess_input(可选)
guess_input.submit(
fn=lambda: None,
inputs=[],
outputs=[guess_input]
)
return demo
demo = build_state_demo()
demo.launch()
3.5 事件监听和触发器
在Blocks中,几乎任何组件都可以触发事件,包括点击、输入变化、拖拽上传等。
import gradio as gr
import numpy as np
import time
def build_events_demo():
with gr.Blocks(title="事件系统演示", theme="soft") as demo:
gr.Markdown("# ⚡ Gradio事件系统")
gr.Markdown("了解各种事件触发器:click, change, submit, upload, blur等")
with gr.Tabs():
# 1. 基本事件
with gr.TabItem("基本事件"):
with gr.Row():
with gr.Column():
gr.Markdown("### 点击事件")
btn = gr.Button("点击我")
click_output = gr.Textbox(label="点击结果")
with gr.Column():
gr.Markdown("### 变化事件")
slider = gr.Slider(minimum=0, maximum=100, label="滑动我")
change_output = gr.Number(label="当前值")
with gr.Row():
with gr.Column():
gr.Markdown("### 输入事件")
text_input = gr.Textbox(label="输入文本", placeholder="输入时实时显示")
input_output = gr.Textbox(label="实时显示")
with gr.Column():
gr.Markdown("### 失焦事件")
blur_input = gr.Textbox(label="输入后点击其他地方", placeholder="离开输入框时触发")
blur_output = gr.Textbox(label="触发结果")
# 绑定事件
btn.click(
fn=lambda: f"按钮被点击于 {time.strftime('%H:%M:%S')}",
outputs=click_output
)
slider.change(
fn=lambda x: x,
inputs=slider,
outputs=change_output
)
text_input.change(
fn=lambda x: f"你输入了: {x}",
inputs=text_input,
outputs=input_output
)
blur_input.blur(
fn=lambda x: f"离开输入框,内容是: {x}",
inputs=blur_input,
outputs=blur_output
)
# 2. 文件上传事件
with gr.TabItem("文件上传"):
with gr.Row():
with gr.Column():
gr.Markdown("### 图片上传")
image = gr.Image(label="上传图片", type="pil")
image_info = gr.JSON(label="图片信息")
with gr.Column():
gr.Markdown("### 文件上传")
file = gr.File(label="上传文件", file_types=[".txt", ".py"])
file_info = gr.Textbox(label="文件信息")
# 图片上传事件
image.upload(
fn=lambda img: {
"格式": str(img.format),
"尺寸": f"{img.size[0]}x{img.size[1]}",
"模式": img.mode
} if img else {},
inputs=image,
outputs=image_info
)
# 文件上传事件
file.upload(
fn=lambda f: f"文件名: {f.name}, 大小: {f.size/1024:.1f}KB" if f else "",
inputs=file,
outputs=file_info
)
# 3. 组合事件
with gr.TabItem("组合事件"):
gr.Markdown("### 多个事件触发同一个函数")
name = gr.Textbox(label="姓名")
age = gr.Number(label="年龄", value=25)
city = gr.Dropdown(label="城市", choices=["北京", "上海", "广州", "深圳"])
submit_btn = gr.Button("提交", variant="primary")
profile = gr.JSON(label="个人信息")
# 定义处理函数
def update_profile(name, age, city):
return {
"姓名": name or "未填写",
"年龄": age,
"城市": city,
"更新时间": time.strftime("%Y-%m-%d %H:%M:%S")
}
# 多个事件可以触发同一个函数
submit_btn.click(update_profile, [name, age, city], profile)
name.submit(update_profile, [name, age, city], profile) # 回车触发
age.submit(update_profile, [name, age, city], profile)
city.change(update_profile, [name, age, city], profile)
# 4. 链式事件
gr.Markdown("### 🔗 链式事件")
gr.Markdown("一个事件可以触发多个函数")
with gr.Row():
with gr.Column():
input_text = gr.Textbox(label="输入文本", placeholder="输入一些文字...")
process_btn = gr.Button("处理", variant="primary")
with gr.Column():
result1 = gr.Textbox(label="处理结果1")
result2 = gr.Textbox(label="处理结果2")
result3 = gr.Textbox(label="处理结果3")
# 定义多个处理函数
def step1(text):
return f"步骤1: 收到 '{text}'"
def step2(text):
return f"步骤2: 长度 {len(text)}"
def step3(text):
return f"步骤3: 大写 {text.upper()}"
# 链式调用:一个按钮触发多个函数
process_btn.click(
fn=step1,
inputs=input_text,
outputs=result1
).then(
fn=step2,
inputs=input_text,
outputs=result2
).then(
fn=step3,
inputs=input_text,
outputs=result3
)
return demo
demo = build_events_demo()
demo.launch()
3.6 进度条显示
对于耗时操作,Gradio提供了进度条功能,提升用户体验。
import gradio as gr
import time
import random
def long_running_task(iterations, progress=gr.Progress()):
"""模拟耗时任务"""
results = []
# 设置进度条描述
progress(0, desc="开始处理...")
for i in progress.tqdm(range(iterations), desc="处理中"):
# 模拟耗时操作
time.sleep(random.uniform(0.1, 0.3))
results.append(f"项目 {i+1} 处理完成")
# 更新进度条描述
progress((i+1)/iterations, desc=f"已处理 {i+1}/{iterations}")
return "\n".join(results)
def download_file(url, progress=gr.Progress()):
"""模拟文件下载"""
progress(0, desc="连接服务器...")
time.sleep(1)
for i in progress.tqdm(range(100), desc="下载中"):
time.sleep(0.05)
progress((i+1)/100, desc=f"下载进度 {i+1}%")
return "✅ 下载完成!"
def batch_process(files, progress=gr.Progress()):
"""批量处理文件"""
if not files:
return "请先上传文件"
progress(0, desc="准备处理...")
time.sleep(0.5)
for i, file in enumerate(files):
progress((i+1)/len(files), desc=f"正在处理文件 {i+1}/{len(files)}: {file.name}")
time.sleep(random.uniform(1, 2))
return f"✅ 已成功处理 {len(files)} 个文件"
def build_progress_demo():
with gr.Blocks(title="进度条演示", theme="soft") as demo:
gr.Markdown("# 📊 进度条演示")
gr.Markdown("使用 `gr.Progress()` 显示长时间运行任务的进度")
with gr.Tabs():
with gr.TabItem("简单循环"):
with gr.Row():
with gr.Column():
iter_slider = gr.Slider(
minimum=5,
maximum=50,
value=10,
step=5,
label="循环次数"
)
run_btn = gr.Button("开始处理", variant="primary")
with gr.Column():
output = gr.Textbox(label="处理结果", lines=10)
run_btn.click(
fn=long_running_task,
inputs=iter_slider,
outputs=output
)
with gr.TabItem("文件下载"):
with gr.Row():
with gr.Column():
url_input = gr.Textbox(
label="下载链接",
placeholder="https://example.com/file.zip",
value="示例文件"
)
download_btn = gr.Button("开始下载", variant="primary")
with gr.Column():
download_output = gr.Textbox(label="下载结果")
download_btn.click(
fn=download_file,
inputs=url_input,
outputs=download_output
)
with gr.TabItem("批量处理"):
with gr.Row():
with gr.Column():
files_input = gr.File(
label="上传多个文件",
file_count="multiple",
file_types=[".txt", ".csv", ".jpg"]
)
batch_btn = gr.Button("批量处理", variant="primary")
with gr.Column():
batch_output = gr.Textbox(label="处理结果")
batch_btn.click(
fn=batch_process,
inputs=files_input,
outputs=batch_output
)
return demo
demo = build_progress_demo()
demo.launch()
3.7 案例实战:多功能图像处理工作室
综合运用所学知识,创建一个功能完整的图像处理应用。
import gradio as gr
from PIL import Image, ImageFilter, ImageEnhance
import numpy as np
import time
class ImageProcessor:
"""图像处理类"""
@staticmethod
def apply_filter(image, filter_type):
"""应用滤镜"""
if image is None:
return None
filters = {
"原图": lambda img: img,
"模糊": lambda img: img.filter(ImageFilter.BLUR),
"轮廓": lambda img: img.filter(ImageFilter.CONTOUR),
"边缘增强": lambda img: img.filter(ImageFilter.EDGE_ENHANCE),
"浮雕": lambda img: img.filter(ImageFilter.EMBOSS),
"锐化": lambda img: img.filter(ImageFilter.SHARPEN),
"平滑": lambda img: img.filter(ImageFilter.SMOOTH)
}
return filters.get(filter_type, lambda img: img)(image)
@staticmethod
def adjust_brightness(image, factor):
"""调整亮度"""
if image is None:
return None
enhancer = ImageEnhance.Brightness(image)
return enhancer.enhance(factor)
@staticmethod
def adjust_contrast(image, factor):
"""调整对比度"""
if image is None:
return None
enhancer = ImageEnhance.Contrast(image)
return enhancer.enhance(factor)
@staticmethod
def rotate_image(image, angle):
"""旋转图像"""
if image is None:
return None
return image.rotate(angle, expand=True)
@staticmethod
def resize_image(image, width, height):
"""调整尺寸"""
if image is None:
return None
return image.resize((width, height))
@staticmethod
def get_image_info(image):
"""获取图像信息"""
if image is None:
return {}
return {
"尺寸": f"{image.size[0]} x {image.size[1]}",
"格式": image.format or "Unknown",
"模式": image.mode,
"文件大小": f"{image.__sizeof__() / 1024:.1f} KB"
}
def build_image_workshop():
with gr.Blocks(title="🖼️ 图像处理工作室", theme="soft") as demo:
gr.Markdown("""
# 🖼️ 专业图像处理工作室
一站式图像处理工具,支持滤镜、调整、变换等功能
""")
# 初始化处理器
processor = ImageProcessor()
# 状态管理:保存原始图像和处理历史
original_image = gr.State(value=None)
processed_image = gr.State(value=None)
history = gr.State(value=[])
with gr.Row():
# 左侧:上传和原始图像
with gr.Column(scale=1):
gr.Markdown("### 📤 上传图像")
image_input = gr.Image(
label="点击上传或拖拽图片",
type="pil",
height=300
)
with gr.Row():
upload_btn = gr.Button("上传", variant="primary")
reset_btn = gr.Button("重置", variant="secondary")
gr.Markdown("### ℹ️ 图像信息")
image_info = gr.JSON(label="详细信息")
# 右侧:处理后的图像
with gr.Column(scale=1):
gr.Markdown("### 🎨 处理结果")
image_output = gr.Image(
label="处理后的图像",
type="pil",
height=300
)
gr.Markdown("### 📋 操作历史")
history_display = gr.JSON(label="历史记录")
# 工具选项卡
gr.Markdown("### 🛠️ 图像处理工具")
with gr.Tabs():
# 滤镜选项卡
with gr.TabItem("🎯 滤镜"):
filter_dropdown = gr.Dropdown(
label="选择滤镜",
choices=["原图", "模糊", "轮廓", "边缘增强", "浮雕", "锐化", "平滑"],
value="原图"
)
apply_filter_btn = gr.Button("应用滤镜", variant="primary")
# 调整选项卡
with gr.TabItem("⚙️ 调整"):
with gr.Row():
brightness_slider = gr.Slider(
label="亮度",
minimum=0.1,
maximum=2.0,
value=1.0,
step=0.1
)
contrast_slider = gr.Slider(
label="对比度",
minimum=0.1,
maximum=2.0,
value=1.0,
step=0.1
)
apply_adjust_btn = gr.Button("应用调整", variant="primary")
# 变换选项卡
with gr.TabItem("🔄 变换"):
with gr.Row():
angle_slider = gr.Slider(
label="旋转角度",
minimum=-180,
maximum=180,
value=0,
step=15
)
with gr.Column():
width_input = gr.Number(label="宽度", value=512, minimum=32, maximum=2048)
height_input = gr.Number(label="高度", value=512, minimum=32, maximum=2048)
apply_transform_btn = gr.Button("应用变换", variant="primary")
# 保存选项卡
with gr.TabItem("💾 保存"):
gr.Markdown("点击下方按钮保存处理后的图像")
save_btn = gr.Button("保存图像", variant="primary")
save_output = gr.File(label="下载文件")
# ============ 事件处理函数 ============
def on_upload(image):
"""上传图像"""
if image is None:
return None, None, {}, [], None, []
info = processor.get_image_info(image)
return image, image, info, [], image, [] # original, processed, info, history, output, history_display
def apply_filter(img, filter_type, current_processed, history_list):
"""应用滤镜"""
if img is None:
return None, None, None
result = processor.apply_filter(current_processed or img, filter_type)
history_list.append(f"应用滤镜: {filter_type}")
return result, result, history_list, history_list
def apply_adjust(img, brightness, contrast, current_processed, history_list):
"""应用调整"""
if img is None:
return None, None, None
temp = processor.adjust_brightness(current_processed or img, brightness)
result = processor.adjust_contrast(temp, contrast)
history_list.append(f"调整: 亮度={brightness}, 对比度={contrast}")
return result, result, history_list, history_list
def apply_transform(img, angle, width, height, current_processed, history_list):
"""应用变换"""
if img is None:
return None, None, None
temp = processor.rotate_image(current_processed or img, angle)
result = processor.resize_image(temp, int(width), int(height))
history_list.append(f"变换: 旋转={angle}°, 尺寸={width}x{height}")
return result, result, history_list, history_list
def reset_image(original):
"""重置到原始图像"""
if original is None:
return None, None, [], []
return original, original, [], []
def save_image(img):
"""保存图像"""
if img is None:
return None
# 这里实际会保存到临时文件
return img
# ============ 绑定事件 ============
# 上传事件
image_input.upload(
fn=on_upload,
inputs=image_input,
outputs=[original_image, processed_image, image_info, history, image_output, history_display]
)
upload_btn.click(
fn=lambda: None, # 占位,实际可以使用file explorer
inputs=[],
outputs=[]
)
# 滤镜事件
apply_filter_btn.click(
fn=apply_filter,
inputs=[image_input, filter_dropdown, processed_image, history],
outputs=[processed_image, image_output, history, history_display]
)
# 调整事件
apply_adjust_btn.click(
fn=apply_adjust,
inputs=[image_input, brightness_slider, contrast_slider, processed_image, history],
outputs=[processed_image, image_output, history, history_display]
)
# 变换事件
apply_transform_btn.click(
fn=apply_transform,
inputs=[image_input, angle_slider, width_input, height_input, processed_image, history],
outputs=[processed_image, image_output, history, history_display]
)
# 重置事件
reset_btn.click(
fn=reset_image,
inputs=[original_image],
outputs=[processed_image, image_output, history, history_display]
)
# 保存事件
save_btn.click(
fn=save_image,
inputs=[processed_image],
outputs=[save_output]
)
# 示例图像
gr.Examples(
examples=[
["examples/cat.jpg"],
["examples/dog.jpg"],
["examples/landscape.jpg"]
],
inputs=image_input
)
return demo
# 运行应用
demo = build_image_workshop()
demo.launch()
第四阶段:精通篇 - 部署、性能与生态
4.1 部署你的应用
开发完成后的应用,需要让它7x24小时在线运行。
方案1:Hugging Face Spaces(推荐,免费)
这是托管Gradio应用最流行的方式。
详细步骤:
-
注册Hugging Face账号
- 访问 huggingface.co/join
- 完成注册和邮箱验证
-
创建新的Space
- 点击右上角头像 → "New Space"
- 填写Space名称(如 "my-gradio-app")
- 选择SDK为 "Gradio"
- 选择可见性(Public/Private)
- 点击 "Create Space"
-
准备文件结构
在你的Space中,需要以下文件:my-gradio-app/ ├── app.py # 主应用代码 ├── requirements.txt # Python依赖 ├── packages.txt # 系统依赖(可选) ├── README.md # 项目说明 └── examples/ # 示例文件(可选) -
app.py 模板
import gradio as gr import os # 你的应用代码 def greet(name): return f"Hello {name}!" # 创建界面 demo = gr.Interface( fn=greet, inputs=gr.Textbox(label="Name"), outputs=gr.Textbox(label="Greeting"), title="My Gradio App", ) # 启动应用(生产环境不需要launch参数) if __name__ == "__main__": demo.launch() -
requirements.txt 模板
gradio>=4.0.0 torch>=2.0.0 transformers>=4.30.0 pillow>=10.0.0 numpy>=1.24.0 -
通过Git上传代码
# 克隆你的Space仓库 git clone https://huggingface.co/spaces/你的用户名/你的Space名 # 进入目录 cd 你的Space名 # 添加你的文件 cp /path/to/your/app.py . cp /path/to/your/requirements.txt . # 提交并推送 git add . git commit -m "Initial commit" git push -
配置Secrets(环境变量)
如果使用API密钥等敏感信息:- 进入Space页面 → Settings → Secrets
- 添加环境变量(如
OPENAI_API_KEY) - 在代码中通过
os.getenv("OPENAI_API_KEY")读取
方案2:本地服务器部署
使用Gunicorn + Nginx(Linux服务器)
-
安装依赖
pip install gunicorn -
创建启动脚本
run.pyfrom app import demo # 假设你的应用在app.py中 if __name__ == "__main__": demo.launch( server_name="0.0.0.0", # 允许外部访问 server_port=7860, share=False # 不使用临时链接 ) -
使用Gunicorn启动
gunicorn -w 4 -b 0.0.0.0:7860 run:demo -
配置Nginx反向代理
server { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:7860; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # WebSocket支持(Gradio需要) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
方案3:Docker部署
Dockerfile
# 使用官方Python镜像
FROM python:3.10-slim
# 设置工作目录
WORKDIR /app
# 安装系统依赖
RUN apt-get update && apt-get install -y \
libgl1-mesa-glx \
libglib2.0-0 \
&& rm -rf /var/lib/apt/lists/*
# 复制依赖文件
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 7860
# 启动命令
CMD ["python", "app.py"]
docker-compose.yml
version: '3.8'
services:
gradio-app:
build: .
ports:
- "7860:7860"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
volumes:
- ./data:/app/data
restart: unless-stopped
构建和运行
# 构建镜像
docker build -t my-gradio-app .
# 运行容器
docker run -p 7860:7860 -e OPENAI_API_KEY=your-key my-gradio-app
# 或使用docker-compose
docker-compose up -d
4.2 性能优化
1. 队列管理
对于耗时操作,使用队列防止服务器过载:
import gradio as gr
import time
def slow_function(text):
time.sleep(5)
return f"处理结果: {text}"
demo = gr.Interface(
fn=slow_function,
inputs="text",
outputs="text"
)
# 启用队列,限制并发数
demo.queue(
max_size=10, # 队列最大长度
concurrency_count=2 # 同时处理的请求数
)
demo.launch()
2. 缓存示例
缓存示例结果,加快用户体验:
demo = gr.Interface(
fn=classify_image,
inputs=gr.Image(),
outputs=gr.Label(),
examples=[["cat.jpg"], ["dog.jpg"]],
cache_examples=True, # 缓存示例结果
cache_mode="lazy" # 懒加载:首次访问时缓存
)
3. 流式输出
对于大模型生成,使用流式输出:
def stream_response(message, history):
response = ""
for word in message.split():
response += word + " "
yield response # 逐步返回结果
demo = gr.ChatInterface(
fn=stream_response,
title="流式聊天机器人"
)
4. 批处理优化
批量处理多个请求:
def batch_fn(images):
"""批量处理多张图片"""
results = []
for img in images:
# 处理单张图片
result = process_image(img)
results.append(result)
return results
demo = gr.Interface(
fn=batch_fn,
inputs=gr.Image(type="pil", image_count="multiple"),
outputs=gr.Gallery()
)
5. 异步处理
使用异步函数提高并发能力:
import asyncio
async def async_process(text):
await asyncio.sleep(1) # 模拟异步IO
return text.upper()
demo = gr.Interface(
fn=async_process,
inputs="text",
outputs="text"
)
demo.queue() # 异步需要队列支持
demo.launch()
4.3 安全最佳实践
1. API密钥管理
不要硬编码密钥:
# ❌ 错误做法
openai.api_key = "sk-xxxxxxxxxxxxxxxxxxxx"
# ✅ 正确做法
import os
openai.api_key = os.getenv("OPENAI_API_KEY")
使用Hugging Face Secrets:
# 在Space的Settings中添加Secrets
import os
# 读取环境变量
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise ValueError("请设置OPENAI_API_KEY环境变量")
2. 输入验证
def safe_process(text, image):
# 文本长度限制
if len(text) > 1000:
return "文本太长,请控制在1000字符以内"
# 图像大小限制
if image and image.size[0] * image.size[1] > 4000 * 3000:
return "图片太大,请压缩后上传"
# 文件类型检查
allowed_formats = ['JPEG', 'PNG', 'WEBP']
if image and image.format not in allowed_formats:
return f"不支持的图片格式,请使用{allowed_formats}"
# 处理逻辑
return process(text, image)
3. 文件上传安全
import os
import tempfile
import uuid
def handle_file_upload(file):
# 生成唯一文件名
ext = os.path.splitext(file.name)[1]
filename = f"{uuid.uuid4()}{ext}"
# 保存在临时目录
save_path = os.path.join(tempfile.gettempdir(), filename)
# 保存文件(需要实现具体保存逻辑)
# file.save(save_path)
return save_path
4. 速率限制
from datetime import datetime, timedelta
from collections import defaultdict
class RateLimiter:
def __init__(self, max_requests=10, time_window=60):
self.max_requests = max_requests
self.time_window = time_window
self.requests = defaultdict(list)
def check(self, user_id):
now = datetime.now()
# 清理旧记录
self.requests[user_id] = [
t for t in self.requests[user_id]
if now - t < timedelta(seconds=self.time_window)
]
if len(self.requests[user_id]) >= self.max_requests:
return False
self.requests[user_id].append(now)
return True
# 使用
limiter = RateLimiter()
def process_with_limit(user_id, text):
if not limiter.check(user_id):
return "请求太频繁,请稍后再试"
return process(text)
4.4 监控与日志
1. 基本日志记录
import logging
import time
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('app.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
def monitored_function(text):
start_time = time.time()
logger.info(f"开始处理: {text[:50]}...")
try:
result = process(text)
elapsed = time.time() - start_time
logger.info(f"处理完成,耗时: {elapsed:.2f}s")
return result
except Exception as e:
logger.error(f"处理失败: {str(e)}")
return f"错误: {str(e)}"
2. 性能监控
from functools import wraps
import time
def monitor_performance(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
# 记录到监控系统
print(f"函数 {func.__name__} 执行时间: {elapsed:.3f}s")
# 如果时间过长,记录警告
if elapsed > 5:
print(f"⚠️ 警告: {func.__name__} 执行时间过长")
return result
return wrapper
@monitor_performance
def slow_model(text):
time.sleep(3)
return text.upper()
4.5 测试与调试
1. 单元测试
import unittest
import gradio as gr
class TestGradioApp(unittest.TestCase):
def setUp(self):
# 创建测试应用
def process(x):
return x.upper()
self.demo = gr.Interface(
fn=process,
inputs="text",
outputs="text"
)
def test_process_function(self):
# 直接测试函数
result = self.demo.fn("hello")
self.assertEqual(result, "HELLO")
def test_integration(self):
# 测试完整流程
with self.demo.launch():
# 模拟请求
response = self.demo.process_api(
fn_index=0,
data=["test"]
)
self.assertEqual(response, "TEST")
if __name__ == "__main__":
unittest.main()
2. 调试技巧
import gradio as gr
import pdb
def debug_function(text):
# 设置断点
# pdb.set_trace()
# 打印调试信息
print(f"Debug - 输入: {text}")
print(f"Debug - 类型: {type(text)}")
result = text.upper()
print(f"Debug - 输出: {result}")
return result
demo = gr.Interface(
fn=debug_function,
inputs="text",
outputs="text"
)
# 开发模式启动
demo.launch(debug=True) # 开启debug模式
4.6 高级特性
1. 自定义主题
import gradio as gr
# 创建自定义主题
custom_theme = gr.themes.Soft(
primary_hue="blue",
secondary_hue="purple",
neutral_hue="gray",
font=gr.themes.GoogleFont("Inter"),
text_size="lg"
)
demo = gr.Interface(
fn=greet,
inputs="text",
outputs="text",
theme=custom_theme
)
2. 多语言支持
import gradio as gr
from typing import Dict
class I18nApp:
def __init__(self):
self.translations = {
"en": {
"title": "Multilingual App",
"input": "Enter text",
"output": "Result"
},
"zh": {
"title": "多语言应用",
"input": "输入文本",
"output": "结果"
},
"ja": {
"title": "多言語アプリ",
"input": "テキストを入力",
"output": "結果"
}
}
def get_text(self, lang: str, key: str) -> str:
return self.translations.get(lang, self.translations["en"]).get(key, key)
i18n = I18nApp()
def build_multilingual_app():
with gr.Blocks() as demo:
lang_selector = gr.Radio(
choices=["en", "zh", "ja"],
label="Language / 语言 / 言語",
value="en"
)
input_text = gr.Textbox(label="input")
output_text = gr.Textbox(label="output")
process_btn = gr.Button("process")
# 动态更新标签
def update_labels(lang):
return {
input_text: gr.update(label=i18n.get_text(lang, "input")),
output_text: gr.update(label=i18n.get_text(lang, "output")),
process_btn: gr.update(value=i18n.get_text(lang, "process"))
}
lang_selector.change(
fn=update_labels,
inputs=lang_selector,
outputs=[input_text, output_text, process_btn]
)
return demo
3. 插件系统
import gradio as gr
import importlib
import pkgutil
class PluginManager:
def __init__(self):
self.plugins = {}
def discover_plugins(self, package_name):
"""自动发现插件"""
package = importlib.import_module(package_name)
for _, name, _ in pkgutil.iter_modules(package.__path__):
module = importlib.import_module(f"{package_name}.{name}")
if hasattr(module, "Plugin"):
plugin = module.Plugin()
self.plugins[name] = plugin
def get_plugin_tabs(self):
"""获取所有插件的选项卡"""
tabs = []
for name, plugin in self.plugins.items():
with gr.TabItem(plugin.title):
plugin.render()
return tabs
# 使用示例
manager = PluginManager()
manager.discover_plugins("myapp.plugins")
with gr.Blocks() as demo:
with gr.Tabs():
manager.get_plugin_tabs()
4.7 案例实战:生产级AI应用
综合所有知识,创建一个生产级的AI图像生成应用:
import gradio as gr
import torch
from diffusers import StableDiffusionPipeline
import os
import logging
import time
from datetime import datetime
import hashlib
import json
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class ProductionAIApp:
"""生产级AI应用示例"""
def __init__(self):
self.model = None
self.device = "cuda" if torch.cuda.is_available() else "cpu"
self.cache_dir = "./cache"
self.max_queue_size = 10
self.request_count = 0
# 创建缓存目录
os.makedirs(self.cache_dir, exist_ok=True)
# 加载模型
self.load_model()
logger.info(f"应用初始化完成,设备: {self.device}")
def load_model(self):
"""加载AI模型"""
try:
logger.info("正在加载模型...")
self.model = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16 if self.device == "cuda" else torch.float32
)
self.model = self.model.to(self.device)
logger.info("模型加载成功")
except Exception as e:
logger.error(f"模型加载失败: {e}")
raise
def generate_image(
self,
prompt: str,
negative_prompt: str = "",
steps: int = 50,
guidance_scale: float = 7.5,
width: int = 512,
height: int = 512,
seed: int = None,
progress=gr.Progress()
):
"""生成图像"""
start_time = time.time()
self.request_count += 1
request_id = hashlib.md5(f"{prompt}{time.time()}".encode()).hexdigest()[:8]
logger.info(f"[{request_id}] 开始生成: {prompt[:50]}...")
# 验证输入
if len(prompt) > 500:
return None, "提示词太长,请控制在500字符以内"
if steps > 100:
steps = 100
# 检查缓存
cache_key = hashlib.md5(f"{prompt}{steps}{guidance_scale}{seed}".encode()).hexdigest()
cache_path = os.path.join(self.cache_dir, f"{cache_key}.png")
if os.path.exists(cache_path):
logger.info(f"[{request_id}] 使用缓存结果")
return cache_path, f"使用缓存 (生成时间: 0s)"
# 设置随机种子
if seed is None:
seed = int(time.time())
generator = torch.Generator(device=self.device).manual_seed(seed)
# 进度条
progress(0, desc="初始化...")
# 生成图像
try:
with torch.autocast(self.device):
result = self.model(
prompt=prompt,
negative_prompt=negative_prompt if negative_prompt else None,
num_inference_steps=steps,
guidance_scale=guidance_scale,
width=width,
height=height,
generator=generator,
callback=lambda i, t, latents: progress(
i/steps,
desc=f"生成中 ({i}/{steps})"
)
)
image = result.images[0]
# 保存到缓存
image.save(cache_path)
elapsed = time.time() - start_time
logger.info(f"[{request_id}] 生成完成,耗时: {elapsed:.2f}s")
# 保存请求日志
log_entry = {
"request_id": request_id,
"prompt": prompt,
"steps": steps,
"guidance_scale": guidance_scale,
"seed": seed,
"elapsed": elapsed,
"timestamp": datetime.now().isoformat()
}
with open(os.path.join(self.cache_dir, "requests.log"), "a") as f:
f.write(json.dumps(log_entry) + "\n")
return image, f"生成成功! 耗时: {elapsed:.1f}s, Seed: {seed}"
except Exception as e:
logger.error(f"[{request_id}] 生成失败: {e}")
return None, f"生成失败: {str(e)}"
def get_stats(self):
"""获取统计信息"""
return {
"总请求数": self.request_count,
"设备": self.device,
"缓存文件数": len(os.listdir(self.cache_dir)),
"最大队列": self.max_queue_size
}
def build_app(self):
"""构建Gradio应用"""
with gr.Blocks(title="🎨 AI图像生成工作室", theme="soft") as demo:
gr.Markdown("""
# 🎨 生产级AI图像生成应用
基于Stable Diffusion的高性能图像生成服务
""")
with gr.Row():
# 左侧:输入区域
with gr.Column(scale=1):
gr.Markdown("### 📝 提示词")
prompt = gr.Textbox(
label="正向提示词",
placeholder="描述你想要的图像...",
lines=3
)
negative_prompt = gr.Textbox(
label="反向提示词(可选)",
placeholder="描述你不想要的效果...",
lines=2
)
with gr.Accordion("⚙️ 高级设置", open=False):
steps = gr.Slider(
label="迭代步数",
minimum=10,
maximum=100,
value=50,
step=5
)
guidance = gr.Slider(
label="引导强度",
minimum=1,
maximum=20,
value=7.5,
step=0.5
)
with gr.Row():
width = gr.Dropdown(
label="宽度",
choices=[384, 512, 768],
value=512
)
height = gr.Dropdown(
label="高度",
choices=[384, 512, 768],
value=512
)
seed = gr.Number(
label="随机种子(留空自动生成)",
value=None,
precision=0
)
generate_btn = gr.Button(
"🎨 生成图像",
variant="primary",
size="lg"
)
status = gr.Textbox(
label="状态",
interactive=False
)
stats_btn = gr.Button("📊 查看统计")
stats_output = gr.JSON(label="统计信息")
# 右侧:输出区域
with gr.Column(scale=1):
gr.Markdown("### 🖼️ 生成结果")
output_image = gr.Image(
label="生成的图像",
type="pil",
height=512
)
with gr.Row():
save_btn = gr.Button("💾 保存到本地")
share_btn = gr.Button("📤 分享")
gr.Markdown("### 📋 使用指南")
gr.Markdown("""
1. 输入正向提示词(英文效果更好)
2. (可选)输入反向提示词,避免不良效果
3. 调整高级参数优化结果
4. 点击生成按钮等待结果
""")
# 示例
gr.Examples(
examples=[
["a beautiful sunset over mountains, highly detailed, 4k"],
["cute cat wearing sunglasses, digital art"],
["futuristic cityscape, cyberpunk style, neon lights"]
],
inputs=prompt
)
# ============ 事件绑定 ============
# 生成图像
generate_btn.click(
fn=self.generate_image,
inputs=[prompt, negative_prompt, steps, guidance, width, height, seed],
outputs=[output_image, status]
).then(
fn=lambda: None,
inputs=[],
outputs=[prompt] # 清空输入
)
# 查看统计
stats_btn.click(
fn=self.get_stats,
inputs=[],
outputs=stats_output
)
# 保存图像
save_btn.click(
fn=lambda img: img,
inputs=output_image,
outputs=gr.File(label="下载")
)
# 键盘快捷键支持
prompt.submit(
fn=self.generate_image,
inputs=[prompt, negative_prompt, steps, guidance, width, height, seed],
outputs=[output_image, status]
)
# 配置队列
demo.queue(
max_size=self.max_queue_size,
concurrency_count=2 if self.device == "cuda" else 1
)
return demo
# 创建并运行应用
if __name__ == "__main__":
app = ProductionAIApp()
demo = app.build_app()
# 生产环境启动配置
demo.launch(
server_name="0.0.0.0", # 允许外部访问
server_port=7860,
share=False, # 不使用临时链接
auth=("admin", "password"), # 可选:添加认证
ssl_verify=False, # 如果使用HTTPS
quiet=False # 显示详细日志
)
总结:从0到大师的学习路径
📚 学习路线图
第一阶段:入门
├── 理解Gradio基本概念
├── 创建第一个Interface
├── 掌握基本组件使用
└── 实现简单AI应用
第二阶段:基础
├── 熟悉30+内置组件
├── 掌握多输入/输出
├── 实践图像/文本处理
└── 构建完整功能应用
第三阶段:进阶
├── 掌握Blocks布局
├── 理解事件系统
├── 管理应用状态
└── 开发复杂交互应用
第四阶段:精通
├── 生产环境部署
├── 性能优化技巧
├── 安全最佳实践
└── 构建企业级应用
🎯 核心能力清单
- 能独立搭建Gradio开发环境
- 熟练使用各种内置组件
- 掌握Interface和Blocks开发模式
- 能处理复杂的状态管理
- 理解事件驱动编程
- 会优化应用性能
- 掌握多种部署方案
- 具备安全意识
- 能开发生产级应用
- 会调试和监控应用
🌟 进阶资源推荐
- 官方文档:gradio.app/docs
- Hugging Face Spaces:huggingface.co/spaces
- GitHub Examples:github.com/gradio-app/…
- 社区教程:gradio.app/community
- Discord社区:discord.gg/gradio