Skip to content

Commit 240f25e

Browse files
committed
convert nodes_flux to V3 schema
1 parent cbee7d3 commit 240f25e

File tree

1 file changed

+116
-75
lines changed

1 file changed

+116
-75
lines changed

comfy_extras/nodes_flux.py

Lines changed: 116 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,80 @@
11
import node_helpers
22
import comfy.utils
3+
from typing_extensions import override
4+
from comfy_api.latest import ComfyExtension, io
5+
6+
7+
class CLIPTextEncodeFlux(io.ComfyNode):
8+
@classmethod
9+
def define_schema(cls):
10+
return io.Schema(
11+
node_id="CLIPTextEncodeFlux",
12+
category="advanced/conditioning/flux",
13+
inputs=[
14+
io.Clip.Input("clip"),
15+
io.String.Input("clip_l", multiline=True, dynamic_prompts=True),
16+
io.String.Input("t5xxl", multiline=True, dynamic_prompts=True),
17+
io.Float.Input("guidance", default=3.5, min=0.0, max=100.0, step=0.1),
18+
],
19+
outputs=[
20+
io.Conditioning.Output(),
21+
],
22+
)
323

4-
class CLIPTextEncodeFlux:
524
@classmethod
6-
def INPUT_TYPES(s):
7-
return {"required": {
8-
"clip": ("CLIP", ),
9-
"clip_l": ("STRING", {"multiline": True, "dynamicPrompts": True}),
10-
"t5xxl": ("STRING", {"multiline": True, "dynamicPrompts": True}),
11-
"guidance": ("FLOAT", {"default": 3.5, "min": 0.0, "max": 100.0, "step": 0.1}),
12-
}}
13-
RETURN_TYPES = ("CONDITIONING",)
14-
FUNCTION = "encode"
15-
16-
CATEGORY = "advanced/conditioning/flux"
17-
18-
def encode(self, clip, clip_l, t5xxl, guidance):
25+
def execute(cls, clip, clip_l, t5xxl, guidance) -> io.NodeOutput:
1926
tokens = clip.tokenize(clip_l)
2027
tokens["t5xxl"] = clip.tokenize(t5xxl)["t5xxl"]
2128

22-
return (clip.encode_from_tokens_scheduled(tokens, add_dict={"guidance": guidance}), )
29+
return io.NodeOutput(clip.encode_from_tokens_scheduled(tokens, add_dict={"guidance": guidance}))
2330

24-
class FluxGuidance:
25-
@classmethod
26-
def INPUT_TYPES(s):
27-
return {"required": {
28-
"conditioning": ("CONDITIONING", ),
29-
"guidance": ("FLOAT", {"default": 3.5, "min": 0.0, "max": 100.0, "step": 0.1}),
30-
}}
31+
encode = execute # TODO: remove
3132

32-
RETURN_TYPES = ("CONDITIONING",)
33-
FUNCTION = "append"
3433

35-
CATEGORY = "advanced/conditioning/flux"
34+
class FluxGuidance(io.ComfyNode):
35+
@classmethod
36+
def define_schema(cls):
37+
return io.Schema(
38+
node_id="FluxGuidance",
39+
category="advanced/conditioning/flux",
40+
inputs=[
41+
io.Conditioning.Input("conditioning"),
42+
io.Float.Input("guidance", default=3.5, min=0.0, max=100.0, step=0.1),
43+
],
44+
outputs=[
45+
io.Conditioning.Output(),
46+
],
47+
)
3648

37-
def append(self, conditioning, guidance):
49+
@classmethod
50+
def execute(cls, conditioning, guidance) -> io.NodeOutput:
3851
c = node_helpers.conditioning_set_values(conditioning, {"guidance": guidance})
39-
return (c, )
52+
return io.NodeOutput(c)
4053

54+
append = execute # TODO: remove
4155

42-
class FluxDisableGuidance:
43-
@classmethod
44-
def INPUT_TYPES(s):
45-
return {"required": {
46-
"conditioning": ("CONDITIONING", ),
47-
}}
48-
49-
RETURN_TYPES = ("CONDITIONING",)
50-
FUNCTION = "append"
5156

52-
CATEGORY = "advanced/conditioning/flux"
53-
DESCRIPTION = "This node completely disables the guidance embed on Flux and Flux like models"
57+
class FluxDisableGuidance(io.ComfyNode):
58+
@classmethod
59+
def define_schema(cls):
60+
return io.Schema(
61+
node_id="FluxDisableGuidance",
62+
category="advanced/conditioning/flux",
63+
description="This node completely disables the guidance embed on Flux and Flux like models",
64+
inputs=[
65+
io.Conditioning.Input("conditioning"),
66+
],
67+
outputs=[
68+
io.Conditioning.Output(),
69+
],
70+
)
5471

55-
def append(self, conditioning):
72+
@classmethod
73+
def execute(cls, conditioning) -> io.NodeOutput:
5674
c = node_helpers.conditioning_set_values(conditioning, {"guidance": None})
57-
return (c, )
75+
return io.NodeOutput(c)
76+
77+
append = execute # TODO: remove
5878

5979

6080
PREFERED_KONTEXT_RESOLUTIONS = [
@@ -78,52 +98,73 @@ def append(self, conditioning):
7898
]
7999

80100

81-
class FluxKontextImageScale:
101+
class FluxKontextImageScale(io.ComfyNode):
82102
@classmethod
83-
def INPUT_TYPES(s):
84-
return {"required": {"image": ("IMAGE", ),
85-
},
86-
}
87-
88-
RETURN_TYPES = ("IMAGE",)
89-
FUNCTION = "scale"
103+
def define_schema(cls):
104+
return io.Schema(
105+
node_id="FluxKontextImageScale",
106+
category="advanced/conditioning/flux",
107+
description="This node resizes the image to one that is more optimal for flux kontext.",
108+
inputs=[
109+
io.Image.Input("image"),
110+
],
111+
outputs=[
112+
io.Image.Output(),
113+
],
114+
)
90115

91-
CATEGORY = "advanced/conditioning/flux"
92-
DESCRIPTION = "This node resizes the image to one that is more optimal for flux kontext."
93-
94-
def scale(self, image):
116+
@classmethod
117+
def execute(cls, image) -> io.NodeOutput:
95118
width = image.shape[2]
96119
height = image.shape[1]
97120
aspect_ratio = width / height
98121
_, width, height = min((abs(aspect_ratio - w / h), w, h) for w, h in PREFERED_KONTEXT_RESOLUTIONS)
99122
image = comfy.utils.common_upscale(image.movedim(-1, 1), width, height, "lanczos", "center").movedim(1, -1)
100-
return (image, )
101-
123+
return io.NodeOutput(image)
102124

103-
class FluxKontextMultiReferenceLatentMethod:
104-
@classmethod
105-
def INPUT_TYPES(s):
106-
return {"required": {
107-
"conditioning": ("CONDITIONING", ),
108-
"reference_latents_method": (("offset", "index", "uxo/uno"), ),
109-
}}
125+
scale = execute # TODO: remove
110126

111-
RETURN_TYPES = ("CONDITIONING",)
112-
FUNCTION = "append"
113-
EXPERIMENTAL = True
114127

115-
CATEGORY = "advanced/conditioning/flux"
128+
class FluxKontextMultiReferenceLatentMethod(io.ComfyNode):
129+
@classmethod
130+
def define_schema(cls):
131+
return io.Schema(
132+
node_id="FluxKontextMultiReferenceLatentMethod",
133+
category="advanced/conditioning/flux",
134+
inputs=[
135+
io.Conditioning.Input("conditioning"),
136+
io.Combo.Input(
137+
"reference_latents_method",
138+
options=["offset", "index", "uxo/uno"],
139+
),
140+
],
141+
outputs=[
142+
io.Conditioning.Output(),
143+
],
144+
is_experimental=True,
145+
)
116146

117-
def append(self, conditioning, reference_latents_method):
147+
@classmethod
148+
def execute(cls, conditioning, reference_latents_method) -> io.NodeOutput:
118149
if "uxo" in reference_latents_method or "uso" in reference_latents_method:
119150
reference_latents_method = "uxo"
120151
c = node_helpers.conditioning_set_values(conditioning, {"reference_latents_method": reference_latents_method})
121-
return (c, )
122-
123-
NODE_CLASS_MAPPINGS = {
124-
"CLIPTextEncodeFlux": CLIPTextEncodeFlux,
125-
"FluxGuidance": FluxGuidance,
126-
"FluxDisableGuidance": FluxDisableGuidance,
127-
"FluxKontextImageScale": FluxKontextImageScale,
128-
"FluxKontextMultiReferenceLatentMethod": FluxKontextMultiReferenceLatentMethod,
129-
}
152+
return io.NodeOutput(c)
153+
154+
append = execute # TODO: remove
155+
156+
157+
class FluxExtension(ComfyExtension):
158+
@override
159+
async def get_node_list(self) -> list[type[io.ComfyNode]]:
160+
return [
161+
CLIPTextEncodeFlux,
162+
FluxGuidance,
163+
FluxDisableGuidance,
164+
FluxKontextImageScale,
165+
FluxKontextMultiReferenceLatentMethod,
166+
]
167+
168+
169+
async def comfy_entrypoint() -> FluxExtension:
170+
return FluxExtension()

0 commit comments

Comments
 (0)