techfreakworm's picture
feat(t2i): raise Width/Height cap to 2048 and switch step to 16
3aed2df unverified
"""Gradio UI builders for z-image-studio (Soft Dark Restraint redesign).
Each ``build_*_tab()`` returns a dict of components so ``app.py:build_app``
can wire ``.click()`` / ``.change()`` handlers without reaching into local
scopes. All param help text flows through Gradio's native ``info=`` parameter
(dim subtitle under each label) — no custom popover or (i) icon helper.
"""
from __future__ import annotations
import gradio as gr
import preprocessors
from tooltips import TOOLTIPS
# Link targets for the small dim row under the model radio. The Z-Image
# README's Model Zoo section is the canonical "where to find more models"
# anchor; Omni Base lives in the same README. When more models ship, swap
# these constants and nothing else needs to change.
MODEL_ZOO_URL = "https://github.com/Tongyi-MAI/Z-Image#-model-zoo"
def _model_soon_row_html() -> str:
"""Return the small dim link row that lives directly under the model radio.
Two anchor links + a "(coming soon)" qualifier. Static — no state, no JS.
"""
return (
'<div class="zis-soon-row">'
f'<a href="{MODEL_ZOO_URL}" target="_blank" rel="noopener noreferrer">Edit ↗</a>'
'<span class="sep">·</span>'
f'<a href="{MODEL_ZOO_URL}" target="_blank" rel="noopener noreferrer">Omni Base ↗</a>'
'<span class="dim">(coming soon)</span>'
"</div>"
)
def build_t2i_tab() -> dict[str, gr.components.Component]:
with gr.Row():
with gr.Column(scale=4):
prompt = gr.Textbox(
label="Prompt",
info=TOOLTIPS["prompt"],
lines=4,
placeholder="A latina model peeking through pine branches…",
)
model = gr.Radio(
["Base", "Turbo"],
value="Turbo",
label="Model",
info=TOOLTIPS["model"],
)
model_soon_row = gr.HTML(_model_soon_row_html())
with gr.Group(visible=False) as base_group:
negative_prompt = gr.Textbox(
label="Negative prompt",
info=TOOLTIPS["negative_prompt"],
lines=2,
placeholder="blurry, lowres, distorted",
)
cfg = gr.Slider(
0.5,
12.0,
value=1.0,
step=0.1,
label="CFG",
info=TOOLTIPS["cfg"],
)
lora_enabled = gr.Checkbox(label="Use a LoRA (compatible with Z-Image-Turbo)", value=False)
with gr.Group(visible=False) as lora_group:
lora_path = gr.File(
label="LoRA file",
file_types=[".safetensors"],
type="filepath",
elem_classes=["zis-lora-file"],
)
lora_strength = gr.Slider(
0.0,
1.5,
value=0.8,
step=0.05,
label="LoRA strength",
info=TOOLTIPS["lora_strength"],
)
steps = gr.Slider(1, 50, value=8, step=1, label="Steps", info=TOOLTIPS["steps"])
with gr.Accordion("Advanced", open=False):
width = gr.Slider(384, 2048, value=1024, step=16, label="Width", info=TOOLTIPS["width"])
height = gr.Slider(384, 2048, value=1024, step=16, label="Height", info=TOOLTIPS["height"])
seed = gr.Number(value=0, precision=0, label="Seed", info=TOOLTIPS["seed"])
generate_btn = gr.Button("Generate", variant="primary")
with gr.Column(scale=5):
gr.Markdown(f"**Output** \n<span style='color:#988B7C;font-size:12px;'>{TOOLTIPS['output']}</span>")
output_image = gr.Image(
show_label=False,
type="pil",
height=512,
show_download_button=True,
)
output_meta = gr.JSON(label="Meta", value={})
return dict(
prompt=prompt,
negative_prompt=negative_prompt,
model=model,
model_soon_row=model_soon_row,
base_group=base_group,
lora_enabled=lora_enabled,
lora_group=lora_group,
steps=steps,
cfg=cfg,
width=width,
height=height,
seed=seed,
lora_path=lora_path,
lora_strength=lora_strength,
generate_btn=generate_btn,
output_image=output_image,
output_meta=output_meta,
)
def build_controlnet_tab() -> dict[str, gr.components.Component]:
with gr.Row():
with gr.Column(scale=4):
prompt = gr.Textbox(
label="Prompt",
info=TOOLTIPS["prompt"],
lines=3,
)
with gr.Row():
with gr.Column():
gr.Markdown(
f"**Control image** \n<span style='color:#988B7C;font-size:12px;'>"
f"{TOOLTIPS['controlnet_image']}</span>"
)
input_image = gr.Image(
show_label=False,
type="pil",
height=240,
)
with gr.Column():
gr.Markdown(
"**Preprocessor preview** \n<span style='color:#988B7C;font-size:12px;'>"
"Live edge map / depth map / pose. Updates as you change the preprocessor.</span>"
)
preview_image = gr.Image(
show_label=False,
type="pil",
height=240,
interactive=False,
)
with gr.Row():
preprocessor = gr.Dropdown(
list(preprocessors.MODES),
value="Canny",
label="Preprocessor",
info=TOOLTIPS["controlnet_preprocessor"],
)
controlnet_scale = gr.Slider(
0.0,
2.0,
value=1.0,
step=0.05,
label="ControlNet scale",
info=TOOLTIPS["controlnet_scale"],
)
lora_enabled = gr.Checkbox(label="Use a LoRA (compatible with Z-Image-Turbo)", value=False)
with gr.Group(visible=False) as lora_group:
lora_path = gr.File(
label="LoRA file",
file_types=[".safetensors"],
type="filepath",
elem_classes=["zis-lora-file"],
)
lora_strength = gr.Slider(
0.0,
1.5,
value=0.8,
step=0.05,
label="LoRA strength",
info=TOOLTIPS["lora_strength"],
)
steps = gr.Slider(1, 30, value=9, step=1, label="Steps", info=TOOLTIPS["steps"])
with gr.Accordion("Advanced", open=False):
seed = gr.Number(value=0, precision=0, label="Seed", info=TOOLTIPS["seed"])
generate_btn = gr.Button("Generate", variant="primary")
with gr.Column(scale=5):
gr.Markdown(f"**Output** \n<span style='color:#988B7C;font-size:12px;'>{TOOLTIPS['output']}</span>")
output_image = gr.Image(
show_label=False,
type="pil",
height=512,
show_download_button=True,
)
output_meta = gr.JSON(label="Meta", value={})
return dict(
prompt=prompt,
input_image=input_image,
preview_image=preview_image,
preprocessor=preprocessor,
controlnet_scale=controlnet_scale,
steps=steps,
seed=seed,
lora_enabled=lora_enabled,
lora_group=lora_group,
lora_path=lora_path,
lora_strength=lora_strength,
generate_btn=generate_btn,
output_image=output_image,
output_meta=output_meta,
)
def build_upscale_tab() -> dict[str, gr.components.Component]:
with gr.Row():
with gr.Column(scale=4):
prompt = gr.Textbox(
label="Refinement prompt",
info=TOOLTIPS["prompt"],
value="masterpiece, 8k",
lines=2,
)
gr.Markdown(
f"**Input image** \n<span style='color:#988B7C;font-size:12px;'>{TOOLTIPS['upscale_image']}</span>"
)
input_image = gr.Image(
show_label=False,
type="pil",
height=240,
)
with gr.Row():
refine_steps = gr.Slider(
1,
20,
value=5,
step=1,
label="Refine steps",
info=TOOLTIPS["refine_steps"],
)
refine_denoise = gr.Slider(
0.0,
1.0,
value=0.33,
step=0.01,
label="Refine denoise",
info=TOOLTIPS["refine_denoise"],
)
with gr.Accordion("Advanced", open=False):
seed = gr.Number(value=0, precision=0, label="Seed", info=TOOLTIPS["seed"])
generate_btn = gr.Button("Generate", variant="primary")
with gr.Column(scale=5):
gr.Markdown(
f"**Output (2x upscaled)** \n<span style='color:#988B7C;font-size:12px;'>{TOOLTIPS['output']}</span>"
)
output_image = gr.Image(
show_label=False,
type="pil",
height=512,
show_download_button=True,
)
output_meta = gr.JSON(label="Meta", value={})
return dict(
prompt=prompt,
input_image=input_image,
refine_steps=refine_steps,
refine_denoise=refine_denoise,
seed=seed,
generate_btn=generate_btn,
output_image=output_image,
output_meta=output_meta,
)