Gradio JavaScript Client 入门:用 @gradio/client 把任意 Gradio 应用当 API 调用
2026/9/9 19:39:12 网站建设 项目流程

Gradio JavaScript Client 入门:用 @gradio/client 把任意 Gradio 应用当 API 调用

【免费下载链接】gradioBuild and share delightful machine learning apps, all in Python. 🌟 Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/gr/gradio

@gradio/client是 Gradio 官方提供的 TypeScript/JavaScript 客户端(仓库内实现位于 client/js),它让你无需手动拼 HTTP 请求,就能把任何运行中的 Gradio 应用——语音转写、图像生成、文本翻译、带状态的聊天机器人、计算器等——当作标准的远程 API 来调用。读完本指南,你将掌握从安装、连接(含 Hugging Face Space、私有 Space、鉴权应用)到查看端点、发起预测、监听流式事件与任务状态、取消任务的完整链路,可直接把任意 Gradio App 集成进你自己的 Node.js 服务或前端页面。

快速上手:一段代码调用一个 Gradio App

本指南以一个「音频转写」类应用(Hugging Face Spaceabidlabs/whisper,可将麦克风录制的音频转成文字)为例。使用@gradio/client,仅需几行代码即可完成从拉取音频到拿到转写结果的完整流程:

import { Client, handle_file } from "@gradio/client"; const response = await fetch( "https://example.com/sample-1.wav" // 换成任何可访问的音频文件 URL ); 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." ]

这条链路背后实际发生了三件事:Client.connect拉取应用的运行时配置与 API 元数据,handle_file把浏览器端拿到的Blob标记为待上传的文件对象,predict完成上传与排队请求并等待最终结果。客户端并不限定只能连接 Hugging Face Space——任何部署在你自己服务器上的 Gradio 应用,只要给出完整 URL 都能连接。

前置知识:使用 JS Client 不需要深入掌握gradio库本身,但了解 Gradio 的「输入/输出组件」这一基本概念会很有帮助——API 的参数与返回值正是按照这些组件的类型来描述的。

安装 @gradio/client

方式一:通过 npm 安装

在 Node.js 或前端工程中,使用 npm 或其他兼容包管理器即可安装:

npm i @gradio/client

从仓库中的 client/js/package.json 可以看到该包的关键信息:当前版本为2.5.1,声明"engines": { "node": ">=18.0.0" },因此要求 Node.js 版本 ≥ 18.0.0;包以"type": "module"方式发布,同时提供 ESM(dist/index.js)、CommonJS(dist/index.cjs)与浏览器构建(dist/browser.jsdist/index.min.js)等入口,可被 Node 项目、打包工具及纯<script>场景分别消费。包的全部公开导出见 client/js/src/index.ts:核心是Client类,其余为predictsubmitupload_fileshandle_fileupload以及SpaceStatusStatusConfig等类型。

方式二:通过 CDN 引入

若只是想在网页里快速实验,可以把最新版直接以 ES Module 形式引入:

<!DOCTYPE html> <html lang="en"> <head> <script type="module"> import { Client } from "https://cdn.jsdelivr.net/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>

注意:上面的import必须放在<head><script type="module">中;CDN 默认加载最新版本,生产环境建议将 URL 中的版本号硬编码固定(package.json 的exports字段中即暴露了./dist/index.min.js这一浏览器构建产物,见 client/js/package.json)。这种方式适合原型验证,但存在版本漂移等局限。

连接到正在运行的 Gradio 应用

核心入口是Client类。连接的本质是两步:先根据应用引用(Space 名或完整 URL)解析出应用配置(config,包括输入输出组件、依赖关系、协议版本等),再通过配置中暴露的依赖信息建立可调用的 API 映射。这一初始化逻辑可在 client/js/src/client.ts 的init()/_resolve_config()中看到:客户端解析端点、拉取 config、自动调用view_api()获取 API 信息并建立「端点名 → fn_index」映射。

连接 Hugging Face Space

传入 Space 名称即可(abidlabs/en2fr是一个英译法翻译应用):

import { Client } from "@gradio/client"; const app = await Client.connect("abidlabs/en2fr");

Client.connect是静态方法,返回解析完成的Client实例(源码见 client/js/src/client.ts)。每个实例会自动生成一个session_hash,用于区分会话、串联有状态应用的多轮交互。

连接私有 Space

如果 Space 是私有的,需要在 options 中传入你的 Hugging Face 访问令牌(Token 可在 Hugging Face 网站的Settings → Access Tokens页面创建):

import { Client } from "@gradio/client"; const app = await Client.connect("abidlabs/my-private-space", { token: "hf_..." })

在 client/js/src/types.ts 的ClientOptions中可以看到,token的类型被限定为`hf_${string}`形式,说明它专用于 Hugging Face 鉴权。除token外,ClientOptions还支持:

选项类型作用
auth[string, string] \| null以用户名/密码元组方式登录启用账号鉴权的 Gradio 应用
eventsEventType[]订阅的事件类型("data" \| "status" \| "log" \| "render"),默认["data"]
status_callbackSpaceStatusCallback连接 Space 过程中的状态回调(如 sleeping/running/error 等加载进度)
headersRecord<string, string> \| Headers附加到每次 HTTP 请求的请求头
query_paramsRecord<string, string>附加的查询参数
session_hashstring手动指定会话哈希(默认随机生成)
cookiesstring手动提供 Cookie
credentialsRequestCredentialsfetch 的 credentials 策略(默认"same-origin"
with_null_stateboolean是否把 State 组件的null一并返回
hf_tokenhf_${string}旧版token别名(标记为 deprecated,仅为兼容保留)
oauth_tokenstring透传给应用的 OAuth 令牌,仅发送给声明需要它的端点

复制(Duplicate)一个 Space 供私人使用

公共 Space 作为 API 高频调用时可能触发 Hugging Face 的频率限制。若需要不限量调用,可以Client.duplicate把 Space 复制成你自己的私有 Space:

import { Client, handle_file } from "@gradio/client"; const response = await fetch("https://example.com/sample-0.mp3"); const audio_file = await response.blob(); const app = await Client.duplicate("abidlabs/whisper", { token: "hf_..." }); const transcription = await app.predict("/predict", [handle_file(audio_file)]);

Client.duplicateClient.connect对外几乎一致,唯一区别在于底层行为:前者会通过 Hugging Face 的副本接口帮你创建一个 Space 并连接它。重复对同一个 Space 调用duplicate不会反复新建副本,而是自动挂载到已创建的 Space 上,因此多次调用是安全的。

计费与硬件说明:如果原 Space 使用了 GPU,副本同样会使用 GPU 并按你的 Hugging Face 账户计费。为控制成本,Space 闲置约 5 分钟后会自动休眠。你也可以在 options 中指定硬件规格与休眠超时:

import { Client } from "@gradio/client"; const app = await Client.duplicate("abidlabs/whisper", { token: "hf_...", timeout: 60, // 空闲 60 分钟后休眠 hardware: "a10g-small" });

DuplicateOptions(见 client/js/src/types.ts)在ClientOptions基础上增加了privatehardwaretimeout。合法的hardware取值在 client/js/src/helpers/spaces.ts 中定义,且duplicate在运行时会对传入值做白名单校验(非法值会直接报错,见 client/js/src/utils/duplicate.ts):

类别取值
CPUcpu-basiccpu-upgradecpu-xl
入门 GPUt4-smallt4-medium
A10G 系列a10g-smalla10g-largea10g-largex2a10g-largex4
高级 GPUa100-largeh100h100x8
其他zero-a10g

连接任意位置的 Gradio 应用

如果应用运行在 Hugging Face 之外(例如自己的服务器、内网或 gradio.live 共享链接),直接传入包含协议前缀的完整 URL 即可:

import { Client } from "@gradio/client"; const app = Client.connect("https://bec81a83-5b5c-471e.gradio.live");

从源码看(client/js/src/helpers/api_info.ts 的process_endpoint),客户端会把传入引用解析为http_protocol + host,进而请求config与 API 信息;Space 名与完整 URL 都走这条统一逻辑。

连接带账号鉴权的 Gradio 应用

如果目标应用在启动时启用了账号密码鉴权(即服务端launch(auth=...),原理可参考 sharing-your-app 指南中的 Authentication 部分),把用户名和密码以元组形式传给auth选项即可:

import { Client } from "@gradio/client"; Client.connect( space_name, { auth: [username, password] } )

客户端在初始化时(见 client/js/src/client.ts)会先解析 Cookie 完成登录,再把 Cookie 附加到后续所有请求(Client.fetch/Client.stream会自动携带已保存的 Cookie 与 options 中的 headers,源码见 client/js/src/client.ts)。

查看 API 端点

连接成功后,调用view_api()即可查看该应用对外暴露的全部 API:

import { Client } from "@gradio/client"; const app = await Client.connect("abidlabs/whisper"); const app_info = await app.view_api(); console.log(app_info);

上述 whisper Space 返回的结构类似:

{ "named_endpoints": { "/predict": { "parameters": [ { "label": "text", "component": "Textbox", "type": "string" } ], "returns": [ { "label": "output", "component": "Textbox", "type": "string" } ] } }, "unnamed_endpoints": {} }

这告诉我们该应用只有 1 个命名端点/predict,以及它的入参、出参各自的组件类型与类型定义。返回结构ApiInfo分为named_endpointsunnamed_endpoints两组(类型定义见 client/js/src/types.ts),每个端点的EndpointInfoparametersreturns等描述。客户端在init()阶段也会自动拉取一次 API 信息,用于把/predict这类端点名映射到底层的fn_index(依赖编号),这一映射api_map的建立见 client/js/src/client.ts。

实践中可以这样理解上面的信息:调用时应使用.predict()方法(下文详解),其参数为类型string的输入;显式传入api_name='/predict'并非必须(应用只有单个命名端点时可省略),但当一个应用暴露多个命名端点时,这能让你精确指定调用哪一个。若应用存在未命名端点,可以调用.view_api(all_endpoints=True)把它们一并展示出来。

备选:「View API」页面与 API Recorder

除了调用view_api(),也可以在应用页脚点击"Use via API"链接打开可视化页面,页面展示同样的端点信息并附有示例代码。该页面还内置了API Recorder(录制器):你可以照常操作 Gradio 界面,录制器会把你的每次交互实时翻译成对应的 JS Client 代码片段,是快速获取「正确参数格式」的捷径。相关内容可进一步阅读 view-api-page。

发起一次预测:.predict()

基本调用

最简单的方式是向.predict()传入端点名与参数数组:

import { Client } from "@gradio/client"; const app = await Client.connect("abidlabs/en2fr"); const result = await app.predict("/predict", ["Hello"]);

predict的参数顺序与view_api()展示的parameters数组一一对应。当端点有多个入参时,把它们按顺序放进数组即可,例如gradio/calculator这个计算器应用(接收两个数与一个运算符):

import { Client } from "@gradio/client"; const app = await Client.connect("gradio/calculator"); const result = await app.predict("/predict", [4, "add", 5]);

传入文件:handle_file

对图像、音频等文件类输入,需要传入BufferBlobFile,具体取决于运行环境:Node.js 中用BufferBlob,浏览器中用BlobFile。统一的推荐姿势是借助handle_file函数包装:

import { Client, handle_file } from "@gradio/client"; const response = await fetch("https://example.com/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)]);

handle_file的实现位于 client/js/src/helpers/data.ts,其接受File | string | Blob | Buffer并按类型分流:

  • HTTP(S) URL 字符串:直接构造为带path/url/orig_nameFileData,客户端将告知服务端从该 URL 拉取,无需本地上传;
  • 本地路径字符串(Node.js):包装为一个Command("upload_file", ...)上传命令,客户端会读取本地文件并上传;
  • File:原样返回,从而保留原始文件名与 MIME 类型;
  • Buffer:在 Node 中包装成Blob后走上传流程;
  • Blob:直接返回;
  • 其他类型会抛出"Invalid input: must be a URL, File, Blob, or Buffer object."

从源码看,predict本质上是「完整跑完一次任务直到结束」的高层封装(见 client/js/src/utils/predict.ts):它调用submit(..., all_events=true)建立异步迭代器,随后在循环里等待data消息拿到结果、以status.complete判断收尾,任何error阶段都会转换为携带完整状态字段的真实Error抛出,方便调用方捕获与排查。

进阶:用事件接口实时消费消息

当端点本身支持排队、生成中阶段,或你希望拿到任务状态、过程性结果时,.predict()的「等全部完成」语义就不够用了。此时使用submit()返回的**异步可迭代对象(iterable interface)**更灵活——它特别适合会随时间产生一系列离散结果的迭代(generator)端点。

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); }

submit返回的SubmitIterable(类型见 client/js/src/types.ts)是一个 AsyncIterable,额外带有cancel()event_id()wait_for_id()等方法。其底层消息处理逻辑(client/js/src/utils/submit.ts)会根据应用 config 中声明的protocol选择传输方式:若该端点不经过队列,直接向/run/run/{api_name}POST;若启用队列,则通过 SSE(/queue/data或流式协议)持续接收服务端推送的status/data/log/generating等事件并逐个转发给迭代器。

订阅任务状态:events: ["status", "data"]

要拿到运行中的状态消息,需要在连接时把events选项设为包含status

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布尔值,任务是否成功完成
timeDate对象,状态生成的时间戳

Status类型在源码 client/js/src/types.ts 中也有完整定义(含queuestagedurationprogress_dataused_cachecache_duration等字段),可对照使用。在事件循环中按消息类型过滤即可:

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()

Job 实例提供.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();

取消的语义区分两种情况:如果第一个任务已开始处理,服务端不会真正中断它,但客户端会停止监听(相当于丢弃该任务的后续消息);如果第二个任务尚未开始,则会被成功取消并移出队列。底层实现会向/cancel/reset端点分别发送请求(见 client/js/src/utils/submit.ts),其中/reset用于清理当前会话的排队状态。

生成器端点:实时接收一系列输出

某些 Gradio 端点不返回单个值,而是按时间依次产生一串值。以计数生成器gradio/count_generator为例,可用异步迭代实时读取每个输出:

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); }

注意这里的第一个参数传的是 **0(fn_index / 依赖编号)**而非"/predict"。在 client/js/src/utils/submit.ts 的get_endpoint_info中可以看到:端点参数允许是字符串(命名端点)或数字(依赖索引)。未命名端点没有/predict这类名称,只能(或恰好只能)用数字索引调用;源码中也提示,命名端点列表会在错误信息中列出,便于排查。

迭代输出的任务同样可以取消——取消后该任务会立即结束:

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);

小结:从源码理解完整调用链

把上文各环节串起来,一次完整调用的链路是:

  1. 连接Client.connect(space|url, options)解析端点、拉取 config 与 API 信息,建立api_map(端点名 → fn_index),并处理鉴权(token/Cookie/auth)与 Space 唤醒(client/js/src/client.ts);
  2. 构造请求submit/predict根据端点在 API 信息中定位参数结构,handle_file把文件类入参解析为FileData/上传命令并先行走上传;
  3. 传输与事件:依据 config 声明的协议(非队列直连/run/{api_name},队列任务走 SSE),接收服务端推送,客户端把原始消息标准化为type: "data" | "status" | "log" | "render"的事件流供for await消费;所有请求默认携带x-gradio-user: api请求头以标记 API 调用来源(见 client/js/src/utils/submit.ts);
  4. 收尾:收到complete状态后关闭事件流;predict自动完成这一等待逻辑,submit则把主动权交给调用方(可中途取消)。

这套机制与仓库中的测试覆盖相互印证——客户端的浏览器/Node 双端测试位于 client/js/src/test,前端各组件消费同一Client能力的代码在 js/core 目录中,可作为深入理解事件协议细节的参考。

延伸阅读

  • 如需了解 Python 版客户端的使用方式,参见 getting-started-with-the-python-client;
  • 想不依赖 SDK、直接以 HTTP/curl 调用 Gradio App,参见 querying-gradio-apps-with-curl;
  • 应用端的鉴权与分享配置,参见 sharing-your-app;
  • 「View API」页面的完整功能介绍,参见 view-api-page。

【免费下载链接】gradioBuild and share delightful machine learning apps, all in Python. 🌟 Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/gr/gradio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询