Gradio 月活用户达到 100 万!
阅读更多Gradio 月活用户达到 100 万!
阅读更多≤# 分享你的应用
在本指南中,我们将更深入地探讨与他人分享 Gradio 应用的各个方面。我们将涵盖
通过在 launch()
方法中设置 share=True
,可以轻松公开分享 Gradio 演示。 就像这样
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox")
demo.launch(share=True) # Share your demo with just 1 extra parameter 🚀
这将生成一个公共的、可分享的链接,您可以将其发送给任何人!当您发送此链接时,另一端的用户可以在他们的浏览器中试用该模型。由于处理发生在您的设备上(只要您的设备保持开启状态),您不必担心任何依赖项的打包问题。
共享链接通常看起来像这样:https://07ff8706ab.gradio.live。虽然链接是通过 Gradio 共享服务器提供的,但这些服务器只是您本地服务器的代理,并且不存储通过您的应用发送的任何数据。共享链接在 72 小时后过期。(也可以在您自己的云服务器上设置您自己的共享服务器,以克服此限制。)
提示: 请记住,共享链接是公开可访问的,这意味着任何人都可以使用您的模型进行预测!因此,请确保不要通过您编写的函数暴露任何敏感信息,也不要允许在您的设备上发生任何关键更改。或者您可以[向您的 Gradio 应用添加身份验证](#authentication),如下所述。
请注意,默认情况下,share=False
,这意味着您的服务器仅在本地运行。(这是默认设置,但在 Google Colab 笔记本中除外,在 Google Colab 笔记本中会自动创建共享链接)。作为使用共享链接的替代方法,您可以使用 SSH 端口转发 与特定用户共享您的本地服务器。
如果您想在互联网上拥有 Gradio 演示的永久链接,请使用 Hugging Face Spaces。Hugging Face Spaces 提供了免费永久托管您的机器学习模型的基础设施!
在您创建免费 Hugging Face 帐户后,您有两种方法将 Gradio 应用部署到 Hugging Face Spaces
从终端:在您的应用目录中运行 gradio deploy
。CLI 将收集一些基本元数据,然后启动您的应用。要更新您的 space,您可以重新运行此命令,或启用 Github Actions 选项以在 git push
时自动更新 Spaces。
从浏览器:将包含您的 Gradio 模型和所有相关文件的文件夹拖放到此处。 有关更多信息,请参阅此关于如何在 Hugging Face Spaces 上托管的指南,或观看嵌入的视频
您可以向 Gradio 应用添加一个按钮,该按钮创建一个唯一的 URL,您可以使用该 URL 与他人分享您的应用以及所有组件的当前状态。 这对于分享来自您的应用的独特而有趣的生成结果,或用于保存在特定时间点的应用快照非常有用。
要向您的应用添加深度链接按钮,请将 gr.DeepLinkButton
组件放置在应用中的任何位置。 为了使 URL 可供其他人访问,您的应用必须在公共 URL 上可用。 因此,请务必像 Hugging Face Spaces 一样托管您的应用,或在使用启动应用时使用 share=True
参数。
让我们看一个例子,了解它是如何工作的。 这是一个简单的 Gradio 聊天应用,它使用了 gr.DeepLinkButton
组件。 在发送几条消息后,单击深度链接按钮并将其粘贴到新的浏览器标签页中,以查看该时间点的应用状态。
import gradio as gr
import random
def random_response(message, history):
return random.choice(["Hi!", "Hello!", "Greetings!"])
with gr.Blocks() as demo:
gr.ChatInterface(
random_response,
title="Greeting Bot",
description="Ask anything and receive a nice greeting!",
)
gr.DeepLinkButton()
if __name__ == "__main__":
demo.launch(share=True)
一旦您将应用托管在 Hugging Face Spaces 上(或您自己的服务器上),您可能希望将演示嵌入到其他网站上,例如您的博客或作品集。 嵌入交互式演示允许人们试用您构建的机器学习模型,而无需下载或安装任何内容 - 就在他们的浏览器中! 最棒的是,即使在静态网站(例如 GitHub 页面)中,您也可以嵌入交互式演示。
有两种方法可以嵌入您的 Gradio 演示。 您可以直接在 Hugging Face Space 页面上的“Embed this Space”下拉选项中找到指向这两种选项的快速链接
与 IFrames 相比,Web components 通常为用户提供更好的体验。 Web components 延迟加载,这意味着它们不会减慢您网站的加载时间,并且它们会根据 Gradio 应用的大小自动调整其高度。
要使用 Web Components 嵌入
<script
type="module"
src="https://#/{GRADIO_VERSION}/gradio.js"
></script>
<gradio-app src="https://$your_space_host.hf.space"></gradio-app>
元素,您要在其中放置应用。 将 src=
属性设置为您的 Space 的嵌入 URL,您可以在“Embed this Space”按钮中找到它。 例如
<gradio-app
src="https://abidlabs-pytorch-image-classifier.hf.space"
></gradio-app>
您可以在 Gradio 登陆页面上查看 Web Components 的外观示例。
您还可以通过传递到 <gradio-app>
标签的属性来自定义您的 Web 组件的外观和行为
src
: 正如我们所见,src
属性链接到您想要嵌入的托管 Gradio 演示的 URLspace
: 如果您的 Gradio 演示托管在 Hugging Face Space 上,则这是一个可选的简写。接受 username/space_name
而不是完整的 URL。示例:gradio/Echocardiogram-Segmentation
。如果提供了此属性,则不需要提供 src
。control_page_title
: 一个布尔值,用于指定是否应将页面的 html 标题设置为 Gradio 应用的标题(默认为 "false"
)initial_height
: Web 组件在加载 Gradio 应用时的初始高度(默认为 "300px"
)。请注意,最终高度是根据 Gradio 应用的大小设置的。container
: 是否显示边框框架以及有关 Space 托管位置的信息(默认为 "true"
)info
: 是否仅在嵌入式应用下方显示有关 Space 托管位置的信息(默认为 "true"
)autoscroll
: 是否在预测完成后自动滚动到输出(默认为 "false"
)eager
: 是否在页面加载时立即加载 Gradio 应用(默认为 "false"
)theme_mode
: 是否使用 dark
、light
或默认的 system
主题模式(默认为 "system"
)render
: 嵌入式 Space 完成渲染后触发的事件。这是一个如何使用这些属性创建不延迟加载且初始高度为 0px 的 Gradio 应用的示例。
<gradio-app
space="gradio/Echocardiogram-Segmentation"
eager="true"
initial_height="0px"
></gradio-app>
这是另一个如何使用 render
事件的示例。事件侦听器用于捕获 render
事件,并在渲染完成后调用 handleLoadComplete()
函数。
<script>
function handleLoadComplete() {
console.log("Embedded space has finished rendering");
}
const gradioApp = document.querySelector("gradio-app");
gradioApp.addEventListener("render", handleLoadComplete);
</script>
注意:虽然 Gradio 的 CSS 永远不会影响嵌入页面,但嵌入页面可能会影响嵌入式 Gradio 应用的样式。请确保父页面中的任何 CSS 都不会过于通用,以至于也可能应用于嵌入式 Gradio 应用并导致样式中断。元素选择器(例如 header { ... }
和 footer { ... }
)最有可能导致问题。
要使用 IFrames 嵌入(例如,如果您无法将 javascript 添加到您的网站),请添加此元素
<iframe src="https://$your_space_host.hf.space"></iframe>
同样,您可以在 Space 的嵌入 URL 中找到 src=
属性,您可以在“Embed this Space(嵌入此 Space)”按钮中找到它。
注意:如果您使用 IFrames,您可能需要添加固定的 height
属性并设置 style="border:0;"
以删除边框。此外,如果您的应用需要网络摄像头或麦克风等权限,您还需要使用 allow
属性提供这些权限。
您可以将几乎任何 Gradio 应用用作 API!在 Gradio 应用的页脚中,例如这个应用,您将看到一个“Use via API(通过 API 使用)”链接。
此页面列出了可用于查询 Gradio 应用的端点,通过我们支持的客户端:Python 客户端,或 JavaScript 客户端。对于每个端点,Gradio 会自动生成参数及其类型,以及示例输入,如下所示。
当您启动 Gradio Interface
时,会自动创建端点。如果您使用的是 Gradio Blocks
,您也可以设置 Gradio API 页面,但我们建议您显式命名每个事件侦听器,例如
btn.click(add, [num1, num2], output, api_name="addition")
这将把端点 /api/addition/
添加到自动生成的 API 页面并进行文档化。否则,您的 API 端点将显示为“unnamed(未命名)”端点。
当用户对您的应用进行预测时,您可能需要底层的网络请求,以便获取请求头(例如,用于高级身份验证)、记录客户端的 IP 地址、获取查询参数或出于其他原因。Gradio 以类似于 FastAPI 的方式支持此功能:只需添加一个类型提示为 gr.Request
的函数参数,Gradio 就会将网络请求作为该参数传入。这是一个示例
import gradio as gr
def echo(text, request: gr.Request):
if request:
print("Request headers dictionary:", request.headers)
print("IP address:", request.client.host)
print("Query parameters:", dict(request.query_params))
return text
io = gr.Interface(echo, "textbox", "textbox").launch()
注意:如果您的函数是直接调用而不是通过 UI 调用(例如,当示例被缓存时,或者当 Gradio 应用通过 API 调用时),则 request
将为 None
。您应该显式处理这种情况,以确保您的应用不会抛出任何错误。这就是我们进行显式检查 if request
的原因。
在某些情况下,您可能已经有一个现有的 FastAPI 应用,并且您想为 Gradio 演示添加一个路径。您可以使用 gradio.mount_gradio_app()
轻松地做到这一点。
这是一个完整的示例
from fastapi import FastAPI
import gradio as gr
CUSTOM_PATH = "/gradio"
app = FastAPI()
@app.get("/")
def read_main():
return {"message": "This is your main app"}
io = gr.Interface(lambda x: "Hello, " + x + "!", "textbox", "textbox")
app = gr.mount_gradio_app(app, io, path=CUSTOM_PATH)
# Run this from the terminal as you would normally start a FastAPI app: `uvicorn run:app`
# and navigate to http://localhost:8000/gradio in your browser.
请注意,这种方法还允许您在自定义路径上运行 Gradio 应用(在上面的示例中为 http://localhost:8000/gradio
)。
您可能希望在您的应用前面放置一个身份验证页面,以限制可以打开您的应用的用户。通过 launch()
方法中的 auth=
关键字参数,您可以提供包含用户名和密码的元组,或可接受的用户名/密码元组列表;这是一个为名为“admin”的单个用户提供基于密码的身份验证的示例
demo.launch(auth=("admin", "pass1234"))
对于更复杂的身份验证处理,您甚至可以传递一个函数,该函数接受用户名和密码作为参数,并返回 True
以允许访问,否则返回 False
。
这是一个接受任何用户名和密码相同的登录的函数示例
def same_auth(username, password):
return username == password
demo.launch(auth=same_auth)
如果您有多个用户,您可能希望根据登录的用户自定义显示的内容。您可以通过直接访问网络请求来检索已登录的用户,如上所述,然后读取请求的 .username
属性。这是一个示例
import gradio as gr
def update_message(request: gr.Request):
return f"Welcome, {request.username}"
with gr.Blocks() as demo:
m = gr.Markdown()
demo.load(update_message, None, m)
demo.launch(auth=[("Abubakar", "Abubakar"), ("Ali", "Ali")])
注意:为了使身份验证正常工作,您的浏览器中必须启用第三方 Cookie。Safari 或 Chrome 隐身模式默认情况下并非如此。
如果用户访问您的 Gradio 应用的 /logout
页面,他们将自动注销,并且会删除会话 Cookie。这允许您也为您的 Gradio 应用添加注销功能。让我们更新之前的示例以包含一个注销按钮
import gradio as gr
def update_message(request: gr.Request):
return f"Welcome, {request.username}"
with gr.Blocks() as demo:
m = gr.Markdown()
logout_button = gr.Button("Logout", link="/logout")
demo.load(update_message, None, m)
demo.launch(auth=[("Pete", "Pete"), ("Dawood", "Dawood")])
注意:Gradio 的内置身份验证提供了一个直接且基本的访问控制层,但对于需要严格访问控制(例如,多因素身份验证、速率限制或自动锁定策略)的应用程序,它不提供强大的安全功能。
Gradio 原生支持通过 Hugging Face 进行 OAuth 登录。换句话说,您可以轻松地向您的演示添加一个“Sign in with Hugging Face(使用 Hugging Face 登录)”按钮,这使您可以获取用户的 HF 用户名以及来自其 HF 个人资料的其他信息。查看 此 Space 以获取实时演示。
要启用 OAuth,您必须在您的 README.md 文件中将 hf_oauth: true
设置为 Space 元数据。这会将您的 Space 注册为 Hugging Face 上的 OAuth 应用程序。接下来,您可以使用 gr.LoginButton
向您的 Gradio 应用添加登录按钮。用户使用其 HF 帐户登录后,您可以通过向任何 Gradio 函数添加 gr.OAuthProfile
类型的参数来检索其个人资料。用户个人资料将自动作为参数值注入。如果您想代表用户执行操作(例如,列出用户的私有仓库、创建仓库等),您可以通过添加 gr.OAuthToken
类型的参数来检索用户令牌。您必须在您的 Space 元数据中定义您将使用的作用域(有关更多详细信息,请参阅 文档)。
这是一个简短的示例
from __future__ import annotations
import gradio as gr
from huggingface_hub import whoami
def hello(profile: gr.OAuthProfile | None) -> str:
if profile is None:
return "I don't know you."
return f"Hello {profile.name}"
def list_organizations(oauth_token: gr.OAuthToken | None) -> str:
if oauth_token is None:
return "Please deploy this on Spaces and log in to list organizations."
org_names = [org["name"] for org in whoami(oauth_token.token)["orgs"]]
return f"You belong to {', '.join(org_names)}."
with gr.Blocks() as demo:
gr.LoginButton()
m1 = gr.Markdown()
m2 = gr.Markdown()
demo.load(hello, inputs=None, outputs=m1)
demo.load(list_organizations, inputs=None, outputs=m2)
demo.launch()
当用户单击登录按钮时,他们将在新页面中被重定向以授权您的 Space。
用户可以随时在其 设置中撤销对其个人资料的访问权限。
如上所述,OAuth 功能仅在您的应用在 Space 中运行时可用。但是,您通常需要在部署之前在本地测试您的应用。要在本地测试 OAuth 功能,您的机器必须登录到 Hugging Face。请运行 huggingface-cli login
或将 HF_TOKEN
设置为环境变量,其中包含您的一个访问令牌。您可以在您的设置页面中生成新令牌 (https://hugging-face.cn/settings/tokens)。然后,单击 gr.LoginButton
将登录您的本地 Hugging Face 个人资料,使您能够在将您的应用部署到 Space 之前使用您的 Hugging Face 帐户调试您的应用。
安全注意事项:重要的是要注意,添加 gr.LoginButton
不会像添加 用户名-密码身份验证 那样限制用户使用您的应用。这意味着您的应用中未通过 Hugging Face 登录的用户仍然可以访问和运行 Gradio 应用中的事件 - 区别在于 gr.OAuthProfile
或 gr.OAuthToken
在相应的函数中将为 None
。
在您的 Gradio 应用中,也可以使用外部 OAuth 提供商(例如 Google OAuth)进行身份验证。为此,首先在 FastAPI 应用中挂载您的 Gradio 应用(如上所述)。然后,您必须编写一个身份验证函数,该函数从 OAuth 提供商处获取用户的用户名并返回它。此函数应传递给 gr.mount_gradio_app
中的 auth_dependency
参数。
与 FastAPI 依赖项函数类似,auth_dependency
指定的函数将在您的 FastAPI 应用中的任何 Gradio 相关路由之前运行。该函数应接受一个参数:FastAPI Request
,并返回一个字符串(表示用户的用户名)或 None
。如果返回字符串,则用户将能够访问您的 FastAPI 应用中的 Gradio 相关路由。
首先,让我们展示一个简单的示例来说明 auth_dependency
参数
from fastapi import FastAPI, Request
import gradio as gr
app = FastAPI()
def get_user(request: Request):
return request.headers.get("user")
demo = gr.Interface(lambda s: f"Hello {s}!", "textbox", "textbox")
app = gr.mount_gradio_app(app, demo, path="/demo", auth_dependency=get_user)
if __name__ == '__main__':
uvicorn.run(app)
在此示例中,只有包含“user”标头的请求才被允许访问 Gradio 应用。当然,这并没有增加太多安全性,因为任何用户都可以在其请求中添加此标头。
这是一个更完整的示例,展示了如何将 Google OAuth 添加到 Gradio 应用(假设您已经在 Google Developer Console 上创建了 OAuth 凭据)
import os
from authlib.integrations.starlette_client import OAuth, OAuthError
from fastapi import FastAPI, Depends, Request
from starlette.config import Config
from starlette.responses import RedirectResponse
from starlette.middleware.sessions import SessionMiddleware
import uvicorn
import gradio as gr
app = FastAPI()
# Replace these with your own OAuth settings
GOOGLE_CLIENT_ID = "..."
GOOGLE_CLIENT_SECRET = "..."
SECRET_KEY = "..."
config_data = {'GOOGLE_CLIENT_ID': GOOGLE_CLIENT_ID, 'GOOGLE_CLIENT_SECRET': GOOGLE_CLIENT_SECRET}
starlette_config = Config(environ=config_data)
oauth = OAuth(starlette_config)
oauth.register(
name='google',
server_metadata_url='https://#/.well-known/openid-configuration',
client_kwargs={'scope': 'openid email profile'},
)
SECRET_KEY = os.environ.get('SECRET_KEY') or "a_very_secret_key"
app.add_middleware(SessionMiddleware, secret_key=SECRET_KEY)
# Dependency to get the current user
def get_user(request: Request):
user = request.session.get('user')
if user:
return user['name']
return None
@app.get('/')
def public(user: dict = Depends(get_user)):
if user:
return RedirectResponse(url='/gradio')
else:
return RedirectResponse(url='/login-demo')
@app.route('/logout')
async def logout(request: Request):
request.session.pop('user', None)
return RedirectResponse(url='/')
@app.route('/login')
async def login(request: Request):
redirect_uri = request.url_for('auth')
# If your app is running on https, you should ensure that the
# `redirect_uri` is https, e.g. uncomment the following lines:
#
# from urllib.parse import urlparse, urlunparse
# redirect_uri = urlunparse(urlparse(str(redirect_uri))._replace(scheme='https'))
return await oauth.google.authorize_redirect(request, redirect_uri)
@app.route('/auth')
async def auth(request: Request):
try:
access_token = await oauth.google.authorize_access_token(request)
except OAuthError:
return RedirectResponse(url='/')
request.session['user'] = dict(access_token)["userinfo"]
return RedirectResponse(url='/')
with gr.Blocks() as login_demo:
gr.Button("Login", link="/login")
app = gr.mount_gradio_app(app, login_demo, path="/login-demo")
def greet(request: gr.Request):
return f"Welcome to Gradio, {request.username}"
with gr.Blocks() as main_demo:
m = gr.Markdown("Welcome to Gradio!")
gr.Button("Logout", link="/logout")
main_demo.load(greet, None, m)
app = gr.mount_gradio_app(app, main_demo, path="/gradio", auth_dependency=get_user)
if __name__ == '__main__':
uvicorn.run(app)
在此示例中,实际上有两个独立的 Gradio 应用!一个只是显示一个登录按钮(任何用户都可以访问此演示),而另一个主演示仅供登录用户访问。您可以在 此 Space 上试用此示例。
默认情况下,Gradio 会收集某些分析数据,以帮助我们更好地了解 gradio
库的使用情况。这包括以下信息
auth
或 show_error
不会从您的 Gradio 应用的用户那里收集任何信息。如果您想完全禁用分析,您可以在 gr.Blocks
、gr.Interface
或 gr.ChatInterface
中将 analytics_enabled
参数设置为 False
。或者,您可以将 GRADIO_ANALYTICS_ENABLED 环境变量设置为 "False"
,以将其应用于在您的系统上创建的所有 Gradio 应用。
注意:这反映了 gradio>=4.32.0
的分析策略。
渐进式 Web 应用 (PWA) 是常规网页或网站的 Web 应用程序,但对用户而言,它们可以像可安装的特定于平台的应用程序一样显示。
通过在 launch()
方法中设置 pwa=True
参数,可以将 Gradio 应用轻松地作为 PWA 提供。这是一个示例
import gradio as gr
def greet(name):
return "Hello " + name + "!"
demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox")
demo.launch(pwa=True) # Launch your app as a PWA
这将生成一个可以安装在您设备上的 PWA。这是它的外观
当您在 launch()
方法中指定 favicon_path
时,该图标将用作应用的图标。这是一个示例
demo.launch(pwa=True, favicon_path="./hf-logo.svg") # Use a custom icon for your PWA