Gradio 代理与 MCP 黑客马拉松

获奖者
Gradio logo

Gradio 新用户?从这里开始:入门

查看 发布历史

介绍

轻量级的 Gradio 客户端库使将任何 Gradio 应用用作 API 变得容易。我们目前支持 Python 客户端库和 JavaScript 客户端库。

Python 客户端库是 gradio_client。它包含在最新版本的 gradio 包中,但为了获得更轻量级的体验,您可以使用 pip 安装它而无需安装 gradio

pip install gradio_client

Gradio Python 客户端入门

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

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

实现此功能的完整代码如下

from gradio_client import Client, file

client = Client("abidlabs/whisper")

client.predict(
    audio=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.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

您还可以通过使用 hf_token 参数传入您的 HF 令牌来连接到私有 Space。您可以在此处获取您的 HF 令牌:https://hugging-face.cn/settings/tokens

from gradio_client import Client

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

复制 Space 以供私人使用

虽然您可以使用任何公共 Space 作为 API,但如果您发出过多请求,可能会受到 Hugging Face 的速率限制。为了无限制地使用 Space,只需复制该 Space 创建一个私有 Space,然后就可以随心所欲地发出请求了!

gradio_client 包含一个类方法:Client.duplicate() 来简化此过程(您需要传入您的Hugging Face 令牌或使用 Hugging Face CLI 登录)

import os
from gradio_client import Client, file

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

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

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

如果您之前已经复制过 Space,则再次运行 duplicate() *不会*创建新的 Space。相反,客户端将连接到之前创建的 Space。因此,多次运行 Client.duplicate() 方法是安全的。

注意:如果原始 Space 使用 GPU,您的私有 Space 也会使用,您的 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")

检查 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 

我们看到这个 space 中有 1 个 API 端点,并展示了如何使用该 API 端点进行预测:我们应该调用 .predict() 方法(稍后将探讨),提供一个类型为 str 的参数 input_audio,它是一个 filepath or URL

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

“查看 API”页面

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

查看 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 组件的初始值。如果组件没有初始值,但 predict 函数中的相应参数的默认值为 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

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

生成器端点

一些 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

包含会话状态的 Demo

Gradio demo 可以包含会话状态,它为 demo 提供了一种在页面会话中持久保存用户交互信息的方式。

例如,考虑以下 demo,它在 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() 来实现。