Add support for SD 2.1 Turbo
diff --git a/modules/sd_hijack.py b/modules/sd_hijack.py
index 0157e19f003..3d340fc9b21 100644
--- a/modules/sd_hijack.py
+++ b/modules/sd_hijack.py
@@ -38,9 +38,6 @@
 optimizers = []
 current_optimizer: sd_hijack_optimizations.SdOptimization = None
 
-ldm_original_forward = patches.patch(__file__, ldm.modules.diffusionmodules.openaimodel.UNetModel, "forward", sd_unet.UNetModel_forward)
-sgm_original_forward = patches.patch(__file__, sgm.modules.diffusionmodules.openaimodel.UNetModel, "forward", sd_unet.UNetModel_forward)
-
 def list_optimizers():
     new_optimizers = script_callbacks.list_optimizers_callback()
 
@@ -258,6 +255,9 @@ def flatten(el):
 
         import modules.models.diffusion.ddpm_edit
 
+        ldm_original_forward = patches.patch(__file__, ldm.modules.diffusionmodules.openaimodel.UNetModel, "forward", sd_unet.UNetModel_forward)
+        sgm_original_forward = patches.patch(__file__, sgm.modules.diffusionmodules.openaimodel.UNetModel, "forward", sd_unet.UNetModel_forward)
+
         if isinstance(m, ldm.models.diffusion.ddpm.LatentDiffusion):
             sd_unet.original_forward = ldm_original_forward
         elif isinstance(m, modules.models.diffusion.ddpm_edit.LatentDiffusion):
@@ -303,6 +303,9 @@ def undo_hijack(self, m):
         self.layers = None
         self.clip = None
 
+        patches.undo(__file__, ldm.modules.diffusionmodules.openaimodel.UNetModel, "forward")
+        patches.undo(__file__, sgm.modules.diffusionmodules.openaimodel.UNetModel, "forward")
+
         sd_unet.original_forward = None
 
 
diff --git a/modules/sd_models.py b/modules/sd_models.py
index 841402e8629..9355f1e16b7 100644
--- a/modules/sd_models.py
+++ b/modules/sd_models.py
@@ -230,15 +230,19 @@ def select_checkpoint():
     return checkpoint_info
 
 
-checkpoint_dict_replacements = {
+checkpoint_dict_replacements_sd1 = {
     'cond_stage_model.transformer.embeddings.': 'cond_stage_model.transformer.text_model.embeddings.',
     'cond_stage_model.transformer.encoder.': 'cond_stage_model.transformer.text_model.encoder.',
     'cond_stage_model.transformer.final_layer_norm.': 'cond_stage_model.transformer.text_model.final_layer_norm.',
 }
 
+checkpoint_dict_replacements_sd2_turbo = { # Converts SD 2.1 Turbo from SGM to LDM format.
+    'conditioner.embedders.0.': 'cond_stage_model.',
+}
+
 
-def transform_checkpoint_dict_key(k):
-    for text, replacement in checkpoint_dict_replacements.items():
+def transform_checkpoint_dict_key(k, replacements):
+    for text, replacement in replacements.items():
         if k.startswith(text):
             k = replacement + k[len(text):]
 
@@ -249,9 +253,14 @@ def get_state_dict_from_checkpoint(pl_sd):
     pl_sd = pl_sd.pop("state_dict", pl_sd)
     pl_sd.pop("state_dict", None)
 
+    is_sd2_turbo = 'conditioner.embedders.0.model.ln_final.weight' in pl_sd and pl_sd['conditioner.embedders.0.model.ln_final.weight'].size()[0] == 1024
+
     sd = {}
     for k, v in pl_sd.items():
-        new_key = transform_checkpoint_dict_key(k)
+        if is_sd2_turbo:
+            new_key = transform_checkpoint_dict_key(k, checkpoint_dict_replacements_sd2_turbo)
+        else:
+            new_key = transform_checkpoint_dict_key(k, checkpoint_dict_replacements_sd1)
 
         if new_key is not None:
             sd[new_key] = v

## Description

This adds support for the newly released [Stable Diffusion 2.1 Turbo](https://huggingface.co/stabilityai/sd-turbo/blob/main/sd_turbo.safetensors) model, which is more lightweight than sdxl-turbo.

Until now, all SD1 and SD2 models have been released in the [LDM format](https://github.com/Stability-AI/stablediffusion), and all SDXL models have been released in [SGM format](https://github.com/Stability-AI/generative-models/tree/main/sgm). Because of that, there is a strong assumption all over the webui codebase that SGM format implies SDXL.

However, the SD 2.1 Turbo checkpoint was released in SGM format, breaking that assumption. Rather than rewrite the whole codebase to account for this possibility (possibly breaking extensions), I opted just to convert the checkpoint from SGM to LDM on load. (Which is as simple as renaming the dict keys from `conditioner.embedders.0.model.*` to `cond_stage_model.model.*`). By doing this, all features and extensions that were working with SD2, immediately work with SD2 Turbo as well.



This PR also fixes an existing issue where undo_hijack was only partially undoing the hijack, causing loading of SD2 models to fail (because is_using_v_parameterization_for_sd2 was not able to run).

## Screenshots/videos:

![image](https://github.com/AUTOMATIC1111/stable-diffusion-webui/assets/6541413/547766e1-5727-4748-ac13-dd018d1d1714)

## Checklist:

- [X] I have read [contributing wiki page](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Contributing)
- [X] I have performed a self-review of my own code
- [X] My code follows the [style guidelines](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Contributing#code-style)
- [X] My code passes [tests](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Tests)
