[diffusion] webui: reference to content task and better visualization capabilities (#16017)

This commit is contained in:
Li Jinliang
2025-12-29 10:22:21 +08:00
committed by GitHub
parent ef4b3c0e96
commit b840d6aaeb
2 changed files with 83 additions and 32 deletions

View File

@@ -18,23 +18,23 @@ SGLang Diffusion now includes an integrated WebUI. Simply add the `--webui` para
### Launch Text-to-Image Service
```bash
SERVER_ARGS=(
--model-path black-forest-labs/FLUX.1-dev
--num-gpus 2
)
WEBUI_PORT=2333
sglang serve "${SERVER_ARGS[@]}" --webui --webui-port ${WEBUI_PORT}
sglang serve black-forest-labs/FLUX.1-dev --num-gpus 1 --webui --webui-port 2333
```
### Launch Text-to-Video Service
```bash
SERVER_ARGS=(
--model-path Wan-AI/Wan2.2-T2V-A14B-Diffusers
--num-gpus 2
)
WEBUI_PORT=2333
sglang serve "${SERVER_ARGS[@]}" --webui --webui-port ${WEBUI_PORT}
sglang serve Wan-AI/Wan2.2-T2V-A14B-Diffusers --num-gpus 1 --webui --webui-port 2333
```
### Launch Image-to-Image Service
```bash
sglang serve --model-path Qwen/Qwen-Image-Edit-2511 --num-gpus 1 --webui --webui-port 2333
```
### Launch Image-to-Video Service
```bash
sglang serve Wan-AI/Wan2.2-TI2V-5B-Diffusers --num-gpus 1 --webui --webui-port 2333
```
## Port Forwarding
@@ -53,11 +53,6 @@ Learn more about port forwarding: [Port Forwarding](https://en.wikipedia.org/wik
## Interface Instructions
1. Task mode is automatically determined by the `num_frames` parameter:
- num_frames = 1: Text-to-Image mode
- num_frames > 1: Text-to-Video mode
2. After generation, manually click:
- Image output: View generated images
- Video output: View generated videos
You can view your model path and task name directly in the UI. We'd appreciate any feedback you'd like to share.
Once launched, access the interface at `http://localhost:${WEBUI_PORT}` in your browser.

View File

@@ -11,6 +11,9 @@ from sglang.multimodal_gen.runtime.entrypoints.utils import (
)
from sglang.multimodal_gen.runtime.scheduler_client import sync_scheduler_client
from sglang.multimodal_gen.runtime.server_args import ServerArgs
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
logger = init_logger(__name__)
def add_webui_args(parser: argparse.ArgumentParser):
@@ -22,15 +25,31 @@ def add_webui_args(parser: argparse.ArgumentParser):
def run_sgl_diffusion_webui(server_args: ServerArgs):
# import gradio in function to avoid CI crash
import gradio as gr
from huggingface_hub import model_info
# init client
sync_scheduler_client.initialize(server_args)
task_name = model_info(server_args.model_path).pipeline_tag
if task_name in ("text-to-video", "image-to-video", "video-to-video"):
task_type = "video"
elif task_name in ["text-to-image", "image-to-image"]:
task_type = "image"
else:
raise ValueError(
f"The task name {task_name} of model {server_args.model_path} is not a valid task name. Please check the model path."
)
video_visible_only = task_type == "video"
image_visible_only = task_type == "image"
# server_args will be reused in gradio_generate function
def gradio_generate(
prompt,
negative_prompt,
reference_image_paths_str,
seed,
num_frames,
frames_per_second,
@@ -45,9 +64,20 @@ def run_sgl_diffusion_webui(server_args: ServerArgs):
So we use global variable sampling_params_kwargs to avoid pass this param, because gradio does not support this.
return [ np.ndarray, None ] | [None, np.ndarray]
"""
if reference_image_paths_str:
if "" in reference_image_paths_str:
logger.warning(
f"Warning: please use English comma to separate the reference image paths, and the reference image paths is: {reference_image_paths_str}"
)
reference_image_paths_str = reference_image_paths_str.replace("", ",")
image_path = [path.strip() for path in reference_image_paths_str.split(",")]
else:
image_path = None
sampling_params_kwargs = dict(
prompt=prompt,
negative_prompt=negative_prompt,
image_path=image_path,
seed=seed,
num_frames=num_frames,
fps=frames_per_second,
@@ -68,6 +98,14 @@ def run_sgl_diffusion_webui(server_args: ServerArgs):
)
result = sync_scheduler_client.forward([batch])
save_file_path = str(os.path.join(batch.output_path, batch.output_file_name))
if result.output is None:
sampling_params_str = "\n".join(
[f"{key}: {value}" for key, value in sampling_params_kwargs.items()]
)
raise ValueError(
f"No output is generated by client, and their sampling params is: {sampling_params_str}"
)
frames = post_process_sample(
result.output[0],
batch.data_type,
@@ -83,7 +121,9 @@ def run_sgl_diffusion_webui(server_args: ServerArgs):
with gr.Blocks() as demo:
gr.Markdown("# 🚀 SGLang Diffusion Application")
launched_model = gr.Textbox(label="Model", value=server_args.model_path)
with gr.Row():
launched_model_box = gr.Textbox(label="Model", value=server_args.model_path)
task_name_box = gr.Textbox(label="Task name", value=task_name)
with gr.Row():
with gr.Column(scale=4):
@@ -98,12 +138,6 @@ def run_sgl_diffusion_webui(server_args: ServerArgs):
with gr.Row():
with gr.Column():
num_frames = gr.Slider(
minimum=1, maximum=161, value=81, step=1, label="num_frames"
)
frames_per_second = gr.Slider(
minimum=4, maximum=60, value=16, step=1, label="frames_per_second"
)
width = gr.Number(label="width", precision=0, value=720)
height = gr.Number(label="height", precision=0, value=480)
num_inference_steps = gr.Slider(
@@ -112,21 +146,42 @@ def run_sgl_diffusion_webui(server_args: ServerArgs):
guidance_scale = gr.Slider(
minimum=0.0, maximum=10, value=5, step=0.01, label="guidance_scale"
)
num_frames = gr.Slider(
minimum=1,
maximum=181,
value=81,
step=1,
label="num_frames",
visible=video_visible_only,
)
frames_per_second = gr.Slider(
minimum=4,
maximum=60,
value=16,
step=1,
label="frames_per_second",
visible=video_visible_only,
)
reference_image_paths_str = gr.Textbox(
label="reference images",
placeholder="Examples: 'image1.png, image2.png' or 'https://example.com/image1.png, https://example.com/image2.png'",
)
enable_teacache = gr.Checkbox(label="enable_teacache", value=False)
with gr.Tabs() as tabs:
with gr.TabItem("Image output", id=1):
image_out = gr.Image(
label="Generated Image",
)
with gr.TabItem("Video output", id=2):
video_out = gr.Video(label="Generated Video")
with gr.Column():
image_out = gr.Image(
label="Generated Image", visible=image_visible_only
)
video_out = gr.Video(
label="Generated Video", visible=video_visible_only
)
run_btn.click(
fn=gradio_generate,
inputs=[
prompt,
negative_prompt,
reference_image_paths_str,
seed,
num_frames,
frames_per_second,
@@ -143,6 +198,7 @@ def run_sgl_diffusion_webui(server_args: ServerArgs):
server_port=server_args.webui_port,
quiet=True,
prevent_thread_lock=True,
show_error=True,
)
# print banner