Gradio Agents & MCP 黑客马拉松
获奖者Gradio Agents & MCP 黑客马拉松
获奖者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
首先实例化一个 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 token 来连接私有 Space。你可以在这里获取你的 HF token:https://hugging-face.cn/settings/tokens
from gradio_client import Client
client = Client("abidlabs/my-private-space", hf_token="...")
虽然你可以将任何公共 Space 作为 API 使用,但如果你发出过多请求,Hugging Face 可能会对你进行速率限制。为了无限使用 Space,只需复制该 Space 创建一个私有 Space,然后就可以随意发出任意数量的请求!
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
参数设置硬件。
如果你的应用运行在其他地方,只需提供完整的 URL,包括“http://”或“https://”。以下是向运行在共享 URL 上的 Gradio 应用进行预测的示例
from gradio_client import Client
client = Client("https://bec81a83-5b5c-471e.gradio.live")
如果你连接的 Gradio 应用需要用户名和密码,则将它们作为元组提供给 Client
类的 auth
参数。
from gradio_client import Client
Client(
space_name,
auth=[username, password]
)
连接到 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
,它是一个 文件路径或 URL
。
我们还应该向 predict()
方法提供 api_name='/predict'
参数。尽管如果 Gradio 应用只有一个命名端点,这并不是必需的,但它确实允许我们在单个应用中调用不同的可用端点。
作为运行 .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 组件的初始值。如果组件没有初始值,但如果预测函数中的相应参数的默认值为 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()
来实现。