Skip to content

Commit 0689c92

Browse files
committed
add Flux2MaxImage API Node
1 parent 894802b commit 0689c92

File tree

1 file changed

+29
-34
lines changed

1 file changed

+29
-34
lines changed

comfy_api_nodes/nodes_bfl.py

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
from inspect import cleandoc
2-
31
import torch
42
from pydantic import BaseModel
53
from typing_extensions import override
64

7-
from comfy_api.latest import IO, ComfyExtension
5+
from comfy_api.latest import IO, ComfyExtension, Input
86
from comfy_api_nodes.apis.bfl_api import (
97
BFLFluxExpandImageRequest,
108
BFLFluxFillImageRequest,
@@ -28,7 +26,7 @@
2826
)
2927

3028

31-
def convert_mask_to_image(mask: torch.Tensor):
29+
def convert_mask_to_image(mask: Input.Image):
3230
"""
3331
Make mask have the expected amount of dims (4) and channels (3) to be recognized as an image.
3432
"""
@@ -38,17 +36,14 @@ def convert_mask_to_image(mask: torch.Tensor):
3836

3937

4038
class FluxProUltraImageNode(IO.ComfyNode):
41-
"""
42-
Generates images using Flux Pro 1.1 Ultra via api based on prompt and resolution.
43-
"""
4439

4540
@classmethod
4641
def define_schema(cls) -> IO.Schema:
4742
return IO.Schema(
4843
node_id="FluxProUltraImageNode",
4944
display_name="Flux 1.1 [pro] Ultra Image",
5045
category="api node/image/BFL",
51-
description=cleandoc(cls.__doc__ or ""),
46+
description="Generates images using Flux Pro 1.1 Ultra via api based on prompt and resolution.",
5247
inputs=[
5348
IO.String.Input(
5449
"prompt",
@@ -117,7 +112,7 @@ async def execute(
117112
prompt_upsampling: bool = False,
118113
raw: bool = False,
119114
seed: int = 0,
120-
image_prompt: torch.Tensor | None = None,
115+
image_prompt: Input.Image | None = None,
121116
image_prompt_strength: float = 0.1,
122117
) -> IO.NodeOutput:
123118
if image_prompt is None:
@@ -155,17 +150,14 @@ async def execute(
155150

156151

157152
class FluxKontextProImageNode(IO.ComfyNode):
158-
"""
159-
Edits images using Flux.1 Kontext [pro] via api based on prompt and aspect ratio.
160-
"""
161153

162154
@classmethod
163155
def define_schema(cls) -> IO.Schema:
164156
return IO.Schema(
165157
node_id=cls.NODE_ID,
166158
display_name=cls.DISPLAY_NAME,
167159
category="api node/image/BFL",
168-
description=cleandoc(cls.__doc__ or ""),
160+
description="Edits images using Flux.1 Kontext [pro] via api based on prompt and aspect ratio.",
169161
inputs=[
170162
IO.String.Input(
171163
"prompt",
@@ -231,7 +223,7 @@ async def execute(
231223
aspect_ratio: str,
232224
guidance: float,
233225
steps: int,
234-
input_image: torch.Tensor | None = None,
226+
input_image: Input.Image | None = None,
235227
seed=0,
236228
prompt_upsampling=False,
237229
) -> IO.NodeOutput:
@@ -271,28 +263,22 @@ async def execute(
271263

272264

273265
class FluxKontextMaxImageNode(FluxKontextProImageNode):
274-
"""
275-
Edits images using Flux.1 Kontext [max] via api based on prompt and aspect ratio.
276-
"""
277266

278-
DESCRIPTION = cleandoc(__doc__ or "")
267+
DESCRIPTION = "Edits images using Flux.1 Kontext [max] via api based on prompt and aspect ratio."
279268
BFL_PATH = "/proxy/bfl/flux-kontext-max/generate"
280269
NODE_ID = "FluxKontextMaxImageNode"
281270
DISPLAY_NAME = "Flux.1 Kontext [max] Image"
282271

283272

284273
class FluxProExpandNode(IO.ComfyNode):
285-
"""
286-
Outpaints image based on prompt.
287-
"""
288274

289275
@classmethod
290276
def define_schema(cls) -> IO.Schema:
291277
return IO.Schema(
292278
node_id="FluxProExpandNode",
293279
display_name="Flux.1 Expand Image",
294280
category="api node/image/BFL",
295-
description=cleandoc(cls.__doc__ or ""),
281+
description="Outpaints image based on prompt.",
296282
inputs=[
297283
IO.Image.Input("image"),
298284
IO.String.Input(
@@ -371,7 +357,7 @@ def define_schema(cls) -> IO.Schema:
371357
@classmethod
372358
async def execute(
373359
cls,
374-
image: torch.Tensor,
360+
image: Input.Image,
375361
prompt: str,
376362
prompt_upsampling: bool,
377363
top: int,
@@ -418,17 +404,14 @@ async def execute(
418404

419405

420406
class FluxProFillNode(IO.ComfyNode):
421-
"""
422-
Inpaints image based on mask and prompt.
423-
"""
424407

425408
@classmethod
426409
def define_schema(cls) -> IO.Schema:
427410
return IO.Schema(
428411
node_id="FluxProFillNode",
429412
display_name="Flux.1 Fill Image",
430413
category="api node/image/BFL",
431-
description=cleandoc(cls.__doc__ or ""),
414+
description="Inpaints image based on mask and prompt.",
432415
inputs=[
433416
IO.Image.Input("image"),
434417
IO.Mask.Input("mask"),
@@ -480,8 +463,8 @@ def define_schema(cls) -> IO.Schema:
480463
@classmethod
481464
async def execute(
482465
cls,
483-
image: torch.Tensor,
484-
mask: torch.Tensor,
466+
image: Input.Image,
467+
mask: Input.Image,
485468
prompt: str,
486469
prompt_upsampling: bool,
487470
steps: int,
@@ -525,11 +508,15 @@ async def execute(
525508

526509
class Flux2ProImageNode(IO.ComfyNode):
527510

511+
NODE_ID = "Flux2ProImageNode"
512+
DISPLAY_NAME = "Flux.2 [pro] Image"
513+
API_ENDPOINT = "/proxy/bfl/flux-2-pro/generate"
514+
528515
@classmethod
529516
def define_schema(cls) -> IO.Schema:
530517
return IO.Schema(
531-
node_id="Flux2ProImageNode",
532-
display_name="Flux.2 [pro] Image",
518+
node_id=cls.NODE_ID,
519+
display_name=cls.DISPLAY_NAME,
533520
category="api node/image/BFL",
534521
description="Generates images synchronously based on prompt and resolution.",
535522
inputs=[
@@ -563,7 +550,7 @@ def define_schema(cls) -> IO.Schema:
563550
),
564551
IO.Boolean.Input(
565552
"prompt_upsampling",
566-
default=False,
553+
default=True,
567554
tooltip="Whether to perform upsampling on the prompt. "
568555
"If active, automatically modifies the prompt for more creative generation, "
569556
"but results are nondeterministic (same seed will not produce exactly the same result).",
@@ -587,7 +574,7 @@ async def execute(
587574
height: int,
588575
seed: int,
589576
prompt_upsampling: bool,
590-
images: torch.Tensor | None = None,
577+
images: Input.Image | None = None,
591578
) -> IO.NodeOutput:
592579
reference_images = {}
593580
if images is not None:
@@ -598,7 +585,7 @@ async def execute(
598585
reference_images[key_name] = tensor_to_base64_string(images[image_index], total_pixels=2048 * 2048)
599586
initial_response = await sync_op(
600587
cls,
601-
ApiEndpoint(path="/proxy/bfl/flux-2-pro/generate", method="POST"),
588+
ApiEndpoint(path=cls.API_ENDPOINT, method="POST"),
602589
response_model=BFLFluxProGenerateResponse,
603590
data=Flux2ProGenerateRequest(
604591
prompt=prompt,
@@ -632,6 +619,13 @@ def price_extractor(_r: BaseModel) -> float | None:
632619
return IO.NodeOutput(await download_url_to_image_tensor(response.result["sample"]))
633620

634621

622+
class Flux2MaxImageNode(Flux2ProImageNode):
623+
624+
NODE_ID = "Flux2MaxImageNode"
625+
DISPLAY_NAME = "Flux.2 [max] Image"
626+
API_ENDPOINT = "/proxy/bfl/flux-2-max/generate"
627+
628+
635629
class BFLExtension(ComfyExtension):
636630
@override
637631
async def get_node_list(self) -> list[type[IO.ComfyNode]]:
@@ -642,6 +636,7 @@ async def get_node_list(self) -> list[type[IO.ComfyNode]]:
642636
FluxProExpandNode,
643637
FluxProFillNode,
644638
Flux2ProImageNode,
639+
Flux2MaxImageNode,
645640
]
646641

647642

0 commit comments

Comments
 (0)