diff --git a/README.md b/README.md index a90e6ec..7a065ad 100644 --- a/README.md +++ b/README.md @@ -120,16 +120,19 @@ If you like what I share, please support me with [PayPal](https://paypal.me/jake 2. Imgen SDXL API workflow bug fixed. 3. Add checkpoint version flux API workflows. 4. Add image grid API workflows. + - 2025-02-20 - v1.9.3 1. Update IPAdapter nodes along with the Main branch. + 2. Add Discord server. -- 2025-02-20 - v1.9.3 -1. Update IPAdapter nodes along with the Main branch. -2. Add Discord server. - - 2025-02-24 - v1.9.4 1. Update Mesh-Get 3D data workflow along with the Load 3D node. 2. Update auto-prompt workflows along with the Flux Prompt Generater node. +- 2025-02-27 - v1.9.5 +1. Add new parameters to SAI API nodes. +2. All SAI API nodes have been approved by [ComfyUI SAI API](https://github.com/Stability-AI/ComfyUI-SAI_API). +3. Update IPAdapter nodes along with the Main branch. + ## Installation 1. `git clone https://github.com/jakechai/ComfyUI-JakeUpgrade` into the `custom_nodes` folder - e.g. `custom_nodes\ComfyUI-JakeUpgrade` @@ -152,7 +155,6 @@ If you like what I share, please support me with [PayPal](https://paypal.me/jake - [ComfyUI Manager](https://github.com/ltdrdata/ComfyUI-Manager) : Copy `_JK.pack` to `...\ComfyUI\user\default\ComfyUI-Manager\components` for saving all JK Group Nodes within each workflow file. - [Prompt Stylers](https://github.com/wolfden/ComfyUi_PromptStylers) : Copy and replace files to `custom_nodes\ComfyUi_PromptStylers` for new styles. -- [ComfyUI SAI API](https://github.com/Stability-AI/ComfyUI-SAI_API) : (Workaround before ComfyUI SAI API approves my pull request) Copy and replace files to `custom_nodes\ComfyUI-SAI_API` for all SAI API methods. - [IP Adapter Plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) : (Workaround before IPAdapter approves my pull request) Copy and replace files to `custom_nodes\ComfyUI_IPAdapter_plus` for better API workflow control by adding "None" selection. > [!NOTE] diff --git a/pyproject.toml b/pyproject.toml index 34ac81a..ff8635d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-jakeupgrade" description = "ComfyUI workflow customization by Jake." -version = "1.9.4" +version = "1.9.5" license = {file = "LICENSE"} dependencies = ["opencv-python", "piexif", "torch", "numpy", "numexpr", "simpleeval"] diff --git a/replacement/ComfyUI-SAI_API/__init__.py b/replacement/ComfyUI-SAI_API/__init__.py deleted file mode 100644 index 5a3921a..0000000 --- a/replacement/ComfyUI-SAI_API/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -from .stability_api import StabilityConservativeUpscale, StabilityCreativeUpscale, StabilityRemoveBackground, StabilityInpainting, StabilityErase, StabilityCore, StabilityImageUltra, StabilitySearchAndReplace, StabilityOutpainting, StabilitySD3, StabilityControlSketch, StabilityControlStructure, StabilitySearchAndRecolor, StabilityControlStyle, StabilityFastUpscale, StabilityReplaceRelight - -NODE_CLASS_MAPPINGS = { - "Stability Conservative Upscale": StabilityConservativeUpscale, - "Stability Creative Upscale": StabilityCreativeUpscale, - "Stability Remove Background": StabilityRemoveBackground, - "Stability Erase": StabilityErase, - "Stability Inpainting": StabilityInpainting, - "Stability Image Core": StabilityCore, - "Stability Image Ultra": StabilityImageUltra, - "Stability Search and Replace": StabilitySearchAndReplace, - "Stability Outpainting": StabilityOutpainting, - "Stability SD3": StabilitySD3, - "Stability Control Sketch": StabilityControlSketch, - "Stability Control Structure": StabilityControlStructure, - "Stability Search And Recolor": StabilitySearchAndRecolor, - "Stability Control Style": StabilityControlStyle, - "Stability Fast Upscale": StabilityFastUpscale, - "Stability Replace Background and Relight": StabilityReplaceRelight, -} diff --git a/replacement/ComfyUI-SAI_API/stability_api.py b/replacement/ComfyUI-SAI_API/stability_api.py deleted file mode 100644 index c9f98eb..0000000 --- a/replacement/ComfyUI-SAI_API/stability_api.py +++ /dev/null @@ -1,509 +0,0 @@ -import requests -from requests.models import PreparedRequest -from PIL import Image -import numpy as np -import torch -from torchvision.transforms import ToPILImage -from io import BytesIO -import os -import time - -ROOT_API = "https://api.stability.ai/v2beta/" -API_KEY = os.environ.get("SAI_API_KEY") - -def get_api_key(): - global API_KEY - if API_KEY is not None: - return API_KEY - - # Check for API key in file as a backup, not recommended - try: - if not API_KEY: - dir_path = os.path.dirname(os.path.realpath(__file__)) - with open(os.path.join(dir_path, "sai_platform_key.txt"), "r") as f: - API_KEY = f.read().strip() - # Validate the key is not empty - if API_KEY.strip() == "": - raise Exception(f"API Key is required to use the Stability API. \nPlease set the SAI_API_KEY environment variable to your API key or place in {dir_path}/sai_platform_key.txt.") - - except Exception as e: - print(f"\n\n***API Key is required to use the Stability API. Please set the SAI_API_KEY environment variable to your API key or place in {dir_path}/sai_platform_key.txt.***\n\n") - - return API_KEY - -class StabilityBase: - API_ENDPOINT = "" - POLL_ENDPOINT = "" - ACCEPT = "" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_SPEC - - RETURN_TYPES = ("IMAGE",) - FUNCTION = "call" - CATEGORY = "Stability" - - def call(self, *args, **kwargs): - - buffered = BytesIO() - files = {'none': None} - data = None - - image = kwargs.get('image', None) - if image is not None: - if self.API_ENDPOINT != "stable-image/control/style": - kwargs["mode"] = "image-to-image" - kwargs.pop("aspect_ratio", None) - image = ToPILImage()(image.squeeze(0).permute(2,0,1)) - image.save(buffered, format="PNG") - files = self._get_files(buffered, **kwargs) - else: - kwargs.pop("strength", None) - - image_subject = kwargs.get('subject_image', None) - if image_subject is not None: - buffered_sub = BytesIO() - image_subject = ToPILImage()(image_subject.squeeze(0).permute(2,0,1)) - image_subject.save(buffered_sub, format="PNG") - files["subject_image"] = buffered_sub.getvalue() - - image_bg_ref = kwargs.get('background_reference', None) - if image_bg_ref is not None: - buffered_bg_ref = BytesIO() - image_bg_ref = ToPILImage()(image_bg_ref.squeeze(0).permute(2,0,1)) - image_bg_ref.save(buffered_bg_ref, format="PNG") - files["background_reference"] = buffered_bg_ref.getvalue() - - image_lt_ref = kwargs.get('light_reference', None) - if image_lt_ref is not None: - buffered_lt_ref = BytesIO() - image_lt_ref = ToPILImage()(image_lt_ref.squeeze(0).permute(2,0,1)) - image_lt_ref.save(buffered_lt_ref, format="PNG") - files["light_reference"] = buffered_lt_ref.getvalue() - - style = kwargs.get('style', False) - if style is False: - kwargs.pop('style_preset', None) - - headers = {} - if kwargs.get("api_key_override"): - headers["Authorization"] = kwargs.get("api_key_override") - else: - headers["Authorization"] = get_api_key() - - if headers.get("Authorization") is None: - raise Exception(f"No Stability key set.\n\nUse your Stability AI API key by:\n1. Setting the SAI_API_KEY environment variable to your API key\n2. Placing inside sai_platform_key.txt\n3. Passing the API key as an argument to the function with the key 'api_key_override'") - - headers["Accept"] = self.ACCEPT - - data = self._get_data(**kwargs) - - if kwargs.get('aspect_ratio', None) is not None: - data['aspect_ratio'] = data['aspect_ratio'].split("(", 1)[0] - - if kwargs.get('subject_image', None) is not None: - if 'subject_image' in data: - del data['subject_image'] - - if 'background_reference' in data: - del data['background_reference'] - - if 'light_reference' in data: - del data['light_reference'] - - if kwargs.get('light_reference', None) is not None: - if 'light_source_direction' in data: - del data['light_source_direction'] - else: - if 'light_source_direction' in data and data['light_source_direction'] == 'none': - if 'light_source_strength' in data: - del data['light_source_strength'] - - req = PreparedRequest() - req.prepare_method('POST') - req.prepare_url(f"{ROOT_API}{self.API_ENDPOINT}", None) - req.prepare_headers(headers) - req.prepare_body(data=data, files=files) - response = requests.Session().send(req) - - if response.status_code == 200: - if self.POLL_ENDPOINT != "": - id = response.json().get("id") - timeout = 240 - start_time = time.time() - while True: - response = requests.get(f"{ROOT_API}{self.POLL_ENDPOINT}{id}", headers=headers) - if response.status_code == 200: - if self.ACCEPT == "image/*" or self.ACCEPT == "*/*": - return self._return_image(response) - if self.ACCEPT == "video/*": - return self._return_video(response) - break - elif response.status_code == 202: - time.sleep(10) - elif time.time() - start_time > timeout: - raise Exception("Stability API Timeout: Request took too long to complete") - else: - error_info = response.json() - raise Exception(f"Stability API Error: {error_info}") - else: - result_image = Image.open(BytesIO(response.content)) - result_image = result_image.convert("RGBA") - result_image = np.array(result_image).astype(np.float32) / 255.0 - result_image = torch.from_numpy(result_image)[None,] - return (result_image,) - else: - error_info = response.json() - if error_info.get("name") == "unauthorized": - raise Exception("Stability API Error: Unauthorized.\n\nUse your Stability AI API key by:\n1. Setting the SAI_API_KEY environment variable to your API key\n2. Placing inside sai_platform_key.txt\n3. Passing the API key as an argument to the function with the key 'api_key_override'") - if error_info.get("name") == "payment_required": - raise Exception("Stability API Error: Not enough credits.\n\nPlease ensure your SAI API account has enough credits to complete this action.") - if error_info.get("name") == "bad_request": - errors = '\n'.join(error_info.get('errors')) - raise Exception(f"Stability API Error: Bad request.\n\n{errors}") - else: - raise Exception(f"Stability API Error: {error_info}") - - def _return_image(self, response): - result_image = Image.open(BytesIO(response.content)) - result_image = result_image.convert("RGBA") - result_image = np.array(result_image).astype(np.float32) / 255.0 - result_image = torch.from_numpy(result_image)[None,] - return (result_image,) - - def _return_video(self, response): - result_video = response.content - return (result_video,) - - def _get_files(self, buffered, **kwargs): - return { - "image": buffered.getvalue() - } - - def _get_data(self, **kwargs): - return {k: v for k, v in kwargs.items() if k != "image" and k != "mask"} - - -class StabilityCore(StabilityBase): - API_ENDPOINT = "stable-image/generate/core" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "negative_prompt": ("STRING", {"multiline": True}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "aspect_ratio": (["1:1(1536, 1536)", "5:4(1632, 1344)", "3:2(1824, 1248)", "16:9(2016, 1152)", "21:9(2304, 960)", "4:5(1344, 1632)", "2:3(1248, 1824)", "9:16(1152, 2016)", "9:21(960, 2304)"],), - "style": ("BOOLEAN", {"default": False}), - "style_preset": (["3d-model", "analog-film", "anime", "cinematic", "comic-book", "digital-art", "enhance", "fantasy-art", "isometric", "line-art", "low-poly", "modeling-compound", "neon-punk", "origami", "photographic", "pixel-art", "tile-texture"],), - "api_key_override": ("STRING", {"multiline": False}), - } - } - - -class StabilityImageUltra(StabilityBase): - API_ENDPOINT = "stable-image/generate/ultra" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "image": ("IMAGE",), - "negative_prompt": ("STRING", {"multiline": True}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "strength": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.01}), - "aspect_ratio": (["1:1(1024, 1024)", "5:4(1088, 896)", "3:2(1216, 832)", "16:9(1344, 768)", "21:9(1536, 640)", "4:5(896, 1088)", "2:3(832, 1216)", "9:16(768, 1344)", "9:21(640, 1536)"],), - "output_format": (["png", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - }, - } - - -class StabilityConservativeUpscale(StabilityBase): - API_ENDPOINT = "stable-image/upscale/conservative" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "negative_prompt": ("STRING", {"multiline": True}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "creativity": ("FLOAT", {"default": 0.35, "min": 0.2, "max": 0.5, "step": 0.01}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - } - } - - -class StabilityCreativeUpscale(StabilityBase): - API_ENDPOINT = "stable-image/upscale/creative" - POLL_ENDPOINT = "results/" - ACCEPT = "*/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "negative_prompt": ("STRING", {"multiline": True}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "creativity": ("FLOAT", {"default": 0.3, "min": 0.0, "max": 0.35, "step": 0.01}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - } - } - - -class StabilityRemoveBackground(StabilityBase): - API_ENDPOINT = "stable-image/edit/remove-background" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - }, - } - - -class StabilityInpainting(StabilityBase): - API_ENDPOINT = "stable-image/edit/inpaint" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "prompt": ("STRING", {"multiline": True, "default": ""}), - }, - "optional": { - "mask": ("MASK",), - "negative_prompt": ("STRING", {"multiline": True, "default": ""}), - "grow_mask": ("INT", {"default": 5, "min": 0, "max": 20}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - } - } - def _get_files(self, buffered, **kwargs): - mask = kwargs.get("mask", None) - if mask != None: - mask = mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])).movedim(1, -1).expand(-1, -1, -1, 3) - mask = ToPILImage()(mask.squeeze(0).permute(2,0,1)) - buffered_mask = BytesIO() - mask.save(buffered_mask, format="PNG") - return { - "image": buffered.getvalue(), - "mask": buffered_mask.getvalue(), - } - else: - return { - "image": buffered.getvalue(), - } - - -class StabilityErase(StabilityBase): - API_ENDPOINT = "stable-image/edit/erase" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - }, - "optional": { - "mask": ("MASK",), - "grow_mask": ("INT", {"default": 5, "min": 0, "max": 20}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - } - } - def _get_files(self, buffered, **kwargs): - mask = kwargs.get("mask", None) - if mask != None: - mask = mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])).movedim(1, -1).expand(-1, -1, -1, 3) - mask = ToPILImage()(mask.squeeze(0).permute(2,0,1)) - buffered_mask = BytesIO() - mask.save(buffered_mask, format="PNG") - return { - "image": buffered.getvalue(), - "mask": buffered_mask.getvalue(), - } - else: - return { - "image": buffered.getvalue(), - } - - -class StabilitySearchAndReplace(StabilityBase): - API_ENDPOINT = "stable-image/edit/search-and-replace" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "search_prompt": ("STRING", {"multiline": True}), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "negative_prompt": ("STRING", {"multiline": True}), - "grow_mask": ("INT", {"default": 3, "min": 0, "max": 20}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "api_key_override": ("STRING", {"multiline": False}), - "output_format": (["png", "webp", "jpeg"],), - }, - } - - -class StabilitySD3(StabilityBase): - API_ENDPOINT = "stable-image/generate/sd3" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "model": (["sd3.5-large", "sd3.5-large-turbo", "sd3.5-medium", "sd3-large", "sd3-large-turbo", "sd3-medium"],), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "image": ("IMAGE",), - "negative_prompt": ("STRING", {"multiline": True}), - "cfg_scale": ("FLOAT", {"default": 7.0, "min": 1.0, "max": 10.0, "step": 0.01}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "strength": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.01}), - "aspect_ratio": (["1:1(1024, 1024)", "5:4(1088, 896)", "3:2(1216, 832)", "16:9(1344, 768)", "21:9(1536, 640)", "4:5(896, 1088)", "2:3(832, 1216)", "9:16(768, 1344)", "9:21(640, 1536)"],), - "output_format": (["png", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - }, - } - - -class StabilityOutpainting(StabilityBase): - API_ENDPOINT = "stable-image/edit/outpaint" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "left": ("INT", {"default": 0, "min": 0, "max": 512}), - "right": ("INT", {"default": 0, "min": 0, "max": 512}), - "up": ("INT", {"default": 0, "min": 0, "max": 512}), - "down": ("INT", {"default": 0, "min": 0, "max": 512}),\ - }, - "optional": { - "prompt": ("STRING", {"multiline": True}), - "creativity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - }, - } - -class StabilityControlSketch(StabilityBase): - API_ENDPOINT = "stable-image/control/sketch" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "control_strength": ("FLOAT", {"default": 0.7, "min": 0.01, "max": 1.0, "step": 0.01}), - "negative_prompt": ("STRING", {"multiline": True}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - }, - } - - -class StabilityControlStructure(StabilityBase): - API_ENDPOINT = "stable-image/control/structure" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "control_strength": ("FLOAT", {"default": 0.7, "min": 0.01, "max": 1.0, "step": 0.01}), - "negative_prompt": ("STRING", {"multiline": True}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - }, - } - - -class StabilitySearchAndRecolor(StabilityBase): - API_ENDPOINT = "stable-image/edit/search-and-recolor" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "select_prompt": ("STRING", {"multiline": True}), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "negative_prompt": ("STRING", {"multiline": True}), - "grow_mask": ("INT", {"default": 3, "min": 0, "max": 20, "step": 1}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "api_key_override": ("STRING", {"multiline": False}), - "output_format": (["png", "webp", "jpeg"],), - }, - } - - -class StabilityControlStyle(StabilityBase): - API_ENDPOINT = "stable-image/control/style" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - "prompt": ("STRING", {"multiline": True}), - }, - "optional": { - "aspect_ratio": (["1:1(1024, 1024)", "5:4(1144, 915)", "3:2(1254, 836)", "16:9(1365, 768)", "21:9(1564, 670)", "4:5(915, 1144)", "2:3(836, 1254)", "9:16(768, 1365)", "9:21(670, 1564)"],), - "fidelity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}), - "negative_prompt": ("STRING", {"multiline": True}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - }, - } - - -class StabilityFastUpscale(StabilityBase): - API_ENDPOINT = "stable-image/upscale/fast" - ACCEPT = "image/*" - INPUT_SPEC = { - "required": { - "image": ("IMAGE",), - }, - "optional": { - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - } - } - -class StabilityReplaceRelight(StabilityBase): - API_ENDPOINT = "stable-image/edit/replace-background-and-relight" - POLL_ENDPOINT = "results/" - ACCEPT = "*/*" - INPUT_SPEC = { - "required": { - "subject_image": ("IMAGE",), - }, - "optional": { - "background_reference": ("IMAGE",), - "background_prompt": ("STRING", {"multiline": True}), - "foreground_prompt": ("STRING", {"multiline": True}), - "negative_prompt": ("STRING", {"multiline": True}), - "preserve_original_subject": ("FLOAT", {"default": 0.6, "min": 0.0, "max": 1.0, "step": 0.01}), - "original_background_depth": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}), - "keep_original_background": ("BOOLEAN", {"default": False}), - "light_source_direction": (["none", "above", "below", "left", "right"],), - "light_reference": ("IMAGE",), - "light_source_strength": ("FLOAT", {"default": 0.3, "min": 0.0, "max": 1.0, "step": 0.01}), - "seed": ("INT", {"default": 0, "min": 0, "max": 4294967294}), - "output_format": (["png", "webp", "jpeg"],), - "api_key_override": ("STRING", {"multiline": False}), - } - } \ No newline at end of file diff --git a/replacement/ComfyUI_IPAdapter_plus/IPAdapterPlus.py b/replacement/ComfyUI_IPAdapter_plus/IPAdapterPlus.py index cbc3200..a16f1c3 100644 --- a/replacement/ComfyUI_IPAdapter_plus/IPAdapterPlus.py +++ b/replacement/ComfyUI_IPAdapter_plus/IPAdapterPlus.py @@ -573,6 +573,15 @@ class IPAdapterUnifiedLoader: else: if ipadapter is not None: pipeline = ipadapter + + if 'insightface' not in pipeline: + pipeline['insightface'] = { 'provider': None, 'model': None } + + if 'ipadapter' not in pipeline: + pipeline['ipadapter'] = { 'file': None, 'model': None } + + if 'clipvision' not in pipeline: + pipeline['clipvision'] = { 'file': None, 'model': None } # 1. Load the clipvision model clipvision_file = get_clipvision_file(preset)