root
Upload L2P NFT training code
a573784
Raw
History Blame Contribute Delete
8.26 kB
"""
Usage:
python app.py
"""
import os
import subprocess
import threading
import torch
import gradio as gr
from diffsynth.pipelines.z_image_L2P import ZImagePipeline, ModelConfig
# ================= Configuration =================
# 1. Main model path
MAIN_MODEL_PATH = "./models/train/L2P_Standard/model-1k-merge.safetensors"
# 2. Text Encoder paths
TEXT_ENCODER_PATHS = [
"/path/Z-Image-Turbo/text_encoder/model-00001-of-00003.safetensors",
"/path/Z-Image-Turbo/text_encoder/model-00002-of-00003.safetensors",
"/path/Z-Image-Turbo/text_encoder/model-00003-of-00003.safetensors",
]
# 3. Tokenizer path
TOKENIZER_PATH = "/path/Z-Image-Turbo/tokenizer"
# 4. Server configuration
SERVER_NAME = "0.0.0.0"
SERVER_PORT = 23231
# ================= GPU detection & pipeline pool =================
def get_available_gpus():
"""Detect all available GPUs and return [(index, mem_used_MB, mem_total_MB), ...]"""
try:
result = subprocess.run(
["nvidia-smi", "--query-gpu=index,memory.used,memory.total",
"--format=csv,noheader,nounits"],
capture_output=True, text=True, timeout=10,
)
gpu_info = []
for line in result.stdout.strip().split("\n"):
parts = line.strip().split(",")
if len(parts) == 3:
idx = int(parts[0].strip())
mem_used = float(parts[1].strip())
mem_total = float(parts[2].strip())
gpu_info.append((idx, mem_used, mem_total))
return gpu_info
except Exception as e:
print(f"GPU detection failed ({e}), falling back to GPU 0 only")
return [(0, 0, 0)]
def select_gpus_for_loading(num_gpus=8):
"""
Select the list of GPUs used for loading models:
1. Prefer idle GPUs (memory used < 100MB)
2. If not enough, fill in with the GPUs that use the least memory
3. Select at most num_gpus
"""
all_gpus = get_available_gpus()
if not all_gpus:
return [0]
free = [g for g in all_gpus if g[1] < 100]
occupied = sorted([g for g in all_gpus if g[1] >= 100], key=lambda x: x[1])
# Use idle cards first
selected = free[:num_gpus]
# If not enough, fill with the least-occupied cards
remaining = num_gpus - len(selected)
if remaining > 0:
selected.extend(occupied[:remaining])
return [g[0] for g in selected]
# Pick the list of GPUs to load on
gpu_ids = select_gpus_for_loading(8)
print(f"Will load pipelines on GPUs: {gpu_ids}")
# Load a pipeline on each selected GPU
pipelines = {} # gpu_id -> pipeline
gpu_locks = {} # gpu_id -> threading.Lock (prevent concurrent inference on the same GPU)
for gid in gpu_ids:
dev = f"cuda:{gid}"
print(f"Loading pipeline on {dev}...")
p = ZImagePipeline.from_pretrained(
torch_dtype=torch.bfloat16,
device=dev,
model_configs=[
ModelConfig(path=[MAIN_MODEL_PATH]),
ModelConfig(path=TEXT_ENCODER_PATHS),
],
tokenizer_config=ModelConfig(path=TOKENIZER_PATH),
)
pipelines[gid] = p
gpu_locks[gid] = threading.Lock()
print(f" GPU {gid}: pipeline loaded.")
print(f"All pipelines ready on GPUs: {list(pipelines.keys())}")
def acquire_pipeline():
"""
Acquire an available (gpu_id, pipeline, lock).
Prefer GPUs that are not currently locked (i.e. idle);
if all are busy, wait for the GPU using the least memory to release its lock.
"""
# 1. Try non-blocking acquisition of an idle GPU
for gid in gpu_ids:
if gpu_locks[gid].acquire(blocking=False):
return gid, pipelines[gid], gpu_locks[gid]
# 2. All busy: pick the one with the least memory used and wait
gpus = get_available_gpus()
gpus_on = [g for g in gpus if g[0] in gpu_ids]
if gpus_on:
best_gid = min(gpus_on, key=lambda x: x[1])[0]
else:
best_gid = gpu_ids[0]
gpu_locks[best_gid].acquire(blocking=True)
return best_gid, pipelines[best_gid], gpu_locks[best_gid]
# ================= Inference function =================
@torch.no_grad()
def generate(
prompt: str,
negative_prompt: str,
num_inference_steps: int,
cfg_scale: float,
height: int,
width: int,
seed: int,
):
"""Generate an image, automatically dispatching to an idle GPU"""
if not prompt.strip():
return None
gid, pipe, lock = acquire_pipeline()
dev = f"cuda:{gid}"
try:
print(f"[Request] Using GPU {gid} | prompt: {prompt[:60]}...")
image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
cfg_scale=cfg_scale,
height=height,
width=width,
seed=seed,
rand_device=dev,
num_inference_steps=num_inference_steps,
)
print(f"[Request] GPU {gid} done.")
return image
except Exception as e:
print(f"[Request] GPU {gid} error: {e}")
raise e
finally:
lock.release()
# ================= Gradio UI =================
with gr.Blocks(title="L2P") as demo:
gr.Markdown("# End-to-End Pixel Diffusion Model")
with gr.Row():
# Left: parameters panel
with gr.Column(scale=1):
prompt = gr.Textbox(
label="Prompt",
value="an origami pig on fire in the middle of a dark room with a pentagram on the floor.",
lines=3,
)
negative_prompt = gr.Textbox(
label="Negative Prompt(Optional)",
value="",
lines=2,
)
num_inference_steps = gr.Slider(
minimum=1, maximum=100, step=1,
label="Inference Steps", value=30,
)
cfg_scale = gr.Slider(
minimum=0.1, maximum=10.0, step=0.1,
label="CFG Scale", value=2.0,
)
height = gr.Slider(
minimum=256, maximum=1024, step=16,
label="Image Height", value=1024,
)
width = gr.Slider(
minimum=256, maximum=1024, step=16,
label="Image Width", value=1024,
)
seed = gr.Slider(
minimum=0, maximum=1000000, step=1,
label="Seed", value=42,
)
btn = gr.Button("Generate", variant="primary")
# Right: output panel
with gr.Column(scale=1):
output_image = gr.Image(label="Generated Image", type="pil")
btn.click(
fn=generate,
inputs=[
prompt,
negative_prompt,
num_inference_steps,
cfg_scale,
height,
width,
seed,
],
outputs=[output_image],
concurrency_limit=8
)
# Example prompts
gr.Examples(
examples=[
["一位年轻汉族女性身穿红白相间、饰有金色花卉刺绣的汉服,背后远景是故宫。乌黑长发挽成精致发髻,点缀珍珠发簪与金饰。她面带温暖微笑望向镜头,双手举起纸卷,上面用毛笔写着\u201c你好\u201d。她身后是朱红色宫墙与金黄色琉璃瓦顶,传统红灯笼悬挂在石柱廊下,日光柔和。光滑的青石地面微微反光,增添空间层次。浅景深确保人物面部与文字清晰对焦。", "", 30, 2.0, 1024, 1024, 42],
["Young Chinese woman in red Hanfu, intricate embroidery. Impeccable makeup, red floral forehead pattern. Elaborate high bun, golden phoenix headdress, red flowers, beads. Holds round folding fan with lady, trees, bird. Neon lightning-bolt lamp (⚡️), bright yellow glow, above extended left palm. Soft-lit outdoor night background, silhouetted tiered pagoda (西安大雁塔), blurred colorful distant lights.", "", 30, 2.0, 1024, 1024, 42],
["an origami pig on fire in the middle of a dark room with a pentagram on the floor", "", 30, 2.0, 1024, 1024, 42],
],
inputs=[
prompt, negative_prompt, num_inference_steps,
cfg_scale, height, width, seed,
],
label="Prompt Examples",
)
demo.launch(server_name=SERVER_NAME, server_port=SERVER_PORT, share=True)