第3章 构建你的第一个 Gradio 应用
现在我们可以动手构建了。
不是什么庞大的 AI 应用,也不是复杂的仪表盘,只是一个接受人名并返回问候语的小应用。
这看起来简单得有点过分,但这是刻意为之。
应用足够小,我们才能专注于理解 Gradio 的工作原理,而不必被不必要的复杂性干扰。
创建问候函数
从这段代码开始:
def greet(name):
return f"Hello, {name}!"
这就是一段普通的 Python 代码,和 Gradio 没有任何关系。
如果你运行:
print(greet("Eva"))
会得到:
Hello, Eva!
这一点很重要,因为这个函数本身并不知道 Gradio 的存在。
它只是接收一个参数,然后返回一个值。
导入 Gradio
在文件顶部添加:
import gradio as gr
现在文件内容如下:
import gradio as gr
def greet(name):
return f"Hello, {name}!"
接下来,我们需要把这个函数连接到一个用户界面上。
创建 Interface
添加:
demo = gr.Interface(
fn=greet,
inputs="text",
outputs="text"
)
完整的程序现在是:
import gradio as gr
def greet(name):
return f"Hello, {name}!"
demo = gr.Interface(
fn=greet,
inputs="text",
outputs="text"
)
demo.launch()
运行它:
python app.py
现在你应该能看到一个网页界面,可以输入文本传给 greet() 函数,并看到它返回的文本。
恭喜!你已经构建了第一个 Gradio 应用。
理解 gr.Interface
我们放慢节奏,仔细看看最关键的部分:
gr.Interface(
fn=greet,
inputs="text",
outputs="text"
)
Interface 是一种便捷方式,可以为函数快速套上一层界面。
在这里,它需要知道三个特别重要的信息:
要调用哪个函数,
函数接收什么类型的输入,
以及函数返回什么类型的输出。
这就是为什么我们需要指定:
fn=greet
inputs="text"
以及:
outputs="text"
理解 fn
这里的:
fn=greet
表示 greet 是 Gradio 需要调用的函数。
注意,我们< strong>没有写成:
fn=greet()
这是一个微妙但很重要的 Python 语法区别。
greet 指向函数本身,而 greet() 会立即执行该函数。
我们希望由 Gradio 来控制函数的调用时机。
所以传入的是函数本身:
fn=greet
而不是立即执行它。
理解输入
这里的:
inputs="text"
告诉 Gradio 应用应提供一个文本输入框。
用户可以在其中输入内容,Gradio 随后将结果值传递给我们的 Python 函数。
比如用户输入了:
Maria
Gradio 实际上就把这个值传给了:
greet(name)
函数接收到的参数就是:
name = "Maria"
然后返回:
Hello, Maria!
理解输出
我们指定:
outputs="text"
因为函数返回的是一个字符串。
返回值会显示在文本输出区域。
所以理解函数的输入和输出类型很有帮助。
我们的函数是:
text → text
接收文本,返回文本。
之后我们会构建处理其他类型数据的函数,例如:
number → number
或:
image → prediction
或:
file → analysis
或:
message + history → response
界面需要与函数匹配。
理解 launch()
最后一行是:
demo.launch()
这会让 Gradio 启动应用。
没有它,你只是创建了界面对象,但应用服务器还没有跑起来。
可以把它理解为一条指令:
"Gradio,把这个应用跑起来,让用户可以使用它。"
添加标题
我们可以让应用的描述更具体一些。
demo = gr.Interface(
fn=greet,
inputs="text",
outputs="text",
title="Greeting App"
)
现在界面上有了标题。
添加描述
还可以加上描述:
demo = gr.Interface(
fn=greet,
inputs="text",
outputs="text",
title="Greeting App",
description="Enter your name and receive a personalized greeting."
)
描述很有用,用户不应该需要猜测你的应用是干什么的。
给输入框加标签
与其依赖通用的文本输入,不如显式地创建一个组件。
name_input = gr.Textbox(
label="Your Name",
placeholder="Enter your name"
)
再创建输出:
output = gr.Textbox(
label="Greeting"
)
现在可以把这些组件传给 Interface:
import gradio as gr
def greet(name):
return f"Hello, {name}!"
name_input = gr.Textbox(
label="Your Name",
placeholder="Enter your name"
)
output = gr.Textbox(
label="Greeting"
)
demo = gr.Interface(
fn=greet,
inputs=name_input,
outputs=output,
title="Greeting App",
description="Enter your name and receive a personalized greeting."
)
demo.launch()
这个版本更明确。不再只是简单写一行:
inputs="text"
而是创建了一个 Textbox 组件并做了配置。
当应用变得更复杂时,这种方式会非常有价值。
用户点击按钮后发生了什么?
一个基础的 Gradio 界面通常会提供某种交互方式,比如一个按钮。
当用户输入内容并触发界面时,流程如下:
Gradio 获取用户输入。
Gradio 把输入传给你的 Python 函数。
你的函数开始执行。
函数返回结果。
Gradio 把结果填入输出组件。
你的 Python 函数不需要关心浏览器是如何渲染输入的,那是 Gradio 的活儿。
函数不一定非得叫 predict
机器学习的示例代码里经常见到这样的写法:
def predict(...):
...
这只是个命名习惯而已。
函数叫什么名字都行,比如:
def greet(...):
...
def analyze(...):
...
def generate(...):
...
Gradio 只在乎你传入的函数本身,不在乎它的名字。
做一个计算器
我们来写点稍微有意思的东西。
import gradio as gr
def add_numbers(a, b):
return a + b
demo = gr.Interface(
fn=add_numbers,
inputs=[
gr.Number(label="First Number"),
gr.Number(label="Second Number")
],
outputs=gr.Number(label="Result"),
title="Addition Calculator"
)
demo.launch()
注意一个新东西:这次函数有两个参数:
def add_numbers(a, b):
所以我们提供了两个输入:
inputs=[
gr.Number(label="First Number"),
gr.Number(label="Second Number")
]
顺序很重要:第一个输入会传给 a,第二个输入会传给 b。
多个输入
假设用户输入了 10 和 25,那么 Gradio 相当于这样调用函数:
add_numbers(10, 25)
函数返回:
35
Gradio 就会显示该结果。
这个模式非常关键。Python 函数接受多少个参数,Gradio 界面就需要对应数量的输入。
一个简单的文本分析器
再做一个小应用。
import gradio as gr
def analyze_text(text):
characters = len(text)
words = len(text.split())
return f"Characters: {characters}\nWords: {words}"
demo = gr.Interface(
fn=analyze_text,
inputs=gr.Textbox(
label="Enter Text",
lines=8,
placeholder="Type or paste some text here..."
),
outputs=gr.Textbox(
label="Analysis"
),
title="Text Analyzer"
)
demo.launch()
这个应用展示了一个很有用的模式。
用户输入文本,Python 处理,界面展示结果。
这里没有用到任何 AI 模型,也不需要。Gradio 同样适用于普通的 Python 应用。
为什么要从简单应用入手?
因为同样的概念可以扩展。
以文本分析器为例。
今天它统计词数和字符数。
明天你可以把函数换成情感分析模型:
def analyze_text(text):
return sentiment_model(text)
或者摘要模型:
def analyze_text(text):
return summarization_model(text)
或者一个 API 调用:
def analyze_text(text):
return call_ai_api(text)
界面基本不用改动。
这正是将 UI 与应用逻辑分离的优势之一。
一个有用的思维练习
构建 Gradio 应用时,随时问自己:
我的 Python 函数需要什么?
例如:
def greet(name):
它需要一个文本参数,所以加一个文本输入。
对于:
def add_numbers(a, b):
需要两个数值输入。
对于:
def classify(image):
需要一个图片输入。
对于:
def analyze(file):
这里需要一个文件输入组件。
用这种思路来思考,设计界面就会轻松很多。
新手常见错误:输入数量不匹配
假设你写了这样的函数:
def multiply(a, b):
return a * b
但创建的却是:
demo = gr.Interface(
fn=multiply,
inputs=gr.Number(),
outputs=gr.Number()
)
函数需要两个参数,你却只提供了一个输入。
Gradio 不可能凭空知道缺失的 b 该填什么。
正确的写法是:
demo = gr.Interface(
fn=multiply,
inputs=[
gr.Number(),
gr.Number()
],
outputs=gr.Number()
)
这是需要重点理解的核心原则之一:界面的输入组件必须与函数期望的参数数量一一对应。
新手常见错误:返回类型不对
假设你的界面期望输出一个数字:
outputs=gr.Number()
但函数实际返回的是:
return "This is a string"
这种不匹配会导致问题。
组件不仅仅是视觉元素,它们还承载着对数据类型预期的约定。
随着你接触更多组件,设计数据流的能力也会越来越强。