Skip to content

Commit e2c585f

Browse files
Fix to allow use of PerpNegGuider with cfg_function_post hooks (like PAG) (comfyanonymous#3618)
1 parent 04b3082 commit e2c585f

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ venv/
1515
!/web/extensions/logging.js.example
1616
!/web/extensions/core/
1717
/tests-ui/data/object_info.json
18-
/user/
18+
/user/
19+
comfyui*.log

comfy_extras/nodes_perpneg.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,38 @@ def set_cfg(self, cfg, neg_scale):
6161
self.neg_scale = neg_scale
6262

6363
def predict_noise(self, x, timestep, model_options={}, seed=None):
64+
# in CFGGuider.predict_noise, we call sampling_function(), which uses cfg_function() to compute pos & neg
65+
# but we'd rather do a single batch of sampling pos, neg, and empty, so we call calc_cond_batch([pos,neg,empty]) directly
66+
6467
positive_cond = self.conds.get("positive", None)
6568
negative_cond = self.conds.get("negative", None)
6669
empty_cond = self.conds.get("empty_negative_prompt", None)
6770

68-
out = comfy.samplers.calc_cond_batch(self.inner_model, [negative_cond, positive_cond, empty_cond], x, timestep, model_options)
69-
return perp_neg(x, out[1], out[0], out[2], self.neg_scale, self.cfg)
71+
(noise_pred_pos, noise_pred_neg, noise_pred_empty) = \
72+
comfy.samplers.calc_cond_batch(self.inner_model, [positive_cond, negative_cond, empty_cond], x, timestep, model_options)
73+
cfg_result = perp_neg(x, noise_pred_pos, noise_pred_neg, noise_pred_empty, self.neg_scale, self.cfg)
74+
75+
# normally this would be done in cfg_function, but we skipped
76+
# that for efficiency: we can compute the noise predictions in
77+
# a single call to calc_cond_batch() (rather than two)
78+
# so we replicate the hook here
79+
for fn in model_options.get("sampler_post_cfg_function", []):
80+
args = {
81+
"denoised": cfg_result,
82+
"cond": positive_cond,
83+
"uncond": negative_cond,
84+
"model": self.inner_model,
85+
"uncond_denoised": noise_pred_neg,
86+
"cond_denoised": noise_pred_pos,
87+
"sigma": timestep,
88+
"model_options": model_options,
89+
"input": x,
90+
# not in the original call in samplers.py:cfg_function, but made available for future hooks
91+
"empty_cond": empty_cond,
92+
"empty_cond_denoised": noise_pred_empty,}
93+
cfg_result = fn(args)
94+
95+
return cfg_result
7096

7197
class PerpNegGuider:
7298
@classmethod

0 commit comments

Comments
 (0)