【Gradio】轻量版 Gradio 客户端使用指南 | Python 客户端入门
Gradio Python 客户端使得使用任何 Gradio 应用作为 API 变得非常容易。例如,考虑这个 Hugging Face Space https://huggingface.co/spaces/abidlabs/whisper,它可以转录从麦克风录制的音频文件。
使用 gradio_client
库,我们可以轻松地使用 Gradio 作为 API 来编程转录音频文件。
这是完成它的全部代码:
# 从gradio_client包中导入Client和file类
from gradio_client import Client, file
# 创建一个Client对象,指定要使用的模型是“abidlabs/whisper”
client = Client("abidlabs/whisper")
# 使用客户端的predict方法进行预测,输入参数是一个通过file函数封装的音频文件“audio_sample.wav”
output = client.predict(
audio=file("audio_sample.wav")
)
# 输出预测结果
print(output)
Gradio 客户端适用于任何托管的 Gradio 应用!尽管客户端主要用于托管在 Hugging Face Spaces 上的应用,但您的应用可以托管在任何地方,例如您自己的服务器。
先决条件:要使用 Gradio 客户端,您不需要非常详细地了解 gradio
库。然而,对 Gradio 的输入和输出组件概念有一般的熟悉是有帮助的。
安装
如果您已经有了最新版本的 gradio
,那么 gradio_client
将作为依赖项包含在内。但请注意,此文档反映了 gradio_client
的最新版本,所以如果您不确定,请升级!
轻量级 gradio_client
包可以通过 pip(或 pip3)安装,并且已测试可与 Python 3.9 或更高版本一起使用:
$ pip install --upgrade gradio_client
连接到 Hugging Face Spaces 上的 Gradio 应用程序
首先连接实例化一个 Client
对象,并将其连接到运行在 Hugging Face Spaces 上的 Gradio 应用程序。
from gradio_client import Client
client = Client("abidlabs/en2fr") # a Space that translates from English to French
from gradio_client import Client
client = Client("abidlabs/my-private-space", hf_token="...")
# 导入os库,用于从环境变量中获取Hugging Face Token
import os
# 从gradio_client包中导入Client和file类
from gradio_client import Client, file
# 从环境变量中读取Hugging Face Token
HF_TOKEN = os.environ.get("HF_TOKEN")
# 使用Client类的duplicate方法创建一个客户端实例,传入模型的名称和Hugging Face Token
# hf_token=HF_TOKEN 用于验证与Hugging Face平台的交互
client = Client.duplicate("abidlabs/whisper", hf_token=HF_TOKEN)
# 使用客户端的predict方法进行预测。输入参数通过file函数包装的音频文件“audio_sample.wav”
# 这里没有直接将结果赋值给一个变量,但是预期的行为是函数会返回处理后的文本
client.predict(file("audio_sample.wav"))
# 输出结果应为“This is a test of the whisper speech recognition model.”,
# 说明“audio_sample.wav”文件中的语音内容被成功识别
注意:如果原始空间使用了 GPU,您的私人空间也会使用,并且您的 Hugging Face 账户将根据 GPU 的价格进行计费。为了减少费用,您的空间在 1 小时无活动后会自动休眠。您也可以使用 hardware
参数来设置硬件 duplicate()
。
连接一个通用的 Gradio 应用
如果您的应用程序在其他地方运行,只需提供完整的 URL,包括"http://"或"https://"。这里有一个例子,展示了如何对运行在共享 URL 上的 Gradio 应用程序进行预测:
from gradio_client import Client
client = Client("https://bec81a83-5b5c-471e.gradio.live")
检查 API 端点
一旦您连接到 Gradio 应用程序,您可以通过调用 Client.view_api()
方法来查看可用的 API。对于 Whisper 空间,我们看到以下内容:
Client.predict() Usage Info
---------------------------
Named API endpoints: 1
- predict(audio, api_name="/predict") -> output
Parameters:
- [Audio] audio: filepath (required)
Returns:
- [Textbox] output: str
我们看到这个空间中有 1 个 API 端点,并向我们展示了如何使用 API 端点进行预测:我们应该调用 .predict()
方法(我们将在下面探讨),提供一个类型为 str
的参数 input_audio
,它是一个 filepath or URL
。
最简单的预测方法就是用适当的参数调用 .predict()
函数:
from gradio_client import Client
client = Client("abidlabs/en2fr", api_name='/predict')
client.predict("Hello")
>> Bonjour
如果有多个参数,那么你应该将它们作为 .predict()
的单独参数传递,像这样:
from gradio_client import Client
client = Client("gradio/calculator")
client.predict(4, "add", 5)
>> 9.0
建议提供关键字参数而不是位置参数:
from gradio_client import Client
client = Client("gradio/calculator")
client.predict(num1=4, operation="add", num2=5)
>> 9.0
这允许您利用默认参数。例如,这个空间包括滑块组件的默认值,所以当客户端访问它时,您不需要提供它。
from gradio_client import Client
client = Client("abidlabs/image_generator")
client.predict(text="an astronaut riding a camel")
默认值是相应 Gradio 组件的初始值。如果组件没有初始值,但是预测函数中的相应参数有一个默认值 None
,那么在客户端中该参数也是可选的。当然,如果您想覆盖它,您也可以包括它:
from gradio_client import Client
client = Client("abidlabs/image_generator")
client.predict(text="an astronaut riding a camel", steps=25)
为了提供文件或 URL 作为输入,您应该将文件路径或文件的 URL 放在 gradio_client.file()
中。这样可以将文件上传到 Gradio 服务器,并确保文件被正确预处理:
from gradio_client import Client, file
client = Client("abidlabs/whisper")
client.predict(
audio=file("https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3")
)
>> "My thought I have nobody by a beauty and will as you poured. Mr. Rochester is serve in that so don't find simpus, and devoted abode, to at might in a r—"
运行作业异步地
我们应该注意 .predict()
是一个阻塞操作,因为它等待操作完成后才返回预测结果。
在许多情况下,您可能更愿意让作业在后台运行,直到您需要预测结果。您可以通过使用 .submit()
方法创建一个 Job
实例,然后稍后调用作业上的 .result()
来获取结果。例如:
from gradio_client import Client
client = Client(space="abidlabs/en2fr")
job = client.submit("Hello", api_name="/predict") # This is not blocking
# Do something else
job.result() # This is blocking
>> Bonjour
添加回调
或者,可以添加一个或多个回调,在作业运行完成后执行操作,如下:
from gradio_client import Client
def print_result(x):
print("The translated result is: {x}")
client = Client(space="abidlabs/en2fr")
job = client.submit("Hello", api_name="/predict", result_callbacks=[print_result])
# Do something else
>> The translated result is: Bonjour
状态
Job
对象还允许您通过调用 .status()
方法来获取正在运行的作业的状态。这将返回一个 StatusUpdate
对象,包含以下属性: code
(状态代码,一组定义的字符串中的一个,代表状态。参见 utils.Status
类), rank
(此作业在队列中的当前位置), queue_size
(队列总大小), eta
(预计此作业完成的时间), success
(一个布尔值,表示作业是否成功完成),以及 time
(生成状态的时间)。
from gradio_client import Client
client = Client(src="gradio/calculator")
job = client.submit(5, "add", 4, api_name="/predict")
job.status()
>> <Status.STARTING: 'STARTING'>
注意: Job
类还有一个 .done()
实例方法,它返回一个布尔值,指示作业是否已完成。
取消工作
Job
类还有一个 .cancel()
实例方法,用于取消已经排队但尚未开始的工作。例如,如果你运行:
client = Client("abidlabs/whisper")
job1 = client.submit(file("audio_sample1.wav"))
job2 = client.submit(file("audio_sample2.wav"))
job1.cancel() # will return False, assuming the job has started
job2.cancel() # will return True, indicating that the job has been canceled
如果第一个工作已经开始处理,那么它将不会被取消。如果第二个工作还没有开始,它将被成功取消并从队列中移除。
Generator 端点
有些 Gradio API 端点不返回单一值,而是返回一系列值。您可以通过运行 job.outputs()
随时获取从这样的生成器端点返回的值序列:
from gradio_client import Client
client = Client(src="gradio/count_generator")
job = client.submit(3, api_name="/count")
while not job.done():
time.sleep(0.1)
job.outputs()
>> ['0', '1', '2']
请注意,在生成器端点上运行 job.result()
只会得到该端点返回的第一个值。
Job
对象也是可迭代的,这意味着您可以使用它来显示生成器函数从端点返回的结果。以下是使用 Job
作为生成器的等效示例:
# 从gradio_client包中导入Client类
from gradio_client import Client
# 创建一个Client对象,指定要使用的模型是“gradio/count_generator”
client = Client(src="gradio/count_generator")
# 使用客户端的submit方法提交一个任务。这里的任务是计数到3(不包括3)。
# api_name参数指定了要调用的API的名称,这里是/count
job = client.submit(3, api_name="/count")
# 循环遍历任务的输出
for o in job:
# 打印每一次迭代的输出值
print(o)
您也可以取消具有迭代输出的作业,在这种情况下,作业将在当前迭代完成运行后尽快结束。
from gradio_client import Client
import time
client = Client("abidlabs/test-yield")
job = client.submit("abcdef")
time.sleep(3)
job.cancel() # job cancels after 2 iterations
演示带有会话状态
Gradio 演示可以包括会话状态,这为演示在页面会话中保持用户交互信息提供了一种方式。
例如,考虑以下演示,它在一个 gr.State
组件中维护用户提交的单词列表。当用户提交一个新单词时,它会被添加到状态中,并显示该单词之前出现的次数:
# 导入gradio库
import gradio as gr
# 定义一个名为count的函数,用于计算一个单词在列表中的出现次数,并返回次数和更新后的列表
def count(word, list_of_words):
# 返回单词在列表中的计数以及更新后的列表(在原列表基础上添加了新单词)
return list_of_words.count(word), list_of_words + [word]
# 使用gradio的Blocks创建一个交互式应用
with gr.Blocks() as demo:
# 使用gr.State创建一个空列表,作为词汇的初始列表
words = gr.State([])
# 创建一个文本框用于用户输入单词
textbox = gr.Textbox()
# 创建一个数字显示组件,用于显示计数结果
number = gr.Number()
# 设置文本框组件的提交行为。当文本框内的数据被提交时,会调用count函数。
# inputs指定了输入参数,分别是用户输入的单词和当前单词列表;
# outputs指定了输出,包括计数结果和更新后的单词列表。
textbox.submit(count, inputs=[textbox, words], outputs=[number, words])
# 启动创建的应用
demo.launch()
如果您使用 Python 客户端连接这个 Gradio 应用程序,您会注意到 API 信息只显示一个输入和一个输出:
Client.predict() Usage Info
---------------------------
Named API endpoints: 1
- predict(word, api_name="/count") -> value_31
Parameters:
- [Textbox] word: str (required)
Returns:
- [Number] value_31: float
那是因为 Python 客户端会自动为您处理状态——当您发出一系列请求时,一个请求的返回状态会被内部存储,并自动为后续请求提供。如果您想要重置状态,您可以通过调用 Client.reset_session()
来实现。
作者:十年一梦实验室