1. Gradio 客户端和 Lite
  2. Python 客户端入门指南

Gradio Python 客户端入门指南

Gradio Python 客户端使得将任何 Gradio 应用程序用作 API 变得非常容易。例如,考虑这个Hugging Face Space,它可以转录从麦克风录制的音频文件

使用gradio_client库,我们可以轻松地将Gradio作为API来编程转录音频文件。

以下是完整的代码:

from gradio_client import Client, handle_file

client = Client("abidlabs/whisper")

client.predict(
    audio=handle_file("audio_sample.wav")
)

>> "This is a test of the whisper speech recognition model."

Gradio 客户端可以与任何托管的 Gradio 应用程序一起使用!尽管客户端主要用于托管在 Hugging Face Spaces 上的应用程序,但您的应用程序可以托管在任何地方,例如您自己的服务器。

先决条件: 要使用Gradio客户端,你不需要详细了解gradio库。然而,对Gradio的输入和输出组件概念有一定的熟悉会有所帮助。

安装

如果你已经有一个最新版本的gradio,那么gradio_client已经作为依赖项包含在内。但请注意,本文档反映的是gradio_client的最新版本,所以如果你不确定,请升级!

轻量级的 gradio_client 包可以从 pip(或 pip3)安装,并且经过测试可以在 Python 3.10 或更高版本 上运行:

$ 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

您还可以通过使用hf_token参数传递您的HF令牌来连接到私有空间。您可以在此处获取您的HF令牌:https://huggingface.co/settings/tokens

from gradio_client import Client

client = Client("abidlabs/my-private-space", hf_token="...")

复制空间以供私人使用

虽然您可以使用任何公共空间作为API,但如果请求过多,可能会被Hugging Face限速。要无限制地使用空间,只需复制该空间以创建私有空间,然后使用它进行任意数量的请求!

gradio_client 包含一个类方法:Client.duplicate() 以使这个过程变得简单(你需要传入你的 Hugging Face token 或使用 Hugging Face CLI 登录):

import os
from gradio_client import Client, handle_file

HF_TOKEN = os.environ.get("HF_TOKEN")

client = Client.duplicate("abidlabs/whisper", hf_token=HF_TOKEN)
client.predict(handle_file("audio_sample.wav"))

>> "This is a test of the whisper speech recognition model."

如果您之前已经复制了一个Space,重新运行duplicate()不会创建一个新的Space。相反,客户端将附加到之前创建的Space。因此,多次重新运行Client.duplicate()方法是安全的。

注意: 如果原始 Space 使用 GPU,您的私有 Space 也会使用 GPU,并且您的 Hugging Face 账户将根据 GPU 的价格进行计费。为了最小化费用,您的 Space 在 1 小时不活动后将自动进入睡眠状态。您还可以使用 duplicate()hardware 参数来设置硬件。

连接一个通用的Gradio应用

如果你的应用程序在其他地方运行,只需提供完整的URL,包括“http://”或“https://”。以下是一个向运行在共享URL上的Gradio应用程序进行预测的示例:

from gradio_client import Client

client = Client("https://bec81a83-5b5c-471e.gradio.live")

连接到需要身份验证的Gradio应用

如果您连接的Gradio应用程序需要用户名和密码,则将它们作为元组提供给Client类的auth参数:

from gradio_client import Client

Client(
  space_name,
  auth=[username, password]
)

检查API端点

一旦你连接到一个Gradio应用,你可以通过调用Client.view_api()方法来查看可用的API。对于Whisper Space,我们看到以下内容:

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,它是一个文件路径或URL

我们还应该向predict()方法提供api_name='/predict'参数。虽然如果一个Gradio应用只有一个命名的端点,这不是必要的,但它确实允许我们在单个应用中调用不同的端点(如果它们可用)。

"查看API"页面

作为运行.view_api()方法的替代方案,您可以点击Gradio应用页脚中的“通过API使用”链接,该链接向我们展示了相同的信息以及示例用法。

View API 页面还包括一个“API 记录器”,它允许您正常与 Gradio UI 进行交互,并将您的交互转换为相应的代码,以便与 Python 客户端一起运行。

进行预测

进行预测的最简单方法是直接调用带有适当参数的.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

这允许您利用默认参数。例如,此Space包含Slider组件的默认值,因此在使用客户端访问时无需提供它。

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.handle_file()。这会负责将文件上传到Gradio服务器,并确保文件被正确预处理:

from gradio_client import Client, handle_file

client = Client("abidlabs/whisper")
client.predict(
    audio=handle_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(handle_file("audio_sample1.wav"))
job2 = client.submit(handle_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

如果第一个作业已经开始处理,那么它将不会被取消。如果第二个作业尚未开始,它将被成功取消并从队列中移除。

生成器端点

一些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 作为生成器的等效示例:

from gradio_client import Client

client = Client(src="gradio/count_generator")
job = client.submit(3, api_name="/count")

for o in job:
    print(o)

>> 0
>> 1
>> 2

您还可以取消具有迭代输出的作业,在这种情况下,作业将在当前迭代运行完成后立即结束。

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组件中提交的单词列表。当用户提交一个新单词时,它会被添加到状态中,并显示该单词之前出现的次数:

import gradio as gr

def count(word, list_of_words):
    return list_of_words.count(word), list_of_words + [word]

with gr.Blocks() as demo:
    words = gr.State([])
    textbox = gr.Textbox()
    number = gr.Number()
    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()来实现。