From b37fc246acc9fddd5d4fcc1e81ef821e5bc25974 Mon Sep 17 00:00:00 2001 From: Alexander Tujicov Date: Thu, 9 Jul 2026 21:18:28 +0300 Subject: [PATCH] Add Flux 2 Klein 9B edit model --- README.md | 12 +++++++--- nano_seed.py | 62 +++++++++++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index e3e3ab3..790a3fc 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ A Custom Node that integrates [Fal.ai's](https://fal.ai) powerful image editing | **Seedream 4.5** | `seedream_4.5` | ByteDance's model. Optimized for high-res editing. | | **Qwen Edit Plus** | `qwen_edit_plus` | Powerful instruction-based editing with guidance control. | | **Flux 2 (Standard, Pro, Flex)** | `flux_2_edit` | (BFL) High-fidelity editing capabilities. | +| **Flux 2 Klein 9B Edit** | `flux_2_klein_9b_edit` | Fast FLUX.2 Klein 9B image editing model. | ## 📦 Installation @@ -58,6 +59,7 @@ You must have a **Fal.ai API Key** to use this node. * *Note:* `nano_banana` models ignore this and use `aspect_ratio`. * *Note:* `seedream_4.5` requires high resolutions (see constraints below). * **num_images**: How many variations to generate (Max 6). +* **num_inference_steps**: Number of inference steps for supported models. * **seed**: Seed for reproducibility. * **aspect_ratio**: Set target aspect ratio (e.g., 16:9, 1:1). * **enable_web_search**: Enables web search context for supported models. @@ -71,17 +73,21 @@ Different models have different requirements implemented in the node: * **Single Image Only:** Do not connect `image2` through `image5`. * **Resolution:** Width and Height must be between **512px and 2048px**. -2. **Seedream 4.5 (`seedream_4.5`)**: +2. **Flux 2 Klein 9B Edit (`flux_2_klein_9b_edit`)**: + * Supports up to **4 input images**. + * `num_inference_steps` is limited to **4-8**. + +3. **Seedream 4.5 (`seedream_4.5`)**: * **High Res Only:** Width and Height must be between **1920px and 4096px**. * **Pixel Count:** Total pixels (W x H) must be between ~3.6MP and 16.7MP. * **Batch Limit:** The sum of input images and output `num_images` cannot exceed 15. -3. **Nano Banana / Pro / 2**: +4. **Nano Banana / Pro / 2**: * These models rely on `aspect_ratio` and `resolution` settings rather than custom width/height integers. * `nano_banana_2` supports `0.5K`, `1K`, `2K`, and `4K` resolution presets. * `nano_banana_2` also supports extended aspect ratios: `4:1`, `1:4`, `8:1`, and `1:8`. -4. **Grok Imagine Edit (`grok_imagine_edit`)**: +5. **Grok Imagine Edit (`grok_imagine_edit`)**: * Supports up to **3 input images**. * Uses up to **4 output images**. diff --git a/nano_seed.py b/nano_seed.py index 0956a5c..fffc0cf 100644 --- a/nano_seed.py +++ b/nano_seed.py @@ -52,7 +52,7 @@ class NanoSeedEdit: return { "required": { "prompt": ("STRING", {"default": "Edit the image according to this prompt.", "multiline": True}), - "model": (["nano_banana", "nano_banana_pro", "nano_banana_2", "gpt_image_2_edit", "grok_imagine_edit", "seedream_4.5", "qwen_edit_plus", "flux_2_edit", "flux_2_pro", "flux_2_flex"],), + "model": (["nano_banana", "nano_banana_pro", "nano_banana_2", "gpt_image_2_edit", "grok_imagine_edit", "seedream_4.5", "qwen_edit_plus", "flux_2_edit", "flux_2_pro", "flux_2_flex", "flux_2_klein_9b_edit"],), "fal_key": ("STRING", {"default": "your_fal_key_here"}), }, "optional": { @@ -70,6 +70,7 @@ class NanoSeedEdit: "width": ("INT", {"default": 0, "min": 0, "max": 4096, "display": "number"}), "height": ("INT", {"default": 0, "min": 0, "max": 4096, "display": "number"}), "num_images": ("INT", {"default": 1, "min": 1, "max": 6}), + "num_inference_steps": ("INT", {"default": 28, "min": 1, "max": 100}), "seed": ("INT", {"default": 0, "min": 0, "max": 2**32 - 1}), "aspect_ratio": (["auto", "21:9", "16:9", "3:2", "4:3", "5:4", "1:1", "4:5", "3:4", "2:3", "9:16", "4:1", "1:4", "8:1", "1:8"], {"default": "auto"}), "resolution": (["0.5K", "1K", "2K", "4K"], {"default": "1K"}), @@ -87,7 +88,7 @@ class NanoSeedEdit: def edit_image(self, prompt, model, fal_key, image1=None, image2=None, image3=None, image4=None, image5=None, image6=None, image7=None, image8=None, image9=None, image10=None, mask=None, - width=0, height=0, num_images=1, seed=0, aspect_ratio="auto", resolution="1K", + width=0, height=0, num_images=1, num_inference_steps=28, seed=0, aspect_ratio="auto", resolution="1K", quality="high", enable_web_search=False, thinking_level="off", acceleration="none"): # Hardcoded to none, kept for compatibility if fal_key == "your_fal_key_here": raise ValueError("Please set your fal.ai API key in the node.") @@ -196,7 +197,7 @@ class NanoSeedEdit: "image_urls": img_data_uris, "num_images": min(num_images, 6), "seed": seed, - "enable_safety_checker": True, + "enable_safety_checker": False, "sync_mode": True, } if custom_size: @@ -214,8 +215,8 @@ class NanoSeedEdit: "num_images": min(num_images, 4), "seed": seed, "guidance_scale": 4.0, - "num_inference_steps": 50, - "enable_safety_checker": True, + "num_inference_steps": num_inference_steps, + "enable_safety_checker": False, "output_format": "png", "sync_mode": True, "acceleration": acceleration, @@ -223,28 +224,35 @@ class NanoSeedEdit: if custom_size: payload["image_size"] = {"width": width, "height": height} - # Combined logic for Flux 2 Edit, Pro, and Flex - elif model in ["flux_2_edit", "flux_2_pro", "flux_2_flex"]: - if model == "flux_2_edit": - url = "https://fal.run/fal-ai/flux-2/edit" - elif model == "flux_2_pro": - url = "https://fal.run/fal-ai/flux-2-pro/edit" - elif model == "flux_2_flex": - url = "https://fal.run/fal-ai/flux-2-flex/edit" - - payload = { - "prompt": prompt, - "image_urls": img_data_uris, # Sends all connected images - "num_images": min(num_images, 4), - "seed": seed, - "guidance_scale": 2.5, - "num_inference_steps": 28, - "enable_prompt_expansion": False, - "enable_safety_checker": True, - "output_format": "png", - "sync_mode": True, - "acceleration": acceleration, - } + # Combined logic for Flux 2 Edit, Pro, Flex, and Klein 9B + elif model in ["flux_2_edit", "flux_2_pro", "flux_2_flex", "flux_2_klein_9b_edit"]: + if model == "flux_2_edit": + url = "https://fal.run/fal-ai/flux-2/edit" + elif model == "flux_2_pro": + url = "https://fal.run/fal-ai/flux-2-pro/edit" + elif model == "flux_2_flex": + url = "https://fal.run/fal-ai/flux-2-flex/edit" + elif model == "flux_2_klein_9b_edit": + url = "https://fal.run/fal-ai/flux-2/klein/9b/edit" + + inference_steps = num_inference_steps + if model == "flux_2_klein_9b_edit": + inference_steps = min(max(num_inference_steps, 4), 8) + + payload = { + "prompt": prompt, + "image_urls": img_data_uris[:4] if model == "flux_2_klein_9b_edit" else img_data_uris, + "num_images": min(num_images, 4), + "seed": seed, + "num_inference_steps": inference_steps, + "enable_safety_checker": False, + "output_format": "png", + "sync_mode": True, + } + if model != "flux_2_klein_9b_edit": + payload["guidance_scale"] = 2.5 + payload["enable_prompt_expansion"] = False + payload["acceleration"] = acceleration if custom_size: # Standard validation for Flux Edit, relaxed for Pro/Flex as they might handle more