ArtelTaleb commited on
Commit
585703b
Β·
verified Β·
1 Parent(s): 84c6c58

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +34 -32
app.py CHANGED
@@ -2,7 +2,6 @@ import random
2
  import torch
3
  import gradio as gr
4
  import spaces
5
- from diffusers import FlowMatchEulerDiscreteScheduler, QwenImageEditPlusPipeline
6
  from PIL import Image
7
 
8
  # ── Constantes poses ──────────────────────────────────────────────────────────
@@ -21,29 +20,6 @@ ELEVATION_NAMES = {
21
  }
22
  DISTANCE_NAMES = {0.6: "close-up", 1.0: "medium shot", 1.8: "wide shot"}
23
 
24
- # ── Chargement modΓ¨le ─────────────────────────────────────────────────────────
25
-
26
- dtype = torch.bfloat16
27
- device = "cuda" if torch.cuda.is_available() else "cpu"
28
-
29
- pipe = QwenImageEditPlusPipeline.from_pretrained(
30
- "Qwen/Qwen-Image-Edit-2511",
31
- torch_dtype=dtype,
32
- )
33
- pipe.to(device)
34
-
35
- pipe.load_lora_weights(
36
- "lightx2v/Qwen-Image-Edit-2511-Lightning",
37
- weight_name="Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors",
38
- adapter_name="lightning",
39
- )
40
- pipe.load_lora_weights(
41
- "fal/Qwen-Image-Edit-2511-Multiple-Angles-LoRA",
42
- weight_name="qwen-image-edit-2511-multiple-angles-lora.safetensors",
43
- adapter_name="angles",
44
- )
45
- pipe.set_adapters(["lightning", "angles"], adapter_weights=[1.0, 1.0])
46
-
47
  # ── Helpers ───────────────────────────────────────────────────────────────────
48
 
49
  def snap_to_nearest(value, options):
@@ -56,9 +32,39 @@ def build_camera_prompt(azimuth: float, elevation: float, distance: float) -> st
56
  di = snap_to_nearest(distance, DISTANCES)
57
  return f"<sks> {AZIMUTH_NAMES[az]} {ELEVATION_NAMES[el]} {DISTANCE_NAMES[di]}"
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  # ── InfΓ©rence ZeroGPU ─────────────────────────────────────────────────────────
60
 
61
- @spaces.GPU
62
  def infer(
63
  image: Image.Image,
64
  azimuth: float,
@@ -70,10 +76,11 @@ def infer(
70
  if randomize_seed:
71
  seed = random.randint(0, 2**31 - 1)
72
 
 
73
  prompt = build_camera_prompt(azimuth, elevation, distance)
74
- generator = torch.Generator(device=device).manual_seed(seed)
75
 
76
- result = pipe(
77
  image=[image],
78
  prompt=prompt,
79
  height=1024,
@@ -88,10 +95,6 @@ def infer(
88
 
89
  # ── UI Gradio ─────────────────────────────────────────────────────────────────
90
 
91
- def update_prompt_preview(azimuth, elevation, distance):
92
- return build_camera_prompt(azimuth, elevation, distance)
93
-
94
-
95
  with gr.Blocks(title="Angle Studio", theme=gr.themes.Base()) as demo:
96
  gr.Markdown(
97
  """
@@ -142,7 +145,6 @@ with gr.Blocks(title="Angle Studio", theme=gr.themes.Base()) as demo:
142
 
143
  session_images = gr.State([])
144
 
145
- # Mise Γ  jour du prompt en temps rΓ©el
146
  for slider in [azimuth_slider, elevation_slider, distance_slider]:
147
  slider.change(
148
  fn=update_prompt_preview,
 
2
  import torch
3
  import gradio as gr
4
  import spaces
 
5
  from PIL import Image
6
 
7
  # ── Constantes poses ──────────────────────────────────────────────────────────
 
20
  }
21
  DISTANCE_NAMES = {0.6: "close-up", 1.0: "medium shot", 1.8: "wide shot"}
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  # ── Helpers ───────────────────────────────────────────────────────────────────
24
 
25
  def snap_to_nearest(value, options):
 
32
  di = snap_to_nearest(distance, DISTANCES)
33
  return f"<sks> {AZIMUTH_NAMES[az]} {ELEVATION_NAMES[el]} {DISTANCE_NAMES[di]}"
34
 
35
+
36
+ def update_prompt_preview(azimuth, elevation, distance):
37
+ return build_camera_prompt(azimuth, elevation, distance)
38
+
39
+ # ── Chargement modΓ¨le (lazy, sur GPU) ────────────────────────────────────────
40
+
41
+ pipe = None
42
+
43
+ def get_pipe():
44
+ global pipe
45
+ if pipe is not None:
46
+ return pipe
47
+ from diffusers import QwenImageEditPlusPipeline
48
+ pipe = QwenImageEditPlusPipeline.from_pretrained(
49
+ "Qwen/Qwen-Image-Edit-2511",
50
+ torch_dtype=torch.bfloat16,
51
+ ).to("cuda")
52
+ pipe.load_lora_weights(
53
+ "lightx2v/Qwen-Image-Edit-2511-Lightning",
54
+ weight_name="Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors",
55
+ adapter_name="lightning",
56
+ )
57
+ pipe.load_lora_weights(
58
+ "fal/Qwen-Image-Edit-2511-Multiple-Angles-LoRA",
59
+ weight_name="qwen-image-edit-2511-multiple-angles-lora.safetensors",
60
+ adapter_name="angles",
61
+ )
62
+ pipe.set_adapters(["lightning", "angles"], adapter_weights=[1.0, 1.0])
63
+ return pipe
64
+
65
  # ── InfΓ©rence ZeroGPU ─────────────────────────────────────────────────────────
66
 
67
+ @spaces.GPU(duration=120)
68
  def infer(
69
  image: Image.Image,
70
  azimuth: float,
 
76
  if randomize_seed:
77
  seed = random.randint(0, 2**31 - 1)
78
 
79
+ p = get_pipe()
80
  prompt = build_camera_prompt(azimuth, elevation, distance)
81
+ generator = torch.Generator(device="cuda").manual_seed(seed)
82
 
83
+ result = p(
84
  image=[image],
85
  prompt=prompt,
86
  height=1024,
 
95
 
96
  # ── UI Gradio ─────────────────────────────────────────────────────────────────
97
 
 
 
 
 
98
  with gr.Blocks(title="Angle Studio", theme=gr.themes.Base()) as demo:
99
  gr.Markdown(
100
  """
 
145
 
146
  session_images = gr.State([])
147
 
 
148
  for slider in [azimuth_slider, elevation_slider, distance_slider]:
149
  slider.change(
150
  fn=update_prompt_preview,