1- from inspect import cleandoc
2-
31import torch
42from pydantic import BaseModel
53from typing_extensions import override
64
7- from comfy_api .latest import IO , ComfyExtension
5+ from comfy_api .latest import IO , ComfyExtension , Input
86from comfy_api_nodes .apis .bfl_api import (
97 BFLFluxExpandImageRequest ,
108 BFLFluxFillImageRequest ,
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
4038class 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
157152class 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
273265class 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
284273class 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
420406class 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
526509class 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+
635629class 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