Professional Noob commited on
Commit
afa509d
·
verified ·
1 Parent(s): 104cf13

Update qwenimage/pipeline_qwenimage_edit_plus.py

Browse files
qwenimage/pipeline_qwenimage_edit_plus.py CHANGED
@@ -166,13 +166,46 @@ def calculate_dimensions(target_area: int, ratio: float, multiple: int = 32):
166
  # Optional: decoder VAE (Wan2x)
167
  _ALT_VAE_WAN2X = None
168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
  def _get_wan2x_vae(device: torch.device, dtype: torch.dtype):
171
  """
172
  Decoder-only finetune that outputs 2x resolution via pixel-shuffle.
173
  Lazy-loaded so it doesn't impact startup unless used.
174
  """
175
- global _ALT_VAE_WAN2X
176
  if _ALT_VAE_WAN2X is None:
177
  from diffusers import AutoencoderKLWan
178
 
@@ -182,7 +215,15 @@ def _get_wan2x_vae(device: torch.device, dtype: torch.dtype):
182
  torch_dtype=dtype,
183
  )
184
  _ALT_VAE_WAN2X.eval()
 
 
 
 
185
  _ALT_VAE_WAN2X = _ALT_VAE_WAN2X.to(device=device, dtype=dtype)
 
 
 
 
186
  return _ALT_VAE_WAN2X
187
 
188
 
@@ -220,6 +261,9 @@ class QwenImageEditPlusPipeline(DiffusionPipeline, QwenImageLoraLoaderMixin):
220
  self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor * 2)
221
  self.tokenizer_max_length = 1024
222
 
 
 
 
223
  self.prompt_template_encode = (
224
  "<|im_start|>system\n"
225
  "Describe the key features of the input image (color, shape, size, texture, objects, background), "
@@ -230,6 +274,32 @@ class QwenImageEditPlusPipeline(DiffusionPipeline, QwenImageLoraLoaderMixin):
230
  self.prompt_template_encode_start_idx = 64
231
  self.default_sample_size = 128
232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  # Copied from diffusers.pipelines.qwenimage.pipeline_qwenimage.QwenImagePipeline._extract_masked_hidden
234
  def _extract_masked_hidden(self, hidden_states: torch.Tensor, mask: torch.Tensor):
235
  bool_mask = mask.bool()
 
166
  # Optional: decoder VAE (Wan2x)
167
  _ALT_VAE_WAN2X = None
168
 
169
+ # Track desired tiling state for the optional decoder VAE, so it stays consistent across lazy loads.
170
+ _ALT_VAE_WAN2X_TILING_ENABLED = False
171
+
172
+
173
+ def _set_vae_tiling(model: Any, enabled: bool) -> bool:
174
+ """
175
+ Best-effort tiling toggle for a VAE-like module.
176
+ Returns True if a tiling method existed and was called, False otherwise.
177
+ """
178
+ if model is None:
179
+ return False
180
+ try:
181
+ if enabled:
182
+ if hasattr(model, "enable_tiling"):
183
+ model.enable_tiling()
184
+ return True
185
+ if hasattr(model, "enable_vae_tiling"):
186
+ model.enable_vae_tiling()
187
+ return True
188
+ else:
189
+ if hasattr(model, "disable_tiling"):
190
+ model.disable_tiling()
191
+ return True
192
+ if hasattr(model, "disable_vae_tiling"):
193
+ model.disable_vae_tiling()
194
+ return True
195
+ except Exception as e:
196
+ # Don't hard-fail inference if tiling toggle fails for an alt decoder.
197
+ logger.warning(f"VAE tiling toggle failed on {type(model)}: {e}")
198
+ return False
199
+ return False
200
+
201
+
202
 
203
  def _get_wan2x_vae(device: torch.device, dtype: torch.dtype):
204
  """
205
  Decoder-only finetune that outputs 2x resolution via pixel-shuffle.
206
  Lazy-loaded so it doesn't impact startup unless used.
207
  """
208
+ global _ALT_VAE_WAN2X, _ALT_VAE_WAN2X_TILING_ENABLED
209
  if _ALT_VAE_WAN2X is None:
210
  from diffusers import AutoencoderKLWan
211
 
 
215
  torch_dtype=dtype,
216
  )
217
  _ALT_VAE_WAN2X.eval()
218
+
219
+ # Apply last requested tiling immediately on first load (if supported).
220
+ _set_vae_tiling(_ALT_VAE_WAN2X, _ALT_VAE_WAN2X_TILING_ENABLED)
221
+
222
  _ALT_VAE_WAN2X = _ALT_VAE_WAN2X.to(device=device, dtype=dtype)
223
+
224
+ # Re-apply after moving to device, just in case.
225
+ _set_vae_tiling(_ALT_VAE_WAN2X, _ALT_VAE_WAN2X_TILING_ENABLED)
226
+
227
  return _ALT_VAE_WAN2X
228
 
229
 
 
261
  self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor * 2)
262
  self.tokenizer_max_length = 1024
263
 
264
+
265
+ # Track tiling state (applies to both primary VAE and optional decoder VAE)
266
+ self._vae_tiling_enabled = False
267
  self.prompt_template_encode = (
268
  "<|im_start|>system\n"
269
  "Describe the key features of the input image (color, shape, size, texture, objects, background), "
 
274
  self.prompt_template_encode_start_idx = 64
275
  self.default_sample_size = 128
276
 
277
+
278
+ # ------------------------------------------------------------
279
+ # VAE tiling control (applies to both primary VAE and optional decoder VAE)
280
+ # ------------------------------------------------------------
281
+ # Expose a stable API so app.py can call pipe.enable_vae_tiling()/disable_vae_tiling()
282
+ # regardless of which decoder VAE is selected at runtime.
283
+
284
+ def set_vae_tiling(self, enabled: bool) -> None:
285
+ global _ALT_VAE_WAN2X_TILING_ENABLED, _ALT_VAE_WAN2X
286
+
287
+ enabled = bool(enabled)
288
+ self._vae_tiling_enabled = enabled
289
+
290
+ # 1) Primary VAE (Qwen)
291
+ _set_vae_tiling(getattr(self, "vae", None), enabled)
292
+
293
+ # 2) Optional decoder VAE (Wan2x): store desired global state; apply now if already loaded.
294
+ _ALT_VAE_WAN2X_TILING_ENABLED = enabled
295
+ if _ALT_VAE_WAN2X is not None:
296
+ _set_vae_tiling(_ALT_VAE_WAN2X, enabled)
297
+
298
+ def enable_vae_tiling(self) -> None:
299
+ self.set_vae_tiling(True)
300
+
301
+ def disable_vae_tiling(self) -> None:
302
+ self.set_vae_tiling(False)
303
  # Copied from diffusers.pipelines.qwenimage.pipeline_qwenimage.QwenImagePipeline._extract_masked_hidden
304
  def _extract_masked_hidden(self, hidden_states: torch.Tensor, mask: torch.Tensor):
305
  bool_mask = mask.bool()