第15章 将 Gradio 接入机器学习模型
Gradio 真正强大的地方在于,它能与机器学习模型无缝对接。
到目前为止,我们写的函数都是简单的 Python 代码:
def greet(name):
return f"Hello, {name}!"
但同样的接口模式同样适用于机器学习。
不再只是:
return f"Hello, {name}!"
你的函数可以执行:
prediction = model(input_data)
然后返回预测结果。
模型与 Gradio 相互独立
这是全书最重要的概念之一。
Gradio 不是机器学习模型,它只是接口。
从概念上看,你的架构可能长这样:
User input
→ Gradio
→ Python function
→ Machine learning model
→ Python function
→ Gradio
→ User
换模型时,无需重新设计整个接口。
一个简单的模拟模型
在接入真实模型之前,先模拟一个。
def predict(number):
if number > 50:
return "High"
return "Low"
对应的接口代码如下:
import gradio as gr
with gr.Blocks() as demo:
number = gr.Number(label="Number")
button = gr.Button("Predict")
result = gr.Label(label="Prediction")
button.click(
fn=predict,
inputs=number,
outputs=result
)
demo.launch()
之后,可以把这个模拟模型替换为真正训练好的分类器。
加载模型
机器学习模型的加载往往需要一些时间。
例如:
model = load_model()
通常,你不想让用户每次点击按钮都重新加载一遍模型。
更好的做法是在合适的时候只加载一次:
model = load_model()
def predict(input_data):
return model(input_data)
这样可以让反复推理快很多。
模型加载位置为什么重要
假设某个模型加载需要二十秒。
如果你的函数是这样的:
def predict(image):
model = load_model()
return model(image)
那么每次请求都要付出一次加载开销。
如果只加载一次模型:
model = load_model()
def predict(image):
return model(image)
模型就可以被复用了。
分类器示例
概念上是这样:
model = load_model()
def classify(image):
prediction = model(image)
return prediction
然后:
image = gr.Image()
result = gr.Label()
button.click(
fn=classify,
inputs=image,
outputs=result
)
预处理
机器学习模型通常要求输入是特定格式。
图像模型可能需要:
缩放尺寸
归一化
转换为 RGB
转换为 tensor
文本模型可能需要:
分词
截断
添加特殊 token
一个典型的推理流程是这样的:
原始输入
→ 预处理
→ 模型
→ 后处理
→ 用户可读的结果
示例:图像预处理
from PIL import Image
def preprocess(image):
image = image.convert("RGB")
image = image.resize((224, 224))
return image
然后:
def classify(image):
image = preprocess(image)
prediction = model(image)
return prediction
后处理
模型返回的值往往对用户来说并不直观。
例如:
{
0: 0.02,
1: 0.95,
2: 0.03
}
用户并不想看这些数字类别 ID。
可以把它们转换一下:
labels = {
0: "Cat",
1: "Dog",
2: "Rabbit"
}
然后:
def format_prediction(prediction):
...
模型置信度
分类模型通常会输出概率。
对用户友好的界面可能会显示:
狗 — 95%
而不是:
类别 1: 0.951238
界面层负责把模型输出清晰地传达给用户。
模型也可以是 API
模型不必跑在本地。
你的 Python 函数可以调用外部推理 API:
def predict(text):
response = client.predict(text)
return response
这样可以降低本地硬件要求,但调用 API 会引入一些额外考量:
延迟
成本
API 密钥
速率限制
隐私
网络故障
Hugging Face 模型
Gradio 常与 Hugging Face 生态中托管的模型搭配使用。
典型应用流程:加载预训练模型,编写推理函数,将其绑定到 Gradio 组件,然后启动应用。
具体的模型加载代码取决于模型和所用库。
示例架构
import gradio as gr
model = load_model()
def generate(prompt):
if not prompt.strip():
return "Please enter a prompt."
result = model(prompt)
return result
with gr.Blocks() as demo:
prompt = gr.Textbox(
label="Prompt",
lines=6
)
button = gr.Button(
"Generate",
variant="primary"
)
output = gr.Textbox(
label="Output",
lines=12
)
button.click(
fn=generate,
inputs=prompt,
outputs=output
)
demo.launch()
关键不在于具体用了哪个模型,而在于模型逻辑与界面逻辑的分离。
模型错误
模型可能出错,常见原因包括:
无效输入
内存不足
API 不可用
响应格式异常
不支持的模型配置
对于可预见的失败,需要优雅地处理。
例如,模型可能拒绝空输入、无法处理不支持的文件,或遇到超出预期格式的数据。与其让这些错误直接导致界面崩溃,不如捕获它们并向用户返回有意义的提示信息。
模型延迟
AI 模型处理一次请求可能需要数秒。更大的模型、更复杂的输入或有限的硬件都会让等待时间进一步拉长。如果应用在此期间没有任何反馈,用户可能会以为界面卡死了,或者认为请求根本没有提交成功。
一个好的 Gradio 应用应当在模型运行期间给出适当的反馈,哪怕只是一个简单的加载指示器:
button.click(
fn=generate_text,
inputs=prompt,
outputs=output,
show_progress="full"
)
在 generate_text() 运行期间,Gradio 可以显示进度反馈,让用户知道请求正在处理中。
比如,用户点击按钮生成 AI 回复时,与其让界面数秒不变,不如显示一条提示:
正在生成回复……可能需要几秒钟。
这条小小的提示意义重大——用户知道应用已收到请求,模型仍在工作中。
对于耗时更长的任务,可以把提示写得更具体:
正在分析文件……请等待 AI 处理您的文档。
提示内容应与应用实际执行的操作一致。文本生成应用可以显示 正在生成回复……,图像处理应用则可以显示 正在处理图片……
核心原则是:用户永远不应该猜测应用是否还在工作。即使你无法让模型跑得更快,清晰的反馈也能让应用显得更流畅、更可靠。
模型资源需求
模型可能需要:
CPU
GPU
RAM
VRAM
专用加速器
本地机器能跑通的模型,部署环境未必支持。
始终要考虑目标运行环境。
不要加载不必要的大模型
如果任务很简单,未必需要一个大模型。
小模型往往延迟更低、占用内存更少、成本更低,部署也更轻松。
根据实际任务来选择模型。
动手试一试
创建一个假的机器学习分类器。
你的应用应该:
接收一个数字
将其分为三类
返回置信度分数
展示简短的说明
然后,如果有可用的真实模型,就把假的预测逻辑替换掉。
关键在于保持界面与模型实现相互独立。
要点回顾
Gradio 是界面层,不是机器学习框架。
Python 函数既可以调用本地模型,也可以调用外部 API。
开销大的模型应在合适时机只加载一次。
推理前先对输入做预处理。
推理后将模型输出处理成用户友好的结果。
考虑模型延迟和硬件需求。
妥善处理推理失败的情况。
把模型逻辑与 UI 代码分离,应用会更容易维护。