diff --git a/.gitignore b/.gitignore index 54433c86dc..08cfaf21aa 100644 --- a/.gitignore +++ b/.gitignore @@ -208,4 +208,7 @@ gfpgan/ configs/models.yaml # weights (will be created by installer) -models/ldm/stable-diffusion-v1/*.ckpt \ No newline at end of file +models/ldm/stable-diffusion-v1/*.ckpt + +# ignore initfile +invokeai.init diff --git a/docs/features/CLI.md b/docs/features/CLI.md index e878bb4444..b8de156412 100644 --- a/docs/features/CLI.md +++ b/docs/features/CLI.md @@ -91,6 +91,10 @@ overridden on a per-prompt basis (see | `--port ` | | `9090` | Which port web server should listen for requests on. | | `--config ` | | `configs/models.yaml` | Configuration file for models and their weights. | | `--iterations ` | `-n` | `1` | How many images to generate per prompt. | +| `--width ` | `-W` | `512` | Width of generated image | +| `--height ` | `-H` | `512` | Height of generated image | `--steps ` | `-s` | `50` | How many steps of refinement to apply | +| `--strength ` | `-s` | `0.75` | For img2img: how hard to try to match the prompt to the initial image. Ranges from 0.0-0.99, with higher values replacing the initial image completely. | +| `--fit` | `-F` | `False` | For img2img: scale the init image to fit into the specified -H and -W dimensions | | `--grid` | `-g` | `False` | Save all image series as a grid rather than individually. | | `--sampler ` | `-A` | `k_lms` | Sampler to use. Use `-h` to get list of available samplers. | | `--seamless` | | `False` | Create interesting effects by tiling elements of the image. | @@ -106,7 +110,7 @@ overridden on a per-prompt basis (see | Argument | Shortcut | Default | Description | |--------------------|------------|---------------------|--------------| - | `--weights ` | | `None` | Pth to weights file; use `--model stable-diffusion-1.4` instead | + | `--weights ` | | `None` | Path to weights file; use `--model stable-diffusion-1.4` instead | | `--laion400m` | `-l` | `False` | Use older LAION400m weights; use `--model=laion400m` instead | @@ -119,6 +123,29 @@ overridden on a per-prompt basis (see You can either double your slashes (ick): `C:\\path\\to\\my\\file`, or use Linux/Mac style forward slashes (better): `C:/path/to/my/file`. +## The .invokeai initialization file + +To start up invoke.py with your preferred settings, place your desired +startup options in a file in your home directory named `.invokeai` The +file should contain the startup options as you would type them on the +command line (`--steps=10 --grid`), one argument per line, or a +mixture of both using any of the accepted command switch formats: + +!!! example "" + + ```bash + --web + --steps=28 + --grid + -f 0.6 -C 11.0 -A k_euler_a + ``` + +Note that the initialization file only accepts the command line arguments. +There are additional arguments that you can provide on the `invoke>` command +line (such as `-n` or `--iterations`) that cannot be entered into this file. +Also be alert for empty blank lines at the end of the file, which will cause +an arguments error at startup time. + ## List of prompt arguments After the invoke.py script initializes, it will present you with a `invoke>` diff --git a/ldm/invoke/args.py b/ldm/invoke/args.py index b40d67c834..98298902b6 100644 --- a/ldm/invoke/args.py +++ b/ldm/invoke/args.py @@ -87,6 +87,7 @@ import json import hashlib import os import re +import sys import shlex import copy import base64 @@ -114,7 +115,8 @@ PRECISION_CHOICES = [ # is there a way to pick this up during git commits? APP_ID = 'invoke-ai/InvokeAI' -APP_VERSION = 'v2.02' +APP_VERSION = 'v2.1.2' +INITFILE = os.path.expanduser('~/.invokeai') class ArgFormatter(argparse.RawTextHelpFormatter): # use defined argument order to display usage @@ -141,11 +143,15 @@ class ArgFormatter(argparse.RawTextHelpFormatter): class PagingArgumentParser(argparse.ArgumentParser): ''' A custom ArgumentParser that uses pydoc to page its output. + It also supports reading defaults from an init file. ''' def print_help(self, file=None): text = self.format_help() pydoc.pager(text) - + + def convert_arg_line_to_args(self, arg_line): + return shlex.split(arg_line,comments=True) + class Args(object): def __init__(self,arg_parser=None,cmd_parser=None): ''' @@ -162,9 +168,16 @@ class Args(object): def parse_args(self): '''Parse the shell switches and store.''' try: - self._arg_switches = self._arg_parser.parse_args() + sysargs = sys.argv[1:] + if os.path.exists(INITFILE): + print(f'>> Initialization file {INITFILE} found. Loading...') + sysargs.insert(0,f'@{INITFILE}') + else: + print(f'>> Initialization file {INITFILE} not found. Applying default settings...') + self._arg_switches = self._arg_parser.parse_args(sysargs) return self._arg_switches - except: + except Exception as e: + print(f'An exception has occurred: {e}') return None def parse_cmd(self,cmd_string): @@ -357,7 +370,7 @@ class Args(object): This defines all the arguments used on the command line when you launch the CLI or web backend. ''' - parser = argparse.ArgumentParser( + parser = PagingArgumentParser( description= """ Generate images using Stable Diffusion. @@ -367,6 +380,7 @@ class Args(object): Other command-line arguments are defaults that can usually be overridden prompt the command prompt. """, + fromfile_prefix_chars='@', ) model_group = parser.add_argument_group('Model selection') file_group = parser.add_argument_group('Input/output') @@ -397,17 +411,6 @@ class Args(object): dest='png_compression', help='level of PNG compression, from 0 (none) to 9 (maximum). Default is 6.' ) - model_group.add_argument( - '--sampler', - '-A', - '-m', - dest='sampler_name', - type=str, - choices=SAMPLER_CHOICES, - metavar='SAMPLER_NAME', - help=f'Switch to a different sampler. Supported samplers: {", ".join(SAMPLER_CHOICES)}', - default='k_lms', - ) model_group.add_argument( '-F', '--full_precision', @@ -467,10 +470,61 @@ class Args(object): type=str, help='Overwrite the filename format. You can use any argument as wildcard enclosed in curly braces. Default is {prefix}.{seed}.png', ) + render_group.add_argument( + '-s', + '--steps', + type=int, + default=50, + help='Number of steps' + ) + render_group.add_argument( + '-W', + '--width', + type=int, + help='Image width, multiple of 64', + ) + render_group.add_argument( + '-H', + '--height', + type=int, + help='Image height, multiple of 64', + ) + render_group.add_argument( + '-C', + '--cfg_scale', + default=7.5, + type=float, + help='Classifier free guidance (CFG) scale - higher numbers cause generator to "try" harder.', + ) + render_group.add_argument( + '--sampler', + '-A', + '-m', + dest='sampler_name', + type=str, + choices=SAMPLER_CHOICES, + metavar='SAMPLER_NAME', + help=f'Set the default sampler. Supported samplers: {", ".join(SAMPLER_CHOICES)}', + default='k_lms', + ) + render_group.add_argument( + '-f', + '--strength', + type=float, + help='img2img strength for noising/unnoising. 0.0 preserves image exactly, 1.0 replaces it completely', + ) + render_group.add_argument( + '-T', + '-fit', + '--fit', + action=argparse.BooleanOptionalAction, + help='If specified, will resize the input image to fit within the dimensions of width x height (512x512 default)', + ) + render_group.add_argument( '--grid', '-g', - action='store_true', + action=argparse.BooleanOptionalAction, help='generate a grid' ) render_group.add_argument( @@ -599,7 +653,6 @@ class Args(object): '-s', '--steps', type=int, - default=50, help='Number of steps' ) render_group.add_argument( @@ -631,7 +684,6 @@ class Args(object): render_group.add_argument( '-C', '--cfg_scale', - default=7.5, type=float, help='Classifier free guidance (CFG) scale - higher numbers cause generator to "try" harder.', ) @@ -656,7 +708,7 @@ class Args(object): render_group.add_argument( '--grid', '-g', - action='store_true', + action=argparse.BooleanOptionalAction, help='generate a grid' ) render_group.add_argument( @@ -750,8 +802,7 @@ class Args(object): '-f', '--strength', type=float, - help='Strength for noising/unnoising. 0.0 preserves image exactly, 1.0 replaces it completely', - default=0.75, + help='img2img strength for noising/unnoising. 0.0 preserves image exactly, 1.0 replaces it completely', ) inpainting_group.add_argument( '-M',