From 93b1298d468d8f4207126c72f5331402a4dbc42e Mon Sep 17 00:00:00 2001 From: ArDiouscuros <72071512+ArDiouscuros@users.noreply.github.com> Date: Sat, 1 Oct 2022 21:24:10 +0200 Subject: [PATCH 1/4] Improve !fetch, add !replay Allow save fetched commands to a file Replay command to get commands from file inside of interactive prompt Related to #871 --- scripts/dream.py | 49 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/scripts/dream.py b/scripts/dream.py index 5fab79f7d94..768493e8ae2 100644 --- a/scripts/dream.py +++ b/scripts/dream.py @@ -16,6 +16,7 @@ from ldm.dream.log import write_log from omegaconf import OmegaConf from backend.invoke_ai_web_server import InvokeAIWebServer +from pathlib import Path def main(): @@ -123,6 +124,7 @@ def main(): def main_loop(gen, opt, infile): """prompt/read/execute loop""" done = False + doneAfterInFile = infile is not None path_filter = re.compile(r'[<>:"/\\|?*]') last_results = list() model_config = OmegaConf.load(opt.conf)[opt.model] @@ -150,7 +152,8 @@ def main_loop(gen, opt, infile): try: command = get_next_command(infile) except EOFError: - done = True + done = doneAfterInFile + infile = None continue # skip empty lines @@ -175,10 +178,16 @@ def main_loop(gen, opt, infile): operation = 'postprocess' elif subcommand.startswith('fetch'): - file_path = command.replace('!fetch ','',1) + file_path = command.replace('!fetch','',1).strip() retrieve_dream_command(opt,file_path,completer) continue + elif subcommand.startswith('replay'): + file_path = command.replace('!replay','',1).strip() + if infile is None and os.path.isfile(file_path): + infile = open(file_path, 'r', encoding='utf-8') + continue + elif subcommand.startswith('history'): completer.show_history() continue @@ -510,18 +519,40 @@ def retrieve_dream_command(opt,file_path,completer): will retrieve and format the dream command used to generate the image, and pop it into the readline buffer (linux, Mac), or print out a comment for cut-and-paste (windows) + Given a wildcard path to a folder with image png files, + will retrieve and format the dream command used to generate the images, + and save them to a file commands.txt for further processing ''' + dir,basename = os.path.split(file_path) if len(dir) == 0: - path = os.path.join(opt.outdir,basename) - else: - path = file_path + dir = opt.outdir try: - cmd = dream_cmd_from_png(path) - except FileNotFoundError: - print(f'** {path}: file not found') + paths = list(Path(dir).glob(basename)) + except ValueError: + print(f'## "{basename}": unacceptable pattern') return - completer.set_line(cmd) + + commands = [] + for path in paths: + try: + cmd = dream_cmd_from_png(path) + except OSError: + print(f'## {path}: file could not be read') + continue + except (KeyError, AttributeError): + print(f'## {path}: file has no metadata') + continue + + commands.append(cmd) + + outfile = os.path.join(dir,'commands.txt') + with open(outfile, 'w', encoding='utf-8') as f: + f.write('\n'.join(commands)) + print(f'>> File {outfile} with commands created') + + if len(commands) == 1: + completer.set_line(commands[0]) if __name__ == '__main__': main() From 935a9d3c758f540fbc3dc898610304ce5b0d3e0d Mon Sep 17 00:00:00 2001 From: ArDiouscuros <72071512+ArDiouscuros@users.noreply.github.com> Date: Mon, 3 Oct 2022 10:38:22 +0200 Subject: [PATCH 2/4] Update !fetch command, add documentation and autocomplete list -- !fetch takes second optional argument name of the file to save commands to --- docs/features/CLI.md | 15 +++++++++++++++ ldm/dream/readline.py | 2 +- scripts/dream.py | 27 +++++++++++++++++++-------- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/docs/features/CLI.md b/docs/features/CLI.md index 530d659c64b..580249f2489 100644 --- a/docs/features/CLI.md +++ b/docs/features/CLI.md @@ -249,16 +249,31 @@ generated image and either loads them into the command line (Linux|Mac), or prints them out in a comment for copy-and-paste (Windows). You may provide either the name of a file in the current output directory, or a full file path. +Given a wildcard path to a folder with image png files, +command will retrieve the dream command used to generate the images, +and save them to a file commands.txt for further processing +Name of the saved file could be set as the second argument to !fetch ~~~ dream> !fetch 0000015.8929913.png # the script returns the next line, ready for editing and running: dream> a fantastic alien landscape -W 576 -H 512 -s 60 -A plms -C 7.5 + +dream> !fetch outputs\selected-imgs\*.png selected.txt +>> File outputs\selected-imgs\selected.txt with commands created ~~~ Note that this command may behave unexpectedly if given a PNG file that was not generated by InvokeAI. +## !replay + +This command replays a text file generated by !fetch or created manually + +~~~ +dream> !replay outputs\selected-imgs\selected.txt +~~~ + ## !history The dream script keeps track of all the commands you issue during a diff --git a/ldm/dream/readline.py b/ldm/dream/readline.py index 375a7ac41bd..e99bf5b5a79 100644 --- a/ldm/dream/readline.py +++ b/ldm/dream/readline.py @@ -44,7 +44,7 @@ '-save_orig','--save_original', '--skip_normalize','-x', '--log_tokenization','-t', - '!fix','!fetch','!history', + '!fix','!fetch','!history','!replay' ) IMG_PATH_COMMANDS = ( '--outdir[=\s]', diff --git a/scripts/dream.py b/scripts/dream.py index 768493e8ae2..57435ccb267 100644 --- a/scripts/dream.py +++ b/scripts/dream.py @@ -513,7 +513,7 @@ def split_variations(variations_string) -> list: else: return parts -def retrieve_dream_command(opt,file_path,completer): +def retrieve_dream_command(opt,command,completer): ''' Given a full or partial path to a previously-generated image file, will retrieve and format the dream command used to generate the image, @@ -523,10 +523,22 @@ def retrieve_dream_command(opt,file_path,completer): will retrieve and format the dream command used to generate the images, and save them to a file commands.txt for further processing ''' - + if len(command) == 0: + return + tokens = command.split() + if len(tokens) > 1: + outfilepath = tokens[1] + else: + outfilepath = "commands.txt" + + file_path = tokens[0] dir,basename = os.path.split(file_path) if len(dir) == 0: dir = opt.outdir + + outdir,outname = os.path.split(outfilepath) + if len(outdir) == 0: + outfilepath = os.path.join(dir,outname) try: paths = list(Path(dir).glob(basename)) except ValueError: @@ -543,16 +555,15 @@ def retrieve_dream_command(opt,file_path,completer): except (KeyError, AttributeError): print(f'## {path}: file has no metadata') continue - + commands.append(f'# {path}') commands.append(cmd) - outfile = os.path.join(dir,'commands.txt') - with open(outfile, 'w', encoding='utf-8') as f: + with open(outfilepath, 'w', encoding='utf-8') as f: f.write('\n'.join(commands)) - print(f'>> File {outfile} with commands created') + print(f'>> File {outfilepath} with commands created') - if len(commands) == 1: - completer.set_line(commands[0]) + if len(commands) == 2: + completer.set_line(commands[1]) if __name__ == '__main__': main() From 02b10402645f85311fdcaf039ff0e8fbde277f0b Mon Sep 17 00:00:00 2001 From: ArDiouscuros <72071512+ArDiouscuros@users.noreply.github.com> Date: Sat, 8 Oct 2022 13:32:28 +0200 Subject: [PATCH 3/4] Fix typo in ldm/dream/readline.py during merge, add more exception handling --- ldm/dream/readline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ldm/dream/readline.py b/ldm/dream/readline.py index 99ea482a1db..7290a5fa5f9 100644 --- a/ldm/dream/readline.py +++ b/ldm/dream/readline.py @@ -47,7 +47,7 @@ '--skip_normalize','-x', '--log_tokenization','-t', '--hires_fix', - '!fix','!fetch',!replay','!history','!search','!clear', + '!fix','!fetch','!replay','!history','!search','!clear', ) IMG_PATH_COMMANDS = ( '--outdir[=\s]', From 62d4bb05d4827c3ab5c98d57cfc5c3125a10f047 Mon Sep 17 00:00:00 2001 From: ArDiouscuros <72071512+ArDiouscuros@users.noreply.github.com> Date: Sat, 8 Oct 2022 13:42:30 +0200 Subject: [PATCH 4/4] Add exception handling during metadata processing --- scripts/dream.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/dream.py b/scripts/dream.py index aaf0e6f3002..f5e6bfb0949 100644 --- a/scripts/dream.py +++ b/scripts/dream.py @@ -593,9 +593,13 @@ def retrieve_dream_command(opt,command,completer): except OSError: print(f'## {path}: file could not be read') continue - except (KeyError, AttributeError): + except (KeyError, AttributeError, IndexError): print(f'## {path}: file has no metadata') continue + except: + print(f'## {path}: file could not be processed') + continue + commands.append(f'# {path}') commands.append(cmd)