gradio-mlp

你是 Shopee MLP 平台上 Gradio 应用的开发专家。用户从事多模态大模型(图片/视频理解与生成)的训练、数据构建和评估工作。

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "gradio-mlp" with this command: npx skills add oneboxcream/claude-code-setup/oneboxcream-claude-code-setup-gradio-mlp

MLP 平台 Gradio 应用开发指南

你是 Shopee MLP 平台上 Gradio 应用的开发专家。用户从事多模态大模型(图片/视频理解与生成)的训练、数据构建和评估工作。

环境信息

  • Python: 3.8.13 (不支持 3.9+ 语法如 match/case 、type X = ... 等)

  • Gradio: 4.44.1

  • 平台: Shopee MLP web-shell

  • 反向代理格式: /proxy/{port} (MLP 实际完整路径较长,见下方说明)

  • 数据存储: /home/work/aigc_video_bpfs_3/ 挂载盘

核心规则

  1. 反向代理配置(必须)

MLP 平台通过 /proxy/{port} 反向代理访问 Gradio 服务。每个 Gradio 应用都必须正确配置。

方式 A:纯 Gradio(简单应用推荐)

import argparse parser = argparse.ArgumentParser() parser.add_argument("--port", type=int, default=7860) parser.add_argument("--root_path", type=str, default=None, help="MLP reverse proxy path, e.g. /proxy/7860") args = parser.parse_args()

demo.launch( server_name="0.0.0.0", server_port=args.port, root_path=args.root_path or f"/proxy/{args.port}", )

启动: python app.py --port 7860

访问: https://{mlp-host}/proxy/7860

方式 B:FastAPI + Gradio(需要 API 或文件访问时推荐)

重要背景: MLP 平台的反向代理实际完整路径很长: https://ais.mlp.shopee.io/api/notebooks/clusters/.../proxy/{port}/

而不是简单的 /proxy/{port} 。因此:

  • Gradio API 调用:通过 FIX_ROOT_JS 中间件从 window.location.pathname 动态获取,自动适配

  • gr.HTML 中的图片/资源路径:必须使用相对路径 ./file={path} ,不要硬编码 root_path

import uvicorn from fastapi import FastAPI, Request from fastapi.responses import Response import gradio as gr

app = FastAPI()

反向代理 root 路径自动修复中间件

从浏览器 URL 动态获取实际代理路径,无需硬编码

FIX_ROOT_JS = b"""<script> (function(){ var c = window.gradio_config; if (c) { var p = window.location.pathname.replace(/\/$/, ''); c.root = p; } })(); </script> </head>"""

@app.middleware("http") async def fix_gradio_root(request: Request, call_next): response = await call_next(request) ct = response.headers.get("content-type", "") if "text/html" in ct: body = b"" async for chunk in response.body_iterator: body += chunk body = body.replace(b"</head>", FIX_ROOT_JS, 1) # 注意:必须移除旧 content-length,因为注入 JS 后 body 长度变了 # 不移除会导致浏览器一直处于加载状态(读到一半连接断开) new_headers = { k: v for k, v in response.headers.items() if k.lower() != "content-length" } return Response(content=body, status_code=response.status_code, headers=new_headers, media_type="text/html") return response

Gradio 挂载

demo = gr.Blocks()

... 构建 UI ...

ALLOWED_PATHS = ["/home/work/aigc_video_bpfs_3/"] gr.mount_gradio_app(app, demo, path="/", allowed_paths=ALLOWED_PATHS)

uvicorn.run(app, host="0.0.0.0", port=7860)

  1. 图片展示

方式 A:gr.Image 组件(单张,推荐)

gr.Image(type="pil", label="Result", interactive=False, height=320)

方式 B:gr.Gallery(多张浏览)

gr.Gallery(label="Results", columns=4, height="auto", object_fit="contain")

方式 C:gr.HTML 自定义表格(带缩放悬浮,数据浏览推荐)

需要 FastAPI 方式,配置 allowed_paths

图片 URL 格式: ./file={绝对路径}(相对路径,自动适配 MLP 反向代理)

⚠️ 不要使用 {root_path}/file={path} 硬编码方式!

MLP 实际代理路径: https://ais.mlp.shopee.io/api/notebooks/.../proxy/{port}/

硬编码 /proxy/{port}/file=... 会丢失中间路径,导致图片 404

相对路径 ./file=... 浏览器会基于当前页面 URL 自动解析为正确的完整路径

def render_table(data): html = '<table><tr><th>Index</th><th>Image</th></tr>' for row in data: img_url = "./file={}".format(row['image_path']) html += '<tr><td>{}</td>'.format(row["idx"]) html += '<td><img src="{}" style="max-height:120px"></td></tr>'.format(img_url) html += '</table>' return html

CSS 悬浮放大

CSS = """ table img { transition: transform 0.2s; cursor: pointer; } table img:hover { transform: scale(3); z-index: 100; box-shadow: 0 4px 20px rgba(0,0,0,0.3); } """

  1. 视频展示

视频输出组件

gr.Video(label="Generated Video", interactive=False, autoplay=True)

视频输入

gr.Video(label="Input Video", sources=["upload"])

  1. 常用 UI 布局模式

图像处理/生成 工作流

with gr.Blocks(title="App Name") as demo: gr.Markdown("## Title") with gr.Row(): with gr.Column(): input_image = gr.Image(type="pil", label="Input", height=320) prompt = gr.Textbox(label="Prompt", lines=2) with gr.Accordion("Advanced Options", open=False): steps = gr.Slider(1, 100, value=50, label="Steps") seed = gr.Slider(-1, 2147483647, value=-1, step=1, label="Seed") resolution = gr.Dropdown( choices=["7201280", "480832", "512512"], value="512512", label="Resolution" ) run_btn = gr.Button("Generate", variant="primary") with gr.Column(): output = gr.Image(type="pil", label="Result", interactive=False) status = gr.Textbox(label="Status", interactive=False)

run_btn.click(fn=process, inputs=[input_image, prompt, steps, seed, resolution],
              outputs=[output, status])

多 Tab 评估结果展示

with gr.Blocks() as demo: with gr.Tabs(): with gr.Tab("Metrics"): metrics_html = gr.HTML() with gr.Tab("Samples"): gallery = gr.Gallery(columns=4) with gr.Tab("Comparison"): with gr.Row(): gr.Image(label="Model A") gr.Image(label="Model B") gr.Image(label="Ground Truth")

数据浏览 + 分页

with gr.Blocks() as demo: with gr.Row(): search = gr.Textbox(label="Search", scale=3) filter_dd = gr.Dropdown(choices=["All", ...], label="Filter", scale=1) sort_dd = gr.Dropdown(choices=["Original", "By Name"], label="Sort", scale=1) table_html = gr.HTML() with gr.Row(): prev_btn = gr.Button("< Prev") page_info = gr.Markdown("Page 1 / N") next_btn = gr.Button("Next >")

  1. 大模型推理集成

全局模型变量 + 延迟加载(节省显存)

model_480p = None model_720p = None

def load_model(resolution): global model_480p, model_720p import gc, torch # 释放旧模型 if resolution == "480P" and model_720p is not None: del model_720p model_720p = None gc.collect() torch.cuda.empty_cache() # 加载新模型 ...

队列模式(长时间推理必须)

demo = gr.Blocks().queue()

进度条集成

def process(image, progress=gr.Progress(track_tqdm=True)): # tqdm 进度会自动同步到 Gradio UI for step in tqdm(range(100)): ...

  1. 启动模板

始终使用以下命令行参数模式:

if name == "main": parser = argparse.ArgumentParser() parser.add_argument("--port", type=int, default=7860) parser.add_argument("--root_path", type=str, default=None) args = parser.parse_args()

demo.queue().launch(
    server_name="0.0.0.0",
    server_port=args.port,
    root_path=args.root_path or f"/proxy/{args.port}",
)

注意事项

  • Gradio 启动慢: 约需 15 秒才能响应请求,测试时需等待

  • Python 3.8 兼容: 不要使用 match/case 、type 别名、X | Y 类型联合等 3.9+ 语法

  • gr.HTML 中的图片/资源路径: 使用相对路径 ./file={绝对路径} ,不要用 {root_path}/file= 硬编码(MLP 实际代理路径很长,硬编码会 404)

  • 中间件 content-length: FIX_ROOT_JS 中间件注入 JS 后 body 变大,必须移除原 content-length header,否则浏览器会一直卡在加载状态

  • allowed_paths: 使用 FastAPI 方式时必须配置,否则无法访问本地文件

  • 显存管理: 加载大模型前用 gc.collect()

  • torch.cuda.empty_cache() 清理
  • 端口冲突: MLP 平台多人共用,注意使用不同端口;启动前建议检测端口占用

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

code-comments

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

design-critique

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

codebase-study-guide

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

personality-profiler

No summary provided by upstream source.

Repository SourceNeeds Review