diff --git a/invokeai/app/invocations/baseinvocation.py b/invokeai/app/invocations/baseinvocation.py index ccc2b4d05f..540571762f 100644 --- a/invokeai/app/invocations/baseinvocation.py +++ b/invokeai/app/invocations/baseinvocation.py @@ -26,6 +26,7 @@ from typing import ( from pydantic import BaseModel, Field, validator from pydantic.fields import Undefined, ModelField from pydantic.typing import NoArgAnyCallable +import semver if TYPE_CHECKING: from ..services.invocation_services import InvocationServices @@ -401,6 +402,9 @@ class UIConfigBase(BaseModel): tags: Optional[list[str]] = Field(default_factory=None, description="The node's tags") title: Optional[str] = Field(default=None, description="The node's display name") category: Optional[str] = Field(default=None, description="The node's category") + version: Optional[str] = Field( + default=None, description='The node\'s version. Should be a valid semver string e.g. "1.0.0" or "3.8.13".' + ) class InvocationContext: @@ -499,6 +503,8 @@ class BaseInvocation(ABC, BaseModel): schema["tags"] = uiconfig.tags if uiconfig and hasattr(uiconfig, "category"): schema["category"] = uiconfig.category + if uiconfig and hasattr(uiconfig, "version"): + schema["version"] = uiconfig.version if "required" not in schema or not isinstance(schema["required"], list): schema["required"] = list() schema["required"].extend(["type", "id"]) @@ -567,7 +573,11 @@ GenericBaseInvocation = TypeVar("GenericBaseInvocation", bound=BaseInvocation) def invocation( - invocation_type: str, title: Optional[str] = None, tags: Optional[list[str]] = None, category: Optional[str] = None + invocation_type: str, + title: Optional[str] = None, + tags: Optional[list[str]] = None, + category: Optional[str] = None, + version: Optional[str] = None, ) -> Callable[[Type[GenericBaseInvocation]], Type[GenericBaseInvocation]]: """ Adds metadata to an invocation. @@ -594,6 +604,9 @@ def invocation( cls.UIConfig.tags = tags if category is not None: cls.UIConfig.category = category + if version is not None: + semver.Version.parse(version) # raises ValueError if invalid semver + cls.UIConfig.version = version # Add the invocation type to the pydantic model of the invocation invocation_type_annotation = Literal[invocation_type] # type: ignore diff --git a/invokeai/app/invocations/collections.py b/invokeai/app/invocations/collections.py index 979f2e43b7..2814a9c3ca 100644 --- a/invokeai/app/invocations/collections.py +++ b/invokeai/app/invocations/collections.py @@ -10,7 +10,9 @@ from invokeai.app.util.misc import SEED_MAX, get_random_seed from .baseinvocation import BaseInvocation, InputField, InvocationContext, invocation -@invocation("range", title="Integer Range", tags=["collection", "integer", "range"], category="collections") +@invocation( + "range", title="Integer Range", tags=["collection", "integer", "range"], category="collections", version="1.0.0" +) class RangeInvocation(BaseInvocation): """Creates a range of numbers from start to stop with step""" @@ -33,6 +35,7 @@ class RangeInvocation(BaseInvocation): title="Integer Range of Size", tags=["collection", "integer", "size", "range"], category="collections", + version="1.0.0", ) class RangeOfSizeInvocation(BaseInvocation): """Creates a range from start to start + size with step""" @@ -50,6 +53,7 @@ class RangeOfSizeInvocation(BaseInvocation): title="Random Range", tags=["range", "integer", "random", "collection"], category="collections", + version="1.0.0", ) class RandomRangeInvocation(BaseInvocation): """Creates a collection of random numbers""" diff --git a/invokeai/app/invocations/compel.py b/invokeai/app/invocations/compel.py index 563d8d97fd..4557c57820 100644 --- a/invokeai/app/invocations/compel.py +++ b/invokeai/app/invocations/compel.py @@ -44,7 +44,7 @@ class ConditioningFieldData: # PerpNeg = "perp_neg" -@invocation("compel", title="Prompt", tags=["prompt", "compel"], category="conditioning") +@invocation("compel", title="Prompt", tags=["prompt", "compel"], category="conditioning", version="1.0.0") class CompelInvocation(BaseInvocation): """Parse prompt using compel package to conditioning.""" @@ -267,6 +267,7 @@ class SDXLPromptInvocationBase: title="SDXL Prompt", tags=["sdxl", "compel", "prompt"], category="conditioning", + version="1.0.0", ) class SDXLCompelPromptInvocation(BaseInvocation, SDXLPromptInvocationBase): """Parse prompt using compel package to conditioning.""" @@ -351,6 +352,7 @@ class SDXLCompelPromptInvocation(BaseInvocation, SDXLPromptInvocationBase): title="SDXL Refiner Prompt", tags=["sdxl", "compel", "prompt"], category="conditioning", + version="1.0.0", ) class SDXLRefinerCompelPromptInvocation(BaseInvocation, SDXLPromptInvocationBase): """Parse prompt using compel package to conditioning.""" @@ -403,7 +405,7 @@ class ClipSkipInvocationOutput(BaseInvocationOutput): clip: ClipField = OutputField(default=None, description=FieldDescriptions.clip, title="CLIP") -@invocation("clip_skip", title="CLIP Skip", tags=["clipskip", "clip", "skip"], category="conditioning") +@invocation("clip_skip", title="CLIP Skip", tags=["clipskip", "clip", "skip"], category="conditioning", version="1.0.0") class ClipSkipInvocation(BaseInvocation): """Skip layers in clip text_encoder model.""" diff --git a/invokeai/app/invocations/controlnet_image_processors.py b/invokeai/app/invocations/controlnet_image_processors.py index 272afb3a4c..2c2eab9155 100644 --- a/invokeai/app/invocations/controlnet_image_processors.py +++ b/invokeai/app/invocations/controlnet_image_processors.py @@ -95,7 +95,7 @@ class ControlOutput(BaseInvocationOutput): control: ControlField = OutputField(description=FieldDescriptions.control) -@invocation("controlnet", title="ControlNet", tags=["controlnet"], category="controlnet") +@invocation("controlnet", title="ControlNet", tags=["controlnet"], category="controlnet", version="1.0.0") class ControlNetInvocation(BaseInvocation): """Collects ControlNet info to pass to other nodes""" @@ -127,7 +127,9 @@ class ControlNetInvocation(BaseInvocation): ) -@invocation("image_processor", title="Base Image Processor", tags=["controlnet"], category="controlnet") +@invocation( + "image_processor", title="Base Image Processor", tags=["controlnet"], category="controlnet", version="1.0.0" +) class ImageProcessorInvocation(BaseInvocation): """Base class for invocations that preprocess images for ControlNet""" @@ -171,6 +173,7 @@ class ImageProcessorInvocation(BaseInvocation): title="Canny Processor", tags=["controlnet", "canny"], category="controlnet", + version="1.0.0", ) class CannyImageProcessorInvocation(ImageProcessorInvocation): """Canny edge detection for ControlNet""" @@ -193,6 +196,7 @@ class CannyImageProcessorInvocation(ImageProcessorInvocation): title="HED (softedge) Processor", tags=["controlnet", "hed", "softedge"], category="controlnet", + version="1.0.0", ) class HedImageProcessorInvocation(ImageProcessorInvocation): """Applies HED edge detection to image""" @@ -221,6 +225,7 @@ class HedImageProcessorInvocation(ImageProcessorInvocation): title="Lineart Processor", tags=["controlnet", "lineart"], category="controlnet", + version="1.0.0", ) class LineartImageProcessorInvocation(ImageProcessorInvocation): """Applies line art processing to image""" @@ -242,6 +247,7 @@ class LineartImageProcessorInvocation(ImageProcessorInvocation): title="Lineart Anime Processor", tags=["controlnet", "lineart", "anime"], category="controlnet", + version="1.0.0", ) class LineartAnimeImageProcessorInvocation(ImageProcessorInvocation): """Applies line art anime processing to image""" @@ -264,6 +270,7 @@ class LineartAnimeImageProcessorInvocation(ImageProcessorInvocation): title="Openpose Processor", tags=["controlnet", "openpose", "pose"], category="controlnet", + version="1.0.0", ) class OpenposeImageProcessorInvocation(ImageProcessorInvocation): """Applies Openpose processing to image""" @@ -288,6 +295,7 @@ class OpenposeImageProcessorInvocation(ImageProcessorInvocation): title="Midas Depth Processor", tags=["controlnet", "midas"], category="controlnet", + version="1.0.0", ) class MidasDepthImageProcessorInvocation(ImageProcessorInvocation): """Applies Midas depth processing to image""" @@ -314,6 +322,7 @@ class MidasDepthImageProcessorInvocation(ImageProcessorInvocation): title="Normal BAE Processor", tags=["controlnet"], category="controlnet", + version="1.0.0", ) class NormalbaeImageProcessorInvocation(ImageProcessorInvocation): """Applies NormalBae processing to image""" @@ -329,7 +338,9 @@ class NormalbaeImageProcessorInvocation(ImageProcessorInvocation): return processed_image -@invocation("mlsd_image_processor", title="MLSD Processor", tags=["controlnet", "mlsd"], category="controlnet") +@invocation( + "mlsd_image_processor", title="MLSD Processor", tags=["controlnet", "mlsd"], category="controlnet", version="1.0.0" +) class MlsdImageProcessorInvocation(ImageProcessorInvocation): """Applies MLSD processing to image""" @@ -350,7 +361,9 @@ class MlsdImageProcessorInvocation(ImageProcessorInvocation): return processed_image -@invocation("pidi_image_processor", title="PIDI Processor", tags=["controlnet", "pidi"], category="controlnet") +@invocation( + "pidi_image_processor", title="PIDI Processor", tags=["controlnet", "pidi"], category="controlnet", version="1.0.0" +) class PidiImageProcessorInvocation(ImageProcessorInvocation): """Applies PIDI processing to image""" @@ -376,6 +389,7 @@ class PidiImageProcessorInvocation(ImageProcessorInvocation): title="Content Shuffle Processor", tags=["controlnet", "contentshuffle"], category="controlnet", + version="1.0.0", ) class ContentShuffleImageProcessorInvocation(ImageProcessorInvocation): """Applies content shuffle processing to image""" @@ -405,6 +419,7 @@ class ContentShuffleImageProcessorInvocation(ImageProcessorInvocation): title="Zoe (Depth) Processor", tags=["controlnet", "zoe", "depth"], category="controlnet", + version="1.0.0", ) class ZoeDepthImageProcessorInvocation(ImageProcessorInvocation): """Applies Zoe depth processing to image""" @@ -420,6 +435,7 @@ class ZoeDepthImageProcessorInvocation(ImageProcessorInvocation): title="Mediapipe Face Processor", tags=["controlnet", "mediapipe", "face"], category="controlnet", + version="1.0.0", ) class MediapipeFaceProcessorInvocation(ImageProcessorInvocation): """Applies mediapipe face processing to image""" @@ -442,6 +458,7 @@ class MediapipeFaceProcessorInvocation(ImageProcessorInvocation): title="Leres (Depth) Processor", tags=["controlnet", "leres", "depth"], category="controlnet", + version="1.0.0", ) class LeresImageProcessorInvocation(ImageProcessorInvocation): """Applies leres processing to image""" @@ -470,6 +487,7 @@ class LeresImageProcessorInvocation(ImageProcessorInvocation): title="Tile Resample Processor", tags=["controlnet", "tile"], category="controlnet", + version="1.0.0", ) class TileResamplerProcessorInvocation(ImageProcessorInvocation): """Tile resampler processor""" @@ -509,6 +527,7 @@ class TileResamplerProcessorInvocation(ImageProcessorInvocation): title="Segment Anything Processor", tags=["controlnet", "segmentanything"], category="controlnet", + version="1.0.0", ) class SegmentAnythingProcessorInvocation(ImageProcessorInvocation): """Applies segment anything processing to image""" diff --git a/invokeai/app/invocations/cv.py b/invokeai/app/invocations/cv.py index 40d8867aa1..411aff8234 100644 --- a/invokeai/app/invocations/cv.py +++ b/invokeai/app/invocations/cv.py @@ -10,12 +10,7 @@ from invokeai.app.models.image import ImageCategory, ResourceOrigin from .baseinvocation import BaseInvocation, InputField, InvocationContext, invocation -@invocation( - "cv_inpaint", - title="OpenCV Inpaint", - tags=["opencv", "inpaint"], - category="inpaint", -) +@invocation("cv_inpaint", title="OpenCV Inpaint", tags=["opencv", "inpaint"], category="inpaint", version="1.0.0") class CvInpaintInvocation(BaseInvocation): """Simple inpaint using opencv.""" diff --git a/invokeai/app/invocations/image.py b/invokeai/app/invocations/image.py index 5eeead7db2..b6f7cc405b 100644 --- a/invokeai/app/invocations/image.py +++ b/invokeai/app/invocations/image.py @@ -16,7 +16,7 @@ from ..models.image import ImageCategory, ResourceOrigin from .baseinvocation import BaseInvocation, FieldDescriptions, InputField, InvocationContext, invocation -@invocation("show_image", title="Show Image", tags=["image"], category="image") +@invocation("show_image", title="Show Image", tags=["image"], category="image", version="1.0.0") class ShowImageInvocation(BaseInvocation): """Displays a provided image using the OS image viewer, and passes it forward in the pipeline.""" @@ -36,7 +36,7 @@ class ShowImageInvocation(BaseInvocation): ) -@invocation("blank_image", title="Blank Image", tags=["image"], category="image") +@invocation("blank_image", title="Blank Image", tags=["image"], category="image", version="1.0.0") class BlankImageInvocation(BaseInvocation): """Creates a blank image and forwards it to the pipeline""" @@ -65,7 +65,7 @@ class BlankImageInvocation(BaseInvocation): ) -@invocation("img_crop", title="Crop Image", tags=["image", "crop"], category="image") +@invocation("img_crop", title="Crop Image", tags=["image", "crop"], category="image", version="1.0.0") class ImageCropInvocation(BaseInvocation): """Crops an image to a specified box. The box can be outside of the image.""" @@ -98,7 +98,7 @@ class ImageCropInvocation(BaseInvocation): ) -@invocation("img_paste", title="Paste Image", tags=["image", "paste"], category="image") +@invocation("img_paste", title="Paste Image", tags=["image", "paste"], category="image", version="1.0.0") class ImagePasteInvocation(BaseInvocation): """Pastes an image into another image.""" @@ -146,7 +146,7 @@ class ImagePasteInvocation(BaseInvocation): ) -@invocation("tomask", title="Mask from Alpha", tags=["image", "mask"], category="image") +@invocation("tomask", title="Mask from Alpha", tags=["image", "mask"], category="image", version="1.0.0") class MaskFromAlphaInvocation(BaseInvocation): """Extracts the alpha channel of an image as a mask.""" @@ -177,7 +177,7 @@ class MaskFromAlphaInvocation(BaseInvocation): ) -@invocation("img_mul", title="Multiply Images", tags=["image", "multiply"], category="image") +@invocation("img_mul", title="Multiply Images", tags=["image", "multiply"], category="image", version="1.0.0") class ImageMultiplyInvocation(BaseInvocation): """Multiplies two images together using `PIL.ImageChops.multiply()`.""" @@ -210,7 +210,7 @@ class ImageMultiplyInvocation(BaseInvocation): IMAGE_CHANNELS = Literal["A", "R", "G", "B"] -@invocation("img_chan", title="Extract Image Channel", tags=["image", "channel"], category="image") +@invocation("img_chan", title="Extract Image Channel", tags=["image", "channel"], category="image", version="1.0.0") class ImageChannelInvocation(BaseInvocation): """Gets a channel from an image.""" @@ -242,7 +242,7 @@ class ImageChannelInvocation(BaseInvocation): IMAGE_MODES = Literal["L", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"] -@invocation("img_conv", title="Convert Image Mode", tags=["image", "convert"], category="image") +@invocation("img_conv", title="Convert Image Mode", tags=["image", "convert"], category="image", version="1.0.0") class ImageConvertInvocation(BaseInvocation): """Converts an image to a different mode.""" @@ -271,7 +271,7 @@ class ImageConvertInvocation(BaseInvocation): ) -@invocation("img_blur", title="Blur Image", tags=["image", "blur"], category="image") +@invocation("img_blur", title="Blur Image", tags=["image", "blur"], category="image", version="1.0.0") class ImageBlurInvocation(BaseInvocation): """Blurs an image""" @@ -325,7 +325,7 @@ PIL_RESAMPLING_MAP = { } -@invocation("img_resize", title="Resize Image", tags=["image", "resize"], category="image") +@invocation("img_resize", title="Resize Image", tags=["image", "resize"], category="image", version="1.0.0") class ImageResizeInvocation(BaseInvocation): """Resizes an image to specific dimensions""" @@ -365,7 +365,7 @@ class ImageResizeInvocation(BaseInvocation): ) -@invocation("img_scale", title="Scale Image", tags=["image", "scale"], category="image") +@invocation("img_scale", title="Scale Image", tags=["image", "scale"], category="image", version="1.0.0") class ImageScaleInvocation(BaseInvocation): """Scales an image by a factor""" @@ -406,7 +406,7 @@ class ImageScaleInvocation(BaseInvocation): ) -@invocation("img_lerp", title="Lerp Image", tags=["image", "lerp"], category="image") +@invocation("img_lerp", title="Lerp Image", tags=["image", "lerp"], category="image", version="1.0.0") class ImageLerpInvocation(BaseInvocation): """Linear interpolation of all pixels of an image""" @@ -439,7 +439,7 @@ class ImageLerpInvocation(BaseInvocation): ) -@invocation("img_ilerp", title="Inverse Lerp Image", tags=["image", "ilerp"], category="image") +@invocation("img_ilerp", title="Inverse Lerp Image", tags=["image", "ilerp"], category="image", version="1.0.0") class ImageInverseLerpInvocation(BaseInvocation): """Inverse linear interpolation of all pixels of an image""" @@ -472,7 +472,7 @@ class ImageInverseLerpInvocation(BaseInvocation): ) -@invocation("img_nsfw", title="Blur NSFW Image", tags=["image", "nsfw"], category="image") +@invocation("img_nsfw", title="Blur NSFW Image", tags=["image", "nsfw"], category="image", version="1.0.0") class ImageNSFWBlurInvocation(BaseInvocation): """Add blur to NSFW-flagged images""" @@ -517,7 +517,9 @@ class ImageNSFWBlurInvocation(BaseInvocation): return caution.resize((caution.width // 2, caution.height // 2)) -@invocation("img_watermark", title="Add Invisible Watermark", tags=["image", "watermark"], category="image") +@invocation( + "img_watermark", title="Add Invisible Watermark", tags=["image", "watermark"], category="image", version="1.0.0" +) class ImageWatermarkInvocation(BaseInvocation): """Add an invisible watermark to an image""" @@ -548,7 +550,7 @@ class ImageWatermarkInvocation(BaseInvocation): ) -@invocation("mask_edge", title="Mask Edge", tags=["image", "mask", "inpaint"], category="image") +@invocation("mask_edge", title="Mask Edge", tags=["image", "mask", "inpaint"], category="image", version="1.0.0") class MaskEdgeInvocation(BaseInvocation): """Applies an edge mask to an image""" @@ -593,7 +595,9 @@ class MaskEdgeInvocation(BaseInvocation): ) -@invocation("mask_combine", title="Combine Masks", tags=["image", "mask", "multiply"], category="image") +@invocation( + "mask_combine", title="Combine Masks", tags=["image", "mask", "multiply"], category="image", version="1.0.0" +) class MaskCombineInvocation(BaseInvocation): """Combine two masks together by multiplying them using `PIL.ImageChops.multiply()`.""" @@ -623,7 +627,7 @@ class MaskCombineInvocation(BaseInvocation): ) -@invocation("color_correct", title="Color Correct", tags=["image", "color"], category="image") +@invocation("color_correct", title="Color Correct", tags=["image", "color"], category="image", version="1.0.0") class ColorCorrectInvocation(BaseInvocation): """ Shifts the colors of a target image to match the reference image, optionally @@ -728,7 +732,7 @@ class ColorCorrectInvocation(BaseInvocation): ) -@invocation("img_hue_adjust", title="Adjust Image Hue", tags=["image", "hue"], category="image") +@invocation("img_hue_adjust", title="Adjust Image Hue", tags=["image", "hue"], category="image", version="1.0.0") class ImageHueAdjustmentInvocation(BaseInvocation): """Adjusts the Hue of an image.""" @@ -774,6 +778,7 @@ class ImageHueAdjustmentInvocation(BaseInvocation): title="Adjust Image Luminosity", tags=["image", "luminosity", "hsl"], category="image", + version="1.0.0", ) class ImageLuminosityAdjustmentInvocation(BaseInvocation): """Adjusts the Luminosity (Value) of an image.""" @@ -826,6 +831,7 @@ class ImageLuminosityAdjustmentInvocation(BaseInvocation): title="Adjust Image Saturation", tags=["image", "saturation", "hsl"], category="image", + version="1.0.0", ) class ImageSaturationAdjustmentInvocation(BaseInvocation): """Adjusts the Saturation of an image.""" diff --git a/invokeai/app/invocations/infill.py b/invokeai/app/invocations/infill.py index 438c56e312..fa322e7864 100644 --- a/invokeai/app/invocations/infill.py +++ b/invokeai/app/invocations/infill.py @@ -116,7 +116,7 @@ def tile_fill_missing(im: Image.Image, tile_size: int = 16, seed: Optional[int] return si -@invocation("infill_rgba", title="Solid Color Infill", tags=["image", "inpaint"], category="inpaint") +@invocation("infill_rgba", title="Solid Color Infill", tags=["image", "inpaint"], category="inpaint", version="1.0.0") class InfillColorInvocation(BaseInvocation): """Infills transparent areas of an image with a solid color""" @@ -151,7 +151,7 @@ class InfillColorInvocation(BaseInvocation): ) -@invocation("infill_tile", title="Tile Infill", tags=["image", "inpaint"], category="inpaint") +@invocation("infill_tile", title="Tile Infill", tags=["image", "inpaint"], category="inpaint", version="1.0.0") class InfillTileInvocation(BaseInvocation): """Infills transparent areas of an image with tiles of the image""" @@ -187,7 +187,9 @@ class InfillTileInvocation(BaseInvocation): ) -@invocation("infill_patchmatch", title="PatchMatch Infill", tags=["image", "inpaint"], category="inpaint") +@invocation( + "infill_patchmatch", title="PatchMatch Infill", tags=["image", "inpaint"], category="inpaint", version="1.0.0" +) class InfillPatchMatchInvocation(BaseInvocation): """Infills transparent areas of an image using the PatchMatch algorithm""" @@ -218,7 +220,7 @@ class InfillPatchMatchInvocation(BaseInvocation): ) -@invocation("infill_lama", title="LaMa Infill", tags=["image", "inpaint"], category="inpaint") +@invocation("infill_lama", title="LaMa Infill", tags=["image", "inpaint"], category="inpaint", version="1.0.0") class LaMaInfillInvocation(BaseInvocation): """Infills transparent areas of an image using the LaMa model""" diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py index c0e53e4e12..8fde088b36 100644 --- a/invokeai/app/invocations/latent.py +++ b/invokeai/app/invocations/latent.py @@ -74,7 +74,7 @@ class SchedulerOutput(BaseInvocationOutput): scheduler: SAMPLER_NAME_VALUES = OutputField(description=FieldDescriptions.scheduler, ui_type=UIType.Scheduler) -@invocation("scheduler", title="Scheduler", tags=["scheduler"], category="latents") +@invocation("scheduler", title="Scheduler", tags=["scheduler"], category="latents", version="1.0.0") class SchedulerInvocation(BaseInvocation): """Selects a scheduler.""" @@ -86,7 +86,9 @@ class SchedulerInvocation(BaseInvocation): return SchedulerOutput(scheduler=self.scheduler) -@invocation("create_denoise_mask", title="Create Denoise Mask", tags=["mask", "denoise"], category="latents") +@invocation( + "create_denoise_mask", title="Create Denoise Mask", tags=["mask", "denoise"], category="latents", version="1.0.0" +) class CreateDenoiseMaskInvocation(BaseInvocation): """Creates mask for denoising model run.""" @@ -186,6 +188,7 @@ def get_scheduler( title="Denoise Latents", tags=["latents", "denoise", "txt2img", "t2i", "t2l", "img2img", "i2i", "l2l"], category="latents", + version="1.0.0", ) class DenoiseLatentsInvocation(BaseInvocation): """Denoises noisy latents to decodable images""" @@ -544,7 +547,9 @@ class DenoiseLatentsInvocation(BaseInvocation): return build_latents_output(latents_name=name, latents=result_latents, seed=seed) -@invocation("l2i", title="Latents to Image", tags=["latents", "image", "vae", "l2i"], category="latents") +@invocation( + "l2i", title="Latents to Image", tags=["latents", "image", "vae", "l2i"], category="latents", version="1.0.0" +) class LatentsToImageInvocation(BaseInvocation): """Generates an image from latents.""" @@ -641,7 +646,7 @@ class LatentsToImageInvocation(BaseInvocation): LATENTS_INTERPOLATION_MODE = Literal["nearest", "linear", "bilinear", "bicubic", "trilinear", "area", "nearest-exact"] -@invocation("lresize", title="Resize Latents", tags=["latents", "resize"], category="latents") +@invocation("lresize", title="Resize Latents", tags=["latents", "resize"], category="latents", version="1.0.0") class ResizeLatentsInvocation(BaseInvocation): """Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8.""" @@ -685,7 +690,7 @@ class ResizeLatentsInvocation(BaseInvocation): return build_latents_output(latents_name=name, latents=resized_latents, seed=self.latents.seed) -@invocation("lscale", title="Scale Latents", tags=["latents", "resize"], category="latents") +@invocation("lscale", title="Scale Latents", tags=["latents", "resize"], category="latents", version="1.0.0") class ScaleLatentsInvocation(BaseInvocation): """Scales latents by a given factor.""" @@ -721,7 +726,9 @@ class ScaleLatentsInvocation(BaseInvocation): return build_latents_output(latents_name=name, latents=resized_latents, seed=self.latents.seed) -@invocation("i2l", title="Image to Latents", tags=["latents", "image", "vae", "i2l"], category="latents") +@invocation( + "i2l", title="Image to Latents", tags=["latents", "image", "vae", "i2l"], category="latents", version="1.0.0" +) class ImageToLatentsInvocation(BaseInvocation): """Encodes an image into latents.""" @@ -801,7 +808,7 @@ class ImageToLatentsInvocation(BaseInvocation): return build_latents_output(latents_name=name, latents=latents, seed=None) -@invocation("lblend", title="Blend Latents", tags=["latents", "blend"], category="latents") +@invocation("lblend", title="Blend Latents", tags=["latents", "blend"], category="latents", version="1.0.0") class BlendLatentsInvocation(BaseInvocation): """Blend two latents using a given alpha. Latents must have same size.""" diff --git a/invokeai/app/invocations/math.py b/invokeai/app/invocations/math.py index 2a8dc12b28..0bc8b7b950 100644 --- a/invokeai/app/invocations/math.py +++ b/invokeai/app/invocations/math.py @@ -7,7 +7,7 @@ from invokeai.app.invocations.primitives import IntegerOutput from .baseinvocation import BaseInvocation, FieldDescriptions, InputField, InvocationContext, invocation -@invocation("add", title="Add Integers", tags=["math", "add"], category="math") +@invocation("add", title="Add Integers", tags=["math", "add"], category="math", version="1.0.0") class AddInvocation(BaseInvocation): """Adds two numbers""" @@ -18,7 +18,7 @@ class AddInvocation(BaseInvocation): return IntegerOutput(value=self.a + self.b) -@invocation("sub", title="Subtract Integers", tags=["math", "subtract"], category="math") +@invocation("sub", title="Subtract Integers", tags=["math", "subtract"], category="math", version="1.0.0") class SubtractInvocation(BaseInvocation): """Subtracts two numbers""" @@ -29,7 +29,7 @@ class SubtractInvocation(BaseInvocation): return IntegerOutput(value=self.a - self.b) -@invocation("mul", title="Multiply Integers", tags=["math", "multiply"], category="math") +@invocation("mul", title="Multiply Integers", tags=["math", "multiply"], category="math", version="1.0.0") class MultiplyInvocation(BaseInvocation): """Multiplies two numbers""" @@ -40,7 +40,7 @@ class MultiplyInvocation(BaseInvocation): return IntegerOutput(value=self.a * self.b) -@invocation("div", title="Divide Integers", tags=["math", "divide"], category="math") +@invocation("div", title="Divide Integers", tags=["math", "divide"], category="math", version="1.0.0") class DivideInvocation(BaseInvocation): """Divides two numbers""" @@ -51,7 +51,7 @@ class DivideInvocation(BaseInvocation): return IntegerOutput(value=int(self.a / self.b)) -@invocation("rand_int", title="Random Integer", tags=["math", "random"], category="math") +@invocation("rand_int", title="Random Integer", tags=["math", "random"], category="math", version="1.0.0") class RandomIntInvocation(BaseInvocation): """Outputs a single random integer.""" diff --git a/invokeai/app/invocations/metadata.py b/invokeai/app/invocations/metadata.py index 9c028a2dc1..39fa3beba0 100644 --- a/invokeai/app/invocations/metadata.py +++ b/invokeai/app/invocations/metadata.py @@ -98,7 +98,9 @@ class MetadataAccumulatorOutput(BaseInvocationOutput): metadata: CoreMetadata = OutputField(description="The core metadata for the image") -@invocation("metadata_accumulator", title="Metadata Accumulator", tags=["metadata"], category="metadata") +@invocation( + "metadata_accumulator", title="Metadata Accumulator", tags=["metadata"], category="metadata", version="1.0.0" +) class MetadataAccumulatorInvocation(BaseInvocation): """Outputs a Core Metadata Object""" diff --git a/invokeai/app/invocations/model.py b/invokeai/app/invocations/model.py index 5a1073df0a..571cb2e730 100644 --- a/invokeai/app/invocations/model.py +++ b/invokeai/app/invocations/model.py @@ -73,7 +73,7 @@ class LoRAModelField(BaseModel): base_model: BaseModelType = Field(description="Base model") -@invocation("main_model_loader", title="Main Model", tags=["model"], category="model") +@invocation("main_model_loader", title="Main Model", tags=["model"], category="model", version="1.0.0") class MainModelLoaderInvocation(BaseInvocation): """Loads a main model, outputting its submodels.""" @@ -173,7 +173,7 @@ class LoraLoaderOutput(BaseInvocationOutput): clip: Optional[ClipField] = OutputField(default=None, description=FieldDescriptions.clip, title="CLIP") -@invocation("lora_loader", title="LoRA", tags=["model"], category="model") +@invocation("lora_loader", title="LoRA", tags=["model"], category="model", version="1.0.0") class LoraLoaderInvocation(BaseInvocation): """Apply selected lora to unet and text_encoder.""" @@ -244,7 +244,7 @@ class SDXLLoraLoaderOutput(BaseInvocationOutput): clip2: Optional[ClipField] = OutputField(default=None, description=FieldDescriptions.clip, title="CLIP 2") -@invocation("sdxl_lora_loader", title="SDXL LoRA", tags=["lora", "model"], category="model") +@invocation("sdxl_lora_loader", title="SDXL LoRA", tags=["lora", "model"], category="model", version="1.0.0") class SDXLLoraLoaderInvocation(BaseInvocation): """Apply selected lora to unet and text_encoder.""" @@ -338,7 +338,7 @@ class VaeLoaderOutput(BaseInvocationOutput): vae: VaeField = OutputField(description=FieldDescriptions.vae, title="VAE") -@invocation("vae_loader", title="VAE", tags=["vae", "model"], category="model") +@invocation("vae_loader", title="VAE", tags=["vae", "model"], category="model", version="1.0.0") class VaeLoaderInvocation(BaseInvocation): """Loads a VAE model, outputting a VaeLoaderOutput""" @@ -376,7 +376,7 @@ class SeamlessModeOutput(BaseInvocationOutput): vae: Optional[VaeField] = OutputField(description=FieldDescriptions.vae, title="VAE") -@invocation("seamless", title="Seamless", tags=["seamless", "model"], category="model") +@invocation("seamless", title="Seamless", tags=["seamless", "model"], category="model", version="1.0.0") class SeamlessModeInvocation(BaseInvocation): """Applies the seamless transformation to the Model UNet and VAE.""" diff --git a/invokeai/app/invocations/noise.py b/invokeai/app/invocations/noise.py index 1f1d9fe3ce..c46747aa89 100644 --- a/invokeai/app/invocations/noise.py +++ b/invokeai/app/invocations/noise.py @@ -78,7 +78,7 @@ def build_noise_output(latents_name: str, latents: torch.Tensor, seed: int): ) -@invocation("noise", title="Noise", tags=["latents", "noise"], category="latents") +@invocation("noise", title="Noise", tags=["latents", "noise"], category="latents", version="1.0.0") class NoiseInvocation(BaseInvocation): """Generates latent noise.""" diff --git a/invokeai/app/invocations/onnx.py b/invokeai/app/invocations/onnx.py index b61ea2da99..d346a5f58f 100644 --- a/invokeai/app/invocations/onnx.py +++ b/invokeai/app/invocations/onnx.py @@ -56,7 +56,7 @@ ORT_TO_NP_TYPE = { PRECISION_VALUES = Literal[tuple(list(ORT_TO_NP_TYPE.keys()))] -@invocation("prompt_onnx", title="ONNX Prompt (Raw)", tags=["prompt", "onnx"], category="conditioning") +@invocation("prompt_onnx", title="ONNX Prompt (Raw)", tags=["prompt", "onnx"], category="conditioning", version="1.0.0") class ONNXPromptInvocation(BaseInvocation): prompt: str = InputField(default="", description=FieldDescriptions.raw_prompt, ui_component=UIComponent.Textarea) clip: ClipField = InputField(description=FieldDescriptions.clip, input=Input.Connection) @@ -143,6 +143,7 @@ class ONNXPromptInvocation(BaseInvocation): title="ONNX Text to Latents", tags=["latents", "inference", "txt2img", "onnx"], category="latents", + version="1.0.0", ) class ONNXTextToLatentsInvocation(BaseInvocation): """Generates latents from conditionings.""" @@ -319,6 +320,7 @@ class ONNXTextToLatentsInvocation(BaseInvocation): title="ONNX Latents to Image", tags=["latents", "image", "vae", "onnx"], category="image", + version="1.0.0", ) class ONNXLatentsToImageInvocation(BaseInvocation): """Generates an image from latents.""" @@ -403,7 +405,7 @@ class OnnxModelField(BaseModel): model_type: ModelType = Field(description="Model Type") -@invocation("onnx_model_loader", title="ONNX Main Model", tags=["onnx", "model"], category="model") +@invocation("onnx_model_loader", title="ONNX Main Model", tags=["onnx", "model"], category="model", version="1.0.0") class OnnxModelLoaderInvocation(BaseInvocation): """Loads a main model, outputting its submodels.""" diff --git a/invokeai/app/invocations/param_easing.py b/invokeai/app/invocations/param_easing.py index 1b3c0dc09e..9cfe447372 100644 --- a/invokeai/app/invocations/param_easing.py +++ b/invokeai/app/invocations/param_easing.py @@ -45,7 +45,7 @@ from invokeai.app.invocations.primitives import FloatCollectionOutput from .baseinvocation import BaseInvocation, InputField, InvocationContext, invocation -@invocation("float_range", title="Float Range", tags=["math", "range"], category="math") +@invocation("float_range", title="Float Range", tags=["math", "range"], category="math", version="1.0.0") class FloatLinearRangeInvocation(BaseInvocation): """Creates a range""" @@ -96,7 +96,7 @@ EASING_FUNCTION_KEYS = Literal[tuple(list(EASING_FUNCTIONS_MAP.keys()))] # actually I think for now could just use CollectionOutput (which is list[Any] -@invocation("step_param_easing", title="Step Param Easing", tags=["step", "easing"], category="step") +@invocation("step_param_easing", title="Step Param Easing", tags=["step", "easing"], category="step", version="1.0.0") class StepParamEasingInvocation(BaseInvocation): """Experimental per-step parameter easing for denoising steps""" diff --git a/invokeai/app/invocations/primitives.py b/invokeai/app/invocations/primitives.py index fdadc4b31b..93cf29f7d6 100644 --- a/invokeai/app/invocations/primitives.py +++ b/invokeai/app/invocations/primitives.py @@ -44,7 +44,9 @@ class BooleanCollectionOutput(BaseInvocationOutput): ) -@invocation("boolean", title="Boolean Primitive", tags=["primitives", "boolean"], category="primitives") +@invocation( + "boolean", title="Boolean Primitive", tags=["primitives", "boolean"], category="primitives", version="1.0.0" +) class BooleanInvocation(BaseInvocation): """A boolean primitive value""" @@ -59,6 +61,7 @@ class BooleanInvocation(BaseInvocation): title="Boolean Collection Primitive", tags=["primitives", "boolean", "collection"], category="primitives", + version="1.0.0", ) class BooleanCollectionInvocation(BaseInvocation): """A collection of boolean primitive values""" @@ -90,7 +93,9 @@ class IntegerCollectionOutput(BaseInvocationOutput): ) -@invocation("integer", title="Integer Primitive", tags=["primitives", "integer"], category="primitives") +@invocation( + "integer", title="Integer Primitive", tags=["primitives", "integer"], category="primitives", version="1.0.0" +) class IntegerInvocation(BaseInvocation): """An integer primitive value""" @@ -105,6 +110,7 @@ class IntegerInvocation(BaseInvocation): title="Integer Collection Primitive", tags=["primitives", "integer", "collection"], category="primitives", + version="1.0.0", ) class IntegerCollectionInvocation(BaseInvocation): """A collection of integer primitive values""" @@ -136,7 +142,7 @@ class FloatCollectionOutput(BaseInvocationOutput): ) -@invocation("float", title="Float Primitive", tags=["primitives", "float"], category="primitives") +@invocation("float", title="Float Primitive", tags=["primitives", "float"], category="primitives", version="1.0.0") class FloatInvocation(BaseInvocation): """A float primitive value""" @@ -151,6 +157,7 @@ class FloatInvocation(BaseInvocation): title="Float Collection Primitive", tags=["primitives", "float", "collection"], category="primitives", + version="1.0.0", ) class FloatCollectionInvocation(BaseInvocation): """A collection of float primitive values""" @@ -182,7 +189,7 @@ class StringCollectionOutput(BaseInvocationOutput): ) -@invocation("string", title="String Primitive", tags=["primitives", "string"], category="primitives") +@invocation("string", title="String Primitive", tags=["primitives", "string"], category="primitives", version="1.0.0") class StringInvocation(BaseInvocation): """A string primitive value""" @@ -197,6 +204,7 @@ class StringInvocation(BaseInvocation): title="String Collection Primitive", tags=["primitives", "string", "collection"], category="primitives", + version="1.0.0", ) class StringCollectionInvocation(BaseInvocation): """A collection of string primitive values""" @@ -236,7 +244,7 @@ class ImageCollectionOutput(BaseInvocationOutput): ) -@invocation("image", title="Image Primitive", tags=["primitives", "image"], category="primitives") +@invocation("image", title="Image Primitive", tags=["primitives", "image"], category="primitives", version="1.0.0") class ImageInvocation(BaseInvocation): """An image primitive value""" @@ -257,6 +265,7 @@ class ImageInvocation(BaseInvocation): title="Image Collection Primitive", tags=["primitives", "image", "collection"], category="primitives", + version="1.0.0", ) class ImageCollectionInvocation(BaseInvocation): """A collection of image primitive values""" @@ -318,7 +327,9 @@ class LatentsCollectionOutput(BaseInvocationOutput): ) -@invocation("latents", title="Latents Primitive", tags=["primitives", "latents"], category="primitives") +@invocation( + "latents", title="Latents Primitive", tags=["primitives", "latents"], category="primitives", version="1.0.0" +) class LatentsInvocation(BaseInvocation): """A latents tensor primitive value""" @@ -335,6 +346,7 @@ class LatentsInvocation(BaseInvocation): title="Latents Collection Primitive", tags=["primitives", "latents", "collection"], category="primitives", + version="1.0.0", ) class LatentsCollectionInvocation(BaseInvocation): """A collection of latents tensor primitive values""" @@ -388,7 +400,7 @@ class ColorCollectionOutput(BaseInvocationOutput): ) -@invocation("color", title="Color Primitive", tags=["primitives", "color"], category="primitives") +@invocation("color", title="Color Primitive", tags=["primitives", "color"], category="primitives", version="1.0.0") class ColorInvocation(BaseInvocation): """A color primitive value""" @@ -430,6 +442,7 @@ class ConditioningCollectionOutput(BaseInvocationOutput): title="Conditioning Primitive", tags=["primitives", "conditioning"], category="primitives", + version="1.0.0", ) class ConditioningInvocation(BaseInvocation): """A conditioning tensor primitive value""" @@ -445,6 +458,7 @@ class ConditioningInvocation(BaseInvocation): title="Conditioning Collection Primitive", tags=["primitives", "conditioning", "collection"], category="primitives", + version="1.0.0", ) class ConditioningCollectionInvocation(BaseInvocation): """A collection of conditioning tensor primitive values""" diff --git a/invokeai/app/invocations/prompt.py b/invokeai/app/invocations/prompt.py index c42deeaa2c..69ce1dba49 100644 --- a/invokeai/app/invocations/prompt.py +++ b/invokeai/app/invocations/prompt.py @@ -10,7 +10,7 @@ from invokeai.app.invocations.primitives import StringCollectionOutput from .baseinvocation import BaseInvocation, InputField, InvocationContext, UIComponent, invocation -@invocation("dynamic_prompt", title="Dynamic Prompt", tags=["prompt", "collection"], category="prompt") +@invocation("dynamic_prompt", title="Dynamic Prompt", tags=["prompt", "collection"], category="prompt", version="1.0.0") class DynamicPromptInvocation(BaseInvocation): """Parses a prompt using adieyal/dynamicprompts' random or combinatorial generator""" @@ -29,7 +29,7 @@ class DynamicPromptInvocation(BaseInvocation): return StringCollectionOutput(collection=prompts) -@invocation("prompt_from_file", title="Prompts from File", tags=["prompt", "file"], category="prompt") +@invocation("prompt_from_file", title="Prompts from File", tags=["prompt", "file"], category="prompt", version="1.0.0") class PromptsFromFileInvocation(BaseInvocation): """Loads prompts from a text file""" diff --git a/invokeai/app/invocations/sdxl.py b/invokeai/app/invocations/sdxl.py index 288858a173..de4ea604b4 100644 --- a/invokeai/app/invocations/sdxl.py +++ b/invokeai/app/invocations/sdxl.py @@ -33,7 +33,7 @@ class SDXLRefinerModelLoaderOutput(BaseInvocationOutput): vae: VaeField = OutputField(description=FieldDescriptions.vae, title="VAE") -@invocation("sdxl_model_loader", title="SDXL Main Model", tags=["model", "sdxl"], category="model") +@invocation("sdxl_model_loader", title="SDXL Main Model", tags=["model", "sdxl"], category="model", version="1.0.0") class SDXLModelLoaderInvocation(BaseInvocation): """Loads an sdxl base model, outputting its submodels.""" @@ -119,6 +119,7 @@ class SDXLModelLoaderInvocation(BaseInvocation): title="SDXL Refiner Model", tags=["model", "sdxl", "refiner"], category="model", + version="1.0.0", ) class SDXLRefinerModelLoaderInvocation(BaseInvocation): """Loads an sdxl refiner model, outputting its submodels.""" diff --git a/invokeai/app/invocations/upscale.py b/invokeai/app/invocations/upscale.py index e9fb3f9963..7dca6d9f21 100644 --- a/invokeai/app/invocations/upscale.py +++ b/invokeai/app/invocations/upscale.py @@ -23,7 +23,7 @@ ESRGAN_MODELS = Literal[ ] -@invocation("esrgan", title="Upscale (RealESRGAN)", tags=["esrgan", "upscale"], category="esrgan") +@invocation("esrgan", title="Upscale (RealESRGAN)", tags=["esrgan", "upscale"], category="esrgan", version="1.0.0") class ESRGANInvocation(BaseInvocation): """Upscales an image using RealESRGAN.""" diff --git a/pyproject.toml b/pyproject.toml index 129538264d..4b06944b33 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,6 +74,7 @@ dependencies = [ "rich~=13.3", "safetensors==0.3.1", "scikit-image~=0.21.0", + "semver~=3.0.1", "send2trash", "test-tube~=0.7.5", "torch~=2.0.1",