AbstractPhil commited on
Commit
6d94ca3
·
verified ·
1 Parent(s): c54bfc9

Update pipeline/pipeline.py

Browse files
Files changed (1) hide show
  1. pipeline/pipeline.py +79 -36
pipeline/pipeline.py CHANGED
@@ -2,57 +2,100 @@
2
 
3
  import torch
4
  from diffusers import StableDiffusionPipeline
 
5
 
6
  class OmegaDiffusionPipeline(StableDiffusionPipeline):
7
- def __init__(self, vae, text_encoder, tokenizer, unet, scheduler, bridge,
8
- safety_checker=None, feature_extractor=None, **kwargs):
9
- super().__init__(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer,
10
- unet=unet, scheduler=scheduler,
11
- safety_checker=safety_checker,
12
- feature_extractor=feature_extractor, **kwargs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  self.register_modules(bridge=bridge)
14
 
15
- # Capture the original decode
16
  _orig_decode = self.vae.decode
17
- in_ch = self.unet.config.in_channels
18
- sc = self.vae.config.scaling_factor
19
 
20
- def _decode_with_bridge(z_scaled, *args, return_dict=False, generator=None, **decode_kwargs):
21
- # z_scaled is latents/scaling_factor
22
- # Reconstruct the raw latent
23
- z = z_scaled * sc
24
-
25
- # If it’s 4-ch, run the bridge → 16-ch
26
- if z.shape[1] == in_ch:
27
  z = self.bridge.dec(z)
 
 
 
 
 
 
 
 
 
 
28
 
29
- # Rescale for the VAE’s conv_in
30
- z_scaled2 = z / sc
31
-
32
- # Now call the real VAE.decode on exactly 16 channels
33
- return _orig_decode(z_scaled2, *args,
34
- return_dict=return_dict,
35
- generator=generator,
36
- **decode_kwargs)
37
-
38
- # Override the instance’s decode method
39
  self.vae.decode = _decode_with_bridge
40
 
41
  @property
42
  def components(self):
 
43
  return {
44
- "scheduler": self.scheduler,
45
- "tokenizer": self.tokenizer,
46
- "vae": self.vae,
47
- "unet": self.unet,
48
- "text_encoder": self.text_encoder,
49
- "bridge": self.bridge,
50
- "feature_extractor": self.feature_extractor,
51
- "safety_checker": self.safety_checker,
52
- "kwargs": {},
53
  }
54
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  @torch.no_grad()
56
  def __call__(self, *args, **kwargs):
57
- # Defer entirely to the parent, which will call our patched decode
 
58
  return super().__call__(*args, **kwargs)
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  import torch
4
  from diffusers import StableDiffusionPipeline
5
+ from diffusers.utils import BaseOutput
6
 
7
  class OmegaDiffusionPipeline(StableDiffusionPipeline):
8
+ def __init__(
9
+ self,
10
+ vae,
11
+ text_encoder,
12
+ tokenizer,
13
+ unet,
14
+ scheduler,
15
+ bridge,
16
+ safety_checker=None,
17
+ feature_extractor=None,
18
+ **kwargs,
19
+ ):
20
+ super().__init__(
21
+ vae=vae,
22
+ text_encoder=text_encoder,
23
+ tokenizer=tokenizer,
24
+ unet=unet,
25
+ scheduler=scheduler,
26
+ safety_checker=safety_checker,
27
+ feature_extractor=feature_extractor,
28
+ **kwargs,
29
+ )
30
+ # register your bridge so Diffusers knows about it
31
  self.register_modules(bridge=bridge)
32
 
33
+ # ─── Monkey-patch the VAE.decode to insert your bridge ───
34
  _orig_decode = self.vae.decode
35
+ in_ch = self.unet.config.in_channels
36
+ sc = self.vae.config.scaling_factor
37
 
38
+ def _decode_with_bridge(
39
+ z_scaled, *args, return_dict=False, generator=None, **decode_kwargs
40
+ ):
41
+ # z_scaled = latents / scaling_factor
42
+ z = z_scaled * sc # back to raw latent
43
+ if z.shape[1] == in_ch: # 4→16 only when needed
 
44
  z = self.bridge.dec(z)
45
+ z = z / sc # scale again
46
+ # call the real decode
47
+ out = _orig_decode(
48
+ z,
49
+ *args,
50
+ return_dict=return_dict,
51
+ generator=generator,
52
+ **decode_kwargs
53
+ )
54
+ return out
55
 
56
+ # override it in place
 
 
 
 
 
 
 
 
 
57
  self.vae.decode = _decode_with_bridge
58
 
59
  @property
60
  def components(self):
61
+ # ensure Diffusers sees exactly the modules you expect
62
  return {
63
+ "scheduler": self.scheduler,
64
+ "tokenizer": self.tokenizer,
65
+ "vae": self.vae,
66
+ "unet": self.unet,
67
+ "text_encoder": self.text_encoder,
68
+ "bridge": self.bridge,
69
+ "feature_extractor": self.feature_extractor,
70
+ "safety_checker": self.safety_checker,
71
+ "kwargs": {},
72
  }
73
 
74
+ @torch.no_grad()
75
+ def _decode_latents(self, latents):
76
+ """
77
+ The single hook that StableDiffusionPipeline.__call__
78
+ uses to turn final latents → images.
79
+ """
80
+ # calling self.vae.decode here actually invokes your _decode_with_bridge
81
+ decoded = self.vae.decode(latents, return_dict=False)
82
+ images = decoded[0] if isinstance(decoded, (tuple, list)) else decoded
83
+ # normalize to [0,1]
84
+ return (images.clamp(-1, 1) + 1) / 2
85
+
86
  @torch.no_grad()
87
  def __call__(self, *args, **kwargs):
88
+ # defer everything to the parent implementation, which
89
+ # will in turn call our patched _decode_latents
90
  return super().__call__(*args, **kwargs)
91
+
92
+ @torch.no_grad()
93
+ def decode_latents(self, latents, return_dict=True):
94
+ """
95
+ If you ever call pipe.decode_latents(...) manually,
96
+ this will route through the same bridge logic.
97
+ """
98
+ imgs = self._decode_latents(latents)
99
+ if return_dict:
100
+ return BaseOutput(images=imgs)
101
+ return imgs