multimodalart's picture
multimodalart HF Staff
Upload folder using huggingface_hub
bf77163 verified
Raw
History Blame Contribute Delete
6.54 kB
import os
# Neutralize torch.compile decorators inside mmdit.py (not supported on ZeroGPU
# forked workers) and reduce allocator fragmentation for the 13B DiT.
os.environ.setdefault("TORCHDYNAMO_DISABLE", "1")
os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
import random
import spaces # noqa: E402 MUST come before torch / CUDA-touching imports
import torch # noqa: E402
import gradio as gr # noqa: E402
from huggingface_hub import hf_hub_download # noqa: E402
from pipeline import DepthLoRAPipeline # noqa: E402
MAX_SEED = 2**31 - 1
# --------------------------------------------------------------------- loading
# Turbo base (8-step, no CFG) — the author's recommended fast configuration.
# Krea-2 base checkpoint (~26GB) + depth-control LoRA + Qwen3-VL-4B text encoder
# + Qwen-Image VAE + Depth-Anything-V2-Large. Loaded once at module scope so
# ZeroGPU packs the weights and streams them to VRAM on the first GPU call.
print("Resolving Krea-2-Turbo base checkpoint...")
BASE_CKPT = os.path.realpath(hf_hub_download("krea/Krea-2-Turbo", "turbo.safetensors"))
LORA_CKPT = os.path.realpath(
hf_hub_download("Patil/Krea-2-depth-controlnet", "depth-control-lora.safetensors")
)
print("Building DepthLoRAPipeline (13B DiT + Qwen3-VL-4B + VAE + DepthAnything)...")
pipe = DepthLoRAPipeline(BASE_CKPT, LORA_CKPT, device="cuda")
print("Pipeline ready.")
# --------------------------------------------------------------------- inference
@spaces.GPU(duration=120)
def generate(
image,
prompt: str = "",
steps: int = 8,
lora_scale: float = 1.0,
seed: int = 0,
randomize_seed: bool = True,
progress=gr.Progress(track_tqdm=True),
):
"""Generate a new image that keeps the 3D structure of an input image.
Extracts a depth map from the input image with Depth-Anything-V2 and
generates a new image following the same depth/composition but with the
content and style described by the prompt (Krea-2-Turbo, 8-step).
Args:
image: The input image whose depth/structure is preserved.
prompt: What to generate. Leave empty for depth-only generation.
steps: Number of sampling steps (8 recommended for Turbo).
lora_scale: Control strength. <1.0 relaxes structure adherence.
seed: RNG seed for reproducibility.
randomize_seed: If True, pick a random seed each run.
Returns:
A tuple of (generated image, extracted depth map, used seed).
"""
if image is None:
raise gr.Error("Please provide an input image.")
if randomize_seed:
seed = random.randint(0, MAX_SEED)
seed = int(seed)
# Turbo config: cfg=0.0, mu=1.15. lora_scale is applied to the loaded LoRA
# layers in place (they were built with scale=1.0), so scale the effective
# weight by mutating each LoRALinear's scale before the run.
from pipeline import LoRALinear
for module in pipe.model.modules():
if isinstance(module, LoRALinear):
module.scale = (64 / 64) * float(lora_scale)
out, depth = pipe(
image,
prompt=prompt or "",
steps=int(steps),
cfg=0.0,
mu=1.15,
seed=seed,
)
return out, depth, seed
# --------------------------------------------------------------------- UI
CSS = """
#col-container { max-width: 1200px; margin: 0 auto; }
.dark .gradio-container { color: var(--body-text-color); }
"""
with gr.Blocks(theme=gr.themes.Citrus(), css=CSS) as demo:
with gr.Column(elem_id="col-container"):
gr.Markdown(
"""
# Krea-2 Depth ControlNet-LoRA
Give it any image and a prompt — it extracts the depth map with
**Depth-Anything-V2** and generates a new image with the **same 3D
structure and composition**, but whatever content and style you ask
for. Powered by [Krea-2-Turbo](https://huggingface.co/krea/Krea-2-Turbo)
(8-step) + the
[depth-control LoRA](https://huggingface.co/Patil/Krea-2-depth-controlnet).
*Best with photos / renders that have real perspective. Flat 2D
illustrations give weak control. Empty prompt = depth-only generation.*
"""
)
with gr.Row():
with gr.Column():
image = gr.Image(label="Input image (depth source)", type="pil")
prompt = gr.Textbox(
label="Prompt",
placeholder="a futuristic spaceship interior, cinematic lighting",
lines=2,
)
run = gr.Button("Generate", variant="primary")
with gr.Accordion("Advanced settings", open=False):
steps = gr.Slider(
4, 16, value=8, step=1, label="Sampling steps"
)
lora_scale = gr.Slider(
0.3,
1.4,
value=1.0,
step=0.05,
label="Control strength (LoRA scale)",
)
randomize_seed = gr.Checkbox(
label="Randomize seed", value=True
)
seed = gr.Slider(
0, MAX_SEED, value=0, step=1, label="Seed"
)
with gr.Column():
output = gr.Image(label="Generated image")
depth_out = gr.Image(label="Extracted depth map")
gr.Examples(
examples=[
["examples/dog.jpg", "a majestic lion, golden hour, photorealistic"],
[
"examples/landscape.jpg",
"an alien planet landscape, purple sky, sci-fi",
],
[
"examples/man_beach.jpg",
"an astronaut on the moon, cinematic lighting",
],
[
"examples/tent.jpg",
"a cozy cabin in a snowy forest at dusk",
],
],
inputs=[image, prompt],
outputs=[output, depth_out, seed],
fn=generate,
cache_examples=True,
cache_mode="lazy",
)
run.click(
fn=generate,
inputs=[image, prompt, steps, lora_scale, seed, randomize_seed],
outputs=[output, depth_out, seed],
api_name="generate",
)
if __name__ == "__main__":
demo.launch(mcp_server=True)