Fix gratuitous, parasitic, endlessly repeated, pointless menu in version 3.2.0 (#4864)

## What type of PR is this? (check all applicable)

- [ ] Refactor
- [ ] Feature
- [X] Bug Fix
- [ ] Optimization
- [ ] Documentation Update
- [ ] Community Node Submission


## Have you discussed this change with the InvokeAI team?
- [X] Yes
- [ ] No, because:

      
## Have you updated all relevant documentation?
- [X] Yes
- [ ] No


## Description

A regression in 3.2.0 causes a seemingly nonsensical multiple choice
menu to appear when importing an SD-1 checkpoint model from the
autoimport directory. The menu asks the user to identify which type of
SD-2 model they are trying to import, which makes no sense.

In fact, the menu is popping up because there are now both "epsilon" and
"vprediction" SchedulerPredictionTypes for SD-1 as well as SD-2 models,
and the prober can't determine which prediction type to use. This PR
does two things:

1) rewords the menu as shown below
2) defaults to the most likely choice -- epsilon for v1 models and
vprediction for v2s

Here is the revised multiple-choice menu:
```
Please select the scheduler prediction type of the checkpoint named v1-5-pruned-emaonly.safetensors:
[1] "epsilon" - most v1.5 models and v2 models trained on 512 pixel images
[2] "vprediction" - v2 models trained on 768 pixel images and a few v1.5 models
[3] Accept the best guess;  you can fix it in the Web UI later

select [3]> 
```

Note that one can also put the appropriate config file into the same
directory as the checkpoint you wish to import. Give it the same name as
the model file, but with the extension `.yaml`. For example
`v1-5-pruned-emaonly.yaml`. The system will notice the yaml file and use
that, suppressing the quiz entirely.

## Related Tickets & Documents
- Closes #4768
- Closes #4827
This commit is contained in:
Lincoln Stein 2023-10-12 22:27:28 -04:00 committed by GitHub
commit d2149a8380
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 28 deletions

View File

@ -20,6 +20,7 @@ from multiprocessing import Process
from multiprocessing.connection import Connection, Pipe from multiprocessing.connection import Connection, Pipe
from pathlib import Path from pathlib import Path
from shutil import get_terminal_size from shutil import get_terminal_size
from typing import Optional
import npyscreen import npyscreen
import torch import torch
@ -630,21 +631,23 @@ def ask_user_for_prediction_type(model_path: Path, tui_conn: Connection = None)
return _ask_user_for_pt_cmdline(model_path) return _ask_user_for_pt_cmdline(model_path)
def _ask_user_for_pt_cmdline(model_path: Path) -> SchedulerPredictionType: def _ask_user_for_pt_cmdline(model_path: Path) -> Optional[SchedulerPredictionType]:
choices = [SchedulerPredictionType.Epsilon, SchedulerPredictionType.VPrediction, None] choices = [SchedulerPredictionType.Epsilon, SchedulerPredictionType.VPrediction, None]
print( print(
f""" f"""
Please select the type of the V2 checkpoint named {model_path.name}: Please select the scheduler prediction type of the checkpoint named {model_path.name}:
[1] A model based on Stable Diffusion v2 trained on 512 pixel images (SD-2-base) [1] "epsilon" - most v1.5 models and v2 models trained on 512 pixel images
[2] A model based on Stable Diffusion v2 trained on 768 pixel images (SD-2-768) [2] "vprediction" - v2 models trained on 768 pixel images and a few v1.5 models
[3] Skip this model and come back later. [3] Accept the best guess; you can fix it in the Web UI later
""" """
) )
choice = None choice = None
ok = False ok = False
while not ok: while not ok:
try: try:
choice = input("select> ").strip() choice = input("select [3]> ").strip()
if not choice:
return None
choice = choices[int(choice) - 1] choice = choices[int(choice) - 1]
ok = True ok = True
except (ValueError, IndexError): except (ValueError, IndexError):
@ -655,7 +658,6 @@ Please select the type of the V2 checkpoint named {model_path.name}:
def _ask_user_for_pt_tui(model_path: Path, tui_conn: Connection) -> SchedulerPredictionType: def _ask_user_for_pt_tui(model_path: Path, tui_conn: Connection) -> SchedulerPredictionType:
try:
tui_conn.send_bytes(f"*need v2 config for:{model_path}".encode("utf-8")) tui_conn.send_bytes(f"*need v2 config for:{model_path}".encode("utf-8"))
# note that we don't do any status checking here # note that we don't do any status checking here
response = tui_conn.recv_bytes().decode("utf-8") response = tui_conn.recv_bytes().decode("utf-8")
@ -665,12 +667,9 @@ def _ask_user_for_pt_tui(model_path: Path, tui_conn: Connection) -> SchedulerPre
return SchedulerPredictionType.epsilon return SchedulerPredictionType.epsilon
elif response == "v": elif response == "v":
return SchedulerPredictionType.VPrediction return SchedulerPredictionType.VPrediction
elif response == "abort": elif response == "guess":
logger.info("Conversion aborted")
return None return None
else: else:
return response
except Exception:
return None return None

View File

@ -381,12 +381,12 @@ def select_stable_diffusion_config_file(
wrap: bool = True, wrap: bool = True,
model_name: str = "Unknown", model_name: str = "Unknown",
): ):
message = f"Please select the correct base model for the V2 checkpoint named '{model_name}'. Press <CANCEL> to skip installation." message = f"Please select the correct prediction type for the checkpoint named '{model_name}'. Press <CANCEL> to skip installation."
title = "CONFIG FILE SELECTION" title = "CONFIG FILE SELECTION"
options = [ options = [
"An SD v2.x base model (512 pixels; no 'parameterization:' line in its yaml file)", "'epsilon' - most v1.5 models and v2 models trained on 512 pixel images",
"An SD v2.x v-predictive model (768 pixels; 'parameterization: \"v\"' line in its yaml file)", "'vprediction' - v2 models trained on 768 pixel images and a few v1.5 models)",
"Skip installation for now and come back later", "Accept the best guess; you can fix it in the Web UI later",
] ]
F = ConfirmCancelPopup( F = ConfirmCancelPopup(
@ -410,7 +410,7 @@ def select_stable_diffusion_config_file(
choice = F.add( choice = F.add(
npyscreen.SelectOne, npyscreen.SelectOne,
values=options, values=options,
value=[0], value=[2],
max_height=len(options) + 1, max_height=len(options) + 1,
scroll_exit=True, scroll_exit=True,
) )
@ -420,5 +420,5 @@ def select_stable_diffusion_config_file(
if not F.value: if not F.value:
return None return None
assert choice.value[0] in range(0, 3), "invalid choice" assert choice.value[0] in range(0, 3), "invalid choice"
choices = ["epsilon", "v", "abort"] choices = ["epsilon", "v", "guess"]
return choices[choice.value[0]] return choices[choice.value[0]]