使用 Gradio 后端构建任意自定义前端
摘要
Hugging Face 推出 `gradio.Server`,一款全新工具,让开发者能够将 Gradio 的后端基础设施(队列、托管)与使用 React、Svelte 或纯 HTML/CSS/JS 构建的自定义前端结合使用。
暂无内容
查看缓存全文
缓存时间: 2026/05/08 09:11
任意自定义前端 + Gradio 后端 来源:https://huggingface.co/blog/introducing-gradio-server 返回文章列表(https://huggingface.co/blog) yuvraj sharma 的头像(https://huggingface.co/ysharma) Abubakar Abid 的头像(https://huggingface.co/abidlabs) - 我们想构建什么(https://huggingface.co/blog/introducing-gradio-server#what-we-wanted-to-build) - 认识 gradio.Server(https://huggingface.co/blog/introducing-gradio-server#enter-gradioserver)- 为什么用 @app.api() 而不是普通 FastAPI 路由?(https://huggingface.co/blog/introducing-gradio-server#why-appapi-instead-of-a-plain-fastapi-route) - 前端:纯 HTML/CSS/JS(https://huggingface.co/blog/introducing-gradio-server#the-frontend-pure-htmlcssjs) - 这解锁了什么(https://huggingface.co/blog/introducing-gradio-server#what-this-unlocks) - 试一试(https://huggingface.co/blog/introducing-gradio-server#try-it) - 下一步(https://huggingface.co/blog/introducing-gradio-server#whats-next) - 推荐阅读(https://huggingface.co/blog/introducing-gradio-server#recommended-reading) 几周前,我们介绍了如何用 gr.HTML 一键构建完整 Web 应用(https://huggingface.co/blog/gradio-html-one-shot-apps):在 Gradio 内部完全使用自定义 HTML、CSS 和 JavaScript 构建丰富、交互式的前端。这解锁了很多可能性。但如果这还不够呢?如果你想完全使用自己的前端框架,比如 React、Svelte,甚至纯 HTML/JS,同时仍然享受 Gradio 的队列系统、API 基础设施、MCP 支持以及 Spaces 上的 ZeroGPU? 这正是 gradio.Server 要解决的问题。它改变了 Gradio 和 Hugging Face Spaces 的可能性边界。 ## https://huggingface.co/blog/introducing-gradio-server#what-we-wanted-to-build 我们想构建什么 Text Behind Image(https://huggingface.co/spaces/ysharma/text-behind-image):一个编辑器,你上传照片后,使用 ML 模型去除背景,然后将风格化文字放置在前景主体和背景之间。文字看起来像是位于图像中人物或物体的后方。 这需要: - 一个拖放画布,支持分层渲染(背景 → 文字 → 前景) - 一个丰富的控制面板,包含字体大小、粗细、字间距、颜色、不透明度、描边、阴影、3D 挤出、透视变换等滑块 - 一个后端 ML 接口,运行背景去除模型并返回透明 PNG - 客户端 PNG 导出 这种 UI 根本无法用 Gradio 组件表达。它是一个完整的 Web 应用。但我们仍然想要 Gradio 的后端能力:队列、并发管理、ZeroGPU 支持,以及在 HF Spaces 上无需基础设施烦恼的托管。 ## https://huggingface.co/blog/introducing-gradio-server#enter-gradioserver 认识 gradio.Server gradio.Server 扩展了 FastAPI。它赋予你 FastAPI 的完整能力(自定义路由、中间件、文件上传、任意响应类型),同时在上方叠加了 Gradio 的 API 引擎:队列、SSE 流式传输、并发控制以及 gradio_client 兼容性。 以下是 Text Behind Image 的完整后端: import os import torch from PIL import Image from torchvision import transforms from transformers import AutoModelForImageSegmentation from gradio import Server from gradio.data_classes import FileData from fastapi.responses import HTMLResponse import spaces torch.set_float32_matmul_precision("high") birefnet = AutoModelForImageSegmentation.from_pretrained( "ZhengPeng7/BiRefNet", trust_remote_code=True ) birefnet.to("cuda") birefnet.float() transform_image = transforms.Compose([ transforms.Resize((1024, 1024)), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ]) app = Server() @spaces.GPU def segment(image: Image.Image) -> Image.Image: """Run BiRefNet segmentation to produce a transparency mask.""" image_size = image.size input_images = transform_image(image).unsqueeze(0).to("cuda") with torch.no_grad(): preds = birefnet(input_images)[-1].sigmoid().cpu() pred = preds[0].squeeze() mask = transforms.ToPILImage()(pred).resize(image_size) image.putalpha(mask) return image @app.api(name="remove_background") def remove_background(image_path: FileData) -> FileData: """Remove background from an image. Returns transparent PNG.""" im = Image.open(image_path["path"]).convert("RGB") result = segment(im) out_path = image_path["path"].rsplit(".", 1)[0] + ".png" result.save(out_path) return FileData(path=out_path) @app.get("/", response_class=HTMLResponse) async def homepage(): html_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "index.html") with open(html_path, "r", encoding="utf-8") as f: return f.read() app.launch(show_error=True) 就这些。大约 50 行 Python。模型在启动时加载,@spaces.GPU 处理 ZeroGPU 分配,gradio.Server 管理队列和并发。 我们来拆解一下发生了什么。 ### https://huggingface.co/blog/introducing-gradio-server#why-appapi-instead-of-a-plain-fastapi-route 为什么用 @app.api() 而不是普通 FastAPI 路由? 如果这是一个普通的 FastAPI 应用,你会为背景去除定义一个 @app.post() 路由。这能工作,直到两个用户同时访问。没有并发管理,两个请求会争夺 GPU,应用崩溃或返回垃圾结果。 @app.api() 解决了这个问题。它用 Gradio 的队列引擎包装你的函数:请求被串行化,并发被控制,在 ZeroGPU Spaces 上,GPU 分配通过 @spaces.GPU 自动处理。 作为额外好处,任何 @app.api() 端点也可以通过 gradio_client 调用,因此其他应用或脚本可以编程方式使用你的 Space: from gradio_client import Client, handle_file client = Client("ysharma/text-behind-image") result = client.predict( image_path=handle_file("photo.jpg"), api_name="/remove_background" ) 同时,@app.get("/") 是一个标准 FastAPI 路由,用于提供 HTML 页面。两者自然共存,因为 Server 就是 FastAPI 应用。 ### https://huggingface.co/blog/introducing-gradio-server#the-frontend-pure-htmlcssjs 前端:纯 HTML/CSS/JS 这个例子中的 index.html 是一个自包含的约 1300 行 Web 应用。没有 React,没有构建步骤,没有打包工具。就是原生 HTML,包含: - 三层画布:背景图像 → 文字层 → 前景(透明 PNG),通过 CSS z-index 堆叠 - 拖放文字定位,使用指针事件 - 控制面板,包含 20+ 参数:字体族(25+ 字体)、大小、粗细、间距、颜色、不透明度、背景填充、描边、阴影、3D 挤出深度和角度、旋转、倾斜,以及完整的 CSS 透视变换 - 客户端 PNG 导出,使用 compositing 前端通过 Gradio JS Client(https://www.gradio.app/guides/getting-started-with-the-js-client)与后端通信: import { Client, handle_file } from “https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js”; const client = await Client.connect(window.location.origin); const result = await client.predict(“/remove_background”, { image_path: handle_file(file), }); foregroundLayer.src = result.data[0].url; // transparent PNG `` 这是关键部分:通过使用 Gradio JS 客户端而不是原始的 fetch() 调用,前端走 Gradio 的队列。这意味着并发被管理,GPU 请求不会冲突,你甚至可以向用户显示队列位置或进度。 其他所有功能——文字渲染、图层合成、导出——都在浏览器中完成。 ## https://huggingface.co/blog/introducing-gradio-server#what-this-unlocks 这解锁了什么 以下是 gradio.Server 出现之前不可能做到的事: | 以前 | 现在 | |——|——| | 自定义 UI 意味着完全离开 Gradio | 自定义 UI 搭配 Gradio 的后端引擎 | | 无法从 Gradio 应用提供静态 HTML | @app.get("/") 可以提供任何内容 | | gradio_client 仅适用于 Gradio 组件应用 | @app.api() 端点兼容客户端 | | 在 Gradio 基础设施和设计自由之间二选一 | 两者兼得 | 有了 gradio.Server,Gradio 同时充当后端框架——需要时用它的 UI 系统,不需要时自带前端。 如果你想要 Gradio 的 UI,可以使用 gr.Blocks、gr.Interface、gr.ChatInterface。如果你想要自己的 UI,使用 gradio.Server,带上你喜欢的前端。无论哪种方式,你都能获得 Spaces 托管、API 队列、gradio_client 访问、完整的 HF 生态,等等。 ## https://huggingface.co/blog/introducing-gradio-server#try-it 试一试 应用已在 Spaces 上线:ysharma/text-behind-image(https://huggingface.co/spaces/ysharma/text-behind-image) 上传任何主体清晰的照片,开始将文字层叠在后方。试试 3D 挤出、透视倾斜和描边效果——它们组合得很好。 ## https://huggingface.co/blog/introducing-gradio-server#whats-next 下一步 本文涵盖了核心概念:gradio.Server 让你将任意前端与 Gradio 后端配对。还有更多可以探索的,包括用 @app.mcp.tool() 进行 MCP 工具注册、用于实时更新的 SSE 流式传输、批处理,以及构建带共享状态的多页面应用的模式。我们将在后续文章中深入探讨。敬请期待。 ## https://huggingface.co/blog/introducing-gradio-server#recommended-reading 推荐阅读 - 文档:gradio.Server(https://www.gradio.app/main/docs/gradio/server) - 指南:Server mode(https://www.gradio.app/guides/server-mode)
相似文章
Tailgrids 3.0
Tailgrids 3.0 是一个专为 Tailwind CSS 和 AI 工作流设计的开源 React UI 库。
Corpus:自托管的 ListenBrainz 和 Last.fm 前端
Corpus 是一个自托管的前端,用于 ListenBrainz 和 Last.fm,它存储音乐收听记录、元数据和封面图片,并提供一个基于 PureScript 的交互界面来探索收听习惯。
@GoSailGlobal: https://x.com/GoSailGlobal/status/2052573500800700560
SWE-WebDev Bench 是 arXiv 上的一篇论文,评测了 6 个主流 vibe coding 平台(Lovable、Replit Agent3、Vercel v0-Max、Base44、Emergent E1-OPUS、QwikBuild),发现所有平台工程综合分都没超过 60%,前端 UI 漂亮但后端、安全、生产就绪度集体翻车,需要 12-60 小时人工修复才能上线。
就他妈用 React
这篇主观性很强的文章激进地主张在复杂 Web 应用中使用现代 JavaScript 框架(如 React)而非纯 HTML,认为复杂性需要合适的工具。
如何使用 OpenAI 的 Privacy Filter 构建可扩展的 Web 应用
本文演示如何利用 OpenAI 的 Privacy Filter 模型和 Gradio Server 构建用于 PII(个人可识别信息)检测的可扩展 Web 应用,并展示了文档探索、图像匿名化等三个具体应用示例。