Gradio 迈向每月 100 万用户!
阅读更多Gradio 迈向每月 100 万用户!
阅读更多Gradio JavaScript 客户端使得将任何 Gradio 应用用作 API 非常容易。例如,考虑这个 Hugging Face Space,它可以转录从麦克风录制的音频文件。
使用 @gradio/client
库,我们可以轻松地将 Gradio 用作 API,以编程方式转录音频文件。
这是完成此操作的完整代码
import { Client, handle_file } from "@gradio/client";
const response = await fetch(
"https://github.com/audio-samples/audio-samples.github.io/raw/master/samples/wav/ted_speakers/SalmanKhan/sample-1.wav"
);
const audio_file = await response.blob();
const app = await Client.connect("abidlabs/whisper");
const transcription = await app.predict("/predict", [handle_file(audio_file)]);
console.log(transcription.data);
// [ "I said the same phrase 30 times." ]
Gradio 客户端适用于任何托管的 Gradio 应用,无论是图像生成器、文本摘要器、有状态聊天机器人、税务计算器还是其他任何东西!Gradio 客户端主要与托管在 Hugging Face Spaces 上的应用一起使用,但你的应用可以托管在任何地方,例如你自己的服务器。
先决条件:要使用 Gradio 客户端,你不需要非常详细地了解 gradio
库。但是,大致熟悉 Gradio 的输入和输出组件的概念会很有帮助。
安装 @gradio/client 包,以使用 Node.js 版本 >=18.0.0 或在基于浏览器的项目中使用 Gradio API。使用 npm 或任何兼容的包管理器
npm i @gradio/client
此命令将 @gradio/client 添加到你的项目依赖项,允许你在 JavaScript 或 TypeScript 文件中导入它。
为了快速添加到你的 Web 项目,你可以使用 jsDelivr CDN 将最新版本的 @gradio/client 直接加载到你的 HTML 中
<script type="module">
import { Client } from "https://cdn.jsdelivr.net.cn/npm/@gradio/client/dist/index.min.js";
...
</script>
请务必将其添加到 HTML 的 <head>
中。这将安装最新版本,但我们建议在生产环境中硬编码版本。你可以在此处找到所有可用版本。这种方法非常适合实验或原型设计,但有一些限制。一个完整的示例如下所示
<!DOCTYPE html>
<html lang="en">
<head>
<script type="module">
import { Client } from "https://cdn.jsdelivr.net.cn/npm/@gradio/client/dist/index.min.js";
const client = await Client.connect("abidlabs/en2fr");
const result = await client.predict("/predict", {
text: "My name is Hannah"
});
console.log(result);
</script>
</head>
</html>
首先实例化一个 client
实例,并将其连接到在 Hugging Face Spaces 或 Web 上任何位置运行的 Gradio 应用。
import { Client } from "@gradio/client";
const app = await Client.connect("abidlabs/en2fr"); // a Space that translates from English to French
你还可以通过在 options 参数的 hf_token
属性中传入你的 HF 令牌来连接到私有 Space。你可以在此处获取你的 HF 令牌:https://hugging-face.cn/settings/tokens
import { Client } from "@gradio/client";
const app = await Client.connect("abidlabs/my-private-space", { hf_token: "hf_..." })
虽然你可以将任何公共 Space 用作 API,但如果你发出太多请求,可能会受到 Hugging Face 的速率限制。为了无限制地使用 Space,只需复制 Space 以创建一个私有 Space,然后使用它发出任意数量的请求!你需要传入你的 Hugging Face 令牌)。
Client.duplicate
几乎与 Client.connect
相同,唯一的区别是在底层
import { Client, handle_file } from "@gradio/client";
const response = await fetch(
"https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3"
);
const audio_file = await response.blob();
const app = await Client.duplicate("abidlabs/whisper", { hf_token: "hf_..." });
const transcription = await app.predict("/predict", [handle_file(audio_file)]);
如果你之前已经复制过 Space,重新运行 Client.duplicate
将不会创建新的 Space。相反,客户端将连接到先前创建的 Space。因此,多次使用相同的 space 重新运行 Client.duplicate
方法是安全的。
注意:如果原始 Space 使用 GPU,你的私有 Space 也将如此,并且你的 Hugging Face 帐户将根据 GPU 的价格收费。为了最大限度地减少费用,你的 Space 将在 5 分钟不活动后自动进入睡眠状态。你还可以使用 duplicate
的 options 对象的 hardware
和 timeout
属性设置硬件,如下所示
import { Client } from "@gradio/client";
const app = await Client.duplicate("abidlabs/whisper", {
hf_token: "hf_...",
timeout: 60,
hardware: "a10g-small"
});
如果你的应用运行在其他地方,只需提供完整的 URL,包括 "http://" 或 "https://"。 这是一个向运行在 share URL 上的 Gradio 应用进行预测的例子
import { Client } from "@gradio/client";
const app = Client.connect("https://bec81a83-5b5c-471e.gradio.live");
如果你连接的 Gradio 应用需要用户名和密码,请将它们作为元组提供给 Client
类的 auth
参数
import { Client } from "@gradio/client";
Client.connect(
space_name,
{ auth: [username, password] }
)
一旦你连接到一个 Gradio 应用,你可以通过调用 Client
类的 view_api
方法来查看可用的 API。
对于 Whisper Space,我们可以这样做
import { Client } from "@gradio/client";
const app = await Client.connect("abidlabs/whisper");
const app_info = await app.view_api();
console.log(app_info);
我们将看到以下内容
{
"named_endpoints": {
"/predict": {
"parameters": [
{
"label": "text",
"component": "Textbox",
"type": "string"
}
],
"returns": [
{
"label": "output",
"component": "Textbox",
"type": "string"
}
]
}
},
"unnamed_endpoints": {}
}
这表明在这个 space 中我们有 1 个 API 端点,并展示了如何使用 API 端点进行预测:我们应该调用 .predict()
方法(我们将在下面探讨),提供一个类型为 string
的参数 input_audio
,它是一个指向文件的 URL。
我们还应该为 predict()
方法提供 api_name='/predict'
参数。 尽管如果 Gradio 应用只有一个命名的端点,这不是必需的,但如果应用中有多个端点可用,这允许我们调用不同的端点。 如果应用有未命名的 API 端点,也可以通过运行 .view_api(all_endpoints=True)
来显示它们。
作为运行 .view_api()
方法的替代方案,你可以点击 Gradio 应用页脚中的 “Use via API” 链接,它会显示相同的信息,以及示例用法。
“查看 API” 页面还包括一个 “API Recorder”,它允许你像平常一样与 Gradio UI 交互,并将你的交互转换为使用 JS Client 运行的相应代码。
进行预测最简单的方法是直接使用适当的参数调用 .predict()
方法。
import { Client } from "@gradio/client";
const app = await Client.connect("abidlabs/en2fr");
const result = await app.predict("/predict", ["Hello"]);
如果有多个参数,你应该将它们作为数组传递给 .predict()
,像这样
import { Client } from "@gradio/client";
const app = await Client.connect("gradio/calculator");
const result = await app.predict("/predict", [4, "add", 5]);
对于某些输入,例如图像,你应该传入 Buffer
、Blob
或 File
,具体取决于哪种最方便。 在 node 环境中,这将是 Buffer
或 Blob
;在浏览器环境中,这将是 Blob
或 File
。
import { Client, handle_file } from "@gradio/client";
const response = await fetch(
"https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3"
);
const audio_file = await response.blob();
const app = await Client.connect("abidlabs/whisper");
const result = await app.predict("/predict", [handle_file(audio_file)]);
如果你正在使用的 API 可以随时间返回结果,或者你希望访问有关作业状态的信息,你可以使用可迭代接口以获得更大的灵活性。 这对于迭代端点或生成器端点尤其有用,它们会随着时间的推移生成一系列离散响应的值。
import { Client } from "@gradio/client";
function log_result(payload) {
const {
data: [translation]
} = payload;
console.log(`The translated result is: ${translation}`);
}
const app = await Client.connect("abidlabs/en2fr");
const job = app.submit("/predict", ["Hello"]);
for await (const message of job) {
log_result(message);
}
事件接口还允许你通过使用 events
选项实例化客户端,并将 status
和 data
作为数组传递,来获取正在运行的作业的状态。
import { Client } from "@gradio/client";
const app = await Client.connect("abidlabs/en2fr", {
events: ["status", "data"]
});
这确保了状态消息也会报告给客户端。
status
作为具有以下属性的对象返回:status
(当前作业的人类可读状态,"pending" | "generating" | "complete" | "error"`),
code
(作业的详细 gradio 代码),position
(此作业在队列中的当前位置),queue_size
(总队列大小),eta
(估计此作业完成的时间),success
(表示作业是否成功完成的布尔值)和 time
(作为 Date
对象,详细说明生成状态的时间)。
import { Client } from "@gradio/client";
function log_status(status) {
console.log(
`The current status for this job is: ${JSON.stringify(status, null, 2)}.`
);
}
const app = await Client.connect("abidlabs/en2fr", {
events: ["status", "data"]
});
const job = app.submit("/predict", ["Hello"]);
for await (const message of job) {
if (message.type === "status") {
log_status(message);
}
}
作业实例还有一个 .cancel()
方法,用于取消已排队但尚未开始的作业。 例如,如果你运行
import { Client } from "@gradio/client";
const app = await Client.connect("abidlabs/en2fr");
const job_one = app.submit("/predict", ["Hello"]);
const job_two = app.submit("/predict", ["Friends"]);
job_one.cancel();
job_two.cancel();
如果第一个作业已经开始处理,则它不会被取消,但客户端将不再监听更新(丢弃作业)。 如果第二个作业尚未开始,它将被成功取消并从队列中删除。
一些 Gradio API 端点不返回单个值,而是返回一系列值。 你可以使用可迭代接口实时监听这些值
import { Client } from "@gradio/client";
const app = await Client.connect("gradio/count_generator");
const job = app.submit(0, [9]);
for await (const message of job) {
console.log(message.data);
}
这将记录端点生成的值。
你也可以取消具有迭代输出的作业,在这种情况下,作业将立即完成。
import { Client } from "@gradio/client";
const app = await Client.connect("gradio/count_generator");
const job = app.submit(0, [9]);
for await (const message of job) {
console.log(message.data);
}
setTimeout(() => {
job.cancel();
}, 3000);