1. 附加功能
  2. 分享您的应用

分享您的应用

在本指南中,我们将更深入地探讨与他人共享Gradio应用程序的各个方面。我们将涵盖:

  1. 使用共享参数分享演示
  2. 在HF Spaces上托管
  3. 嵌入托管空间
  4. 使用API页面
  5. 访问网络请求
  6. 在FastAPI中挂载
  7. 认证
  8. 分析

分享演示

Gradio 演示可以通过在 launch() 方法中设置 share=True 轻松公开分享。像这样:

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 🚀

这将生成一个公开的、可分享的链接,您可以发送给任何人!当您发送此链接时,另一端的用户可以在他们的浏览器中试用该模型。由于处理发生在您的设备上(只要您的设备保持开启),您不必担心任何依赖项的打包。

sharing

分享链接通常看起来像这样:https://07ff8706ab.gradio.live。虽然链接是通过Gradio分享服务器提供的,但这些服务器只是您本地服务器的代理,不会存储通过您的应用程序发送的任何数据。分享链接在72小时后过期。(也可以在您自己的云服务器上设置自己的分享服务器来克服此限制。)

提示: 请记住,分享链接是公开可访问的,这意味着任何人都可以使用你的模型进行预测!因此,请确保不要通过你编写的函数暴露任何敏感信息,或允许在你的设备上发生任何关键更改。或者你可以按照下面讨论的[为你的Gradio应用添加认证](#authentication)。

请注意,默认情况下,share=False,这意味着您的服务器仅在本地运行。(这是默认设置,除了在Google Colab笔记本中,会自动创建共享链接)。作为使用共享链接的替代方案,您可以使用SSH端口转发与特定用户共享您的本地服务器。

在HF Spaces上托管

如果您希望在互联网上拥有一个永久链接到您的Gradio演示,请使用Hugging Face Spaces。Hugging Face Spaces提供了永久免费托管您的机器学习模型的基础设施!

在您创建了一个免费的Hugging Face账户之后,您有两种方法可以将您的Gradio应用程序部署到Hugging Face Spaces:

  1. 从终端:在您的应用程序目录中运行 gradio deploy。CLI 将收集一些基本元数据,然后启动您的应用程序。要更新您的空间,您可以重新运行此命令或启用 Github Actions 选项以在 git push 时自动更新空间。

  2. 从您的浏览器:拖放一个包含您的Gradio模型和所有相关文件的文件夹这里。有关更多信息,请参阅此指南如何在Hugging Face Spaces上托管,或观看嵌入的视频:

嵌入托管空间

一旦你在Hugging Face Spaces(或你自己的服务器)上托管了你的应用程序,你可能希望将演示嵌入到不同的网站上,比如你的博客或作品集。嵌入一个交互式演示可以让人们尝试你构建的机器学习模型,而无需下载或安装任何东西——直接在他们的浏览器中!最棒的是,你甚至可以在静态网站上嵌入交互式演示,比如GitHub页面。

有两种方法可以嵌入你的Gradio演示。你可以在Hugging Face Space页面的“嵌入此Space”下拉选项中找到这两种选项的快速链接:

Embed this Space dropdown option

使用Web组件嵌入

Web组件通常比IFrames提供更好的用户体验。Web组件是懒加载的,这意味着它们不会减慢您网站的加载时间,并且它们会根据Gradio应用程序的大小自动调整高度。

使用Web Components嵌入:

  1. 通过将以下脚本添加到您的站点中,将gradio JS库导入到您的站点中(将URL中的{GRADIO_VERSION}替换为您正在使用的Gradio库版本)。
<script
	type="module"
	src="https://gradio.s3-us-west-2.amazonaws.com/{GRADIO_VERSION}/gradio.js"
></script>
  1. 添加
<gradio-app src="https://$your_space_host.hf.space"></gradio-app>

你想要放置应用程序的元素。将src=属性设置为你空间的嵌入URL,你可以在“嵌入此空间”按钮中找到它。例如:

<gradio-app
	src="https://abidlabs-pytorch-image-classifier.hf.space"
></gradio-app>

你可以看到网页组件的示例 在Grio的登陆页面.

您还可以通过传递给标签的属性来自定义您的Web组件的外观和行为:

  • src: 正如我们所看到的,src 属性链接到您想要嵌入的托管 Gradio 演示的 URL
  • space: 如果你的Gradio演示托管在Hugging Face Space上,这是一个可选的简写。接受username/space_name而不是完整的URL。例如:gradio/Echocardiogram-Segmentation。如果提供了此属性,则不需要提供src
  • control_page_title: 一个布尔值,指定页面的HTML标题是否应设置为Gradio应用的标题(默认为"false"
  • initial_height: 网页组件在加载 Gradio 应用时的初始高度,(默认为 "300px")。请注意,最终高度是根据 Gradio 应用的大小设置的。
  • container: 是否显示边框框架和有关Space托管位置的信息(默认为"true"
  • info: 是否仅显示有关嵌入式应用程序下方托管空间位置的信息(默认情况下为 "true"
  • autoscroll: 预测完成后是否自动滚动到输出(默认为 "false"
  • eager: 是否在页面加载时立即加载Gradio应用(默认为"false"
  • theme_mode: 是否使用darklight或默认的system主题模式(默认为"system"
  • render: 嵌入空间完成渲染后触发的事件。

这里有一个示例,展示了如何使用这些属性创建一个不进行懒加载且初始高度为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嵌入

要使用IFrames嵌入(例如,如果您无法将javascript添加到您的网站),请添加此元素:

<iframe src="https://$your_space_host.hf.space"></iframe>

再次,你可以找到你的Space的嵌入URL中的src=属性,你可以在“嵌入此Space”按钮中找到它。

注意:如果您使用IFrames,您可能希望添加一个固定的height属性并设置style="border:0;"以移除边框。此外,如果您的应用程序需要访问网络摄像头或麦克风等权限,您还需要使用allow属性来提供这些权限。

API页面

你可以将几乎任何Gradio应用用作API!在Gradio应用的页脚,比如这个,你会看到一个“通过API使用”的链接。

Use via API

这是一个页面,列出了可以通过我们支持的客户端查询Gradio应用程序的端点:Python客户端JavaScript客户端。对于每个端点,Gradio会自动生成参数及其类型,以及示例输入,如下所示。

当您启动Gradio Interface时,端点会自动创建。如果您使用Gradio Blocks,您也可以设置一个Gradio API页面,但我们建议您明确命名每个事件监听器,例如

btn.click(add, [num1, num2], output, api_name="addition")

这将添加并记录端点 /api/addition/ 到自动生成的API页面。否则,您的API端点将显示为“未命名”端点。

直接访问网络请求

当用户向您的应用程序做出预测时,您可能需要底层的网络请求,以便获取请求头(例如用于高级身份验证)、记录客户端的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应用程序中挂载

在某些情况下,您可能已经有一个现有的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的内置认证提供了一个简单且基础的访问控制层,但对于需要严格访问控制的应用(例如多因素认证、速率限制或自动锁定策略),它并不提供强大的安全功能。

OAuth(通过Hugging Face登录)

Gradio 原生支持通过 Hugging Face 进行 OAuth 登录。换句话说,您可以轻松地在您的演示中添加一个"使用 Hugging Face 登录"按钮,该按钮允许您获取用户的 HF 用户名以及他们 HF 个人资料中的其他信息。查看这个 Space以获取实时演示。

要启用OAuth,您必须在README.md文件中将hf_oauth: true设置为Space元数据。这将在Hugging Face上将您的Space注册为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()

当用户点击登录按钮时,他们将被重定向到一个新页面以授权您的空间。

用户可以随时在他们的设置中撤销对其个人资料的访问权限。

如上所示,OAuth 功能仅在您的应用程序在 Space 中运行时可用。然而,您通常需要在部署之前在本地测试您的应用程序。要在本地测试 OAuth 功能,您的机器必须登录到 Hugging Face。请运行 huggingface-cli login 或使用您的访问令牌之一设置 HF_TOKEN 作为环境变量。您可以在设置页面生成一个新令牌 (https://huggingface.co/settings/tokens)。然后,点击 gr.LoginButton 将登录您的本地 Hugging Face 配置文件,允许您在将应用程序部署到 Space 之前使用您的 Hugging Face 帐户调试应用程序。

安全提示: 需要注意的是,添加一个gr.LoginButton并不会像添加用户名-密码认证那样限制用户使用你的应用。这意味着,即使没有通过Hugging Face登录的用户仍然可以访问并运行你的Gradio应用中的事件——不同之处在于,在相应的函数中,gr.OAuthProfilegr.OAuthToken将会是None

OAuth(使用外部提供商)

也可以在您的Gradio应用程序中使用外部OAuth提供者(例如Google OAuth)进行身份验证。为此,首先将您的Gradio应用程序挂载到FastAPI应用程序中(如上所述)。然后,您必须编写一个身份验证函数,该函数从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开发者控制台上创建了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://accounts.google.com/.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 库的使用情况。这包括以下信息:

  • Gradio 应用程序运行的环境(例如 Colab Notebook, Hugging Face Spaces)
  • Gradio 应用中使用了哪些输入/输出组件
  • Gradio 应用程序是否正在使用某些高级功能,例如 authshow_error
  • 仅用于测量使用Gradio的唯一开发者数量的IP地址
  • 正在运行的Gradio版本

不会从您的Gradio应用程序的用户那里收集任何信息。如果您想完全禁用分析功能,可以通过在gr.Blocksgr.Interfacegr.ChatInterface中将analytics_enabled参数设置为False来实现。或者,您可以将GRADIO_ANALYTICS_ENABLED环境变量设置为"False",以将此设置应用于您系统上创建的所有Gradio应用程序。

注意: 这反映了自 gradio>=4.32.0 以来的分析政策。