diff --git a/README.md b/README.md index f10c372545..c40b9ef418 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Web Interface, interactive Command Line Interface, and also serves as the foundation for multiple commercial products. **Quick links**: [[How to - Install](https://invoke-ai.github.io/InvokeAI/#installation)] [Discord Server] [Documentation and Tutorials] [ + --> + diff --git a/docs/features/NODES.md b/docs/features/NODES.md deleted file mode 100644 index eef71eb974..0000000000 --- a/docs/features/NODES.md +++ /dev/null @@ -1,208 +0,0 @@ -# Nodes Editor (Experimental) - -🚨 -*The node editor is experimental. We've made it accessible because we use it to develop the application, but we have not addressed the many known rough edges. It's very easy to shoot yourself in the foot, and we cannot offer support for it until it sees full release (ETA v3.1). Everything is subject to change without warning.* -🚨 - -The nodes editor is a blank canvas allowing for the use of individual functions and image transformations to control the image generation workflow. The node processing flow is usually done from left (inputs) to right (outputs), though linearity can become abstracted the more complex the node graph becomes. Nodes inputs and outputs are connected by dragging connectors from node to node. - -To better understand how nodes are used, think of how an electric power bar works. It takes in one input (electricity from a wall outlet) and passes it to multiple devices through multiple outputs. Similarly, a node could have multiple inputs and outputs functioning at the same (or different) time, but all node outputs pass information onward like a power bar passes electricity. Not all outputs are compatible with all inputs, however - Each node has different constraints on how it is expecting to input/output information. In general, node outputs are colour-coded to match compatible inputs of other nodes. - -## Anatomy of a Node - -Individual nodes are made up of the following: - -- Inputs: Edge points on the left side of the node window where you connect outputs from other nodes. -- Outputs: Edge points on the right side of the node window where you connect to inputs on other nodes. -- Options: Various options which are either manually configured, or overridden by connecting an output from another node to the input. - -## Diffusion Overview - -Taking the time to understand the diffusion process will help you to understand how to set up your nodes in the nodes editor. - -There are two main spaces Stable Diffusion works in: image space and latent space. - -Image space represents images in pixel form that you look at. Latent space represents compressed inputs. It’s in latent space that Stable Diffusion processes images. A VAE (Variational Auto Encoder) is responsible for compressing and encoding inputs into latent space, as well as decoding outputs back into image space. - -When you generate an image using text-to-image, multiple steps occur in latent space: -1. Random noise is generated at the chosen height and width. The noise’s characteristics are dictated by the chosen (or not chosen) seed. This noise tensor is passed into latent space. We’ll call this noise A. -1. Using a model’s U-Net, a noise predictor examines noise A, and the words tokenized by CLIP from your prompt (conditioning). It generates its own noise tensor to predict what the final image might look like in latent space. We’ll call this noise B. -1. Noise B is subtracted from noise A in an attempt to create a final latent image indicative of the inputs. This step is repeated for the number of sampler steps chosen. -1. The VAE decodes the final latent image from latent space into image space. - -image-to-image is a similar process, with only step 1 being different: -1. The input image is decoded from image space into latent space by the VAE. Noise is then added to the input latent image. Denoising Strength dictates how much noise is added, 0 being none, and 1 being all-encompassing. We’ll call this noise A. The process is then the same as steps 2-4 in the text-to-image explanation above. - -Furthermore, a model provides the CLIP prompt tokenizer, the VAE, and a U-Net (where noise prediction occurs given a prompt and initial noise tensor). - -A noise scheduler (eg. DPM++ 2M Karras) schedules the subtraction of noise from the latent image across the sampler steps chosen (step 3 above). Less noise is usually subtracted at higher sampler steps. - -## Node Types (Base Nodes) - -| Node | Function | -| ---------------------------------- | --------------------------------------------------------------------------------------| -| Add | Adds two numbers | -| CannyImageProcessor | Canny edge detection for ControlNet | -| ClipSkip | Skip layers in clip text_encoder model | -| Collect | Collects values into a collection | -| Prompt (Compel) | Parse prompt using compel package to conditioning | -| ContentShuffleImageProcessor | Applies content shuffle processing to image | -| ControlNet | Collects ControlNet info to pass to other nodes | -| CvInpaint | Simple inpaint using opencv | -| Divide | Divides two numbers | -| DynamicPrompt | Parses a prompt using adieyal/dynamic prompt's random or combinatorial generator | -| FloatLinearRange | Creates a range | -| HedImageProcessor | Applies HED edge detection to image | -| ImageBlur | Blurs an image | -| ImageChannel | Gets a channel from an image | -| ImageCollection | Load a collection of images and provide it as output | -| ImageConvert | Converts an image to a different mode | -| ImageCrop | Crops an image to a specified box. The box can be outside of the image. | -| ImageInverseLerp | Inverse linear interpolation of all pixels of an image | -| ImageLerp | Linear interpolation of all pixels of an image | -| ImageMultiply | Multiplies two images together using `PIL.ImageChops.Multiply()` | -| ImageNSFWBlurInvocation | Detects and blurs images that may contain sexually explicit content | -| ImagePaste | Pastes an image into another image | -| ImageProcessor | Base class for invocations that reprocess images for ControlNet | -| ImageResize | Resizes an image to specific dimensions | -| ImageScale | Scales an image by a factor | -| ImageToLatents | Scales latents by a given factor | -| ImageWatermarkInvocation | Adds an invisible watermark to images | -| InfillColor | Infills transparent areas of an image with a solid color | -| InfillPatchMatch | Infills transparent areas of an image using the PatchMatch algorithm | -| InfillTile | Infills transparent areas of an image with tiles of the image | -| Inpaint | Generates an image using inpaint | -| Iterate | Iterates over a list of items | -| LatentsToImage | Generates an image from latents | -| LatentsToLatents | Generates latents using latents as base image | -| LeresImageProcessor | Applies leres processing to image | -| LineartAnimeImageProcessor | Applies line art anime processing to image | -| LineartImageProcessor | Applies line art processing to image | -| LoadImage | Load an image and provide it as output | -| Lora Loader | Apply selected lora to unet and text_encoder | -| Model Loader | Loads a main model, outputting its submodels | -| MaskFromAlpha | Extracts the alpha channel of an image as a mask | -| MediapipeFaceProcessor | Applies mediapipe face processing to image | -| MidasDepthImageProcessor | Applies Midas depth processing to image | -| MlsdImageProcessor | Applied MLSD processing to image | -| Multiply | Multiplies two numbers | -| Noise | Generates latent noise | -| NormalbaeImageProcessor | Applies NormalBAE processing to image | -| OpenposeImageProcessor | Applies Openpose processing to image | -| ParamFloat | A float parameter | -| ParamInt | An integer parameter | -| PidiImageProcessor | Applies PIDI processing to an image | -| Progress Image | Displays the progress image in the Node Editor | -| RandomInit | Outputs a single random integer | -| RandomRange | Creates a collection of random numbers | -| Range | Creates a range of numbers from start to stop with step | -| RangeOfSize | Creates a range from start to start + size with step | -| ResizeLatents | Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8. | -| RestoreFace | Restores faces in the image | -| ScaleLatents | Scales latents by a given factor | -| SegmentAnythingProcessor | Applies segment anything processing to image | -| ShowImage | Displays a provided image, and passes it forward in the pipeline | -| StepParamEasing | Experimental per-step parameter for easing for denoising steps | -| Subtract | Subtracts two numbers | -| TextToLatents | Generates latents from conditionings | -| TileResampleProcessor | Bass class for invocations that preprocess images for ControlNet | -| Upscale | Upscales an image | -| VAE Loader | Loads a VAE model, outputting a VaeLoaderOutput | -| ZoeDepthImageProcessor | Applies Zoe depth processing to image | - -## Node Grouping Concepts - -There are several node grouping concepts that can be examined with a narrow focus. These (and other) groupings can be pieced together to make up functional graph setups, and are important to understanding how groups of nodes work together as part of a whole. Note that the screenshots below aren't examples of complete functioning node graphs (see Examples). - -### Noise - -As described, an initial noise tensor is necessary for the latent diffusion process. As a result, all non-image *ToLatents nodes require a noise node input. - -![groupsnoise](../assets/nodes/groupsnoise.png) - -### Conditioning - -As described, conditioning is necessary for the latent diffusion process, whether empty or not. As a result, all non-image *ToLatents nodes require positive and negative conditioning inputs. Conditioning is reliant on a CLIP tokenizer provided by the Model Loader node. - -![groupsconditioning](../assets/nodes/groupsconditioning.png) - -### Image Space & VAE - -The ImageToLatents node doesn't require a noise node input, but requires a VAE input to convert the image from image space into latent space. In reverse, the LatentsToImage node requires a VAE input to convert from latent space back into image space. - -![groupsimgvae](../assets/nodes/groupsimgvae.png) - -### Defined & Random Seeds - -It is common to want to use both the same seed (for continuity) and random seeds (for variance). To define a seed, simply enter it into the 'Seed' field on a noise node. Conversely, the RandomInt node generates a random integer between 'Low' and 'High', and can be used as input to the 'Seed' edge point on a noise node to randomize your seed. - -![groupsrandseed](../assets/nodes/groupsrandseed.png) - -### Control - -Control means to guide the diffusion process to adhere to a defined input or structure. Control can be provided as input to non-image *ToLatents nodes from ControlNet nodes. ControlNet nodes usually require an image processor which converts an input image for use with ControlNet. - -![groupscontrol](../assets/nodes/groupscontrol.png) - -### LoRA - -The Lora Loader node lets you load a LoRA (say that ten times fast) and pass it as output to both the Prompt (Compel) and non-image *ToLatents nodes. A model's CLIP tokenizer is passed through the LoRA into Prompt (Compel), where it affects conditioning. A model's U-Net is also passed through the LoRA into a non-image *ToLatents node, where it affects noise prediction. - -![groupslora](../assets/nodes/groupslora.png) - -### Scaling - -Use the ImageScale, ScaleLatents, and Upscale nodes to upscale images and/or latent images. The chosen method differs across contexts. However, be aware that latents are already noisy and compressed at their original resolution; scaling an image could produce more detailed results. - -![groupsallscale](../assets/nodes/groupsallscale.png) - -### Iteration + Multiple Images as Input - -Iteration is a common concept in any processing, and means to repeat a process with given input. In nodes, you're able to use the Iterate node to iterate through collections usually gathered by the Collect node. The Iterate node has many potential uses, from processing a collection of images one after another, to varying seeds across multiple image generations and more. This screenshot demonstrates how to collect several images and pass them out one at a time. - -![groupsiterate](../assets/nodes/groupsiterate.png) - -### Multiple Image Generation + Random Seeds - -Multiple image generation in the node editor is done using the RandomRange node. In this case, the 'Size' field represents the number of images to generate. As RandomRange produces a collection of integers, we need to add the Iterate node to iterate through the collection. - -To control seeds across generations takes some care. The first row in the screenshot will generate multiple images with different seeds, but using the same RandomRange parameters across invocations will result in the same group of random seeds being used across the images, producing repeatable results. In the second row, adding the RandomInt node as input to RandomRange's 'Seed' edge point will ensure that seeds are varied across all images across invocations, producing varied results. - -![groupsmultigenseeding](../assets/nodes/groupsmultigenseeding.png) - -## Examples - -With our knowledge of node grouping and the diffusion process, let’s break down some basic graphs in the nodes editor. Note that a node's options can be overridden by inputs from other nodes. These examples aren't strict rules to follow and only demonstrate some basic configurations. - -### Basic text-to-image Node Graph - -![nodest2i](../assets/nodes/nodest2i.png) - -- Model Loader: A necessity to generating images (as we’ve read above). We choose our model from the dropdown. It outputs a U-Net, CLIP tokenizer, and VAE. -- Prompt (Compel): Another necessity. Two prompt nodes are created. One will output positive conditioning (what you want, ‘dog’), one will output negative (what you don’t want, ‘cat’). They both input the CLIP tokenizer that the Model Loader node outputs. -- Noise: Consider this noise A from step one of the text-to-image explanation above. Choose a seed number, width, and height. -- TextToLatents: This node takes many inputs for converting and processing text & noise from image space into latent space, hence the name TextTo**Latents**. In this setup, it inputs positive and negative conditioning from the prompt nodes for processing (step 2 above). It inputs noise from the noise node for processing (steps 2 & 3 above). Lastly, it inputs a U-Net from the Model Loader node for processing (step 2 above). It outputs latents for use in the next LatentsToImage node. Choose number of sampler steps, CFG scale, and scheduler. -- LatentsToImage: This node takes in processed latents from the TextToLatents node, and the model’s VAE from the Model Loader node which is responsible for decoding latents back into the image space, hence the name LatentsTo**Image**. This node is the last stop, and once the image is decoded, it is saved to the gallery. - -### Basic image-to-image Node Graph - -![nodesi2i](../assets/nodes/nodesi2i.png) - -- Model Loader: Choose a model from the dropdown. -- Prompt (Compel): Two prompt nodes. One positive (dog), one negative (dog). Same CLIP inputs from the Model Loader node as before. -- ImageToLatents: Upload a source image directly in the node window, via drag'n'drop from the gallery, or passed in as input. The ImageToLatents node inputs the VAE from the Model Loader node to decode the chosen image from image space into latent space, hence the name ImageTo**Latents**. It outputs latents for use in the next LatentsToLatents node. It also outputs the source image's width and height for use in the next Noise node if the final image is to be the same dimensions as the source image. -- Noise: A noise tensor is created with the width and height of the source image, and connected to the next LatentsToLatents node. Notice the width and height fields are overridden by the input from the ImageToLatents width and height outputs. -- LatentsToLatents: The inputs and options are nearly identical to TextToLatents, except that LatentsToLatents also takes latents as an input. Considering our source image is already converted to latents in the last ImageToLatents node, and text + noise are no longer the only inputs to process, we use the LatentsToLatents node. -- LatentsToImage: Like previously, the LatentsToImage node will use the VAE from the Model Loader as input to decode the latents from LatentsToLatents into image space, and save it to the gallery. - -### Basic ControlNet Node Graph - -![nodescontrol](../assets/nodes/nodescontrol.png) - -- Model Loader -- Prompt (Compel) -- Noise: Width and height of the CannyImageProcessor ControlNet image is passed in to set the dimensions of the noise passed to TextToLatents. -- CannyImageProcessor: The CannyImageProcessor node is used to process the source image being used as a ControlNet. Each ControlNet processor node applies control in different ways, and has some different options to configure. Width and height are passed to noise, as mentioned. The processed ControlNet image is output to the ControlNet node. -- ControlNet: Select the type of control model. In this case, canny is chosen as the CannyImageProcessor was used to generate the ControlNet image. Configure the control node options, and pass the control output to TextToLatents. -- TextToLatents: Similar to the basic text-to-image example, except ControlNet is passed to the control input edge point. -- LatentsToImage diff --git a/docs/features/PROMPTS.md b/docs/features/PROMPTS.md index 1fd4550493..66af903072 100644 --- a/docs/features/PROMPTS.md +++ b/docs/features/PROMPTS.md @@ -4,80 +4,6 @@ title: Prompting-Features # :octicons-command-palette-24: Prompting-Features -## **Negative and Unconditioned Prompts** - -Any words between a pair of square brackets will instruct Stable -Diffusion to attempt to ban the concept from the generated image. The -same effect is achieved by placing words in the "Negative Prompts" -textbox in the Web UI. - -```text -this is a test prompt [not really] to make you understand [cool] how this works. -``` - -In the above statement, the words 'not really cool` will be ignored by Stable -Diffusion. - -Here's a prompt that depicts what it does. - -original prompt: - -`#!bash "A fantastical translucent pony made of water and foam, ethereal, radiant, hyperalism, scottish folklore, digital painting, artstation, concept art, smooth, 8 k frostbite 3 engine, ultra detailed, art by artgerm and greg rutkowski and magali villeneuve"` - -`#!bash parameters: steps=20, dimensions=512x768, CFG=7.5, Scheduler=k_euler_a, seed=1654590180` - -
- -![step1](../assets/negative_prompt_walkthru/step1.png) - -
- -That image has a woman, so if we want the horse without a rider, we can -influence the image not to have a woman by putting [woman] in the prompt, like -this: - -`#!bash "A fantastical translucent poney made of water and foam, ethereal, radiant, hyperalism, scottish folklore, digital painting, artstation, concept art, smooth, 8 k frostbite 3 engine, ultra detailed, art by artgerm and greg rutkowski and magali villeneuve [woman]"` -(same parameters as above) - -
- -![step2](../assets/negative_prompt_walkthru/step2.png) - -
- -That's nice - but say we also don't want the image to be quite so blue. We can -add "blue" to the list of negative prompts, so it's now [woman blue]: - -`#!bash "A fantastical translucent poney made of water and foam, ethereal, radiant, hyperalism, scottish folklore, digital painting, artstation, concept art, smooth, 8 k frostbite 3 engine, ultra detailed, art by artgerm and greg rutkowski and magali villeneuve [woman blue]"` -(same parameters as above) - -
- -![step3](../assets/negative_prompt_walkthru/step3.png) - -
- -Getting close - but there's no sense in having a saddle when our horse doesn't -have a rider, so we'll add one more negative prompt: [woman blue saddle]. - -`#!bash "A fantastical translucent poney made of water and foam, ethereal, radiant, hyperalism, scottish folklore, digital painting, artstation, concept art, smooth, 8 k frostbite 3 engine, ultra detailed, art by artgerm and greg rutkowski and magali villeneuve [woman blue saddle]"` -(same parameters as above) - -
- -![step4](../assets/negative_prompt_walkthru/step4.png) - -
- -!!! notes "Notes about this feature:" - - * The only requirement for words to be ignored is that they are in between a pair of square brackets. - * You can provide multiple words within the same bracket. - * You can provide multiple brackets with multiple words in different places of your prompt. That works just fine. - * To improve typical anatomy problems, you can add negative prompts like `[bad anatomy, extra legs, extra arms, extra fingers, poorly drawn hands, poorly drawn feet, disfigured, out of frame, tiling, bad art, deformed, mutated]`. - ---- - ## **Prompt Syntax Features** The InvokeAI prompting language has the following features: @@ -102,9 +28,6 @@ The following syntax is recognised: `a tall thin man (picking (apricots)1.3)1.1`. (`+` is equivalent to 1.1, `++` is pow(1.1,2), `+++` is pow(1.1,3), etc; `-` means 0.9, `--` means pow(0.9,2), etc.) -- attention also applies to `[unconditioning]` so - `a tall thin man picking apricots [(ladder)0.01]` will _very gently_ nudge SD - away from trying to draw the man on a ladder You can use this to increase or decrease the amount of something. Starting from this prompt of `a man picking apricots from a tree`, let's see what happens if @@ -150,7 +73,7 @@ Or, alternatively, with more man: | ---------------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | | ![](../assets/prompt_syntax/mountain-man1.png) | ![](../assets/prompt_syntax/mountain-man2.png) | ![](../assets/prompt_syntax/mountain-man3.png) | ![](../assets/prompt_syntax/mountain-man4.png) | -### Blending between prompts +### Prompt Blending - `("a tall thin man picking apricots", "a tall thin man picking pears").blend(1,1)` - The existing prompt blending using `:` will continue to be supported - @@ -168,6 +91,24 @@ Or, alternatively, with more man: See the section below on "Prompt Blending" for more information about how this works. +### Prompt Conjunction +Join multiple clauses together to create a conjoined prompt. Each clause will be passed to CLIP separately. + +For example, the prompt: + +```bash +"A mystical valley surround by towering granite cliffs, watercolor, warm" +``` + +Can be used with .and(): +```bash +("A mystical valley", "surround by towering granite cliffs", "watercolor", "warm").and() +``` + +Each will give you different results - try them out and see what you prefer! + + + ### Cross-Attention Control ('prompt2prompt') Sometimes an image you generate is almost right, and you just want to change one @@ -190,7 +131,7 @@ For example, consider the prompt `a cat.swap(dog) playing with a ball in the for - For multiple word swaps, use parentheses: `a (fluffy cat).swap(barking dog) playing with a ball in the forest`. - To swap a comma, use quotes: `a ("fluffy, grey cat").swap("big, barking dog") playing with a ball in the forest`. -- Supports options `t_start` and `t_end` (each 0-1) loosely corresponding to bloc97's `prompt_edit_tokens_start/_end` but with the math swapped to make it easier to +- Supports options `t_start` and `t_end` (each 0-1) loosely corresponding to (bloc97's)[(https://github.com/bloc97/CrossAttentionControl)] `prompt_edit_tokens_start/_end` but with the math swapped to make it easier to intuitively understand. `t_start` and `t_end` are used to control on which steps cross-attention control should run. With the default values `t_start=0` and `t_end=1`, cross-attention control is active on every step of image generation. Other values can be used to turn cross-attention control off for part of the image generation process. - For example, if doing a diffusion with 10 steps for the prompt is `a cat.swap(dog, t_start=0.3, t_end=1.0) playing with a ball in the forest`, the first 3 steps will be run as `a cat playing with a ball in the forest`, while the last 7 steps will run as `a dog playing with a ball in the forest`, but the pixels that represent `dog` will be locked to the pixels that would have represented `cat` if the `cat` prompt had been used instead. - Conversely, for `a cat.swap(dog, t_start=0, t_end=0.7) playing with a ball in the forest`, the first 7 steps will run as `a dog playing with a ball in the forest` with the pixels that represent `dog` locked to the same pixels that would have represented `cat` if the `cat` prompt was being used instead. The final 3 steps will just run `a cat playing with a ball in the forest`. @@ -201,7 +142,7 @@ Prompt2prompt `.swap()` is not compatible with xformers, which will be temporari The `prompt2prompt` code is based off [bloc97's colab](https://github.com/bloc97/CrossAttentionControl). -### Escaping parantheses () and speech marks "" +### Escaping parentheses () and speech marks "" If the model you are using has parentheses () or speech marks "" as part of its syntax, you will need to "escape" these using a backslash, so that`(my_keyword)` @@ -212,23 +153,16 @@ the parentheses as part of the prompt syntax and it will get confused. ## **Prompt Blending** -You may blend together different sections of the prompt to explore the AI's +You may blend together prompts to explore the AI's latent semantic space and generate interesting (and often surprising!) variations. The syntax is: ```bash -blue sphere:0.25 red cube:0.75 hybrid +("prompt #1", "prompt #2").blend(0.25, 0.75) ``` -This will tell the sampler to blend 25% of the concept of a blue sphere with 75% -of the concept of a red cube. The blend weights can use any combination of -integers and floating point numbers, and they do not need to add up to 1. -Everything to the left of the `:XX` up to the previous `:XX` is used for -merging, so the overall effect is: - -```bash -0.25 * "blue sphere" + 0.75 * "white duck" + hybrid -``` +This will tell the sampler to blend 25% of the concept of prompt #1 with 75% +of the concept of prompt #2. It is recommended to keep the sum of the weights to around 1.0, but interesting things might happen if you go outside of this range. Because you are exploring the "mind" of the AI, the AI's way of mixing two concepts may not match yours, leading to surprising effects. To illustrate, here @@ -236,13 +170,14 @@ are three images generated using various combinations of blend weights. As usual, unless you fix the seed, the prompts will give you different results each time you run them. -
+Let's examine how this affects image generation results: -### "blue sphere, red cube, hybrid" -
+```bash +"blue sphere, red cube, hybrid" +``` -This example doesn't use melding at all and represents the default way of mixing +This example doesn't use blending at all and represents the default way of mixing concepts.
@@ -251,55 +186,47 @@ concepts.
-It's interesting to see how the AI expressed the concept of "cube" as the four -quadrants of the enclosing frame. If you look closely, there is depth there, so -the enclosing frame is actually a cube. +It's interesting to see how the AI expressed the concept of "cube" within the sphere. If you look closely, there is depth there, so the enclosing frame is actually a cube.
-### "blue sphere:0.25 red cube:0.75 hybrid" +```bash +("blue sphere", "red cube").blend(0.25, 0.75) +``` ![blue-sphere-25-red-cube-75](../assets/prompt-blending/blue-sphere-0.25-red-cube-0.75-hybrid.png)
-Now that's interesting. We get neither a blue sphere nor a red cube, but a red -sphere embedded in a brick wall, which represents a melding of concepts within -the AI's "latent space" of semantic representations. Where is Ludwig -Wittgenstein when you need him? +Now that's interesting. We get an image with a resemblance of a red cube, with a hint of blue shadows which represents a melding of concepts within the AI's "latent space" of semantic representations.
-### "blue sphere:0.75 red cube:0.25 hybrid" +```bash +("blue sphere", "red cube").blend(0.75, 0.25) +``` ![blue-sphere-75-red-cube-25](../assets/prompt-blending/blue-sphere-0.75-red-cube-0.25-hybrid.png)
-Definitely more blue-spherey. The cube is gone entirely, but it's really cool -abstract art. +Definitely more blue-spherey.
-### "blue sphere:0.5 red cube:0.5 hybrid" +```bash +("blue sphere", "red cube").blend(0.5, 0.5) +``` +
+
![blue-sphere-5-red-cube-5-hybrid](../assets/prompt-blending/blue-sphere-0.5-red-cube-0.5-hybrid.png) -
-Whoa...! I see blue and red, but no spheres or cubes. Is the word "hybrid" -summoning up the concept of some sort of scifi creature? Let's find out. -
+Whoa...! I see blue and red, and if I squint, spheres and cubes. -### "blue sphere:0.5 red cube:0.5" -![blue-sphere-5-red-cube-5](../assets/prompt-blending/blue-sphere-0.5-red-cube-0.5.png) - -
- -Indeed, removing the word "hybrid" produces an image that is more like what we'd -expect. ## Dynamic Prompts diff --git a/docs/features/index.md b/docs/features/index.md index e55917af5b..490da5e31f 100644 --- a/docs/features/index.md +++ b/docs/features/index.md @@ -30,10 +30,6 @@ image output. ### * [Image-to-Image Guide](IMG2IMG.md) Use a seed image to build new creations in the CLI. -### * [Generating Variations](VARIATIONS.md) -Have an image you like and want to generate many more like it? Variations -are the ticket. - ## Model Management ### * [Model Installation](../installation/050_INSTALLING_MODELS.md) diff --git a/docs/help/diffusion.md b/docs/help/diffusion.md new file mode 100644 index 0000000000..0dbb09f304 --- /dev/null +++ b/docs/help/diffusion.md @@ -0,0 +1,27 @@ +Taking the time to understand the diffusion process will help you to understand how to more effectively use InvokeAI. + +There are two main ways Stable Diffusion works - with images, and latents. + +Image space represents images in pixel form that you look at. Latent space represents compressed inputs. It’s in latent space that Stable Diffusion processes images. A VAE (Variational Auto Encoder) is responsible for compressing and encoding inputs into latent space, as well as decoding outputs back into image space. + +To fully understand the diffusion process, we need to understand a few more terms: UNet, CLIP, and conditioning. + +A U-Net is a model trained on a large number of latent images with with known amounts of random noise added. This means that the U-Net can be given a slightly noisy image and it will predict the pattern of noise needed to subtract from the image in order to recover the original. + +CLIP is a model that tokenizes and encodes text into conditioning. This conditioning guides the model during the denoising steps to produce a new image. + +The U-Net and CLIP work together during the image generation process at each denoising step, with the U-Net removing noise in such a way that the result is similar to images in the U-Net’s training set, while CLIP guides the U-Net towards creating images that are most similar to the prompt. + + +When you generate an image using text-to-image, multiple steps occur in latent space: +1. Random noise is generated at the chosen height and width. The noise’s characteristics are dictated by seed. This noise tensor is passed into latent space. We’ll call this noise A. +2. Using a model’s U-Net, a noise predictor examines noise A, and the words tokenized by CLIP from your prompt (conditioning). It generates its own noise tensor to predict what the final image might look like in latent space. We’ll call this noise B. +3. Noise B is subtracted from noise A in an attempt to create a latent image consistent with the prompt. This step is repeated for the number of sampler steps chosen. +4. The VAE decodes the final latent image from latent space into image space. + +Image-to-image is a similar process, with only step 1 being different: +1. The input image is encoded from image space into latent space by the VAE. Noise is then added to the input latent image. Denoising Strength dictates how may noise steps are added, and the amount of noise added at each step. A Denoising Strength of 0 means there are 0 steps and no noise added, resulting in an unchanged image, while a Denoising Strength of 1 results in the image being completely replaced with noise and a full set of denoising steps are performance. The process is then the same as steps 2-4 in the text-to-image process. + +Furthermore, a model provides the CLIP prompt tokenizer, the VAE, and a U-Net (where noise prediction occurs given a prompt and initial noise tensor). + +A noise scheduler (eg. DPM++ 2M Karras) schedules the subtraction of noise from the latent image across the sampler steps chosen (step 3 above). Less noise is usually subtracted at higher sampler steps. diff --git a/docs/index.md b/docs/index.md index 099e66908e..a317f4590e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -49,9 +49,9 @@ title: Home [![github stars badge]][github stars link] [![github forks badge]][github forks link] -[![CI checks on main badge]][ci checks on main link] + +[![latest commit to dev badge]][latest commit to dev link] --> [![github open issues badge]][github open issues link] [![github open prs badge]][github open prs link] diff --git a/docs/installation/020_INSTALL_MANUAL.md b/docs/installation/020_INSTALL_MANUAL.md index a68e5b1414..fd0fbe35ed 100644 --- a/docs/installation/020_INSTALL_MANUAL.md +++ b/docs/installation/020_INSTALL_MANUAL.md @@ -8,9 +8,9 @@ title: Installing Manually -!!! warning "This is for advanced Users" +!!! warning "This is for Advanced Users" - **python experience is mandatory** + **Python experience is mandatory** ## Introduction diff --git a/docs/installation/040_INSTALL_DOCKER.md b/docs/installation/040_INSTALL_DOCKER.md index 07e7f55e93..fd75067cf1 100644 --- a/docs/installation/040_INSTALL_DOCKER.md +++ b/docs/installation/040_INSTALL_DOCKER.md @@ -4,9 +4,9 @@ title: Installing with Docker # :fontawesome-brands-docker: Docker -!!! warning "For end users" +!!! warning "For most users" - We highly recommend to Install InvokeAI locally using [these instructions](index.md) + We highly recommend to Install InvokeAI locally using [these instructions](INSTALLATION.md) !!! tip "For developers" diff --git a/docs/javascripts/tablesort.js b/docs/javascripts/tablesort.js new file mode 100644 index 0000000000..ceb1f94acd --- /dev/null +++ b/docs/javascripts/tablesort.js @@ -0,0 +1,7 @@ +document$.subscribe(function() { + var tables = document.querySelectorAll("article table:not([class])") + tables.forEach(function(table) { + new Tablesort(table) + }) + }) + \ No newline at end of file diff --git a/docs/nodes/NODES.md b/docs/nodes/NODES.md new file mode 100644 index 0000000000..9455e6bdcf --- /dev/null +++ b/docs/nodes/NODES.md @@ -0,0 +1,68 @@ +# Using the Node Editor + +The nodes editor is a blank canvas allowing for the use of individual functions and image transformations to control the image generation workflow. Nodes take in inputs on the left side of the node, and return an output on the right side of the node. A node graph is composed of multiple nodes that are connected together to create a workflow. Nodes' inputs and outputs are connected by dragging connectors from node to node. Inputs and outputs are color coded for ease of use. + +To better understand how nodes are used, think of how an electric power bar works. It takes in one input (electricity from a wall outlet) and passes it to multiple devices through multiple outputs. Similarly, a node could have multiple inputs and outputs functioning at the same (or different) time, but all node outputs pass information onward like a power bar passes electricity. Not all outputs are compatible with all inputs, however - Each node has different constraints on how it is expecting to input/output information. In general, node outputs are colour-coded to match compatible inputs of other nodes. + + +If you're not familiar with Diffusion, take a look at our [Diffusion Overview.](../help/diffusion.md) Understanding how diffusion works will enable you to more easily use the Nodes Editor and build workflows to suit your needs. + +## Important Concepts + +There are several node grouping concepts that can be examined with a narrow focus. These (and other) groupings can be pieced together to make up functional graph setups, and are important to understanding how groups of nodes work together as part of a whole. Note that the screenshots below aren't examples of complete functioning node graphs (see Examples). + +### Noise + +An initial noise tensor is necessary for the latent diffusion process. As a result, the Denoising node requires a noise node input. + +![groupsnoise](../assets/nodes/groupsnoise.png) + +### Text Prompt Conditioning + +Conditioning is necessary for the latent diffusion process, whether empty or not. As a result, the Denoising node requires positive and negative conditioning inputs. Conditioning is reliant on a CLIP text encoder provided by the Model Loader node. + +![groupsconditioning](../assets/nodes/groupsconditioning.png) + +### Image to Latents & VAE + +The ImageToLatents node takes in a pixel image and a VAE and outputs a latents. The LatentsToImage node does the opposite, taking in a latents and a VAE and outpus a pixel image. + +![groupsimgvae](../assets/nodes/groupsimgvae.png) + +### Defined & Random Seeds + +It is common to want to use both the same seed (for continuity) and random seeds (for variety). To define a seed, simply enter it into the 'Seed' field on a noise node. Conversely, the RandomInt node generates a random integer between 'Low' and 'High', and can be used as input to the 'Seed' edge point on a noise node to randomize your seed. + +![groupsrandseed](../assets/nodes/groupsrandseed.png) + +### ControlNet + +The ControlNet node outputs a Control, which can be provided as input to non-image *ToLatents nodes. Depending on the type of ControlNet desired, ControlNet nodes usually require an image processor node, such as a Canny Processor or Depth Processor, which prepares an input image for use with ControlNet. + +![groupscontrol](../assets/nodes/groupscontrol.png) + +### LoRA + +The Lora Loader node lets you load a LoRA and pass it as output.A LoRA provides fine-tunes to the UNet and text encoder weights that augment the base model’s image and text vocabularies. + +![groupslora](../assets/nodes/groupslora.png) + +### Scaling + +Use the ImageScale, ScaleLatents, and Upscale nodes to upscale images and/or latent images. Upscaling is the process of enlarging an image and adding more detail. The chosen method differs across contexts. However, be aware that latents are already noisy and compressed at their original resolution; scaling an image could produce more detailed results. + +![groupsallscale](../assets/nodes/groupsallscale.png) + +### Iteration + Multiple Images as Input + +Iteration is a common concept in any processing, and means to repeat a process with given input. In nodes, you're able to use the Iterate node to iterate through collections usually gathered by the Collect node. The Iterate node has many potential uses, from processing a collection of images one after another, to varying seeds across multiple image generations and more. This screenshot demonstrates how to collect several images and use them in an image generation workflow. + +![groupsiterate](../assets/nodes/groupsiterate.png) + +### Multiple Image Generation + Random Seeds + +Multiple image generation in the node editor is done using the RandomRange node. In this case, the 'Size' field represents the number of images to generate. As RandomRange produces a collection of integers, we need to add the Iterate node to iterate through the collection. + +To control seeds across generations takes some care. The first row in the screenshot will generate multiple images with different seeds, but using the same RandomRange parameters across invocations will result in the same group of random seeds being used across the images, producing repeatable results. In the second row, adding the RandomInt node as input to RandomRange's 'Seed' edge point will ensure that seeds are varied across all images across invocations, producing varied results. + +![groupsmultigenseeding](../assets/nodes/groupsmultigenseeding.png) diff --git a/docs/nodes/comfyToInvoke.md b/docs/nodes/comfyToInvoke.md new file mode 100644 index 0000000000..2d894dc74c --- /dev/null +++ b/docs/nodes/comfyToInvoke.md @@ -0,0 +1,80 @@ +# ComfyUI to InvokeAI + +If you're coming to InvokeAI from ComfyUI, welcome! You'll find things are similar but different - the good news is that you already know how things should work, and it's just a matter of wiring them up! + +Some things to note: + +- InvokeAI's nodes tend to be more granular than default nodes in Comfy. This means each node in Invoke will do a specific task and you might need to use multiple nodes to achieve the same result. The added granularity improves the control you have have over your workflows. +- InvokeAI's backend and ComfyUI's backend are very different which means Comfy workflows are not able to be imported into InvokeAI. However, we have created a [list of popular workflows](exampleWorkflows.md) for you to get started with Nodes in InvokeAI! + +## Node Equivalents: + +| Comfy UI Category | ComfyUI Node | Invoke Equivalent | +|:---------------------------------- |:---------------------------------- | :----------------------------------| +| Sampling |KSampler |Denoise Latents| +| Sampling |Ksampler Advanced|Denoise Latents | +| Loaders |Load Checkpoint | Main Model Loader _or_ SDXL Main Model Loader| +| Loaders |Load VAE | VAE Loader | +| Loaders |Load Lora | LoRA Loader _or_ SDXL Lora Loader| +| Loaders |Load ControlNet Model | ControlNet| +| Loaders |Load ControlNet Model (diff) | ControlNet| +| Loaders |Load Style Model | Reference Only ControlNet will be coming in a future version of InvokeAI| +| Loaders |unCLIPCheckpointLoader | N/A | +| Loaders |GLIGENLoader | N/A | +| Loaders |Hypernetwork Loader | N/A | +| Loaders |Load Upscale Model | Occurs within "Upscale (RealESRGAN)"| +|Conditioning |CLIP Text Encode (Prompt) | Compel (Prompt) or SDXL Compel (Prompt) | +|Conditioning |CLIP Set Last Layer | CLIP Skip| +|Conditioning |Conditioning (Average) | Use the .blend() feature of prompts | +|Conditioning |Conditioning (Combine) | N/A | +|Conditioning |Conditioning (Concat) | See the Prompt Tools Community Node| +|Conditioning |Conditioning (Set Area) | N/A | +|Conditioning |Conditioning (Set Mask) | Mask Edge | +|Conditioning |CLIP Vision Encode | N/A | +|Conditioning |unCLIPConditioning | N/A | +|Conditioning |Apply ControlNet | ControlNet | +|Conditioning |Apply ControlNet (Advanced) | ControlNet | +|Latent |VAE Decode | Latents to Image| +|Latent |VAE Encode | Image to Latents | +|Latent |Empty Latent Image | Noise | +|Latent |Upscale Latent |Resize Latents | +|Latent |Upscale Latent By |Scale Latents | +|Latent |Latent Composite | Blend Latents | +|Latent |LatentCompositeMasked | N/A | +|Image |Save Image | Image | +|Image |Preview Image |Current | +|Image |Load Image | Image| +|Image |Empty Image| Blank Image | +|Image |Invert Image | Invert Lerp Image | +|Image |Batch Images | Link "Image" nodes into an "Image Collection" node | +|Image |Pad Image for Outpainting | Outpainting is easily accomplished in the Unified Canvas | +|Image |ImageCompositeMasked | Paste Image | +|Image | Upscale Image | Resize Image | +|Image | Upscale Image By | Upscale Image | +|Image | Upscale Image (using Model) | Upscale Image | +|Image | ImageBlur | Blur Image | +|Image | ImageQuantize | N/A | +|Image | ImageSharpen | N/A | +|Image | Canny | Canny Processor | +|Mask |Load Image (as Mask) | Image | +|Mask |Convert Mask to Image | Image| +|Mask |Convert Image to Mask | Image | +|Mask |SolidMask | N/A | +|Mask |InvertMask |Invert Lerp Image | +|Mask |CropMask | Crop Image | +|Mask |MaskComposite | Combine Mask | +|Mask |FeatherMask | Blur Image | +|Advanced | Load CLIP | Main Model Loader _or_ SDXL Main Model Loader| +|Advanced | UNETLoader | Main Model Loader _or_ SDXL Main Model Loader| +|Advanced | DualCLIPLoader | Main Model Loader _or_ SDXL Main Model Loader| +|Advanced | Load Checkpoint | Main Model Loader _or_ SDXL Main Model Loader | +|Advanced | ConditioningZeroOut | N/A | +|Advanced | ConditioningSetTimestepRange | N/A | +|Advanced | CLIPTextEncodeSDXLRefiner | Compel (Prompt) or SDXL Compel (Prompt) | +|Advanced | CLIPTextEncodeSDXL |Compel (Prompt) or SDXL Compel (Prompt) | +|Advanced | ModelMergeSimple | Model Merging is available in the Model Manager | +|Advanced | ModelMergeBlocks | Model Merging is available in the Model Manager| +|Advanced | CheckpointSave | Model saving is available in the Model Manager| +|Advanced | CLIPMergeSimple | N/A | + + diff --git a/docs/nodes/communityNodes.md b/docs/nodes/communityNodes.md index 2e04018b45..1be68eae1c 100644 --- a/docs/nodes/communityNodes.md +++ b/docs/nodes/communityNodes.md @@ -2,17 +2,13 @@ These are nodes that have been developed by the community, for the community. If you're not sure what a node is, you can learn more about nodes [here](overview.md). -If you'd like to submit a node for the community, please refer to the [node creation overview](./overview.md#contributing-nodes). +If you'd like to submit a node for the community, please refer to the [node creation overview](contributingNodes.md). -To download a node, simply download the `.py` node file from the link and add it to the `invokeai/app/invocations/` folder in your Invoke AI install location. Along with the node, an example node graph should be provided to help you get started with the node. +To download a node, simply download the `.py` node file from the link and add it to the `invokeai/app/invocations` folder in your Invoke AI install location. Along with the node, an example node graph should be provided to help you get started with the node. To use a community node graph, download the the `.json` node graph file and load it into Invoke AI via the **Load Nodes** button on the Node Editor. -## Disclaimer - -The nodes linked below have been developed and contributed by members of the Invoke AI community. While we strive to ensure the quality and safety of these contributions, we do not guarantee the reliability or security of the nodes. If you have issues or concerns with any of the nodes below, please raise it on GitHub or in the Discord. - -## List of Nodes +## Community Nodes ### FaceTools @@ -34,6 +30,33 @@ The nodes linked below have been developed and contributed by members of the Inv **Node Link:** https://github.com/JPPhoto/ideal-size-node +
+ +### Retroize + +**Description:** Retroize is a collection of nodes for InvokeAI to "Retroize" images. Any image can be given a fresh coat of retro paint with these nodes, either from your gallery or from within the graph itself. It includes nodes to pixelize, quantize, palettize, and ditherize images; as well as to retrieve palettes from existing images. + +**Node Link:** https://github.com/Ar7ific1al/invokeai-retroizeinode/ + +**Retroize Output Examples** + +![image](https://github.com/Ar7ific1al/InvokeAI_nodes_retroize/assets/2306586/de8b4fa6-324c-4c2d-b36c-297600c73974) + +-------------------------------- +### GPT2RandomPromptMaker + +**Description:** A node for InvokeAI utilizes the GPT-2 language model to generate random prompts based on a provided seed and context. + +**Node Link:** https://github.com/mickr777/GPT2RandomPromptMaker + +**Output Examples** + +Generated Prompt: An enchanted weapon will be usable by any character regardless of their alignment. + +![9acf5aef-7254-40dd-95b3-8eac431dfab0 (1)](https://github.com/mickr777/InvokeAI/assets/115216705/8496ba09-bcdd-4ff7-8076-ff213b6a1e4c) + + + -------------------------------- ### Example Node Template @@ -47,7 +70,12 @@ The nodes linked below have been developed and contributed by members of the Inv ![Example Image](https://invoke-ai.github.io/InvokeAI/assets/invoke_ai_banner.png){: style="height:115px;width:240px"} + +## Disclaimer + +The nodes linked have been developed and contributed by members of the Invoke AI community. While we strive to ensure the quality and safety of these contributions, we do not guarantee the reliability or security of the nodes. If you have issues or concerns with any of the nodes below, please raise it on GitHub or in the Discord. + + ## Help If you run into any issues with a node, please post in the [InvokeAI Discord](https://discord.gg/ZmtBAhwWhy). - diff --git a/docs/nodes/contributingNodes.md b/docs/nodes/contributingNodes.md new file mode 100644 index 0000000000..a34d429cd8 --- /dev/null +++ b/docs/nodes/contributingNodes.md @@ -0,0 +1,27 @@ +# Contributing Nodes + +To learn about the specifics of creating a new node, please visit our [Node creation documentation](../contributing/INVOCATIONS.md). + +Once you’ve created a node and confirmed that it behaves as expected locally, follow these steps: + +- Make sure the node is contained in a new Python (.py) file +- Submit a pull request with a link to your node in GitHub against the `nodes` branch to add the node to the [Community Nodes](Community Nodes) list + - Make sure you are following the template below and have provided all relevant details about the node and what it does. +- A maintainer will review the pull request and node. If the node is aligned with the direction of the project, you might be asked for permission to include it in the core project. + +### Community Node Template + +```markdown +-------------------------------- +### Super Cool Node Template + +**Description:** This node allows you to do super cool things with InvokeAI. + +**Node Link:** https://github.com/invoke-ai/InvokeAI/fake_node.py + +**Example Node Graph:** https://github.com/invoke-ai/InvokeAI/fake_node_graph.json + +**Output Examples** + +![InvokeAI](https://invoke-ai.github.io/InvokeAI/assets/invoke_ai_banner.png) +``` diff --git a/docs/nodes/defaultNodes.md b/docs/nodes/defaultNodes.md new file mode 100644 index 0000000000..7748f635cb --- /dev/null +++ b/docs/nodes/defaultNodes.md @@ -0,0 +1,97 @@ +# List of Default Nodes + +The table below contains a list of the default nodes shipped with InvokeAI and their descriptions. + +| Node | Function | +|: ---------------------------------- | :--------------------------------------------------------------------------------------| +|Add Integers | Adds two numbers| +|Boolean Primitive Collection | A collection of boolean primitive values| +|Boolean Primitive | A boolean primitive value| +|Canny Processor | Canny edge detection for ControlNet| +|CLIP Skip | Skip layers in clip text_encoder model.| +|Collect | Collects values into a collection| +|Color Correct | Shifts the colors of a target image to match the reference image, optionally using a mask to only color-correct certain regions of the target image.| +|Color Primitive | A color primitive value| +|Compel Prompt | Parse prompt using compel package to conditioning.| +|Conditioning Primitive Collection | A collection of conditioning tensor primitive values| +|Conditioning Primitive | A conditioning tensor primitive value| +|Content Shuffle Processor | Applies content shuffle processing to image| +|ControlNet | Collects ControlNet info to pass to other nodes| +|OpenCV Inpaint | Simple inpaint using opencv.| +|Denoise Latents | Denoises noisy latents to decodable images| +|Divide Integers | Divides two numbers| +|Dynamic Prompt | Parses a prompt using adieyal/dynamicprompts' random or combinatorial generator| +|Upscale (RealESRGAN) | Upscales an image using RealESRGAN.| +|Float Primitive Collection | A collection of float primitive values| +|Float Primitive | A float primitive value| +|Float Range | Creates a range| +|HED (softedge) Processor | Applies HED edge detection to image| +|Blur Image | Blurs an image| +|Extract Image Channel | Gets a channel from an image.| +|Image Primitive Collection | A collection of image primitive values| +|Convert Image Mode | Converts an image to a different mode.| +|Crop Image | Crops an image to a specified box. The box can be outside of the image.| +|Image Hue Adjustment | Adjusts the Hue of an image.| +|Inverse Lerp Image | Inverse linear interpolation of all pixels of an image| +|Image Primitive | An image primitive value| +|Lerp Image | Linear interpolation of all pixels of an image| +|Image Luminosity Adjustment | Adjusts the Luminosity (Value) of an image.| +|Multiply Images | Multiplies two images together using `PIL.ImageChops.multiply()`.| +|Blur NSFW Image | Add blur to NSFW-flagged images| +|Paste Image | Pastes an image into another image.| +|ImageProcessor | Base class for invocations that preprocess images for ControlNet| +|Resize Image | Resizes an image to specific dimensions| +|Image Saturation Adjustment | Adjusts the Saturation of an image.| +|Scale Image | Scales an image by a factor| +|Image to Latents | Encodes an image into latents.| +|Add Invisible Watermark | Add an invisible watermark to an image| +|Solid Color Infill | Infills transparent areas of an image with a solid color| +|PatchMatch Infill | Infills transparent areas of an image using the PatchMatch algorithm| +|Tile Infill | Infills transparent areas of an image with tiles of the image| +|Integer Primitive Collection | A collection of integer primitive values| +|Integer Primitive | An integer primitive value| +|Iterate | Iterates over a list of items| +|Latents Primitive Collection | A collection of latents tensor primitive values| +|Latents Primitive | A latents tensor primitive value| +|Latents to Image | Generates an image from latents.| +|Leres (Depth) Processor | Applies leres processing to image| +|Lineart Anime Processor | Applies line art anime processing to image| +|Lineart Processor | Applies line art processing to image| +|LoRA Loader | Apply selected lora to unet and text_encoder.| +|Main Model Loader | Loads a main model, outputting its submodels.| +|Combine Mask | Combine two masks together by multiplying them using `PIL.ImageChops.multiply()`.| +|Mask Edge | Applies an edge mask to an image| +|Mask from Alpha | Extracts the alpha channel of an image as a mask.| +|Mediapipe Face Processor | Applies mediapipe face processing to image| +|Midas (Depth) Processor | Applies Midas depth processing to image| +|MLSD Processor | Applies MLSD processing to image| +|Multiply Integers | Multiplies two numbers| +|Noise | Generates latent noise.| +|Normal BAE Processor | Applies NormalBae processing to image| +|ONNX Latents to Image | Generates an image from latents.| +|ONNX Prompt (Raw) | A node to process inputs and produce outputs. May use dependency injection in __init__ to receive providers.| +|ONNX Text to Latents | Generates latents from conditionings.| +|ONNX Model Loader | Loads a main model, outputting its submodels.| +|Openpose Processor | Applies Openpose processing to image| +|PIDI Processor | Applies PIDI processing to image| +|Prompts from File | Loads prompts from a text file| +|Random Integer | Outputs a single random integer.| +|Random Range | Creates a collection of random numbers| +|Integer Range | Creates a range of numbers from start to stop with step| +|Integer Range of Size | Creates a range from start to start + size with step| +|Resize Latents | Resizes latents to explicit width/height (in pixels). Provided dimensions are floor-divided by 8.| +|SDXL Compel Prompt | Parse prompt using compel package to conditioning.| +|SDXL LoRA Loader | Apply selected lora to unet and text_encoder.| +|SDXL Main Model Loader | Loads an sdxl base model, outputting its submodels.| +|SDXL Refiner Compel Prompt | Parse prompt using compel package to conditioning.| +|SDXL Refiner Model Loader | Loads an sdxl refiner model, outputting its submodels.| +|Scale Latents | Scales latents by a given factor.| +|Segment Anything Processor | Applies segment anything processing to image| +|Show Image | Displays a provided image, and passes it forward in the pipeline.| +|Step Param Easing | Experimental per-step parameter easing for denoising steps| +|String Primitive Collection | A collection of string primitive values| +|String Primitive | A string primitive value| +|Subtract Integers | Subtracts two numbers| +|Tile Resample Processor | Tile resampler processor| +|VAE Loader | Loads a VAE model, outputting a VaeLoaderOutput| +|Zoe (Depth) Processor | Applies Zoe depth processing to image| \ No newline at end of file diff --git a/docs/nodes/exampleWorkflows.md b/docs/nodes/exampleWorkflows.md new file mode 100644 index 0000000000..5f8dabb67c --- /dev/null +++ b/docs/nodes/exampleWorkflows.md @@ -0,0 +1,15 @@ +# Example Workflows + +TODO: Will update once uploading workflows is available. + +## Text2Image + +## Image2Image + +## ControlNet + +## Upscaling + +## Inpainting / Outpainting + +## LoRAs diff --git a/docs/nodes/overview.md b/docs/nodes/overview.md index e959ad9d7b..71e316c856 100644 --- a/docs/nodes/overview.md +++ b/docs/nodes/overview.md @@ -1,42 +1,26 @@ # Nodes ## What are Nodes? -An Node is simply a single operation that takes in some inputs and gives -out some outputs. We can then chain multiple nodes together to create more +An Node is simply a single operation that takes in inputs and returns +out outputs. Multiple nodes can be linked together to create more complex functionality. All InvokeAI features are added through nodes. -This means nodes can be used to easily extend the image generation capabilities of InvokeAI, and allow you build workflows to suit your needs. +### Anatomy of a Node -You can read more about nodes and the node editor [here](../features/NODES.md). +Individual nodes are made up of the following: + +- Inputs: Edge points on the left side of the node window where you connect outputs from other nodes. +- Outputs: Edge points on the right side of the node window where you connect to inputs on other nodes. +- Options: Various options which are either manually configured, or overridden by connecting an output from another node to the input. -## Downloading Nodes -To download a new node, visit our list of [Community Nodes](communityNodes.md). These are nodes that have been created by the community, for the community. +With nodes, you can can easily extend the image generation capabilities of InvokeAI, and allow you build workflows that suit your needs. + +You can read more about nodes and the node editor [here](../nodes/NODES.md). + +To get started with nodes, take a look at some of our examples for [common workflows](../nodes/exampleWorkflows.md) + +## Downloading New Nodes +To download a new node, visit our list of [Community Nodes](../nodes/communityNodes.md). These are nodes that have been created by the community, for the community. -## Contributing Nodes - -To learn about creating a new node, please visit our [Node creation documenation](../contributing/INVOCATIONS.md). - -Once you’ve created a node and confirmed that it behaves as expected locally, follow these steps: -* Make sure the node is contained in a new Python (.py) file -* Submit a pull request with a link to your node in GitHub against the `nodes` branch to add the node to the [Community Nodes](Community Nodes) list - * Make sure you are following the template below and have provided all relevant details about the node and what it does. -* A maintainer will review the pull request and node. If the node is aligned with the direction of the project, you might be asked for permission to include it in the core project. - -### Community Node Template - -```markdown --------------------------------- -### Super Cool Node Template - -**Description:** This node allows you to do super cool things with InvokeAI. - -**Node Link:** https://github.com/invoke-ai/InvokeAI/fake_node.py - -**Example Node Graph:** https://github.com/invoke-ai/InvokeAI/fake_node_graph.json - -**Output Examples** - -![InvokeAI](https://invoke-ai.github.io/InvokeAI/assets/invoke_ai_banner.png) -``` diff --git a/invokeai/backend/install/invokeai_configure.py b/invokeai/backend/install/invokeai_configure.py index 7925066562..90298ce076 100755 --- a/invokeai/backend/install/invokeai_configure.py +++ b/invokeai/backend/install/invokeai_configure.py @@ -50,7 +50,7 @@ from invokeai.frontend.install.model_install import addModelsForm, process_and_e # TO DO - Move all the frontend code into invokeai.frontend.install from invokeai.frontend.install.widgets import ( - SingleSelectColumns, + SingleSelectColumnsSimple, MultiSelectColumns, CenteredButtonPress, FileBox, @@ -354,7 +354,6 @@ Use cursor arrows to make a checkbox selection, and space to toggle. device = old_opts.device attention_type = old_opts.attention_type attention_slice_size = old_opts.attention_slice_size - self.nextrely += 1 self.add_widget_intelligent( npyscreen.TitleFixedText, @@ -385,7 +384,7 @@ Use cursor arrows to make a checkbox selection, and space to toggle. ) self.nextrely -= 2 self.precision = self.add_widget_intelligent( - SingleSelectColumns, + SingleSelectColumnsSimple, columns=len(PRECISION_CHOICES), name="Precision", values=PRECISION_CHOICES, @@ -406,10 +405,10 @@ Use cursor arrows to make a checkbox selection, and space to toggle. ) self.nextrely -= 2 self.device = self.add_widget_intelligent( - SingleSelectColumns, + SingleSelectColumnsSimple, columns=len(DEVICE_CHOICES), values=DEVICE_CHOICES, - value=DEVICE_CHOICES.index(device), + value=[DEVICE_CHOICES.index(device)], begin_entry_at=3, relx=30, max_height=2, @@ -426,10 +425,10 @@ Use cursor arrows to make a checkbox selection, and space to toggle. ) self.nextrely -= 2 self.attention_type = self.add_widget_intelligent( - SingleSelectColumns, + SingleSelectColumnsSimple, columns=len(ATTENTION_CHOICES), values=ATTENTION_CHOICES, - value=ATTENTION_CHOICES.index(attention_type), + value=[ATTENTION_CHOICES.index(attention_type)], begin_entry_at=3, max_height=2, relx=30, @@ -448,17 +447,16 @@ Use cursor arrows to make a checkbox selection, and space to toggle. ) self.nextrely -= 2 self.attention_slice_size = self.add_widget_intelligent( - SingleSelectColumns, + SingleSelectColumnsSimple, columns=len(ATTENTION_SLICE_CHOICES), values=ATTENTION_SLICE_CHOICES, - value=ATTENTION_SLICE_CHOICES.index(attention_slice_size), + value=[ATTENTION_SLICE_CHOICES.index(attention_slice_size)], relx=30, hidden=attention_type != "sliced", max_height=2, max_width=110, scroll_exit=True, ) - self.add_widget_intelligent( npyscreen.TitleFixedText, name="Model RAM cache size (GB). Make this at least large enough to hold a single full model.", @@ -707,8 +705,6 @@ def initialize_rootdir(root: Path, yes_to_all: bool = False): path = dest / "core" path.mkdir(parents=True, exist_ok=True) - maybe_create_models_yaml(root) - def maybe_create_models_yaml(root: Path): models_yaml = root / "configs" / "models.yaml" diff --git a/invokeai/frontend/install/widgets.py b/invokeai/frontend/install/widgets.py index f7d1d044c8..9eefd93e09 100644 --- a/invokeai/frontend/install/widgets.py +++ b/invokeai/frontend/install/widgets.py @@ -177,6 +177,8 @@ class FloatTitleSlider(npyscreen.TitleText): class SelectColumnBase: + """Base class for selection widget arranged in columns.""" + def make_contained_widgets(self): self._my_widgets = [] column_width = self.width // self.columns @@ -253,6 +255,7 @@ class MultiSelectColumns(SelectColumnBase, npyscreen.MultiSelect): class SingleSelectWithChanged(npyscreen.SelectOne): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self.on_changed = None def h_select(self, ch): super().h_select(ch) @@ -260,7 +263,9 @@ class SingleSelectWithChanged(npyscreen.SelectOne): self.on_changed(self.value) -class SingleSelectColumns(SelectColumnBase, SingleSelectWithChanged): +class SingleSelectColumnsSimple(SelectColumnBase, SingleSelectWithChanged): + """Row of radio buttons. Spacebar to select.""" + def __init__(self, screen, columns: int = 1, values: list = [], **keywords): self.columns = columns self.value_cnt = len(values) @@ -268,12 +273,6 @@ class SingleSelectColumns(SelectColumnBase, SingleSelectWithChanged): self.on_changed = None super().__init__(screen, values=values, **keywords) - def when_value_edited(self): - self.h_select(self.cursor_line) - - def when_cursor_moved(self): - self.h_select(self.cursor_line) - def h_cursor_line_right(self, ch): self.h_exit_down("bye bye") @@ -281,6 +280,13 @@ class SingleSelectColumns(SelectColumnBase, SingleSelectWithChanged): self.h_exit_up("bye bye") +class SingleSelectColumns(SingleSelectColumnsSimple): + """Row of radio buttons. When tabbing over a selection, it is auto selected.""" + + def when_cursor_moved(self): + self.h_select(self.cursor_line) + + class TextBoxInner(npyscreen.MultiLineEdit): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/mkdocs.yml b/mkdocs.yml index 6cbf410971..2888f2e6ba 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -98,6 +98,15 @@ plugins: 'installation/INSTALLING_MODELS.md': 'installation/050_INSTALLING_MODELS.md' 'installation/INSTALL_PATCHMATCH.md': 'installation/060_INSTALL_PATCHMATCH.md' +extra_javascript: + - https://unpkg.com/tablesort@5.3.0/dist/tablesort.min.js + - javascripts/tablesort.js + +extra: + analytics: + provider: google + property: G-2X4JR4S4FB + nav: - Home: 'index.md' - Installation: @@ -118,9 +127,14 @@ nav: - Manual Installation on Windows: 'installation/deprecated_documentation/INSTALL_WINDOWS.md' - Installing Invoke with pip: 'installation/deprecated_documentation/INSTALL_PCP.md' - Source Installer: 'installation/deprecated_documentation/INSTALL_SOURCE.md' - - Community Nodes: + - Nodes: - Community Nodes: 'nodes/communityNodes.md' - - Overview: 'nodes/overview.md' + - Example Workflows: 'nodes/exampleWorkflows.md' + - Nodes Overview: 'nodes/overview.md' + - List of Default Nodes: 'nodes/defaultNodes.md' + - Node Editor Usage: 'nodes/NODES.md' + - ComfyUI to InvokeAI: 'nodes/comfyToInvoke.md' + - Contributing Nodes: 'nodes/contributingNodes.md' - Features: - Overview: 'features/index.md' - New to InvokeAI?: 'help/gettingStartedWithAI.md' @@ -130,13 +144,12 @@ nav: - Image-to-Image: 'features/IMG2IMG.md' - Controlling Logging: 'features/LOGGING.md' - Model Merging: 'features/MODEL_MERGING.md' - - Nodes Editor (Experimental): 'features/NODES.md' - - NSFW Checker: 'features/NSFW.md' + - Using Nodes : './nodes/overview' + - NSFW Checker: 'features/WATERMARK+NSFW.md' - Postprocessing: 'features/POSTPROCESS.md' - Prompting Features: 'features/PROMPTS.md' - Training: 'features/TRAINING.md' - Unified Canvas: 'features/UNIFIED_CANVAS.md' - - Variations: 'features/VARIATIONS.md' - InvokeAI Web Server: 'features/WEB.md' - WebUI Hotkeys: "features/WEBUIHOTKEYS.md" - Other: 'features/OTHER.md' @@ -148,6 +161,7 @@ nav: - Frontend Documentation: 'contributing/contribution_guides/development_guides/contributingToFrontend.md' - Local Development: 'contributing/LOCAL_DEVELOPMENT.md' - Documentation: 'contributing/contribution_guides/documentation.md' + - Nodes: 'contributing/INVOCATIONS.md' - Translation: 'contributing/contribution_guides/translation.md' - Tutorials: 'contributing/contribution_guides/tutorials.md' - Changelog: 'CHANGELOG.md' @@ -158,6 +172,7 @@ nav: - Outpainting: 'deprecated/OUTPAINTING.md' - Help: - Getting Started: 'help/gettingStartedWithAI.md' + - Diffusion Overview: 'help/diffusion.md' - Sampler Convergence: 'help/SAMPLER_CONVERGENCE.md' - Other: - Contributors: 'other/CONTRIBUTORS.md'