Stable Diffusion WebUI Forge is a platform on top of Stable Diffusion WebUI (based on Gradio ) to make development easier, optimize resource management, speed up inference, and study experimental features.
The name "Forge" is inspired from "Minecraft Forge". This project is aimed at becoming SD WebUI's Forge.
Forge is currently based on SD-WebUI 1.10.1 at this commit. (Because original SD-WebUI is almost static now, Forge will sync with original WebUI every 90 days, or when important fixes.)
If you are proficient in Git and you want to install Forge as another branch of SD-WebUI, please see here. In this way, you can reuse all SD checkpoints and all extensions you installed previously in your OG SD-WebUI, but you should know what you are doing.
If you know what you are doing, you can install Forge using same method as SD-WebUI. (Install Git, Python, Git Clone the forge repo https://github.com/lllyasviel/stable-diffusion-webui-forge.git
and then run webui-user.bat).
Or you can just use this one-click installation package (with git and python included).
>>> Click Here to Download One-Click Package (CUDA 12.1 + Pytorch 2.3.1) <<<
Some other CUDA/Torch Versions:
Forge with CUDA 12.1 + Pytorch 2.3.1 <- Recommended
Forge with CUDA 12.4 + Pytorch 2.4 <- Fastest, but MSVC may be broken, xformers may not work
Forge with CUDA 12.1 + Pytorch 2.1 <- the previously used old environments
After you download, you uncompress, use update.bat
to update, and use run.bat
to run.
Note that running update.bat
is important, otherwise you may be using a previous version with potential bugs unfixed.
You can download previous versions here.
Based on manual test one-by-one:
Component | Status | Last Test |
---|---|---|
Basic Diffusion | Normal | 2024 July 27 |
GPU Memory Management System | Normal | 2024 July 27 |
LoRAs | Normal | 2024 July 27 |
All Preprocessors | Normal | 2024 July 27 |
All ControlNets | Normal | 2024 July 27 |
All IP-Adapters | Normal | 2024 July 27 |
All Instant-IDs | Normal | 2024 July 27 |
All Reference-only Methods | Normal | 2024 July 27 |
All Integrated Extensions | Normal | 2024 July 27 |
Popular Extensions (Adetailer, etc) | Normal | 2024 July 27 |
Gradio 4 UIs | Normal | 2024 July 27 |
Gradio 4 Forge Canvas | Normal | 2024 July 27 |
LoRA/Checkpoint Selection UI for Gradio 4 | Normal | 2024 July 27 |
Photopea/OpenposeEditor/etc for ControlNet | Normal | 2024 July 27 |
Wacom 128 level touch pressure support for Canvas | Normal | 2024 July 15 |
Microsoft Surface touch pressure support for Canvas | Broken, pending fix | 2024 July 29 |
Feel free to open issue if anything is broken and I will take a look every several days. If I do not update this "Forge Status" then it means I cannot reproduce any problem. In that case, fresh re-install should help most.
Below are self-supported single file of all codes to implement FreeU V2.
See also extension-builtin/sd_forge_freeu/scripts/forge_freeu.py
:
1import torch
2import gradio as gr
3
4from modules import scripts
5
6
7def Fourier_filter(x, threshold, scale):
8 # FFT
9 x_freq = torch.fft.fftn(x.float(), dim=(-2, -1))
10 x_freq = torch.fft.fftshift(x_freq, dim=(-2, -1))
11
12 B, C, H, W = x_freq.shape
13 mask = torch.ones((B, C, H, W), device=x.device)
14
15 crow, ccol = H // 2, W // 2
16 mask[..., crow - threshold:crow + threshold, ccol - threshold:ccol + threshold] = scale
17 x_freq = x_freq * mask
18
19 # IFFT
20 x_freq = torch.fft.ifftshift(x_freq, dim=(-2, -1))
21 x_filtered = torch.fft.ifftn(x_freq, dim=(-2, -1)).real
22
23 return x_filtered.to(x.dtype)
24
25
26def patch_freeu_v2(unet_patcher, b1, b2, s1, s2):
27 model_channels = unet_patcher.model.diffusion_model.config["model_channels"]
28 scale_dict = {model_channels * 4: (b1, s1), model_channels * 2: (b2, s2)}
29 on_cpu_devices = {}
30
31 def output_block_patch(h, hsp, transformer_options):
32 scale = scale_dict.get(h.shape[1], None)
33 if scale is not None:
34 hidden_mean = h.mean(1).unsqueeze(1)
35 B = hidden_mean.shape[0]
36 hidden_max, _ = torch.max(hidden_mean.view(B, -1), dim=-1, keepdim=True)
37 hidden_min, _ = torch.min(hidden_mean.view(B, -1), dim=-1, keepdim=True)
38 hidden_mean = (hidden_mean - hidden_min.unsqueeze(2).unsqueeze(3)) / (hidden_max - hidden_min).unsqueeze(2).unsqueeze(3)
39
40 h[:, :h.shape[1] // 2] = h[:, :h.shape[1] // 2] * ((scale[0] - 1) * hidden_mean + 1)
41
42 if hsp.device not in on_cpu_devices:
43 try:
44 hsp = Fourier_filter(hsp, threshold=1, scale=scale[1])
45 except:
46 print("Device", hsp.device, "does not support the torch.fft.")
47 on_cpu_devices[hsp.device] = True
48 hsp = Fourier_filter(hsp.cpu(), threshold=1, scale=scale[1]).to(hsp.device)
49 else:
50 hsp = Fourier_filter(hsp.cpu(), threshold=1, scale=scale[1]).to(hsp.device)
51
52 return h, hsp
53
54 m = unet_patcher.clone()
55 m.set_model_output_block_patch(output_block_patch)
56 return m
57
58
59class FreeUForForge(scripts.Script):
60 sorting_priority = 12 # It will be the 12th item on UI.
61
62 def title(self):
63 return "FreeU Integrated"
64
65 def show(self, is_img2img):
66 # make this extension visible in both txt2img and img2img tab.
67 return scripts.AlwaysVisible
68
69 def ui(self, *args, **kwargs):
70 with gr.Accordion(open=False, label=self.title()):
71 freeu_enabled = gr.Checkbox(label='Enabled', value=False)
72 freeu_b1 = gr.Slider(label='B1', minimum=0, maximum=2, step=0.01, value=1.01)
73 freeu_b2 = gr.Slider(label='B2', minimum=0, maximum=2, step=0.01, value=1.02)
74 freeu_s1 = gr.Slider(label='S1', minimum=0, maximum=4, step=0.01, value=0.99)
75 freeu_s2 = gr.Slider(label='S2', minimum=0, maximum=4, step=0.01, value=0.95)
76
77 return freeu_enabled, freeu_b1, freeu_b2, freeu_s1, freeu_s2
78
79 def process_before_every_sampling(self, p, *script_args, **kwargs):
80 # This will be called before every sampling.
81 # If you use highres fix, this will be called twice.
82
83 freeu_enabled, freeu_b1, freeu_b2, freeu_s1, freeu_s2 = script_args
84
85 if not freeu_enabled:
86 return
87
88 unet = p.sd_model.forge_objects.unet
89
90 unet = patch_freeu_v2(unet, freeu_b1, freeu_b2, freeu_s1, freeu_s2)
91
92 p.sd_model.forge_objects.unet = unet
93
94 # Below codes will add some logs to the texts below the image outputs on UI.
95 # The extra_generation_params does not influence results.
96 p.extra_generation_params.update(dict(
97 freeu_enabled=freeu_enabled,
98 freeu_b1=freeu_b1,
99 freeu_b2=freeu_b2,
100 freeu_s1=freeu_s1,
101 freeu_s2=freeu_s2,
102 ))
103
104 return
See also Forge's Unet Implementation.
WebUI Forge is now under some constructions, and docs / UI / functionality may change with updates.