python系列&deep_study系列:Gradio中文教程(三)Sharing Your App
Gradio中文教程(三)Sharing Your App
Gradio中文教程(三)Sharing Your App
分享你的应用
如何分享你的Gradio应用:
-
通过共享参数分享演示
-
在HF Spaces上托管
-
嵌入托管空间
-
使用API页面
-
访问网络请求
-
在FastAPI中挂载
-
认证
-
安全和文件访问
分享演示
通过在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
这会生成一个公共的、可分享的链接,你可以将其发送给任何人!当你发送这个链接时,另一端的用户可以在他们的浏览器中尝试使用该模型。因为处理发生在你的设备上(只要你的设备保持开启状态),你不必担心打包任何依赖项。
共享链接通常看起来像这样:No interface is running。尽管链接是通过Gradio Share Servers
提供的,但这些服务器只是你本地服务器的代理,不会存储通过你的应用发送的任何数据。共享链接在72小时后过期。(也可以在自己的云服务器上设置自己的Share Server
来克服这个限制。)✍️提示:请记住,共享链接是公开可访问的,这意味着任何人都可以使用你的模型进行预测!因此,请确保不要通过你编写的函数暴露任何敏感信息,或者允许在你的设备上发生任何关键更改。或者,你可以像下面讨论的那样为你的Gradio应用
添加认证。
请注意,默认情况下,share=Fals
e,这意味着你的服务器只在本地运行。(这是默认设置,除非在Google Colab笔记本
中,那里会自动创建共享链接)。作为使用共享链接的替代方案,你可以使用SSH端口
转发与特定用户共享你的本地服务器。
在HF Spaces上托管
如果你想在互联网上拥有一个永久链接指向你的Gradio演示
,请使用Hugging Face Spaces
。Hugging Face Spaces
提供了免费永久托管你的机器学习模型的基础设施!
创建一个免费的Hugging Face账户
后,你有两种方法将你的Gradio应用
部署到Hugging Face Spaces
:
-
从终端:在你的应用目录中
运行gradio deploy
。CLI
将收集一些基本元数据,然后启动你的应用。要更新你的空间,你可以重新运行此命令或启用Github Actions选项
,在git push
时自动更新Spaces
。 -
从你的浏览器:将包含你的
Gradio模型
和所有相关文件的文件夹拖放到这里。查看如何在Hugging Face Spaces
上托管的指南,或者观看嵌入的视频:
嵌入托管空间
一旦你在Hugging Face Spaces
(或你自己的服务器)上托管了你的应用,你可能想将其嵌入到不同的网站上,比如你的博客或你的作品集。嵌入一个交互式演示允许人们尝试你构建的机器学习模型,而无需下载或安装任何东西——就在他们的浏览器中!最好的部分是,你甚至可以在静态网站(如GitHub页
面)上嵌入交互式演示。
有两种方法可以嵌入你的Gradio演示
。你可以在Hugging Face Space页面
上直接找到两个选项的快速链接,在“Embed this Space
”下拉选项中:
使用Web组件嵌入
Web组件
通常为用户提供比IFrames
更好的体验。Web组件
懒加载,这意味着它们不会减慢你网站的加载时间,并且它们会根据Gradio应用
的大小自动调整其高度。
要使用Web组件
嵌入:
将gradio JS库
导入到你的站点中,通过在你的站点中添加下面的脚本(将{GRADIO_VERSION}
替换为你使用的Gradio库版本)。
<script
type="module"
src="https://gradio.s3-us-west-2.amazonaws.com/{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组件的示例。
你还可以使用传递给标签的属性自定义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:
Web组件
加载Gradio应用时的初始高度(默认值为"300px
")。请注意,最终高度是根据Gradio应用
的大小设置的。 -
container:是否显示边框框架和有关
Space托管位置
的信息(默认值为"true
") -
info:是否仅在嵌入的应用下方显示有关
Space托管
位置的信息(默认值为"true
") -
autoscroll:预测完成后是否自动滚动到输出(默认值为"
false
") -
eager:页面加载时是否加载
Gradio应用
(默认值为"false
") -
theme_mode:是否使用
dark
、light
或默认的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嵌入
如果你不能向你的网站添加javascript(例如),则可以使用IFrames嵌入:
<iframe src="https://$your_space_host.hf.space"></iframe>
再次,你可以在“Embed this Spac
e”按钮中找到src=属性
的Space
的嵌入URL
。
注意:如果你使用IFrames
,你可能想要添加一个固定的height属性
并设置style="border:0
;"来移除边框。此外,如果你的应用需要权限(如访问摄像头或麦克风),你还需要使用allow属性
提供这些权限。
API页面
你可以将几乎任何Gradio应用
用作API
!在像这样的Gradio应用
的页脚中,你会看到一个“Use via API
”链接。
这是一个列出了可以用来查询Gradio应用
的端点的页面,通过我们支持的客户端:Python客户端
或JavaScript客户端
。对于每个端点,Gradio
自动生成参数及其类型,以及示例输入,像这样。
端点是在你启动Gradio Interface
时自动创建的。如果你使用Gradio Blocks
,你也可以设置一个Gradio API页面
,但我们建议你显式命名每个事件监听器,例如
btn.click(add, [num1, num2], output, api_name="addition")
这将向自动生成的API页面添加并记录端点/api/addition/
。否则,你的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 Incognito
模式不启用此功能。
如果用户访问你的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元数据
。这将把你的Space注册
为Hugging Face
上的OAuth应用程序
。接下来,你可以使用gr.LoginButton
为你的Gradio应用
添加一个登录按钮。一旦用户使用他们的HF账户
登录,你可以通过在任何Gradio函数
中添加一个类型为gr.OAuthProfile
的参数来检索他们的个人资料。个人资料将自动作为参数值注入。如果你想代表用户执行操作(例如列出用户的私有仓库、创建仓库等),你可以通过添加一个类型为gr.OAuthToken
的参数来检索用户令牌。你必须在Space元数据
中定义你将使用的范围(请参阅文档了解更多细节)。
这里是一个简短的示例:
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 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://huggingface.co/settings/tokens)生成一个新的令牌。然后,点击gr.LoginButton
将登录你的本地Hugging Face个人资料
,允许你在部署到Space
之前使用你的Hugging Face账户
调试你的应用。
OAuth(使用外部提供商)
在你的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应用
。当然,这并没有增加多少安全性,因为任何用户都可以在他们的请求中添加这个头。
这里是一个更完整的示例,展示了如何为Gradio应用
添加Google OAuth
(假设你已经在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应
用(通过在Spaces
上托管、在你自己的服务器上托管或通过临时共享链接)会向你的Gradio应用
的用户暴露主机机器上的某些文件。
特别是,Gradio应用
允许用户访问以下四种类型的文件:
-
由
Gradio
创建的临时文件。这些文件是由Gradio
在运行你的预测函数时创建的。例如,如果你的预测函数返回一个视频文件,那么Gradio
会将该视频保存到你设备上的一个临时缓存中,然后将文件的路径发送到前端。你可以通过将环境变量GRADIO_TEMP_DIR
设置为绝对路径(例如/home/usr/scripts/project/temp/
)来自定义由Gradio
创建的临时缓存文件的位置。你可以通过gradio.Blocks
、gradio.Interface
和gradio.ChatInterface
的delete_cache参数
在应用关闭时删除由你的应用创建的文件。这个参数是一个整数元组,形式为[frequency, age]
,其中frequency
是删除文件的频率,age
是自文件最后修改以来的时间(以秒为单位)。 -
由
Gradio
创建的缓存示例。如果你在gr.Interface()
、gr.ChatInterface()
或gr.Examples()
中设置cache_examples=True
或cache_examples="lazy"
,这些文件是由Gradio
在缓存示例以加快运行时间时创建的。默认情况下,这些文件保存在你的应用工作目录内的gradio_cached_examples/子目录
中。你可以通过将环境变量GRADIO_EXAMPLES_CACHE
设置为绝对路径或相对于你的工作目录的路径来自定义由Gradio
创建的缓存示例文件的位置。 -
通过
launch()
中的allowed_paths参数
显式允许的文件。这个参数允许你传递一个额外的目录或你希望允许用户访问的精确文件路径的列表。(默认情况下,这个参数是一个空列表)。 -
通过
gr.set_static_paths函数
显式设置的静态文件。这个参数允许你传递一个目录或文件名的列表,这些将被视为静态文件。这意味着它们不会被复制到缓存中,而是直接从你的计算机提供。这可以帮助节省磁盘空间并减少你的应用启动所需的时间,但要留意可能的安全影响。
Gradio不允许访问:
通过launch()
中的blocked_paths参数
显式阻止的文件。你可以向launch()
中的blocked_paths参数
传递一个额外的目录或精确文件路径的列表。这个参数优先于Gradio
默认暴露的文件或通过allowed_paths
允许的文件。
主机机器上的任何其他路径。用户不应该能够访问主机上的其他任意路径。
分享你的Gradio应用
还将允许用户将文件上传到你的计算机或服务器。你可以为上传设置最大文件大小,以防止滥用并节省磁盘空间。你可以通过.launch
的max_file_size参数
来做到这一点。例如,以下两个代码片段将文件上传限制为每文件5兆字节
。
import gradio as gr
demo = gr.Interface(lambda x: x, "image", "image")
demo.launch(max_file_size="5mb")
# or
demo.launch(max_file_size=5 * gr.FileSize.MB)
请确保你运行的是最新版本的gradio
,以便这些安全设置生效。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)