Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a36a30fb93 | |||
| 2ea8726597 | |||
| 5dbd0355b0 | |||
| 64fd916334 | |||
| 9c1c0da026 | |||
| 656437e0a5 | |||
| 6ad666e479 | |||
| 80d639a440 | |||
| 96ee3eff6c | |||
| ff805d8d0e | |||
| c3699d4fd1 | |||
| 4d4a9e7332 | |||
| 44c5097375 | |||
| 44db35fb1a | |||
| ff1609f91e | |||
| d9499f4301 | |||
| 16ab174290 | |||
| 046c7b053a | |||
| 6b8c661c49 | |||
| 2b06cefe66 | |||
| 452ab8fe72 | |||
| 399baa54c2 | |||
| 21d561885e | |||
| 73c74baa6a | |||
| 1f373a2baa | |||
| 4afaaf8a02 | |||
| bda2ecdbf5 | |||
| 4c423f6d37 | |||
| cc80a09d82 | |||
| 8052a4971e | |||
| fbc5c531b9 | |||
| 5121846d34 | |||
| dfc4c27b24 | |||
| 88b2ef3b04 | |||
| 236dd55dbe | |||
| 443ca983ad | |||
| 464fbcd921 | |||
| 384fab9627 | |||
| 861cbd5636 | |||
| d33cb2b812 | |||
| 3e223523ce | |||
| d295e97a0d | |||
| 77bd953da2 | |||
| 2f6ea8b103 | |||
| a3d9b011a3 | |||
| 282903bb67 | |||
| 0d65d0eabd | |||
| f00eaa4d00 | |||
| d4255506ff | |||
| 117ec71994 | |||
| 4be7b620c2 | |||
| a8cbe50c9f | |||
| 19f5795c27 | |||
| 6fe16a9e1a | |||
| eadef35512 | |||
| 771dac9c5f | |||
| 0619df9835 | |||
| 7cc96429f2 | |||
| 26500b8c1b | |||
| a109c7aeb8 | |||
| 27fdc26a74 | |||
| 3a66c3c9e1 | |||
| 499543cf1d | |||
| 902afa6b4c | |||
| fff1a0c74f | |||
| 954499a494 | |||
| 44d14bc32e | |||
| fbc8d21354 | |||
| 906d1179e9 | |||
| dbb10fbd8c | |||
| 9821625a76 | |||
| 3562b0dc74 | |||
| fd51b8501e | |||
| 09a2da835e | |||
| 770ee23f18 | |||
| 76010a51ef | |||
| e34949be52 | |||
| 35fd24e857 | |||
| f71e919ecb | |||
| 2d947175b9 | |||
| f8f4ff2bb8 | |||
| 702a1e1cc7 | |||
| c3d51fc696 | |||
| 25189b29af | |||
| 061a4a295d |
@@ -1,25 +1,45 @@
|
|||||||
name: Bug Report
|
name: Bug Report
|
||||||
description: You think somethings is broken in the UI
|
description: You think something is broken in the UI
|
||||||
title: "[Bug]: "
|
title: "[Bug]: "
|
||||||
labels: ["bug-report"]
|
labels: ["bug-report"]
|
||||||
|
|
||||||
body:
|
body:
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Is there an existing issue for this?
|
|
||||||
description: Please search to see if an issue already exists for the bug you encountered, and that it hasn't been fixed in a recent build/commit.
|
|
||||||
options:
|
|
||||||
- label: I have searched the existing issues and checked the recent builds/commits
|
|
||||||
required: true
|
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
value: |
|
||||||
*Please fill this form with as much information as possible, don't forget to fill "What OS..." and "What browsers" and *provide screenshots if possible**
|
> The title of the bug report should be short and descriptive.
|
||||||
|
> Use relevant keywords for searchability.
|
||||||
|
> Do not leave it blank, but also do not put an entire error log in it.
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: |
|
||||||
|
Please perform basic debugging to see if extensions or configuration is the cause of the issue.
|
||||||
|
Basic debug procedure
|
||||||
|
1. Disable all third-party extensions - check if extension is the cause
|
||||||
|
2. Update extensions and webui - sometimes things just need to be updated
|
||||||
|
3. Backup and remove your config.json and ui-config.json - check if the issue is caused by bad configuration
|
||||||
|
4. Delete venv with third-party extensions disabled - sometimes extensions might cause wrong libraries to be installed
|
||||||
|
5. Try a fresh installation webui in a different directory - see if a clean installation solves the issue
|
||||||
|
Before making a issue report please, check that the issue hasn't been reported recently.
|
||||||
|
options:
|
||||||
|
- label: The issue exists after disabling all extensions
|
||||||
|
- label: The issue exists on a clean installation of webui
|
||||||
|
- label: The issue is caused by an extension, but I believe it is caused by a bug in the webui
|
||||||
|
- label: The issue exists in the current version of the webui
|
||||||
|
- label: The issue has not been reported before recently
|
||||||
|
- label: The issue has been reported before but has not been fixed yet
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
> Please fill this form with as much information as possible. Don't forget to "Upload Sysinfo" and "What browsers" and provide screenshots if possible
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: what-did
|
id: what-did
|
||||||
attributes:
|
attributes:
|
||||||
label: What happened?
|
label: What happened?
|
||||||
description: Tell us what happened in a very clear and simple way
|
description: Tell us what happened in a very clear and simple way
|
||||||
|
placeholder: |
|
||||||
|
txt2img is not working as intended.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
@@ -27,9 +47,9 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Steps to reproduce the problem
|
label: Steps to reproduce the problem
|
||||||
description: Please provide us with precise step by step instructions on how to reproduce the bug
|
description: Please provide us with precise step by step instructions on how to reproduce the bug
|
||||||
value: |
|
placeholder: |
|
||||||
1. Go to ....
|
1. Go to ...
|
||||||
2. Press ....
|
2. Press ...
|
||||||
3. ...
|
3. ...
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
@@ -38,13 +58,8 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: What should have happened?
|
label: What should have happened?
|
||||||
description: Tell us what you think the normal behavior should be
|
description: Tell us what you think the normal behavior should be
|
||||||
validations:
|
placeholder: |
|
||||||
required: true
|
WebUI should ...
|
||||||
- type: textarea
|
|
||||||
id: sysinfo
|
|
||||||
attributes:
|
|
||||||
label: Sysinfo
|
|
||||||
description: System info file, generated by WebUI. You can generate it in settings, on the Sysinfo page. Drag the file into the field to upload it. If you submit your report without including the sysinfo file, the report will be closed. If needed, review the report to make sure it includes no personal information you don't want to share. If you can't start WebUI, you can use --dump-sysinfo commandline argument to generate the file.
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
@@ -58,12 +73,25 @@ body:
|
|||||||
- Brave
|
- Brave
|
||||||
- Apple Safari
|
- Apple Safari
|
||||||
- Microsoft Edge
|
- Microsoft Edge
|
||||||
|
- Android
|
||||||
|
- iOS
|
||||||
- Other
|
- Other
|
||||||
|
- type: textarea
|
||||||
|
id: sysinfo
|
||||||
|
attributes:
|
||||||
|
label: Sysinfo
|
||||||
|
description: System info file, generated by WebUI. You can generate it in settings, on the Sysinfo page. Drag the file into the field to upload it. If you submit your report without including the sysinfo file, the report will be closed. If needed, review the report to make sure it includes no personal information you don't want to share. If you can't start WebUI, you can use --dump-sysinfo commandline argument to generate the file.
|
||||||
|
placeholder: |
|
||||||
|
1. Go to WebUI Settings -> Sysinfo -> Download system info.
|
||||||
|
If WebUI fails to launch, use --dump-sysinfo commandline argument to generate the file
|
||||||
|
2. Upload the Sysinfo as a attached file, Do NOT paste it in as plain text.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: logs
|
id: logs
|
||||||
attributes:
|
attributes:
|
||||||
label: Console logs
|
label: Console logs
|
||||||
description: Please provide **full** cmd/terminal logs from the moment you started UI to the end of it, after your bug happened. If it's very long, provide a link to pastebin or similar service.
|
description: Please provide **full** cmd/terminal logs from the moment you started UI to the end of it, after the bug occured. If it's very long, provide a link to pastebin or similar service.
|
||||||
render: Shell
|
render: Shell
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
@@ -71,4 +99,7 @@ body:
|
|||||||
id: misc
|
id: misc
|
||||||
attributes:
|
attributes:
|
||||||
label: Additional information
|
label: Additional information
|
||||||
description: Please provide us with any relevant additional info or context.
|
description: |
|
||||||
|
Please provide us with any relevant additional info or context.
|
||||||
|
Examples:
|
||||||
|
I have updated my GPU driver recently.
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
## 1.6.1
|
||||||
|
|
||||||
|
### Bug Fixes:
|
||||||
|
* fix an error causing the webui to fail to start ([#13839](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/13839))
|
||||||
|
|
||||||
## 1.6.0
|
## 1.6.0
|
||||||
|
|
||||||
### Features:
|
### Features:
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ A browser interface based on Gradio library for Stable Diffusion.
|
|||||||
- Eased resolution restriction: generated image's dimensions must be a multiple of 8 rather than 64
|
- Eased resolution restriction: generated image's dimensions must be a multiple of 8 rather than 64
|
||||||
- Now with a license!
|
- Now with a license!
|
||||||
- Reorder elements in the UI from settings screen
|
- Reorder elements in the UI from settings screen
|
||||||
|
- [Segmind Stable Diffusion](https://huggingface.co/segmind/SSD-1B) support
|
||||||
|
|
||||||
## Installation and Running
|
## Installation and Running
|
||||||
Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for:
|
Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for:
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
model:
|
||||||
|
base_learning_rate: 1.0e-04
|
||||||
|
target: ldm.models.diffusion.ddpm.LatentDiffusion
|
||||||
|
params:
|
||||||
|
linear_start: 0.00085
|
||||||
|
linear_end: 0.0120
|
||||||
|
num_timesteps_cond: 1
|
||||||
|
log_every_t: 200
|
||||||
|
timesteps: 1000
|
||||||
|
first_stage_key: "jpg"
|
||||||
|
cond_stage_key: "txt"
|
||||||
|
image_size: 64
|
||||||
|
channels: 4
|
||||||
|
cond_stage_trainable: false # Note: different from the one we trained before
|
||||||
|
conditioning_key: crossattn
|
||||||
|
monitor: val/loss_simple_ema
|
||||||
|
scale_factor: 0.18215
|
||||||
|
use_ema: False
|
||||||
|
|
||||||
|
scheduler_config: # 10000 warmup steps
|
||||||
|
target: ldm.lr_scheduler.LambdaLinearScheduler
|
||||||
|
params:
|
||||||
|
warm_up_steps: [ 10000 ]
|
||||||
|
cycle_lengths: [ 10000000000000 ] # incredibly large number to prevent corner cases
|
||||||
|
f_start: [ 1.e-6 ]
|
||||||
|
f_max: [ 1. ]
|
||||||
|
f_min: [ 1. ]
|
||||||
|
|
||||||
|
unet_config:
|
||||||
|
target: ldm.modules.diffusionmodules.openaimodel.UNetModel
|
||||||
|
params:
|
||||||
|
image_size: 32 # unused
|
||||||
|
in_channels: 4
|
||||||
|
out_channels: 4
|
||||||
|
model_channels: 320
|
||||||
|
attention_resolutions: [ 4, 2, 1 ]
|
||||||
|
num_res_blocks: 2
|
||||||
|
channel_mult: [ 1, 2, 4, 4 ]
|
||||||
|
num_head_channels: 64
|
||||||
|
use_spatial_transformer: True
|
||||||
|
use_linear_in_transformer: True
|
||||||
|
transformer_depth: 1
|
||||||
|
context_dim: 1024
|
||||||
|
use_checkpoint: True
|
||||||
|
legacy: False
|
||||||
|
|
||||||
|
first_stage_config:
|
||||||
|
target: ldm.models.autoencoder.AutoencoderKL
|
||||||
|
params:
|
||||||
|
embed_dim: 4
|
||||||
|
monitor: val/rec_loss
|
||||||
|
ddconfig:
|
||||||
|
double_z: true
|
||||||
|
z_channels: 4
|
||||||
|
resolution: 256
|
||||||
|
in_channels: 3
|
||||||
|
out_ch: 3
|
||||||
|
ch: 128
|
||||||
|
ch_mult:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 4
|
||||||
|
- 4
|
||||||
|
num_res_blocks: 2
|
||||||
|
attn_resolutions: []
|
||||||
|
dropout: 0.0
|
||||||
|
lossconfig:
|
||||||
|
target: torch.nn.Identity
|
||||||
|
|
||||||
|
cond_stage_config:
|
||||||
|
target: modules.xlmr_m18.BertSeriesModelWithTransformation
|
||||||
|
params:
|
||||||
|
name: "XLMR-Large"
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
import network
|
||||||
|
|
||||||
|
class ModuleTypeGLora(network.ModuleType):
|
||||||
|
def create_module(self, net: network.Network, weights: network.NetworkWeights):
|
||||||
|
if all(x in weights.w for x in ["a1.weight", "a2.weight", "alpha", "b1.weight", "b2.weight"]):
|
||||||
|
return NetworkModuleGLora(net, weights)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
# adapted from https://github.com/KohakuBlueleaf/LyCORIS
|
||||||
|
class NetworkModuleGLora(network.NetworkModule):
|
||||||
|
def __init__(self, net: network.Network, weights: network.NetworkWeights):
|
||||||
|
super().__init__(net, weights)
|
||||||
|
|
||||||
|
if hasattr(self.sd_module, 'weight'):
|
||||||
|
self.shape = self.sd_module.weight.shape
|
||||||
|
|
||||||
|
self.w1a = weights.w["a1.weight"]
|
||||||
|
self.w1b = weights.w["b1.weight"]
|
||||||
|
self.w2a = weights.w["a2.weight"]
|
||||||
|
self.w2b = weights.w["b2.weight"]
|
||||||
|
|
||||||
|
def calc_updown(self, orig_weight):
|
||||||
|
w1a = self.w1a.to(orig_weight.device, dtype=orig_weight.dtype)
|
||||||
|
w1b = self.w1b.to(orig_weight.device, dtype=orig_weight.dtype)
|
||||||
|
w2a = self.w2a.to(orig_weight.device, dtype=orig_weight.dtype)
|
||||||
|
w2b = self.w2b.to(orig_weight.device, dtype=orig_weight.dtype)
|
||||||
|
|
||||||
|
output_shape = [w1a.size(0), w1b.size(1)]
|
||||||
|
updown = ((w2b @ w1b) + ((orig_weight @ w2a) @ w1a))
|
||||||
|
|
||||||
|
return self.finalize_updown(updown, orig_weight, output_shape)
|
||||||
@@ -5,6 +5,7 @@ import re
|
|||||||
import lora_patches
|
import lora_patches
|
||||||
import network
|
import network
|
||||||
import network_lora
|
import network_lora
|
||||||
|
import network_glora
|
||||||
import network_hada
|
import network_hada
|
||||||
import network_ia3
|
import network_ia3
|
||||||
import network_lokr
|
import network_lokr
|
||||||
@@ -15,7 +16,7 @@ import torch
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from modules import shared, devices, sd_models, errors, scripts, sd_hijack
|
from modules import shared, devices, sd_models, errors, scripts, sd_hijack
|
||||||
from modules.textual_inversion.textual_inversion import Embedding
|
import modules.textual_inversion.textual_inversion as textual_inversion
|
||||||
|
|
||||||
from lora_logger import logger
|
from lora_logger import logger
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ module_types = [
|
|||||||
network_lokr.ModuleTypeLokr(),
|
network_lokr.ModuleTypeLokr(),
|
||||||
network_full.ModuleTypeFull(),
|
network_full.ModuleTypeFull(),
|
||||||
network_norm.ModuleTypeNorm(),
|
network_norm.ModuleTypeNorm(),
|
||||||
|
network_glora.ModuleTypeGLora(),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -210,34 +212,7 @@ def load_network(name, network_on_disk):
|
|||||||
|
|
||||||
embeddings = {}
|
embeddings = {}
|
||||||
for emb_name, data in bundle_embeddings.items():
|
for emb_name, data in bundle_embeddings.items():
|
||||||
# textual inversion embeddings
|
embedding = textual_inversion.create_embedding_from_data(data, emb_name, filename=network_on_disk.filename + "/" + emb_name)
|
||||||
if 'string_to_param' in data:
|
|
||||||
param_dict = data['string_to_param']
|
|
||||||
param_dict = getattr(param_dict, '_parameters', param_dict) # fix for torch 1.12.1 loading saved file from torch 1.11
|
|
||||||
assert len(param_dict) == 1, 'embedding file has multiple terms in it'
|
|
||||||
emb = next(iter(param_dict.items()))[1]
|
|
||||||
vec = emb.detach().to(devices.device, dtype=torch.float32)
|
|
||||||
shape = vec.shape[-1]
|
|
||||||
vectors = vec.shape[0]
|
|
||||||
elif type(data) == dict and 'clip_g' in data and 'clip_l' in data: # SDXL embedding
|
|
||||||
vec = {k: v.detach().to(devices.device, dtype=torch.float32) for k, v in data.items()}
|
|
||||||
shape = data['clip_g'].shape[-1] + data['clip_l'].shape[-1]
|
|
||||||
vectors = data['clip_g'].shape[0]
|
|
||||||
elif type(data) == dict and type(next(iter(data.values()))) == torch.Tensor: # diffuser concepts
|
|
||||||
assert len(data.keys()) == 1, 'embedding file has multiple terms in it'
|
|
||||||
|
|
||||||
emb = next(iter(data.values()))
|
|
||||||
if len(emb.shape) == 1:
|
|
||||||
emb = emb.unsqueeze(0)
|
|
||||||
vec = emb.detach().to(devices.device, dtype=torch.float32)
|
|
||||||
shape = vec.shape[-1]
|
|
||||||
vectors = vec.shape[0]
|
|
||||||
else:
|
|
||||||
raise Exception(f"Couldn't identify {emb_name} in lora: {name} as neither textual inversion embedding nor diffuser concept.")
|
|
||||||
|
|
||||||
embedding = Embedding(vec, emb_name)
|
|
||||||
embedding.vectors = vectors
|
|
||||||
embedding.shape = shape
|
|
||||||
embedding.loaded = None
|
embedding.loaded = None
|
||||||
embeddings[emb_name] = embedding
|
embeddings[emb_name] = embedding
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ function isMobile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reportWindowSize() {
|
function reportWindowSize() {
|
||||||
|
if (gradioApp().querySelector('.toprow-compact-tools')) return; // not applicable for compact prompt layout
|
||||||
|
|
||||||
var currentlyMobile = isMobile();
|
var currentlyMobile = isMobile();
|
||||||
if (currentlyMobile == isSetupForMobile) return;
|
if (currentlyMobile == isSetupForMobile) return;
|
||||||
isSetupForMobile = currentlyMobile;
|
isSetupForMobile = currentlyMobile;
|
||||||
|
|||||||
@@ -19,16 +19,28 @@ function keyupEditAttention(event) {
|
|||||||
let beforeParen = before.lastIndexOf(OPEN);
|
let beforeParen = before.lastIndexOf(OPEN);
|
||||||
if (beforeParen == -1) return false;
|
if (beforeParen == -1) return false;
|
||||||
|
|
||||||
|
let beforeClosingParen = before.lastIndexOf(CLOSE);
|
||||||
|
if (beforeClosingParen != -1 && beforeClosingParen > beforeParen) return false;
|
||||||
|
|
||||||
// Find closing parenthesis around current cursor
|
// Find closing parenthesis around current cursor
|
||||||
const after = text.substring(selectionStart);
|
const after = text.substring(selectionStart);
|
||||||
let afterParen = after.indexOf(CLOSE);
|
let afterParen = after.indexOf(CLOSE);
|
||||||
if (afterParen == -1) return false;
|
if (afterParen == -1) return false;
|
||||||
|
|
||||||
|
let afterOpeningParen = after.indexOf(OPEN);
|
||||||
|
if (afterOpeningParen != -1 && afterOpeningParen < afterParen) return false;
|
||||||
|
|
||||||
// Set the selection to the text between the parenthesis
|
// Set the selection to the text between the parenthesis
|
||||||
const parenContent = text.substring(beforeParen + 1, selectionStart + afterParen);
|
const parenContent = text.substring(beforeParen + 1, selectionStart + afterParen);
|
||||||
const lastColon = parenContent.lastIndexOf(":");
|
if (/.*:-?[\d.]+/s.test(parenContent)) {
|
||||||
selectionStart = beforeParen + 1;
|
const lastColon = parenContent.lastIndexOf(":");
|
||||||
selectionEnd = selectionStart + lastColon;
|
selectionStart = beforeParen + 1;
|
||||||
|
selectionEnd = selectionStart + lastColon;
|
||||||
|
} else {
|
||||||
|
selectionStart = beforeParen + 1;
|
||||||
|
selectionEnd = selectionStart + parenContent.length;
|
||||||
|
}
|
||||||
|
|
||||||
target.setSelectionRange(selectionStart, selectionEnd);
|
target.setSelectionRange(selectionStart, selectionEnd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -57,7 +69,7 @@ function keyupEditAttention(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the user hasn't selected anything, let's select their current parenthesis block or word
|
// If the user hasn't selected anything, let's select their current parenthesis block or word
|
||||||
if (!selectCurrentParenthesisBlock('<', '>') && !selectCurrentParenthesisBlock('(', ')')) {
|
if (!selectCurrentParenthesisBlock('<', '>') && !selectCurrentParenthesisBlock('(', ')') && !selectCurrentParenthesisBlock('[', ']')) {
|
||||||
selectCurrentWord();
|
selectCurrentWord();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,33 +77,54 @@ function keyupEditAttention(event) {
|
|||||||
|
|
||||||
var closeCharacter = ')';
|
var closeCharacter = ')';
|
||||||
var delta = opts.keyedit_precision_attention;
|
var delta = opts.keyedit_precision_attention;
|
||||||
|
var start = selectionStart > 0 ? text[selectionStart - 1] : "";
|
||||||
|
var end = text[selectionEnd];
|
||||||
|
|
||||||
if (selectionStart > 0 && text[selectionStart - 1] == '<') {
|
if (start == '<') {
|
||||||
closeCharacter = '>';
|
closeCharacter = '>';
|
||||||
delta = opts.keyedit_precision_extra;
|
delta = opts.keyedit_precision_extra;
|
||||||
} else if (selectionStart == 0 || text[selectionStart - 1] != "(") {
|
} else if (start == '(' && end == ')' || start == '[' && end == ']') { // convert old-style (((emphasis)))
|
||||||
|
let numParen = 0;
|
||||||
|
|
||||||
|
while (text[selectionStart - numParen - 1] == start && text[selectionEnd + numParen] == end) {
|
||||||
|
numParen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start == "[") {
|
||||||
|
weight = (1 / 1.1) ** numParen;
|
||||||
|
} else {
|
||||||
|
weight = 1.1 ** numParen;
|
||||||
|
}
|
||||||
|
|
||||||
|
weight = Math.round(weight / opts.keyedit_precision_attention) * opts.keyedit_precision_attention;
|
||||||
|
|
||||||
|
text = text.slice(0, selectionStart - numParen) + "(" + text.slice(selectionStart, selectionEnd) + ":" + weight + ")" + text.slice(selectionEnd + numParen);
|
||||||
|
selectionStart -= numParen - 1;
|
||||||
|
selectionEnd -= numParen - 1;
|
||||||
|
} else if (start != '(') {
|
||||||
// do not include spaces at the end
|
// do not include spaces at the end
|
||||||
while (selectionEnd > selectionStart && text[selectionEnd - 1] == ' ') {
|
while (selectionEnd > selectionStart && text[selectionEnd - 1] == ' ') {
|
||||||
selectionEnd -= 1;
|
selectionEnd--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectionStart == selectionEnd) {
|
if (selectionStart == selectionEnd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
text = text.slice(0, selectionStart) + "(" + text.slice(selectionStart, selectionEnd) + ":1.0)" + text.slice(selectionEnd);
|
text = text.slice(0, selectionStart) + "(" + text.slice(selectionStart, selectionEnd) + ":1.0)" + text.slice(selectionEnd);
|
||||||
|
|
||||||
selectionStart += 1;
|
selectionStart++;
|
||||||
selectionEnd += 1;
|
selectionEnd++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var end = text.slice(selectionEnd + 1).indexOf(closeCharacter) + 1;
|
if (text[selectionEnd] != ':') return;
|
||||||
var weight = parseFloat(text.slice(selectionEnd + 1, selectionEnd + end));
|
var weightLength = text.slice(selectionEnd + 1).indexOf(closeCharacter) + 1;
|
||||||
|
var weight = parseFloat(text.slice(selectionEnd + 1, selectionEnd + weightLength));
|
||||||
if (isNaN(weight)) return;
|
if (isNaN(weight)) return;
|
||||||
|
|
||||||
weight += isPlus ? delta : -delta;
|
weight += isPlus ? delta : -delta;
|
||||||
weight = parseFloat(weight.toPrecision(12));
|
weight = parseFloat(weight.toPrecision(12));
|
||||||
if (String(weight).length == 1) weight += ".0";
|
if (Number.isInteger(weight)) weight += ".0";
|
||||||
|
|
||||||
if (closeCharacter == ')' && weight == 1) {
|
if (closeCharacter == ')' && weight == 1) {
|
||||||
var endParenPos = text.substring(selectionEnd).indexOf(')');
|
var endParenPos = text.substring(selectionEnd).indexOf(')');
|
||||||
@@ -99,7 +132,7 @@ function keyupEditAttention(event) {
|
|||||||
selectionStart--;
|
selectionStart--;
|
||||||
selectionEnd--;
|
selectionEnd--;
|
||||||
} else {
|
} else {
|
||||||
text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + end);
|
text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + weightLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
target.focus();
|
target.focus();
|
||||||
|
|||||||
+49
-11
@@ -26,8 +26,9 @@ function setupExtraNetworksForTab(tabname) {
|
|||||||
var refresh = gradioApp().getElementById(tabname + '_extra_refresh');
|
var refresh = gradioApp().getElementById(tabname + '_extra_refresh');
|
||||||
var showDirsDiv = gradioApp().getElementById(tabname + '_extra_show_dirs');
|
var showDirsDiv = gradioApp().getElementById(tabname + '_extra_show_dirs');
|
||||||
var showDirs = gradioApp().querySelector('#' + tabname + '_extra_show_dirs input');
|
var showDirs = gradioApp().querySelector('#' + tabname + '_extra_show_dirs input');
|
||||||
|
var promptContainer = gradioApp().querySelector('.prompt-container-compact#' + tabname + '_prompt_container');
|
||||||
|
var negativePrompt = gradioApp().querySelector('#' + tabname + '_neg_prompt');
|
||||||
|
|
||||||
sort.dataset.sortkey = 'sortDefault';
|
|
||||||
tabs.appendChild(searchDiv);
|
tabs.appendChild(searchDiv);
|
||||||
tabs.appendChild(sort);
|
tabs.appendChild(sort);
|
||||||
tabs.appendChild(sortOrder);
|
tabs.appendChild(sortOrder);
|
||||||
@@ -49,20 +50,23 @@ function setupExtraNetworksForTab(tabname) {
|
|||||||
|
|
||||||
elem.style.display = visible ? "" : "none";
|
elem.style.display = visible ? "" : "none";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
applySort();
|
||||||
};
|
};
|
||||||
|
|
||||||
var applySort = function() {
|
var applySort = function() {
|
||||||
|
var cards = gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card');
|
||||||
|
|
||||||
var reverse = sortOrder.classList.contains("sortReverse");
|
var reverse = sortOrder.classList.contains("sortReverse");
|
||||||
var sortKey = sort.querySelector("input").value.toLowerCase().replace("sort", "").replaceAll(" ", "_").replace(/_+$/, "").trim();
|
var sortKey = sort.querySelector("input").value.toLowerCase().replace("sort", "").replaceAll(" ", "_").replace(/_+$/, "").trim() || "name";
|
||||||
sortKey = sortKey ? "sort" + sortKey.charAt(0).toUpperCase() + sortKey.slice(1) : "";
|
sortKey = "sort" + sortKey.charAt(0).toUpperCase() + sortKey.slice(1);
|
||||||
var sortKeyStore = sortKey ? sortKey + (reverse ? "Reverse" : "") : "";
|
var sortKeyStore = sortKey + "-" + (reverse ? "Descending" : "Ascending") + "-" + cards.length;
|
||||||
if (!sortKey || sortKeyStore == sort.dataset.sortkey) {
|
|
||||||
|
if (sortKeyStore == sort.dataset.sortkey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.dataset.sortkey = sortKeyStore;
|
sort.dataset.sortkey = sortKeyStore;
|
||||||
|
|
||||||
var cards = gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card');
|
|
||||||
cards.forEach(function(card) {
|
cards.forEach(function(card) {
|
||||||
card.originalParentElement = card.parentElement;
|
card.originalParentElement = card.parentElement;
|
||||||
});
|
});
|
||||||
@@ -88,15 +92,13 @@ function setupExtraNetworksForTab(tabname) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
search.addEventListener("input", applyFilter);
|
search.addEventListener("input", applyFilter);
|
||||||
applyFilter();
|
|
||||||
["change", "blur", "click"].forEach(function(evt) {
|
|
||||||
sort.querySelector("input").addEventListener(evt, applySort);
|
|
||||||
});
|
|
||||||
sortOrder.addEventListener("click", function() {
|
sortOrder.addEventListener("click", function() {
|
||||||
sortOrder.classList.toggle("sortReverse");
|
sortOrder.classList.toggle("sortReverse");
|
||||||
applySort();
|
applySort();
|
||||||
});
|
});
|
||||||
|
applyFilter();
|
||||||
|
|
||||||
|
extraNetworksApplySort[tabname] = applySort;
|
||||||
extraNetworksApplyFilter[tabname] = applyFilter;
|
extraNetworksApplyFilter[tabname] = applyFilter;
|
||||||
|
|
||||||
var showDirsUpdate = function() {
|
var showDirsUpdate = function() {
|
||||||
@@ -109,11 +111,47 @@ function setupExtraNetworksForTab(tabname) {
|
|||||||
showDirsUpdate();
|
showDirsUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePrompt) {
|
||||||
|
if (!gradioApp().querySelector('.toprow-compact-tools')) return; // only applicable for compact prompt layout
|
||||||
|
|
||||||
|
var promptContainer = gradioApp().getElementById(tabname + '_prompt_container');
|
||||||
|
var prompt = gradioApp().getElementById(tabname + '_prompt_row');
|
||||||
|
var negPrompt = gradioApp().getElementById(tabname + '_neg_prompt_row');
|
||||||
|
var elem = id ? gradioApp().getElementById(id) : null;
|
||||||
|
|
||||||
|
if (showNegativePrompt && elem) {
|
||||||
|
elem.insertBefore(negPrompt, elem.firstChild);
|
||||||
|
} else {
|
||||||
|
promptContainer.insertBefore(negPrompt, promptContainer.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showPrompt && elem) {
|
||||||
|
elem.insertBefore(prompt, elem.firstChild);
|
||||||
|
} else {
|
||||||
|
promptContainer.insertBefore(prompt, promptContainer.firstChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function extraNetworksUrelatedTabSelected(tabname) { // called from python when user selects an unrelated tab (generate)
|
||||||
|
extraNetworksMovePromptToTab(tabname, '', false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function extraNetworksTabSelected(tabname, id, showPrompt, showNegativePrompt) { // called from python when user selects an extra networks tab
|
||||||
|
extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePrompt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function applyExtraNetworkFilter(tabname) {
|
function applyExtraNetworkFilter(tabname) {
|
||||||
setTimeout(extraNetworksApplyFilter[tabname], 1);
|
setTimeout(extraNetworksApplyFilter[tabname], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyExtraNetworkSort(tabname) {
|
||||||
|
setTimeout(extraNetworksApplySort[tabname], 1);
|
||||||
|
}
|
||||||
|
|
||||||
var extraNetworksApplyFilter = {};
|
var extraNetworksApplyFilter = {};
|
||||||
|
var extraNetworksApplySort = {};
|
||||||
var activePromptTextarea = {};
|
var activePromptTextarea = {};
|
||||||
|
|
||||||
function setupExtraNetworks() {
|
function setupExtraNetworks() {
|
||||||
|
|||||||
@@ -33,8 +33,11 @@ function updateOnBackgroundChange() {
|
|||||||
const modalImage = gradioApp().getElementById("modalImage");
|
const modalImage = gradioApp().getElementById("modalImage");
|
||||||
if (modalImage && modalImage.offsetParent) {
|
if (modalImage && modalImage.offsetParent) {
|
||||||
let currentButton = selected_gallery_button();
|
let currentButton = selected_gallery_button();
|
||||||
|
let preview = gradioApp().querySelectorAll('.livePreview > img');
|
||||||
if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
|
if (preview.length > 0) {
|
||||||
|
// show preview image if available
|
||||||
|
modalImage.src = preview[preview.length - 1].src;
|
||||||
|
} else if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
|
||||||
modalImage.src = currentButton.children[0].src;
|
modalImage.src = currentButton.children[0].src;
|
||||||
if (modalImage.style.display === 'none') {
|
if (modalImage.style.display === 'none') {
|
||||||
const modal = gradioApp().getElementById("lightboxModal");
|
const modal = gradioApp().getElementById("lightboxModal");
|
||||||
|
|||||||
@@ -1,37 +1,68 @@
|
|||||||
var observerAccordionOpen = new MutationObserver(function(mutations) {
|
|
||||||
mutations.forEach(function(mutationRecord) {
|
|
||||||
var elem = mutationRecord.target;
|
|
||||||
var open = elem.classList.contains('open');
|
|
||||||
|
|
||||||
var accordion = elem.parentNode;
|
|
||||||
accordion.classList.toggle('input-accordion-open', open);
|
|
||||||
|
|
||||||
var checkbox = gradioApp().querySelector('#' + accordion.id + "-checkbox input");
|
|
||||||
checkbox.checked = open;
|
|
||||||
updateInput(checkbox);
|
|
||||||
|
|
||||||
var extra = gradioApp().querySelector('#' + accordion.id + "-extra");
|
|
||||||
if (extra) {
|
|
||||||
extra.style.display = open ? "" : "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function inputAccordionChecked(id, checked) {
|
function inputAccordionChecked(id, checked) {
|
||||||
var label = gradioApp().querySelector('#' + id + " .label-wrap");
|
var accordion = gradioApp().getElementById(id);
|
||||||
if (label.classList.contains('open') != checked) {
|
accordion.visibleCheckbox.checked = checked;
|
||||||
label.click();
|
accordion.onVisibleCheckboxChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupAccordion(accordion) {
|
||||||
|
var labelWrap = accordion.querySelector('.label-wrap');
|
||||||
|
var gradioCheckbox = gradioApp().querySelector('#' + accordion.id + "-checkbox input");
|
||||||
|
var extra = gradioApp().querySelector('#' + accordion.id + "-extra");
|
||||||
|
var span = labelWrap.querySelector('span');
|
||||||
|
var linked = true;
|
||||||
|
|
||||||
|
var isOpen = function() {
|
||||||
|
return labelWrap.classList.contains('open');
|
||||||
|
};
|
||||||
|
|
||||||
|
var observerAccordionOpen = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(function(mutationRecord) {
|
||||||
|
accordion.classList.toggle('input-accordion-open', isOpen());
|
||||||
|
|
||||||
|
if (linked) {
|
||||||
|
accordion.visibleCheckbox.checked = isOpen();
|
||||||
|
accordion.onVisibleCheckboxChange();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
observerAccordionOpen.observe(labelWrap, {attributes: true, attributeFilter: ['class']});
|
||||||
|
|
||||||
|
if (extra) {
|
||||||
|
labelWrap.insertBefore(extra, labelWrap.lastElementChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accordion.onChecked = function(checked) {
|
||||||
|
if (isOpen() != checked) {
|
||||||
|
labelWrap.click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var visibleCheckbox = document.createElement('INPUT');
|
||||||
|
visibleCheckbox.type = 'checkbox';
|
||||||
|
visibleCheckbox.checked = isOpen();
|
||||||
|
visibleCheckbox.id = accordion.id + "-visible-checkbox";
|
||||||
|
visibleCheckbox.className = gradioCheckbox.className + " input-accordion-checkbox";
|
||||||
|
span.insertBefore(visibleCheckbox, span.firstChild);
|
||||||
|
|
||||||
|
accordion.visibleCheckbox = visibleCheckbox;
|
||||||
|
accordion.onVisibleCheckboxChange = function() {
|
||||||
|
if (linked && isOpen() != visibleCheckbox.checked) {
|
||||||
|
labelWrap.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
gradioCheckbox.checked = visibleCheckbox.checked;
|
||||||
|
updateInput(gradioCheckbox);
|
||||||
|
};
|
||||||
|
|
||||||
|
visibleCheckbox.addEventListener('click', function(event) {
|
||||||
|
linked = false;
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
visibleCheckbox.addEventListener('input', accordion.onVisibleCheckboxChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
onUiLoaded(function() {
|
onUiLoaded(function() {
|
||||||
for (var accordion of gradioApp().querySelectorAll('.input-accordion')) {
|
for (var accordion of gradioApp().querySelectorAll('.input-accordion')) {
|
||||||
var labelWrap = accordion.querySelector('.label-wrap');
|
setupAccordion(accordion);
|
||||||
observerAccordionOpen.observe(labelWrap, {attributes: true, attributeFilter: ['class']});
|
|
||||||
|
|
||||||
var extra = gradioApp().querySelector('#' + accordion.id + "-extra");
|
|
||||||
if (extra) {
|
|
||||||
labelWrap.insertBefore(extra, labelWrap.lastElementChild);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+7
-7
@@ -17,15 +17,14 @@ from fastapi.encoders import jsonable_encoder
|
|||||||
from secrets import compare_digest
|
from secrets import compare_digest
|
||||||
|
|
||||||
import modules.shared as shared
|
import modules.shared as shared
|
||||||
from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing, errors, restart, shared_items, script_callbacks, generation_parameters_copypaste
|
from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing, errors, restart, shared_items, script_callbacks, generation_parameters_copypaste, sd_models
|
||||||
from modules.api import models
|
from modules.api import models
|
||||||
from modules.shared import opts
|
from modules.shared import opts
|
||||||
from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
|
from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
|
||||||
from modules.textual_inversion.textual_inversion import create_embedding, train_embedding
|
from modules.textual_inversion.textual_inversion import create_embedding, train_embedding
|
||||||
from modules.textual_inversion.preprocess import preprocess
|
from modules.textual_inversion.preprocess import preprocess
|
||||||
from modules.hypernetworks.hypernetwork import create_hypernetwork, train_hypernetwork
|
from modules.hypernetworks.hypernetwork import create_hypernetwork, train_hypernetwork
|
||||||
from PIL import PngImagePlugin,Image
|
from PIL import PngImagePlugin, Image
|
||||||
from modules.sd_models import unload_model_weights, reload_model_weights, checkpoint_aliases
|
|
||||||
from modules.sd_models_config import find_checkpoint_config_near_filename
|
from modules.sd_models_config import find_checkpoint_config_near_filename
|
||||||
from modules.realesrgan_model import get_realesrgan_models
|
from modules.realesrgan_model import get_realesrgan_models
|
||||||
from modules import devices
|
from modules import devices
|
||||||
@@ -103,7 +102,8 @@ def decode_base64_to_image(encoding):
|
|||||||
|
|
||||||
def encode_pil_to_base64(image):
|
def encode_pil_to_base64(image):
|
||||||
with io.BytesIO() as output_bytes:
|
with io.BytesIO() as output_bytes:
|
||||||
|
if isinstance(image, str):
|
||||||
|
return image
|
||||||
if opts.samples_format.lower() == 'png':
|
if opts.samples_format.lower() == 'png':
|
||||||
use_metadata = False
|
use_metadata = False
|
||||||
metadata = PngImagePlugin.PngInfo()
|
metadata = PngImagePlugin.PngInfo()
|
||||||
@@ -540,12 +540,12 @@ class Api:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
def unloadapi(self):
|
def unloadapi(self):
|
||||||
unload_model_weights()
|
sd_models.unload_model_weights()
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def reloadapi(self):
|
def reloadapi(self):
|
||||||
reload_model_weights()
|
sd_models.send_model_to_device(shared.sd_model)
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@@ -565,7 +565,7 @@ class Api:
|
|||||||
|
|
||||||
def set_config(self, req: dict[str, Any]):
|
def set_config(self, req: dict[str, Any]):
|
||||||
checkpoint_name = req.get("sd_model_checkpoint", None)
|
checkpoint_name = req.get("sd_model_checkpoint", None)
|
||||||
if checkpoint_name is not None and checkpoint_name not in checkpoint_aliases:
|
if checkpoint_name is not None and checkpoint_name not in sd_models.checkpoint_aliases:
|
||||||
raise RuntimeError(f"model {checkpoint_name!r} not found")
|
raise RuntimeError(f"model {checkpoint_name!r} not found")
|
||||||
|
|
||||||
for k, v in req.items():
|
for k, v in req.items():
|
||||||
|
|||||||
+1
-1
@@ -107,7 +107,7 @@ parser.add_argument("--tls-certfile", type=str, help="Partially enables TLS, req
|
|||||||
parser.add_argument("--disable-tls-verify", action="store_false", help="When passed, enables the use of self-signed certificates.", default=None)
|
parser.add_argument("--disable-tls-verify", action="store_false", help="When passed, enables the use of self-signed certificates.", default=None)
|
||||||
parser.add_argument("--server-name", type=str, help="Sets hostname of server", default=None)
|
parser.add_argument("--server-name", type=str, help="Sets hostname of server", default=None)
|
||||||
parser.add_argument("--gradio-queue", action='store_true', help="does not do anything", default=True)
|
parser.add_argument("--gradio-queue", action='store_true', help="does not do anything", default=True)
|
||||||
parser.add_argument("--no-gradio-queue", action='store_true', help="Disables gradio queue; causes the webpage to use http requests instead of websockets; was the defaul in earlier versions")
|
parser.add_argument("--no-gradio-queue", action='store_true', help="Disables gradio queue; causes the webpage to use http requests instead of websockets; was the default in earlier versions")
|
||||||
parser.add_argument("--skip-version-check", action='store_true', help="Do not check versions of torch and xformers")
|
parser.add_argument("--skip-version-check", action='store_true', help="Do not check versions of torch and xformers")
|
||||||
parser.add_argument("--no-hashing", action='store_true', help="disable sha256 hashing of checkpoints to help loading performance", default=False)
|
parser.add_argument("--no-hashing", action='store_true', help="disable sha256 hashing of checkpoints to help loading performance", default=False)
|
||||||
parser.add_argument("--no-download-sd-model", action='store_true', help="don't download SD1.5 model even if no model is found in --ckpt-dir", default=False)
|
parser.add_argument("--no-download-sd-model", action='store_true', help="don't download SD1.5 model even if no model is found in --ckpt-dir", default=False)
|
||||||
|
|||||||
+20
-5
@@ -9,6 +9,7 @@ from modules import paths, shared, devices, modelloader, errors
|
|||||||
model_dir = "GFPGAN"
|
model_dir = "GFPGAN"
|
||||||
user_path = None
|
user_path = None
|
||||||
model_path = os.path.join(paths.models_path, model_dir)
|
model_path = os.path.join(paths.models_path, model_dir)
|
||||||
|
model_file_path = None
|
||||||
model_url = "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth"
|
model_url = "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth"
|
||||||
have_gfpgan = False
|
have_gfpgan = False
|
||||||
loaded_gfpgan_model = None
|
loaded_gfpgan_model = None
|
||||||
@@ -17,6 +18,7 @@ loaded_gfpgan_model = None
|
|||||||
def gfpgann():
|
def gfpgann():
|
||||||
global loaded_gfpgan_model
|
global loaded_gfpgan_model
|
||||||
global model_path
|
global model_path
|
||||||
|
global model_file_path
|
||||||
if loaded_gfpgan_model is not None:
|
if loaded_gfpgan_model is not None:
|
||||||
loaded_gfpgan_model.gfpgan.to(devices.device_gfpgan)
|
loaded_gfpgan_model.gfpgan.to(devices.device_gfpgan)
|
||||||
return loaded_gfpgan_model
|
return loaded_gfpgan_model
|
||||||
@@ -24,17 +26,24 @@ def gfpgann():
|
|||||||
if gfpgan_constructor is None:
|
if gfpgan_constructor is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
models = modelloader.load_models(model_path, model_url, user_path, ext_filter="GFPGAN")
|
models = modelloader.load_models(model_path, model_url, user_path, ext_filter=['.pth'])
|
||||||
|
|
||||||
if len(models) == 1 and models[0].startswith("http"):
|
if len(models) == 1 and models[0].startswith("http"):
|
||||||
model_file = models[0]
|
model_file = models[0]
|
||||||
elif len(models) != 0:
|
elif len(models) != 0:
|
||||||
latest_file = max(models, key=os.path.getctime)
|
gfp_models = []
|
||||||
|
for item in models:
|
||||||
|
if 'GFPGAN' in os.path.basename(item):
|
||||||
|
gfp_models.append(item)
|
||||||
|
latest_file = max(gfp_models, key=os.path.getctime)
|
||||||
model_file = latest_file
|
model_file = latest_file
|
||||||
else:
|
else:
|
||||||
print("Unable to load gfpgan model!")
|
print("Unable to load gfpgan model!")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if hasattr(facexlib.detection.retinaface, 'device'):
|
if hasattr(facexlib.detection.retinaface, 'device'):
|
||||||
facexlib.detection.retinaface.device = devices.device_gfpgan
|
facexlib.detection.retinaface.device = devices.device_gfpgan
|
||||||
|
model_file_path = model_file
|
||||||
model = gfpgan_constructor(model_path=model_file, upscale=1, arch='clean', channel_multiplier=2, bg_upsampler=None, device=devices.device_gfpgan)
|
model = gfpgan_constructor(model_path=model_file, upscale=1, arch='clean', channel_multiplier=2, bg_upsampler=None, device=devices.device_gfpgan)
|
||||||
loaded_gfpgan_model = model
|
loaded_gfpgan_model = model
|
||||||
|
|
||||||
@@ -77,19 +86,25 @@ def setup_model(dirname):
|
|||||||
global user_path
|
global user_path
|
||||||
global have_gfpgan
|
global have_gfpgan
|
||||||
global gfpgan_constructor
|
global gfpgan_constructor
|
||||||
|
global model_file_path
|
||||||
|
|
||||||
|
facexlib_path = model_path
|
||||||
|
|
||||||
|
if dirname is not None:
|
||||||
|
facexlib_path = dirname
|
||||||
|
|
||||||
load_file_from_url_orig = gfpgan.utils.load_file_from_url
|
load_file_from_url_orig = gfpgan.utils.load_file_from_url
|
||||||
facex_load_file_from_url_orig = facexlib.detection.load_file_from_url
|
facex_load_file_from_url_orig = facexlib.detection.load_file_from_url
|
||||||
facex_load_file_from_url_orig2 = facexlib.parsing.load_file_from_url
|
facex_load_file_from_url_orig2 = facexlib.parsing.load_file_from_url
|
||||||
|
|
||||||
def my_load_file_from_url(**kwargs):
|
def my_load_file_from_url(**kwargs):
|
||||||
return load_file_from_url_orig(**dict(kwargs, model_dir=model_path))
|
return load_file_from_url_orig(**dict(kwargs, model_dir=model_file_path))
|
||||||
|
|
||||||
def facex_load_file_from_url(**kwargs):
|
def facex_load_file_from_url(**kwargs):
|
||||||
return facex_load_file_from_url_orig(**dict(kwargs, save_dir=model_path, model_dir=None))
|
return facex_load_file_from_url_orig(**dict(kwargs, save_dir=facexlib_path, model_dir=None))
|
||||||
|
|
||||||
def facex_load_file_from_url2(**kwargs):
|
def facex_load_file_from_url2(**kwargs):
|
||||||
return facex_load_file_from_url_orig2(**dict(kwargs, save_dir=model_path, model_dir=None))
|
return facex_load_file_from_url_orig2(**dict(kwargs, save_dir=facexlib_path, model_dir=None))
|
||||||
|
|
||||||
gfpgan.utils.load_file_from_url = my_load_file_from_url
|
gfpgan.utils.load_file_from_url = my_load_file_from_url
|
||||||
facexlib.detection.load_file_from_url = facex_load_file_from_url
|
facexlib.detection.load_file_from_url = facex_load_file_from_url
|
||||||
|
|||||||
@@ -150,10 +150,14 @@ def dumpstacks():
|
|||||||
|
|
||||||
def configure_sigint_handler():
|
def configure_sigint_handler():
|
||||||
# make the program just exit at ctrl+c without waiting for anything
|
# make the program just exit at ctrl+c without waiting for anything
|
||||||
|
|
||||||
|
from modules import shared
|
||||||
|
|
||||||
def sigint_handler(sig, frame):
|
def sigint_handler(sig, frame):
|
||||||
print(f'Interrupted with signal {sig} in {frame}')
|
print(f'Interrupted with signal {sig} in {frame}')
|
||||||
|
|
||||||
dumpstacks()
|
if shared.opts.dump_stacks_on_signal:
|
||||||
|
dumpstacks()
|
||||||
|
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
|
|||||||
@@ -711,7 +711,7 @@ def process_images(p: StableDiffusionProcessing) -> Processed:
|
|||||||
if p.scripts is not None:
|
if p.scripts is not None:
|
||||||
p.scripts.before_process(p)
|
p.scripts.before_process(p)
|
||||||
|
|
||||||
stored_opts = {k: opts.data[k] for k in p.override_settings.keys() if k in opts.data}
|
stored_opts = {k: opts.data[k] if k in opts.data else opts.get_default(k) for k in p.override_settings.keys() if k in opts.data}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint
|
# if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint
|
||||||
@@ -886,6 +886,8 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
|||||||
|
|
||||||
devices.torch_gc()
|
devices.torch_gc()
|
||||||
|
|
||||||
|
state.nextjob()
|
||||||
|
|
||||||
if p.scripts is not None:
|
if p.scripts is not None:
|
||||||
p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n)
|
p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n)
|
||||||
|
|
||||||
@@ -958,7 +960,8 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
|||||||
|
|
||||||
devices.torch_gc()
|
devices.torch_gc()
|
||||||
|
|
||||||
state.nextjob()
|
if not infotexts:
|
||||||
|
infotexts.append(Processed(p, []).infotext(p, 0))
|
||||||
|
|
||||||
p.color_corrections = None
|
p.color_corrections = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import re
|
|||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import lark
|
import lark
|
||||||
|
|
||||||
# a prompt like this: "fantasy landscape with a [mountain:lake:0.25] and [an oak:a christmas tree:0.75][ in foreground::0.6][ in background:0.25] [shoddy:masterful:0.5]"
|
# a prompt like this: "fantasy landscape with a [mountain:lake:0.25] and [an oak:a christmas tree:0.75][ in foreground::0.6][: in background:0.25] [shoddy:masterful:0.5]"
|
||||||
# will be represented with prompt_schedule like this (assuming steps=100):
|
# will be represented with prompt_schedule like this (assuming steps=100):
|
||||||
# [25, 'fantasy landscape with a mountain and an oak in foreground shoddy']
|
# [25, 'fantasy landscape with a mountain and an oak in foreground shoddy']
|
||||||
# [50, 'fantasy landscape with a lake and an oak in foreground in background shoddy']
|
# [50, 'fantasy landscape with a lake and an oak in foreground in background shoddy']
|
||||||
|
|||||||
+20
-2
@@ -5,7 +5,7 @@ from types import MethodType
|
|||||||
from modules import devices, sd_hijack_optimizations, shared, script_callbacks, errors, sd_unet, patches
|
from modules import devices, sd_hijack_optimizations, shared, script_callbacks, errors, sd_unet, patches
|
||||||
from modules.hypernetworks import hypernetwork
|
from modules.hypernetworks import hypernetwork
|
||||||
from modules.shared import cmd_opts
|
from modules.shared import cmd_opts
|
||||||
from modules import sd_hijack_clip, sd_hijack_open_clip, sd_hijack_unet, sd_hijack_xlmr, xlmr
|
from modules import sd_hijack_clip, sd_hijack_open_clip, sd_hijack_unet, sd_hijack_xlmr, xlmr, xlmr_m18
|
||||||
|
|
||||||
import ldm.modules.attention
|
import ldm.modules.attention
|
||||||
import ldm.modules.diffusionmodules.model
|
import ldm.modules.diffusionmodules.model
|
||||||
@@ -184,6 +184,20 @@ class StableDiffusionModelHijack:
|
|||||||
errors.display(e, "applying cross attention optimization")
|
errors.display(e, "applying cross attention optimization")
|
||||||
undo_optimizations()
|
undo_optimizations()
|
||||||
|
|
||||||
|
def convert_sdxl_to_ssd(self, m):
|
||||||
|
"""Converts an SDXL model to a Segmind Stable Diffusion model (see https://huggingface.co/segmind/SSD-1B)"""
|
||||||
|
|
||||||
|
delattr(m.model.diffusion_model.middle_block, '1')
|
||||||
|
delattr(m.model.diffusion_model.middle_block, '2')
|
||||||
|
for i in ['9', '8', '7', '6', '5', '4']:
|
||||||
|
delattr(m.model.diffusion_model.input_blocks[7][1].transformer_blocks, i)
|
||||||
|
delattr(m.model.diffusion_model.input_blocks[8][1].transformer_blocks, i)
|
||||||
|
delattr(m.model.diffusion_model.output_blocks[0][1].transformer_blocks, i)
|
||||||
|
delattr(m.model.diffusion_model.output_blocks[1][1].transformer_blocks, i)
|
||||||
|
delattr(m.model.diffusion_model.output_blocks[4][1].transformer_blocks, '1')
|
||||||
|
delattr(m.model.diffusion_model.output_blocks[5][1].transformer_blocks, '1')
|
||||||
|
devices.torch_gc()
|
||||||
|
|
||||||
def hijack(self, m):
|
def hijack(self, m):
|
||||||
conditioner = getattr(m, 'conditioner', None)
|
conditioner = getattr(m, 'conditioner', None)
|
||||||
if conditioner:
|
if conditioner:
|
||||||
@@ -211,7 +225,7 @@ class StableDiffusionModelHijack:
|
|||||||
else:
|
else:
|
||||||
m.cond_stage_model = conditioner
|
m.cond_stage_model = conditioner
|
||||||
|
|
||||||
if type(m.cond_stage_model) == xlmr.BertSeriesModelWithTransformation:
|
if type(m.cond_stage_model) == xlmr.BertSeriesModelWithTransformation or type(m.cond_stage_model) == xlmr_m18.BertSeriesModelWithTransformation:
|
||||||
model_embeddings = m.cond_stage_model.roberta.embeddings
|
model_embeddings = m.cond_stage_model.roberta.embeddings
|
||||||
model_embeddings.token_embedding = EmbeddingsWithFixes(model_embeddings.word_embeddings, self)
|
model_embeddings.token_embedding = EmbeddingsWithFixes(model_embeddings.word_embeddings, self)
|
||||||
m.cond_stage_model = sd_hijack_xlmr.FrozenXLMREmbedderWithCustomWords(m.cond_stage_model, self)
|
m.cond_stage_model = sd_hijack_xlmr.FrozenXLMREmbedderWithCustomWords(m.cond_stage_model, self)
|
||||||
@@ -242,8 +256,12 @@ class StableDiffusionModelHijack:
|
|||||||
|
|
||||||
self.layers = flatten(m)
|
self.layers = flatten(m)
|
||||||
|
|
||||||
|
import modules.models.diffusion.ddpm_edit
|
||||||
|
|
||||||
if isinstance(m, ldm.models.diffusion.ddpm.LatentDiffusion):
|
if isinstance(m, ldm.models.diffusion.ddpm.LatentDiffusion):
|
||||||
sd_unet.original_forward = ldm_original_forward
|
sd_unet.original_forward = ldm_original_forward
|
||||||
|
elif isinstance(m, modules.models.diffusion.ddpm_edit.LatentDiffusion):
|
||||||
|
sd_unet.original_forward = ldm_original_forward
|
||||||
elif isinstance(m, sgm.models.diffusion.DiffusionEngine):
|
elif isinstance(m, sgm.models.diffusion.DiffusionEngine):
|
||||||
sd_unet.original_forward = sgm_original_forward
|
sd_unet.original_forward = sgm_original_forward
|
||||||
else:
|
else:
|
||||||
|
|||||||
+8
-16
@@ -1,7 +1,6 @@
|
|||||||
import collections
|
import collections
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import gc
|
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
@@ -353,16 +352,19 @@ def load_model_weights(model, checkpoint_info: CheckpointInfo, state_dict, timer
|
|||||||
model.is_sdxl = hasattr(model, 'conditioner')
|
model.is_sdxl = hasattr(model, 'conditioner')
|
||||||
model.is_sd2 = not model.is_sdxl and hasattr(model.cond_stage_model, 'model')
|
model.is_sd2 = not model.is_sdxl and hasattr(model.cond_stage_model, 'model')
|
||||||
model.is_sd1 = not model.is_sdxl and not model.is_sd2
|
model.is_sd1 = not model.is_sdxl and not model.is_sd2
|
||||||
|
model.is_ssd = model.is_sdxl and 'model.diffusion_model.middle_block.1.transformer_blocks.0.attn1.to_q.weight' not in state_dict.keys()
|
||||||
if model.is_sdxl:
|
if model.is_sdxl:
|
||||||
sd_models_xl.extend_sdxl(model)
|
sd_models_xl.extend_sdxl(model)
|
||||||
|
|
||||||
model.load_state_dict(state_dict, strict=False)
|
if model.is_ssd:
|
||||||
timer.record("apply weights to model")
|
sd_hijack.model_hijack.convert_sdxl_to_ssd(model)
|
||||||
|
|
||||||
if shared.opts.sd_checkpoint_cache > 0:
|
if shared.opts.sd_checkpoint_cache > 0:
|
||||||
# cache newly loaded model
|
# cache newly loaded model
|
||||||
checkpoints_loaded[checkpoint_info] = state_dict
|
checkpoints_loaded[checkpoint_info] = state_dict.copy()
|
||||||
|
|
||||||
|
model.load_state_dict(state_dict, strict=False)
|
||||||
|
timer.record("apply weights to model")
|
||||||
|
|
||||||
del state_dict
|
del state_dict
|
||||||
|
|
||||||
@@ -798,17 +800,7 @@ def reload_model_weights(sd_model=None, info=None):
|
|||||||
|
|
||||||
|
|
||||||
def unload_model_weights(sd_model=None, info=None):
|
def unload_model_weights(sd_model=None, info=None):
|
||||||
timer = Timer()
|
send_model_to_cpu(sd_model or shared.sd_model)
|
||||||
|
|
||||||
if model_data.sd_model:
|
|
||||||
model_data.sd_model.to(devices.cpu)
|
|
||||||
sd_hijack.model_hijack.undo_hijack(model_data.sd_model)
|
|
||||||
model_data.sd_model = None
|
|
||||||
sd_model = None
|
|
||||||
gc.collect()
|
|
||||||
devices.torch_gc()
|
|
||||||
|
|
||||||
print(f"Unloaded weights {timer.summary()}.")
|
|
||||||
|
|
||||||
return sd_model
|
return sd_model
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ config_unopenclip = os.path.join(sd_repo_configs_path, "v2-1-stable-unclip-h-inf
|
|||||||
config_inpainting = os.path.join(sd_configs_path, "v1-inpainting-inference.yaml")
|
config_inpainting = os.path.join(sd_configs_path, "v1-inpainting-inference.yaml")
|
||||||
config_instruct_pix2pix = os.path.join(sd_configs_path, "instruct-pix2pix.yaml")
|
config_instruct_pix2pix = os.path.join(sd_configs_path, "instruct-pix2pix.yaml")
|
||||||
config_alt_diffusion = os.path.join(sd_configs_path, "alt-diffusion-inference.yaml")
|
config_alt_diffusion = os.path.join(sd_configs_path, "alt-diffusion-inference.yaml")
|
||||||
|
config_alt_diffusion_m18 = os.path.join(sd_configs_path, "alt-diffusion-m18-inference.yaml")
|
||||||
|
|
||||||
def is_using_v_parameterization_for_sd2(state_dict):
|
def is_using_v_parameterization_for_sd2(state_dict):
|
||||||
"""
|
"""
|
||||||
@@ -95,7 +95,10 @@ def guess_model_config_from_state_dict(sd, filename):
|
|||||||
if diffusion_model_input.shape[1] == 8:
|
if diffusion_model_input.shape[1] == 8:
|
||||||
return config_instruct_pix2pix
|
return config_instruct_pix2pix
|
||||||
|
|
||||||
|
|
||||||
if sd.get('cond_stage_model.roberta.embeddings.word_embeddings.weight', None) is not None:
|
if sd.get('cond_stage_model.roberta.embeddings.word_embeddings.weight', None) is not None:
|
||||||
|
if sd.get('cond_stage_model.transformation.weight').size()[0] == 1024:
|
||||||
|
return config_alt_diffusion_m18
|
||||||
return config_alt_diffusion
|
return config_alt_diffusion
|
||||||
|
|
||||||
return config_default
|
return config_default
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ class WebuiSdModel(LatentDiffusion):
|
|||||||
"""structure with additional information about the file with model's weights"""
|
"""structure with additional information about the file with model's weights"""
|
||||||
|
|
||||||
is_sdxl: bool
|
is_sdxl: bool
|
||||||
"""True if the model's architecture is SDXL"""
|
"""True if the model's architecture is SDXL or SSD"""
|
||||||
|
|
||||||
|
is_ssd: bool
|
||||||
|
"""True if the model is SSD"""
|
||||||
|
|
||||||
is_sd2: bool
|
is_sd2: bool
|
||||||
"""True if the model's architecture is SD 2.x"""
|
"""True if the model's architecture is SD 2.x"""
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from collections import namedtuple
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import torch
|
import torch
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from modules import devices, images, sd_vae_approx, sd_samplers, sd_vae_taesd, shared, sd_models
|
from modules import devices, images, sd_vae_approx, sd_samplers, sd_vae_taesd, sd_vae_consistency, shared, sd_models
|
||||||
from modules.shared import opts, state
|
from modules.shared import opts, state
|
||||||
import k_diffusion.sampling
|
import k_diffusion.sampling
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ def setup_img2img_steps(p, steps=None):
|
|||||||
return steps, t_enc
|
return steps, t_enc
|
||||||
|
|
||||||
|
|
||||||
approximation_indexes = {"Full": 0, "Approx NN": 1, "Approx cheap": 2, "TAESD": 3}
|
approximation_indexes = {"Full": 0, "Approx NN": 1, "Approx cheap": 2, "TAESD": 3, "Consistency Decoder": 4}
|
||||||
|
|
||||||
|
|
||||||
def samples_to_images_tensor(sample, approximation=None, model=None):
|
def samples_to_images_tensor(sample, approximation=None, model=None):
|
||||||
@@ -51,6 +51,13 @@ def samples_to_images_tensor(sample, approximation=None, model=None):
|
|||||||
elif approximation == 3:
|
elif approximation == 3:
|
||||||
x_sample = sd_vae_taesd.decoder_model()(sample.to(devices.device, devices.dtype)).detach()
|
x_sample = sd_vae_taesd.decoder_model()(sample.to(devices.device, devices.dtype)).detach()
|
||||||
x_sample = x_sample * 2 - 1
|
x_sample = x_sample * 2 - 1
|
||||||
|
elif approximation == 4:
|
||||||
|
with devices.autocast(), torch.no_grad():
|
||||||
|
x_sample = sd_vae_consistency.decoder_model()(
|
||||||
|
sample.detach().to(devices.device, devices.dtype)/0.18215,
|
||||||
|
schedule=[float(i.strip()) for i in shared.opts.sd_vae_consistency_schedule.split(',')],
|
||||||
|
)
|
||||||
|
sd_vae_consistency.unload()
|
||||||
else:
|
else:
|
||||||
if model is None:
|
if model is None:
|
||||||
model = shared.sd_model
|
model = shared.sd_model
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
"""
|
||||||
|
Consistency Decoder
|
||||||
|
Improved decoding for stable diffusion vaes.
|
||||||
|
|
||||||
|
https://github.com/openai/consistencydecoder
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
from modules import devices, paths_internal, shared
|
||||||
|
from consistencydecoder import ConsistencyDecoder
|
||||||
|
|
||||||
|
|
||||||
|
sd_vae_consistency_models = None
|
||||||
|
model_path = os.path.join(paths_internal.models_path, 'consistencydecoder')
|
||||||
|
|
||||||
|
|
||||||
|
def decoder_model():
|
||||||
|
global sd_vae_consistency_models
|
||||||
|
if getattr(shared.sd_model, 'is_sdxl', False):
|
||||||
|
raise NotImplementedError("SDXL is not supported for consistency decoder")
|
||||||
|
if sd_vae_consistency_models is not None:
|
||||||
|
sd_vae_consistency_models.ckpt.to(devices.device)
|
||||||
|
return sd_vae_consistency_models
|
||||||
|
|
||||||
|
loaded_model = ConsistencyDecoder(devices.device, model_path)
|
||||||
|
sd_vae_consistency_models = loaded_model
|
||||||
|
return loaded_model
|
||||||
|
|
||||||
|
|
||||||
|
def unload():
|
||||||
|
global sd_vae_consistency_models
|
||||||
|
if sd_vae_consistency_models is not None:
|
||||||
|
devices.torch_gc()
|
||||||
|
sd_vae_consistency_models.ckpt.to('cpu')
|
||||||
@@ -67,6 +67,8 @@ def reload_hypernetworks():
|
|||||||
|
|
||||||
|
|
||||||
ui_reorder_categories_builtin_items = [
|
ui_reorder_categories_builtin_items = [
|
||||||
|
"prompt",
|
||||||
|
"image",
|
||||||
"inpaint",
|
"inpaint",
|
||||||
"sampler",
|
"sampler",
|
||||||
"accordions",
|
"accordions",
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ options_templates.update(options_section(('saving-images', "Saving images/grids"
|
|||||||
"clean_temp_dir_at_start": OptionInfo(False, "Cleanup non-default temporary directory when starting webui"),
|
"clean_temp_dir_at_start": OptionInfo(False, "Cleanup non-default temporary directory when starting webui"),
|
||||||
|
|
||||||
"save_incomplete_images": OptionInfo(False, "Save incomplete images").info("save images that has been interrupted in mid-generation; even if not saved, they will still show up in webui output."),
|
"save_incomplete_images": OptionInfo(False, "Save incomplete images").info("save images that has been interrupted in mid-generation; even if not saved, they will still show up in webui output."),
|
||||||
|
|
||||||
|
"notification_audio": OptionInfo(True, "Play notification sound after image generation").info("notification.mp3 should be present in the root directory").needs_reload_ui(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
options_templates.update(options_section(('saving-paths', "Paths for saving"), {
|
options_templates.update(options_section(('saving-paths', "Paths for saving"), {
|
||||||
@@ -110,6 +112,7 @@ options_templates.update(options_section(('system', "System"), {
|
|||||||
"list_hidden_files": OptionInfo(True, "Load models/files in hidden directories").info("directory is hidden if its name starts with \".\""),
|
"list_hidden_files": OptionInfo(True, "Load models/files in hidden directories").info("directory is hidden if its name starts with \".\""),
|
||||||
"disable_mmap_load_safetensors": OptionInfo(False, "Disable memmapping for loading .safetensors files.").info("fixes very slow loading speed in some cases"),
|
"disable_mmap_load_safetensors": OptionInfo(False, "Disable memmapping for loading .safetensors files.").info("fixes very slow loading speed in some cases"),
|
||||||
"hide_ldm_prints": OptionInfo(True, "Prevent Stability-AI's ldm/sgm modules from printing noise to console."),
|
"hide_ldm_prints": OptionInfo(True, "Prevent Stability-AI's ldm/sgm modules from printing noise to console."),
|
||||||
|
"dump_stacks_on_signal": OptionInfo(False, "Print stack traces before exiting the program with ctrl+c."),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
options_templates.update(options_section(('API', "API"), {
|
options_templates.update(options_section(('API', "API"), {
|
||||||
@@ -169,7 +172,8 @@ For img2img, VAE is used to process user's input image before the sampling, and
|
|||||||
"sd_vae_overrides_per_model_preferences": OptionInfo(True, "Selected VAE overrides per-model preferences").info("you can set per-model VAE either by editing user metadata for checkpoints, or by making the VAE have same name as checkpoint"),
|
"sd_vae_overrides_per_model_preferences": OptionInfo(True, "Selected VAE overrides per-model preferences").info("you can set per-model VAE either by editing user metadata for checkpoints, or by making the VAE have same name as checkpoint"),
|
||||||
"auto_vae_precision": OptionInfo(True, "Automatically revert VAE to 32-bit floats").info("triggers when a tensor with NaNs is produced in VAE; disabling the option in this case will result in a black square image"),
|
"auto_vae_precision": OptionInfo(True, "Automatically revert VAE to 32-bit floats").info("triggers when a tensor with NaNs is produced in VAE; disabling the option in this case will result in a black square image"),
|
||||||
"sd_vae_encode_method": OptionInfo("Full", "VAE type for encode", gr.Radio, {"choices": ["Full", "TAESD"]}, infotext='VAE Encoder').info("method to encode image to latent (use in img2img, hires-fix or inpaint mask)"),
|
"sd_vae_encode_method": OptionInfo("Full", "VAE type for encode", gr.Radio, {"choices": ["Full", "TAESD"]}, infotext='VAE Encoder').info("method to encode image to latent (use in img2img, hires-fix or inpaint mask)"),
|
||||||
"sd_vae_decode_method": OptionInfo("Full", "VAE type for decode", gr.Radio, {"choices": ["Full", "TAESD"]}, infotext='VAE Decoder').info("method to decode latent to image"),
|
"sd_vae_decode_method": OptionInfo("Full", "VAE type for decode", gr.Radio, {"choices": ["Full", "TAESD", "Consistency Decoder"]}, infotext='VAE Decoder').info("method to decode latent to image"),
|
||||||
|
"sd_vae_consistency_schedule": OptionInfo("1.0, 0.5", "consistency schedule").info("sampling schedule for consistency decoder."),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
options_templates.update(options_section(('img2img', "img2img"), {
|
options_templates.update(options_section(('img2img', "img2img"), {
|
||||||
@@ -231,6 +235,8 @@ options_templates.update(options_section(('extra_networks', "Extra Networks"), {
|
|||||||
"extra_networks_card_height": OptionInfo(0, "Card height for Extra Networks").info("in pixels"),
|
"extra_networks_card_height": OptionInfo(0, "Card height for Extra Networks").info("in pixels"),
|
||||||
"extra_networks_card_text_scale": OptionInfo(1.0, "Card text scale", gr.Slider, {"minimum": 0.0, "maximum": 2.0, "step": 0.01}).info("1 = original size"),
|
"extra_networks_card_text_scale": OptionInfo(1.0, "Card text scale", gr.Slider, {"minimum": 0.0, "maximum": 2.0, "step": 0.01}).info("1 = original size"),
|
||||||
"extra_networks_card_show_desc": OptionInfo(True, "Show description on card"),
|
"extra_networks_card_show_desc": OptionInfo(True, "Show description on card"),
|
||||||
|
"extra_networks_card_order_field": OptionInfo("Name", "Default order field for Extra Networks cards", gr.Dropdown, {"choices": ['Name', 'Date Created', 'Date Modified']}).needs_reload_ui(),
|
||||||
|
"extra_networks_card_order": OptionInfo("Ascending", "Default order for Extra Networks cards", gr.Dropdown, {"choices": ['Ascending', 'Descending']}).needs_reload_ui(),
|
||||||
"extra_networks_add_text_separator": OptionInfo(" ", "Extra networks separator").info("extra text to add before <...> when adding extra network to prompt"),
|
"extra_networks_add_text_separator": OptionInfo(" ", "Extra networks separator").info("extra text to add before <...> when adding extra network to prompt"),
|
||||||
"ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order").needs_reload_ui(),
|
"ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order").needs_reload_ui(),
|
||||||
"textual_inversion_print_at_load": OptionInfo(False, "Print a list of Textual Inversion embeddings when loading model"),
|
"textual_inversion_print_at_load": OptionInfo(False, "Print a list of Textual Inversion embeddings when loading model"),
|
||||||
@@ -267,6 +273,7 @@ options_templates.update(options_section(('ui', "User interface"), {
|
|||||||
"hires_fix_show_sampler": OptionInfo(False, "Hires fix: show hires checkpoint and sampler selection").needs_reload_ui(),
|
"hires_fix_show_sampler": OptionInfo(False, "Hires fix: show hires checkpoint and sampler selection").needs_reload_ui(),
|
||||||
"hires_fix_show_prompts": OptionInfo(False, "Hires fix: show hires prompt and negative prompt").needs_reload_ui(),
|
"hires_fix_show_prompts": OptionInfo(False, "Hires fix: show hires prompt and negative prompt").needs_reload_ui(),
|
||||||
"disable_token_counters": OptionInfo(False, "Disable prompt token counters").needs_reload_ui(),
|
"disable_token_counters": OptionInfo(False, "Disable prompt token counters").needs_reload_ui(),
|
||||||
|
"compact_prompt_box": OptionInfo(False, "Compact prompt layout").info("puts prompt and negative prompt inside the Generate tab, leaving more vertical space for the image on the right").needs_reload_ui(),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
@@ -332,4 +339,3 @@ options_templates.update(options_section((None, "Hidden options"), {
|
|||||||
"restore_config_state_file": OptionInfo("", "Config state file to restore from, under 'config-states/' folder"),
|
"restore_config_state_file": OptionInfo("", "Config state file to restore from, under 'config-states/' folder"),
|
||||||
"sd_checkpoint_hash": OptionInfo("", "SHA256 hash of the current checkpoint"),
|
"sd_checkpoint_hash": OptionInfo("", "SHA256 hash of the current checkpoint"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|||||||
@@ -181,40 +181,7 @@ class EmbeddingDatabase:
|
|||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
embedding = create_embedding_from_data(data, name, filename=filename, filepath=path)
|
||||||
# textual inversion embeddings
|
|
||||||
if 'string_to_param' in data:
|
|
||||||
param_dict = data['string_to_param']
|
|
||||||
param_dict = getattr(param_dict, '_parameters', param_dict) # fix for torch 1.12.1 loading saved file from torch 1.11
|
|
||||||
assert len(param_dict) == 1, 'embedding file has multiple terms in it'
|
|
||||||
emb = next(iter(param_dict.items()))[1]
|
|
||||||
vec = emb.detach().to(devices.device, dtype=torch.float32)
|
|
||||||
shape = vec.shape[-1]
|
|
||||||
vectors = vec.shape[0]
|
|
||||||
elif type(data) == dict and 'clip_g' in data and 'clip_l' in data: # SDXL embedding
|
|
||||||
vec = {k: v.detach().to(devices.device, dtype=torch.float32) for k, v in data.items()}
|
|
||||||
shape = data['clip_g'].shape[-1] + data['clip_l'].shape[-1]
|
|
||||||
vectors = data['clip_g'].shape[0]
|
|
||||||
elif type(data) == dict and type(next(iter(data.values()))) == torch.Tensor: # diffuser concepts
|
|
||||||
assert len(data.keys()) == 1, 'embedding file has multiple terms in it'
|
|
||||||
|
|
||||||
emb = next(iter(data.values()))
|
|
||||||
if len(emb.shape) == 1:
|
|
||||||
emb = emb.unsqueeze(0)
|
|
||||||
vec = emb.detach().to(devices.device, dtype=torch.float32)
|
|
||||||
shape = vec.shape[-1]
|
|
||||||
vectors = vec.shape[0]
|
|
||||||
else:
|
|
||||||
raise Exception(f"Couldn't identify {filename} as neither textual inversion embedding nor diffuser concept.")
|
|
||||||
|
|
||||||
embedding = Embedding(vec, name)
|
|
||||||
embedding.step = data.get('step', None)
|
|
||||||
embedding.sd_checkpoint = data.get('sd_checkpoint', None)
|
|
||||||
embedding.sd_checkpoint_name = data.get('sd_checkpoint_name', None)
|
|
||||||
embedding.vectors = vectors
|
|
||||||
embedding.shape = shape
|
|
||||||
embedding.filename = path
|
|
||||||
embedding.set_hash(hashes.sha256(embedding.filename, "textual_inversion/" + name) or '')
|
|
||||||
|
|
||||||
if self.expected_shape == -1 or self.expected_shape == embedding.shape:
|
if self.expected_shape == -1 or self.expected_shape == embedding.shape:
|
||||||
self.register_embedding(embedding, shared.sd_model)
|
self.register_embedding(embedding, shared.sd_model)
|
||||||
@@ -313,6 +280,45 @@ def create_embedding(name, num_vectors_per_token, overwrite_old, init_text='*'):
|
|||||||
return fn
|
return fn
|
||||||
|
|
||||||
|
|
||||||
|
def create_embedding_from_data(data, name, filename='unknown embedding file', filepath=None):
|
||||||
|
if 'string_to_param' in data: # textual inversion embeddings
|
||||||
|
param_dict = data['string_to_param']
|
||||||
|
param_dict = getattr(param_dict, '_parameters', param_dict) # fix for torch 1.12.1 loading saved file from torch 1.11
|
||||||
|
assert len(param_dict) == 1, 'embedding file has multiple terms in it'
|
||||||
|
emb = next(iter(param_dict.items()))[1]
|
||||||
|
vec = emb.detach().to(devices.device, dtype=torch.float32)
|
||||||
|
shape = vec.shape[-1]
|
||||||
|
vectors = vec.shape[0]
|
||||||
|
elif type(data) == dict and 'clip_g' in data and 'clip_l' in data: # SDXL embedding
|
||||||
|
vec = {k: v.detach().to(devices.device, dtype=torch.float32) for k, v in data.items()}
|
||||||
|
shape = data['clip_g'].shape[-1] + data['clip_l'].shape[-1]
|
||||||
|
vectors = data['clip_g'].shape[0]
|
||||||
|
elif type(data) == dict and type(next(iter(data.values()))) == torch.Tensor: # diffuser concepts
|
||||||
|
assert len(data.keys()) == 1, 'embedding file has multiple terms in it'
|
||||||
|
|
||||||
|
emb = next(iter(data.values()))
|
||||||
|
if len(emb.shape) == 1:
|
||||||
|
emb = emb.unsqueeze(0)
|
||||||
|
vec = emb.detach().to(devices.device, dtype=torch.float32)
|
||||||
|
shape = vec.shape[-1]
|
||||||
|
vectors = vec.shape[0]
|
||||||
|
else:
|
||||||
|
raise Exception(f"Couldn't identify {filename} as neither textual inversion embedding nor diffuser concept.")
|
||||||
|
|
||||||
|
embedding = Embedding(vec, name)
|
||||||
|
embedding.step = data.get('step', None)
|
||||||
|
embedding.sd_checkpoint = data.get('sd_checkpoint', None)
|
||||||
|
embedding.sd_checkpoint_name = data.get('sd_checkpoint_name', None)
|
||||||
|
embedding.vectors = vectors
|
||||||
|
embedding.shape = shape
|
||||||
|
|
||||||
|
if filepath:
|
||||||
|
embedding.filename = filepath
|
||||||
|
embedding.set_hash(hashes.sha256(filepath, "textual_inversion/" + name) or '')
|
||||||
|
|
||||||
|
return embedding
|
||||||
|
|
||||||
|
|
||||||
def write_loss(log_directory, filename, step, epoch_len, values):
|
def write_loss(log_directory, filename, step, epoch_len, values):
|
||||||
if shared.opts.training_write_csv_every == 0:
|
if shared.opts.training_write_csv_every == 0:
|
||||||
return
|
return
|
||||||
|
|||||||
+101
-168
@@ -12,7 +12,7 @@ from PIL import Image, PngImagePlugin # noqa: F401
|
|||||||
from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call
|
from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call
|
||||||
|
|
||||||
from modules import gradio_extensons # noqa: F401
|
from modules import gradio_extensons # noqa: F401
|
||||||
from modules import sd_hijack, sd_models, script_callbacks, ui_extensions, deepbooru, extra_networks, ui_common, ui_postprocessing, progress, ui_loadsave, shared_items, ui_settings, timer, sysinfo, ui_checkpoint_merger, ui_prompt_styles, scripts, sd_samplers, processing, ui_extra_networks
|
from modules import sd_hijack, sd_models, script_callbacks, ui_extensions, deepbooru, extra_networks, ui_common, ui_postprocessing, progress, ui_loadsave, shared_items, ui_settings, timer, sysinfo, ui_checkpoint_merger, scripts, sd_samplers, processing, ui_extra_networks, ui_toprow
|
||||||
from modules.ui_components import FormRow, FormGroup, ToolButton, FormHTML, InputAccordion, ResizeHandleRow
|
from modules.ui_components import FormRow, FormGroup, ToolButton, FormHTML, InputAccordion, ResizeHandleRow
|
||||||
from modules.paths import script_path
|
from modules.paths import script_path
|
||||||
from modules.ui_common import create_refresh_button
|
from modules.ui_common import create_refresh_button
|
||||||
@@ -25,7 +25,6 @@ import modules.hypernetworks.ui as hypernetworks_ui
|
|||||||
import modules.textual_inversion.ui as textual_inversion_ui
|
import modules.textual_inversion.ui as textual_inversion_ui
|
||||||
import modules.textual_inversion.textual_inversion as textual_inversion
|
import modules.textual_inversion.textual_inversion as textual_inversion
|
||||||
import modules.shared as shared
|
import modules.shared as shared
|
||||||
import modules.images
|
|
||||||
from modules import prompt_parser
|
from modules import prompt_parser
|
||||||
from modules.sd_hijack import model_hijack
|
from modules.sd_hijack import model_hijack
|
||||||
from modules.generation_parameters_copypaste import image_from_url_text
|
from modules.generation_parameters_copypaste import image_from_url_text
|
||||||
@@ -177,79 +176,6 @@ def update_negative_prompt_token_counter(text, steps):
|
|||||||
return update_token_counter(text, steps, is_positive=False)
|
return update_token_counter(text, steps, is_positive=False)
|
||||||
|
|
||||||
|
|
||||||
class Toprow:
|
|
||||||
"""Creates a top row UI with prompts, generate button, styles, extra little buttons for things, and enables some functionality related to their operation"""
|
|
||||||
|
|
||||||
def __init__(self, is_img2img):
|
|
||||||
id_part = "img2img" if is_img2img else "txt2img"
|
|
||||||
self.id_part = id_part
|
|
||||||
|
|
||||||
with gr.Row(elem_id=f"{id_part}_toprow", variant="compact"):
|
|
||||||
with gr.Column(elem_id=f"{id_part}_prompt_container", scale=6):
|
|
||||||
with gr.Row():
|
|
||||||
with gr.Column(scale=80):
|
|
||||||
with gr.Row():
|
|
||||||
self.prompt = gr.Textbox(label="Prompt", elem_id=f"{id_part}_prompt", show_label=False, lines=3, placeholder="Prompt (press Ctrl+Enter or Alt+Enter to generate)", elem_classes=["prompt"])
|
|
||||||
self.prompt_img = gr.File(label="", elem_id=f"{id_part}_prompt_image", file_count="single", type="binary", visible=False)
|
|
||||||
|
|
||||||
with gr.Row():
|
|
||||||
with gr.Column(scale=80):
|
|
||||||
with gr.Row():
|
|
||||||
self.negative_prompt = gr.Textbox(label="Negative prompt", elem_id=f"{id_part}_neg_prompt", show_label=False, lines=3, placeholder="Negative prompt (press Ctrl+Enter or Alt+Enter to generate)", elem_classes=["prompt"])
|
|
||||||
|
|
||||||
self.button_interrogate = None
|
|
||||||
self.button_deepbooru = None
|
|
||||||
if is_img2img:
|
|
||||||
with gr.Column(scale=1, elem_classes="interrogate-col"):
|
|
||||||
self.button_interrogate = gr.Button('Interrogate\nCLIP', elem_id="interrogate")
|
|
||||||
self.button_deepbooru = gr.Button('Interrogate\nDeepBooru', elem_id="deepbooru")
|
|
||||||
|
|
||||||
with gr.Column(scale=1, elem_id=f"{id_part}_actions_column"):
|
|
||||||
with gr.Row(elem_id=f"{id_part}_generate_box", elem_classes="generate-box"):
|
|
||||||
self.interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt", elem_classes="generate-box-interrupt")
|
|
||||||
self.skip = gr.Button('Skip', elem_id=f"{id_part}_skip", elem_classes="generate-box-skip")
|
|
||||||
self.submit = gr.Button('Generate', elem_id=f"{id_part}_generate", variant='primary')
|
|
||||||
|
|
||||||
self.skip.click(
|
|
||||||
fn=lambda: shared.state.skip(),
|
|
||||||
inputs=[],
|
|
||||||
outputs=[],
|
|
||||||
)
|
|
||||||
|
|
||||||
self.interrupt.click(
|
|
||||||
fn=lambda: shared.state.interrupt(),
|
|
||||||
inputs=[],
|
|
||||||
outputs=[],
|
|
||||||
)
|
|
||||||
|
|
||||||
with gr.Row(elem_id=f"{id_part}_tools"):
|
|
||||||
self.paste = ToolButton(value=paste_symbol, elem_id="paste", tooltip="Read generation parameters from prompt or last generation if prompt is empty into user interface.")
|
|
||||||
self.clear_prompt_button = ToolButton(value=clear_prompt_symbol, elem_id=f"{id_part}_clear_prompt", tooltip="Clear prompt")
|
|
||||||
self.apply_styles = ToolButton(value=ui_prompt_styles.styles_materialize_symbol, elem_id=f"{id_part}_style_apply", tooltip="Apply all selected styles to prompts.")
|
|
||||||
self.restore_progress_button = ToolButton(value=restore_progress_symbol, elem_id=f"{id_part}_restore_progress", visible=False, tooltip="Restore progress")
|
|
||||||
|
|
||||||
self.token_counter = gr.HTML(value="<span>0/75</span>", elem_id=f"{id_part}_token_counter", elem_classes=["token-counter"])
|
|
||||||
self.token_button = gr.Button(visible=False, elem_id=f"{id_part}_token_button")
|
|
||||||
self.negative_token_counter = gr.HTML(value="<span>0/75</span>", elem_id=f"{id_part}_negative_token_counter", elem_classes=["token-counter"])
|
|
||||||
self.negative_token_button = gr.Button(visible=False, elem_id=f"{id_part}_negative_token_button")
|
|
||||||
|
|
||||||
self.clear_prompt_button.click(
|
|
||||||
fn=lambda *x: x,
|
|
||||||
_js="confirm_clear_prompt",
|
|
||||||
inputs=[self.prompt, self.negative_prompt],
|
|
||||||
outputs=[self.prompt, self.negative_prompt],
|
|
||||||
)
|
|
||||||
|
|
||||||
self.ui_styles = ui_prompt_styles.UiPromptStyles(id_part, self.prompt, self.negative_prompt)
|
|
||||||
self.ui_styles.setup_apply_button(self.apply_styles)
|
|
||||||
|
|
||||||
self.prompt_img.change(
|
|
||||||
fn=modules.images.image_data,
|
|
||||||
inputs=[self.prompt_img],
|
|
||||||
outputs=[self.prompt, self.prompt_img],
|
|
||||||
show_progress=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_progressbar(*args, **kwargs):
|
def setup_progressbar(*args, **kwargs):
|
||||||
pass
|
pass
|
||||||
@@ -288,8 +214,8 @@ def apply_setting(key, value):
|
|||||||
return getattr(opts, key)
|
return getattr(opts, key)
|
||||||
|
|
||||||
|
|
||||||
def create_output_panel(tabname, outdir):
|
def create_output_panel(tabname, outdir, toprow=None):
|
||||||
return ui_common.create_output_panel(tabname, outdir)
|
return ui_common.create_output_panel(tabname, outdir, toprow)
|
||||||
|
|
||||||
|
|
||||||
def create_sampler_and_steps_selection(choices, tabname):
|
def create_sampler_and_steps_selection(choices, tabname):
|
||||||
@@ -336,7 +262,7 @@ def create_ui():
|
|||||||
scripts.scripts_txt2img.initialize_scripts(is_img2img=False)
|
scripts.scripts_txt2img.initialize_scripts(is_img2img=False)
|
||||||
|
|
||||||
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
|
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
|
||||||
toprow = Toprow(is_img2img=False)
|
toprow = ui_toprow.Toprow(is_img2img=False, is_compact=shared.opts.compact_prompt_box)
|
||||||
|
|
||||||
dummy_component = gr.Label(visible=False)
|
dummy_component = gr.Label(visible=False)
|
||||||
|
|
||||||
@@ -348,6 +274,9 @@ def create_ui():
|
|||||||
scripts.scripts_txt2img.prepare_ui()
|
scripts.scripts_txt2img.prepare_ui()
|
||||||
|
|
||||||
for category in ordered_ui_categories():
|
for category in ordered_ui_categories():
|
||||||
|
if category == "prompt":
|
||||||
|
toprow.create_inline_toprow_prompts()
|
||||||
|
|
||||||
if category == "sampler":
|
if category == "sampler":
|
||||||
steps, sampler_name = create_sampler_and_steps_selection(sd_samplers.visible_sampler_names(), "txt2img")
|
steps, sampler_name = create_sampler_and_steps_selection(sd_samplers.visible_sampler_names(), "txt2img")
|
||||||
|
|
||||||
@@ -442,7 +371,7 @@ def create_ui():
|
|||||||
show_progress=False,
|
show_progress=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
txt2img_gallery, generation_info, html_info, html_log = create_output_panel("txt2img", opts.outdir_txt2img_samples)
|
txt2img_gallery, generation_info, html_info, html_log = create_output_panel("txt2img", opts.outdir_txt2img_samples, toprow)
|
||||||
|
|
||||||
txt2img_args = dict(
|
txt2img_args = dict(
|
||||||
fn=wrap_gradio_gpu_call(modules.txt2img.txt2img, extra_outputs=[None, '', '']),
|
fn=wrap_gradio_gpu_call(modules.txt2img.txt2img, extra_outputs=[None, '', '']),
|
||||||
@@ -554,7 +483,7 @@ def create_ui():
|
|||||||
scripts.scripts_img2img.initialize_scripts(is_img2img=True)
|
scripts.scripts_img2img.initialize_scripts(is_img2img=True)
|
||||||
|
|
||||||
with gr.Blocks(analytics_enabled=False) as img2img_interface:
|
with gr.Blocks(analytics_enabled=False) as img2img_interface:
|
||||||
toprow = Toprow(is_img2img=True)
|
toprow = ui_toprow.Toprow(is_img2img=True, is_compact=shared.opts.compact_prompt_box)
|
||||||
|
|
||||||
extra_tabs = gr.Tabs(elem_id="img2img_extra_tabs")
|
extra_tabs = gr.Tabs(elem_id="img2img_extra_tabs")
|
||||||
extra_tabs.__enter__()
|
extra_tabs.__enter__()
|
||||||
@@ -577,85 +506,89 @@ def create_ui():
|
|||||||
button = gr.Button(title)
|
button = gr.Button(title)
|
||||||
copy_image_buttons.append((button, name, elem))
|
copy_image_buttons.append((button, name, elem))
|
||||||
|
|
||||||
with gr.Tabs(elem_id="mode_img2img"):
|
|
||||||
img2img_selected_tab = gr.State(0)
|
|
||||||
|
|
||||||
with gr.TabItem('img2img', id='img2img', elem_id="img2img_img2img_tab") as tab_img2img:
|
|
||||||
init_img = gr.Image(label="Image for img2img", elem_id="img2img_image", show_label=False, source="upload", interactive=True, type="pil", tool="editor", image_mode="RGBA", height=opts.img2img_editor_height)
|
|
||||||
add_copy_image_controls('img2img', init_img)
|
|
||||||
|
|
||||||
with gr.TabItem('Sketch', id='img2img_sketch', elem_id="img2img_img2img_sketch_tab") as tab_sketch:
|
|
||||||
sketch = gr.Image(label="Image for img2img", elem_id="img2img_sketch", show_label=False, source="upload", interactive=True, type="pil", tool="color-sketch", image_mode="RGB", height=opts.img2img_editor_height, brush_color=opts.img2img_sketch_default_brush_color)
|
|
||||||
add_copy_image_controls('sketch', sketch)
|
|
||||||
|
|
||||||
with gr.TabItem('Inpaint', id='inpaint', elem_id="img2img_inpaint_tab") as tab_inpaint:
|
|
||||||
init_img_with_mask = gr.Image(label="Image for inpainting with mask", show_label=False, elem_id="img2maskimg", source="upload", interactive=True, type="pil", tool="sketch", image_mode="RGBA", height=opts.img2img_editor_height, brush_color=opts.img2img_inpaint_mask_brush_color)
|
|
||||||
add_copy_image_controls('inpaint', init_img_with_mask)
|
|
||||||
|
|
||||||
with gr.TabItem('Inpaint sketch', id='inpaint_sketch', elem_id="img2img_inpaint_sketch_tab") as tab_inpaint_color:
|
|
||||||
inpaint_color_sketch = gr.Image(label="Color sketch inpainting", show_label=False, elem_id="inpaint_sketch", source="upload", interactive=True, type="pil", tool="color-sketch", image_mode="RGB", height=opts.img2img_editor_height, brush_color=opts.img2img_inpaint_sketch_default_brush_color)
|
|
||||||
inpaint_color_sketch_orig = gr.State(None)
|
|
||||||
add_copy_image_controls('inpaint_sketch', inpaint_color_sketch)
|
|
||||||
|
|
||||||
def update_orig(image, state):
|
|
||||||
if image is not None:
|
|
||||||
same_size = state is not None and state.size == image.size
|
|
||||||
has_exact_match = np.any(np.all(np.array(image) == np.array(state), axis=-1))
|
|
||||||
edited = same_size and has_exact_match
|
|
||||||
return image if not edited or state is None else state
|
|
||||||
|
|
||||||
inpaint_color_sketch.change(update_orig, [inpaint_color_sketch, inpaint_color_sketch_orig], inpaint_color_sketch_orig)
|
|
||||||
|
|
||||||
with gr.TabItem('Inpaint upload', id='inpaint_upload', elem_id="img2img_inpaint_upload_tab") as tab_inpaint_upload:
|
|
||||||
init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", elem_id="img_inpaint_base")
|
|
||||||
init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", image_mode="RGBA", elem_id="img_inpaint_mask")
|
|
||||||
|
|
||||||
with gr.TabItem('Batch', id='batch', elem_id="img2img_batch_tab") as tab_batch:
|
|
||||||
hidden = '<br>Disabled when launched with --hide-ui-dir-config.' if shared.cmd_opts.hide_ui_dir_config else ''
|
|
||||||
gr.HTML(
|
|
||||||
"<p style='padding-bottom: 1em;' class=\"text-gray-500\">Process images in a directory on the same machine where the server is running." +
|
|
||||||
"<br>Use an empty output directory to save pictures normally instead of writing to the output directory." +
|
|
||||||
f"<br>Add inpaint batch mask directory to enable inpaint batch processing."
|
|
||||||
f"{hidden}</p>"
|
|
||||||
)
|
|
||||||
img2img_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs, elem_id="img2img_batch_input_dir")
|
|
||||||
img2img_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs, elem_id="img2img_batch_output_dir")
|
|
||||||
img2img_batch_inpaint_mask_dir = gr.Textbox(label="Inpaint batch mask directory (required for inpaint batch processing only)", **shared.hide_dirs, elem_id="img2img_batch_inpaint_mask_dir")
|
|
||||||
with gr.Accordion("PNG info", open=False):
|
|
||||||
img2img_batch_use_png_info = gr.Checkbox(label="Append png info to prompts", **shared.hide_dirs, elem_id="img2img_batch_use_png_info")
|
|
||||||
img2img_batch_png_info_dir = gr.Textbox(label="PNG info directory", **shared.hide_dirs, placeholder="Leave empty to use input directory", elem_id="img2img_batch_png_info_dir")
|
|
||||||
img2img_batch_png_info_props = gr.CheckboxGroup(["Prompt", "Negative prompt", "Seed", "CFG scale", "Sampler", "Steps", "Model hash"], label="Parameters to take from png info", info="Prompts from png info will be appended to prompts set in ui.")
|
|
||||||
|
|
||||||
img2img_tabs = [tab_img2img, tab_sketch, tab_inpaint, tab_inpaint_color, tab_inpaint_upload, tab_batch]
|
|
||||||
|
|
||||||
for i, tab in enumerate(img2img_tabs):
|
|
||||||
tab.select(fn=lambda tabnum=i: tabnum, inputs=[], outputs=[img2img_selected_tab])
|
|
||||||
|
|
||||||
def copy_image(img):
|
|
||||||
if isinstance(img, dict) and 'image' in img:
|
|
||||||
return img['image']
|
|
||||||
|
|
||||||
return img
|
|
||||||
|
|
||||||
for button, name, elem in copy_image_buttons:
|
|
||||||
button.click(
|
|
||||||
fn=copy_image,
|
|
||||||
inputs=[elem],
|
|
||||||
outputs=[copy_image_destinations[name]],
|
|
||||||
)
|
|
||||||
button.click(
|
|
||||||
fn=lambda: None,
|
|
||||||
_js=f"switch_to_{name.replace(' ', '_')}",
|
|
||||||
inputs=[],
|
|
||||||
outputs=[],
|
|
||||||
)
|
|
||||||
|
|
||||||
with FormRow():
|
|
||||||
resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", choices=["Just resize", "Crop and resize", "Resize and fill", "Just resize (latent upscale)"], type="index", value="Just resize")
|
|
||||||
|
|
||||||
scripts.scripts_img2img.prepare_ui()
|
scripts.scripts_img2img.prepare_ui()
|
||||||
|
|
||||||
for category in ordered_ui_categories():
|
for category in ordered_ui_categories():
|
||||||
|
if category == "prompt":
|
||||||
|
toprow.create_inline_toprow_prompts()
|
||||||
|
|
||||||
|
if category == "image":
|
||||||
|
with gr.Tabs(elem_id="mode_img2img"):
|
||||||
|
img2img_selected_tab = gr.State(0)
|
||||||
|
|
||||||
|
with gr.TabItem('img2img', id='img2img', elem_id="img2img_img2img_tab") as tab_img2img:
|
||||||
|
init_img = gr.Image(label="Image for img2img", elem_id="img2img_image", show_label=False, source="upload", interactive=True, type="pil", tool="editor", image_mode="RGBA", height=opts.img2img_editor_height)
|
||||||
|
add_copy_image_controls('img2img', init_img)
|
||||||
|
|
||||||
|
with gr.TabItem('Sketch', id='img2img_sketch', elem_id="img2img_img2img_sketch_tab") as tab_sketch:
|
||||||
|
sketch = gr.Image(label="Image for img2img", elem_id="img2img_sketch", show_label=False, source="upload", interactive=True, type="pil", tool="color-sketch", image_mode="RGB", height=opts.img2img_editor_height, brush_color=opts.img2img_sketch_default_brush_color)
|
||||||
|
add_copy_image_controls('sketch', sketch)
|
||||||
|
|
||||||
|
with gr.TabItem('Inpaint', id='inpaint', elem_id="img2img_inpaint_tab") as tab_inpaint:
|
||||||
|
init_img_with_mask = gr.Image(label="Image for inpainting with mask", show_label=False, elem_id="img2maskimg", source="upload", interactive=True, type="pil", tool="sketch", image_mode="RGBA", height=opts.img2img_editor_height, brush_color=opts.img2img_inpaint_mask_brush_color)
|
||||||
|
add_copy_image_controls('inpaint', init_img_with_mask)
|
||||||
|
|
||||||
|
with gr.TabItem('Inpaint sketch', id='inpaint_sketch', elem_id="img2img_inpaint_sketch_tab") as tab_inpaint_color:
|
||||||
|
inpaint_color_sketch = gr.Image(label="Color sketch inpainting", show_label=False, elem_id="inpaint_sketch", source="upload", interactive=True, type="pil", tool="color-sketch", image_mode="RGB", height=opts.img2img_editor_height, brush_color=opts.img2img_inpaint_sketch_default_brush_color)
|
||||||
|
inpaint_color_sketch_orig = gr.State(None)
|
||||||
|
add_copy_image_controls('inpaint_sketch', inpaint_color_sketch)
|
||||||
|
|
||||||
|
def update_orig(image, state):
|
||||||
|
if image is not None:
|
||||||
|
same_size = state is not None and state.size == image.size
|
||||||
|
has_exact_match = np.any(np.all(np.array(image) == np.array(state), axis=-1))
|
||||||
|
edited = same_size and has_exact_match
|
||||||
|
return image if not edited or state is None else state
|
||||||
|
|
||||||
|
inpaint_color_sketch.change(update_orig, [inpaint_color_sketch, inpaint_color_sketch_orig], inpaint_color_sketch_orig)
|
||||||
|
|
||||||
|
with gr.TabItem('Inpaint upload', id='inpaint_upload', elem_id="img2img_inpaint_upload_tab") as tab_inpaint_upload:
|
||||||
|
init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", elem_id="img_inpaint_base")
|
||||||
|
init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", image_mode="RGBA", elem_id="img_inpaint_mask")
|
||||||
|
|
||||||
|
with gr.TabItem('Batch', id='batch', elem_id="img2img_batch_tab") as tab_batch:
|
||||||
|
hidden = '<br>Disabled when launched with --hide-ui-dir-config.' if shared.cmd_opts.hide_ui_dir_config else ''
|
||||||
|
gr.HTML(
|
||||||
|
"<p style='padding-bottom: 1em;' class=\"text-gray-500\">Process images in a directory on the same machine where the server is running." +
|
||||||
|
"<br>Use an empty output directory to save pictures normally instead of writing to the output directory." +
|
||||||
|
f"<br>Add inpaint batch mask directory to enable inpaint batch processing."
|
||||||
|
f"{hidden}</p>"
|
||||||
|
)
|
||||||
|
img2img_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs, elem_id="img2img_batch_input_dir")
|
||||||
|
img2img_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs, elem_id="img2img_batch_output_dir")
|
||||||
|
img2img_batch_inpaint_mask_dir = gr.Textbox(label="Inpaint batch mask directory (required for inpaint batch processing only)", **shared.hide_dirs, elem_id="img2img_batch_inpaint_mask_dir")
|
||||||
|
with gr.Accordion("PNG info", open=False):
|
||||||
|
img2img_batch_use_png_info = gr.Checkbox(label="Append png info to prompts", **shared.hide_dirs, elem_id="img2img_batch_use_png_info")
|
||||||
|
img2img_batch_png_info_dir = gr.Textbox(label="PNG info directory", **shared.hide_dirs, placeholder="Leave empty to use input directory", elem_id="img2img_batch_png_info_dir")
|
||||||
|
img2img_batch_png_info_props = gr.CheckboxGroup(["Prompt", "Negative prompt", "Seed", "CFG scale", "Sampler", "Steps", "Model hash"], label="Parameters to take from png info", info="Prompts from png info will be appended to prompts set in ui.")
|
||||||
|
|
||||||
|
img2img_tabs = [tab_img2img, tab_sketch, tab_inpaint, tab_inpaint_color, tab_inpaint_upload, tab_batch]
|
||||||
|
|
||||||
|
for i, tab in enumerate(img2img_tabs):
|
||||||
|
tab.select(fn=lambda tabnum=i: tabnum, inputs=[], outputs=[img2img_selected_tab])
|
||||||
|
|
||||||
|
def copy_image(img):
|
||||||
|
if isinstance(img, dict) and 'image' in img:
|
||||||
|
return img['image']
|
||||||
|
|
||||||
|
return img
|
||||||
|
|
||||||
|
for button, name, elem in copy_image_buttons:
|
||||||
|
button.click(
|
||||||
|
fn=copy_image,
|
||||||
|
inputs=[elem],
|
||||||
|
outputs=[copy_image_destinations[name]],
|
||||||
|
)
|
||||||
|
button.click(
|
||||||
|
fn=lambda: None,
|
||||||
|
_js=f"switch_to_{name.replace(' ', '_')}",
|
||||||
|
inputs=[],
|
||||||
|
outputs=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
with FormRow():
|
||||||
|
resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", choices=["Just resize", "Crop and resize", "Resize and fill", "Just resize (latent upscale)"], type="index", value="Just resize")
|
||||||
|
|
||||||
if category == "sampler":
|
if category == "sampler":
|
||||||
steps, sampler_name = create_sampler_and_steps_selection(sd_samplers.visible_sampler_names(), "img2img")
|
steps, sampler_name = create_sampler_and_steps_selection(sd_samplers.visible_sampler_names(), "img2img")
|
||||||
|
|
||||||
@@ -756,20 +689,20 @@ def create_ui():
|
|||||||
with gr.Column(scale=4):
|
with gr.Column(scale=4):
|
||||||
inpaint_full_res_padding = gr.Slider(label='Only masked padding, pixels', minimum=0, maximum=256, step=4, value=32, elem_id="img2img_inpaint_full_res_padding")
|
inpaint_full_res_padding = gr.Slider(label='Only masked padding, pixels', minimum=0, maximum=256, step=4, value=32, elem_id="img2img_inpaint_full_res_padding")
|
||||||
|
|
||||||
def select_img2img_tab(tab):
|
|
||||||
return gr.update(visible=tab in [2, 3, 4]), gr.update(visible=tab == 3),
|
|
||||||
|
|
||||||
for i, elem in enumerate(img2img_tabs):
|
|
||||||
elem.select(
|
|
||||||
fn=lambda tab=i: select_img2img_tab(tab),
|
|
||||||
inputs=[],
|
|
||||||
outputs=[inpaint_controls, mask_alpha],
|
|
||||||
)
|
|
||||||
|
|
||||||
if category not in {"accordions"}:
|
if category not in {"accordions"}:
|
||||||
scripts.scripts_img2img.setup_ui_for_section(category)
|
scripts.scripts_img2img.setup_ui_for_section(category)
|
||||||
|
|
||||||
img2img_gallery, generation_info, html_info, html_log = create_output_panel("img2img", opts.outdir_img2img_samples)
|
def select_img2img_tab(tab):
|
||||||
|
return gr.update(visible=tab in [2, 3, 4]), gr.update(visible=tab == 3),
|
||||||
|
|
||||||
|
for i, elem in enumerate(img2img_tabs):
|
||||||
|
elem.select(
|
||||||
|
fn=lambda tab=i: select_img2img_tab(tab),
|
||||||
|
inputs=[],
|
||||||
|
outputs=[inpaint_controls, mask_alpha],
|
||||||
|
)
|
||||||
|
|
||||||
|
img2img_gallery, generation_info, html_info, html_log = create_output_panel("img2img", opts.outdir_img2img_samples, toprow)
|
||||||
|
|
||||||
img2img_args = dict(
|
img2img_args = dict(
|
||||||
fn=wrap_gradio_gpu_call(modules.img2img.img2img, extra_outputs=[None, '', '']),
|
fn=wrap_gradio_gpu_call(modules.img2img.img2img, extra_outputs=[None, '', '']),
|
||||||
@@ -1296,7 +1229,7 @@ def create_ui():
|
|||||||
|
|
||||||
loadsave.setup_ui()
|
loadsave.setup_ui()
|
||||||
|
|
||||||
if os.path.exists(os.path.join(script_path, "notification.mp3")):
|
if os.path.exists(os.path.join(script_path, "notification.mp3")) and shared.opts.notification_audio:
|
||||||
gr.Audio(interactive=False, value=os.path.join(script_path, "notification.mp3"), elem_id="audio_notification", visible=False)
|
gr.Audio(interactive=False, value=os.path.join(script_path, "notification.mp3"), elem_id="audio_notification", visible=False)
|
||||||
|
|
||||||
footer = shared.html("footer.html")
|
footer = shared.html("footer.html")
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ def save_files(js_data, images, do_make_zip, index):
|
|||||||
return gr.File.update(value=fullfns, visible=True), plaintext_to_html(f"Saved: {filenames[0]}")
|
return gr.File.update(value=fullfns, visible=True), plaintext_to_html(f"Saved: {filenames[0]}")
|
||||||
|
|
||||||
|
|
||||||
def create_output_panel(tabname, outdir):
|
def create_output_panel(tabname, outdir, toprow=None):
|
||||||
|
|
||||||
def open_folder(f):
|
def open_folder(f):
|
||||||
if not os.path.exists(f):
|
if not os.path.exists(f):
|
||||||
@@ -130,12 +130,15 @@ Requested path was: {f}
|
|||||||
else:
|
else:
|
||||||
sp.Popen(["xdg-open", path])
|
sp.Popen(["xdg-open", path])
|
||||||
|
|
||||||
with gr.Column(variant='panel', elem_id=f"{tabname}_results"):
|
with gr.Column(elem_id=f"{tabname}_results"):
|
||||||
with gr.Group(elem_id=f"{tabname}_gallery_container"):
|
if toprow:
|
||||||
result_gallery = gr.Gallery(label='Output', show_label=False, elem_id=f"{tabname}_gallery", columns=4, preview=True, height=shared.opts.gallery_height or None)
|
toprow.create_inline_toprow_image()
|
||||||
|
|
||||||
generation_info = None
|
with gr.Column(variant='panel', elem_id=f"{tabname}_results_panel"):
|
||||||
with gr.Column():
|
with gr.Group(elem_id=f"{tabname}_gallery_container"):
|
||||||
|
result_gallery = gr.Gallery(label='Output', show_label=False, elem_id=f"{tabname}_gallery", columns=4, preview=True, height=shared.opts.gallery_height or None)
|
||||||
|
|
||||||
|
generation_info = None
|
||||||
with gr.Row(elem_id=f"image_buttons_{tabname}", elem_classes="image-buttons"):
|
with gr.Row(elem_id=f"image_buttons_{tabname}", elem_classes="image-buttons"):
|
||||||
open_folder_button = ToolButton(folder_symbol, elem_id=f'{tabname}_open_folder', visible=not shared.cmd_opts.hide_ui_dir_config, tooltip="Open images output directory.")
|
open_folder_button = ToolButton(folder_symbol, elem_id=f'{tabname}_open_folder', visible=not shared.cmd_opts.hide_ui_dir_config, tooltip="Open images output directory.")
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ class ExtraNetworksPage:
|
|||||||
self.name = title.lower()
|
self.name = title.lower()
|
||||||
self.id_page = self.name.replace(" ", "_")
|
self.id_page = self.name.replace(" ", "_")
|
||||||
self.card_page = shared.html("extra-networks-card.html")
|
self.card_page = shared.html("extra-networks-card.html")
|
||||||
|
self.allow_prompt = True
|
||||||
self.allow_negative_prompt = False
|
self.allow_negative_prompt = False
|
||||||
self.metadata = {}
|
self.metadata = {}
|
||||||
self.items = {}
|
self.items = {}
|
||||||
@@ -367,7 +368,7 @@ def create_ui(interface: gr.Blocks, unrelated_tabs, tabname):
|
|||||||
related_tabs = []
|
related_tabs = []
|
||||||
|
|
||||||
for page in ui.stored_extra_pages:
|
for page in ui.stored_extra_pages:
|
||||||
with gr.Tab(page.title, id=page.id_page) as tab:
|
with gr.Tab(page.title, elem_id=f"{tabname}_{page.id_page}", elem_classes=["extra-page"]) as tab:
|
||||||
elem_id = f"{tabname}_{page.id_page}_cards_html"
|
elem_id = f"{tabname}_{page.id_page}_cards_html"
|
||||||
page_elem = gr.HTML('Loading...', elem_id=elem_id)
|
page_elem = gr.HTML('Loading...', elem_id=elem_id)
|
||||||
ui.pages.append(page_elem)
|
ui.pages.append(page_elem)
|
||||||
@@ -381,19 +382,28 @@ def create_ui(interface: gr.Blocks, unrelated_tabs, tabname):
|
|||||||
related_tabs.append(tab)
|
related_tabs.append(tab)
|
||||||
|
|
||||||
edit_search = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", elem_classes="search", placeholder="Search...", visible=False, interactive=True)
|
edit_search = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", elem_classes="search", placeholder="Search...", visible=False, interactive=True)
|
||||||
dropdown_sort = gr.Dropdown(choices=['Default Sort', 'Date Created', 'Date Modified', 'Name'], value='Default Sort', elem_id=tabname+"_extra_sort", elem_classes="sort", multiselect=False, visible=False, show_label=False, interactive=True, label=tabname+"_extra_sort_order")
|
dropdown_sort = gr.Dropdown(choices=['Name', 'Date Created', 'Date Modified', ], value=shared.opts.extra_networks_card_order_field, elem_id=tabname+"_extra_sort", elem_classes="sort", multiselect=False, visible=False, show_label=False, interactive=True, label=tabname+"_extra_sort_order")
|
||||||
button_sortorder = ToolButton(switch_values_symbol, elem_id=tabname+"_extra_sortorder", elem_classes="sortorder", visible=False, tooltip="Invert sort order")
|
button_sortorder = ToolButton(switch_values_symbol, elem_id=tabname+"_extra_sortorder", elem_classes=["sortorder"] + ([] if shared.opts.extra_networks_card_order == "Ascending" else ["sortReverse"]), visible=False, tooltip="Invert sort order")
|
||||||
button_refresh = gr.Button('Refresh', elem_id=tabname+"_extra_refresh", visible=False)
|
button_refresh = gr.Button('Refresh', elem_id=tabname+"_extra_refresh", visible=False)
|
||||||
checkbox_show_dirs = gr.Checkbox(True, label='Show dirs', elem_id=tabname+"_extra_show_dirs", elem_classes="show-dirs", visible=False)
|
checkbox_show_dirs = gr.Checkbox(True, label='Show dirs', elem_id=tabname+"_extra_show_dirs", elem_classes="show-dirs", visible=False)
|
||||||
|
|
||||||
ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False)
|
ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False)
|
||||||
ui.preview_target_filename = gr.Textbox('Preview save filename', elem_id=tabname+"_preview_filename", visible=False)
|
ui.preview_target_filename = gr.Textbox('Preview save filename', elem_id=tabname+"_preview_filename", visible=False)
|
||||||
|
|
||||||
for tab in unrelated_tabs:
|
tab_controls = [edit_search, dropdown_sort, button_sortorder, button_refresh, checkbox_show_dirs]
|
||||||
tab.select(fn=lambda: [gr.update(visible=False) for _ in range(5)], inputs=[], outputs=[edit_search, dropdown_sort, button_sortorder, button_refresh, checkbox_show_dirs], show_progress=False)
|
|
||||||
|
|
||||||
for tab in related_tabs:
|
for tab in unrelated_tabs:
|
||||||
tab.select(fn=lambda: [gr.update(visible=True) for _ in range(5)], inputs=[], outputs=[edit_search, dropdown_sort, button_sortorder, button_refresh, checkbox_show_dirs], show_progress=False)
|
tab.select(fn=lambda: [gr.update(visible=False) for _ in tab_controls], _js='function(){ extraNetworksUrelatedTabSelected("' + tabname + '"); }', inputs=[], outputs=tab_controls, show_progress=False)
|
||||||
|
|
||||||
|
for page, tab in zip(ui.stored_extra_pages, related_tabs):
|
||||||
|
allow_prompt = "true" if page.allow_prompt else "false"
|
||||||
|
allow_negative_prompt = "true" if page.allow_negative_prompt else "false"
|
||||||
|
|
||||||
|
jscode = 'extraNetworksTabSelected("' + tabname + '", "' + f"{tabname}_{page.id_page}" + '", ' + allow_prompt + ', ' + allow_negative_prompt + ');'
|
||||||
|
|
||||||
|
tab.select(fn=lambda: [gr.update(visible=True) for _ in tab_controls], _js='function(){ ' + jscode + ' }', inputs=[], outputs=tab_controls, show_progress=False)
|
||||||
|
|
||||||
|
dropdown_sort.change(fn=lambda: None, _js="function(){ applyExtraNetworkSort('" + tabname + "'); }")
|
||||||
|
|
||||||
def pages_html():
|
def pages_html():
|
||||||
if not ui.pages_contents:
|
if not ui.pages_contents:
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('Checkpoints')
|
super().__init__('Checkpoints')
|
||||||
|
|
||||||
|
self.allow_prompt = False
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
shared.refresh_checkpoints()
|
shared.refresh_checkpoints()
|
||||||
|
|
||||||
|
|||||||
+17
-7
@@ -1,6 +1,6 @@
|
|||||||
import gradio as gr
|
import gradio as gr
|
||||||
|
|
||||||
from modules import ui_common, shared, script_callbacks, scripts, sd_models, sysinfo
|
from modules import ui_common, shared, script_callbacks, scripts, sd_models, sysinfo, timer
|
||||||
from modules.call_queue import wrap_gradio_call
|
from modules.call_queue import wrap_gradio_call
|
||||||
from modules.shared import opts
|
from modules.shared import opts
|
||||||
from modules.ui_components import FormRow
|
from modules.ui_components import FormRow
|
||||||
@@ -177,8 +177,8 @@ class UiSettings:
|
|||||||
download_localization = gr.Button(value='Download localization template', elem_id="download_localization")
|
download_localization = gr.Button(value='Download localization template', elem_id="download_localization")
|
||||||
reload_script_bodies = gr.Button(value='Reload custom script bodies (No ui updates, No restart)', variant='secondary', elem_id="settings_reload_script_bodies")
|
reload_script_bodies = gr.Button(value='Reload custom script bodies (No ui updates, No restart)', variant='secondary', elem_id="settings_reload_script_bodies")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
unload_sd_model = gr.Button(value='Unload SD checkpoint to free VRAM', elem_id="sett_unload_sd_model")
|
unload_sd_model = gr.Button(value='Unload SD checkpoint to RAM', elem_id="sett_unload_sd_model")
|
||||||
reload_sd_model = gr.Button(value='Reload the last SD checkpoint back into VRAM', elem_id="sett_reload_sd_model")
|
reload_sd_model = gr.Button(value='Load SD checkpoint to VRAM from RAM', elem_id="sett_reload_sd_model")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
calculate_all_checkpoint_hash = gr.Button(value='Calculate hash for all checkpoint', elem_id="calculate_all_checkpoint_hash")
|
calculate_all_checkpoint_hash = gr.Button(value='Calculate hash for all checkpoint', elem_id="calculate_all_checkpoint_hash")
|
||||||
calculate_all_checkpoint_hash_threads = gr.Number(value=1, label="Number of parallel calculations", elem_id="calculate_all_checkpoint_hash_threads", precision=0, minimum=1)
|
calculate_all_checkpoint_hash_threads = gr.Number(value=1, label="Number of parallel calculations", elem_id="calculate_all_checkpoint_hash_threads", precision=0, minimum=1)
|
||||||
@@ -194,16 +194,26 @@ class UiSettings:
|
|||||||
|
|
||||||
self.text_settings = gr.Textbox(elem_id="settings_json", value=lambda: opts.dumpjson(), visible=False)
|
self.text_settings = gr.Textbox(elem_id="settings_json", value=lambda: opts.dumpjson(), visible=False)
|
||||||
|
|
||||||
|
def call_func_and_return_text(func, text):
|
||||||
|
def handler():
|
||||||
|
t = timer.Timer()
|
||||||
|
func()
|
||||||
|
t.record(text)
|
||||||
|
|
||||||
|
return f'{text} in {t.total:.1f}s'
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
unload_sd_model.click(
|
unload_sd_model.click(
|
||||||
fn=sd_models.unload_model_weights,
|
fn=call_func_and_return_text(sd_models.unload_model_weights, 'Unloaded the checkpoint'),
|
||||||
inputs=[],
|
inputs=[],
|
||||||
outputs=[]
|
outputs=[self.result]
|
||||||
)
|
)
|
||||||
|
|
||||||
reload_sd_model.click(
|
reload_sd_model.click(
|
||||||
fn=sd_models.reload_model_weights,
|
fn=call_func_and_return_text(lambda: sd_models.send_model_to_device(shared.sd_model), 'Loaded the checkpoint'),
|
||||||
inputs=[],
|
inputs=[],
|
||||||
outputs=[]
|
outputs=[self.result]
|
||||||
)
|
)
|
||||||
|
|
||||||
request_notifications.click(
|
request_notifications.click(
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
import gradio as gr
|
||||||
|
|
||||||
|
from modules import shared, ui_prompt_styles
|
||||||
|
import modules.images
|
||||||
|
|
||||||
|
from modules.ui_components import ToolButton
|
||||||
|
|
||||||
|
|
||||||
|
class Toprow:
|
||||||
|
"""Creates a top row UI with prompts, generate button, styles, extra little buttons for things, and enables some functionality related to their operation"""
|
||||||
|
|
||||||
|
prompt = None
|
||||||
|
prompt_img = None
|
||||||
|
negative_prompt = None
|
||||||
|
|
||||||
|
button_interrogate = None
|
||||||
|
button_deepbooru = None
|
||||||
|
|
||||||
|
interrupt = None
|
||||||
|
skip = None
|
||||||
|
submit = None
|
||||||
|
|
||||||
|
paste = None
|
||||||
|
clear_prompt_button = None
|
||||||
|
apply_styles = None
|
||||||
|
restore_progress_button = None
|
||||||
|
|
||||||
|
token_counter = None
|
||||||
|
token_button = None
|
||||||
|
negative_token_counter = None
|
||||||
|
negative_token_button = None
|
||||||
|
|
||||||
|
ui_styles = None
|
||||||
|
|
||||||
|
submit_box = None
|
||||||
|
|
||||||
|
def __init__(self, is_img2img, is_compact=False):
|
||||||
|
id_part = "img2img" if is_img2img else "txt2img"
|
||||||
|
self.id_part = id_part
|
||||||
|
self.is_img2img = is_img2img
|
||||||
|
self.is_compact = is_compact
|
||||||
|
|
||||||
|
if not is_compact:
|
||||||
|
with gr.Row(elem_id=f"{id_part}_toprow", variant="compact"):
|
||||||
|
self.create_classic_toprow()
|
||||||
|
else:
|
||||||
|
self.create_submit_box()
|
||||||
|
|
||||||
|
def create_classic_toprow(self):
|
||||||
|
self.create_prompts()
|
||||||
|
|
||||||
|
with gr.Column(scale=1, elem_id=f"{self.id_part}_actions_column"):
|
||||||
|
self.create_submit_box()
|
||||||
|
|
||||||
|
self.create_tools_row()
|
||||||
|
|
||||||
|
self.create_styles_ui()
|
||||||
|
|
||||||
|
def create_inline_toprow_prompts(self):
|
||||||
|
if not self.is_compact:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.create_prompts()
|
||||||
|
|
||||||
|
with gr.Row(elem_classes=["toprow-compact-stylerow"]):
|
||||||
|
with gr.Column(elem_classes=["toprow-compact-tools"]):
|
||||||
|
self.create_tools_row()
|
||||||
|
with gr.Column():
|
||||||
|
self.create_styles_ui()
|
||||||
|
|
||||||
|
def create_inline_toprow_image(self):
|
||||||
|
if not self.is_compact:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.submit_box.render()
|
||||||
|
|
||||||
|
def create_prompts(self):
|
||||||
|
with gr.Column(elem_id=f"{self.id_part}_prompt_container", elem_classes=["prompt-container-compact"] if self.is_compact else [], scale=6):
|
||||||
|
with gr.Row(elem_id=f"{self.id_part}_prompt_row", elem_classes=["prompt-row"]):
|
||||||
|
self.prompt = gr.Textbox(label="Prompt", elem_id=f"{self.id_part}_prompt", show_label=False, lines=3, placeholder="Prompt (press Ctrl+Enter or Alt+Enter to generate)", elem_classes=["prompt"])
|
||||||
|
self.prompt_img = gr.File(label="", elem_id=f"{self.id_part}_prompt_image", file_count="single", type="binary", visible=False)
|
||||||
|
|
||||||
|
with gr.Row(elem_id=f"{self.id_part}_neg_prompt_row", elem_classes=["prompt-row"]):
|
||||||
|
self.negative_prompt = gr.Textbox(label="Negative prompt", elem_id=f"{self.id_part}_neg_prompt", show_label=False, lines=3, placeholder="Negative prompt (press Ctrl+Enter or Alt+Enter to generate)", elem_classes=["prompt"])
|
||||||
|
|
||||||
|
self.prompt_img.change(
|
||||||
|
fn=modules.images.image_data,
|
||||||
|
inputs=[self.prompt_img],
|
||||||
|
outputs=[self.prompt, self.prompt_img],
|
||||||
|
show_progress=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_submit_box(self):
|
||||||
|
with gr.Row(elem_id=f"{self.id_part}_generate_box", elem_classes=["generate-box"] + (["generate-box-compact"] if self.is_compact else []), render=not self.is_compact) as submit_box:
|
||||||
|
self.submit_box = submit_box
|
||||||
|
|
||||||
|
self.interrupt = gr.Button('Interrupt', elem_id=f"{self.id_part}_interrupt", elem_classes="generate-box-interrupt")
|
||||||
|
self.skip = gr.Button('Skip', elem_id=f"{self.id_part}_skip", elem_classes="generate-box-skip")
|
||||||
|
self.submit = gr.Button('Generate', elem_id=f"{self.id_part}_generate", variant='primary')
|
||||||
|
|
||||||
|
self.skip.click(
|
||||||
|
fn=lambda: shared.state.skip(),
|
||||||
|
inputs=[],
|
||||||
|
outputs=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.interrupt.click(
|
||||||
|
fn=lambda: shared.state.interrupt(),
|
||||||
|
inputs=[],
|
||||||
|
outputs=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_tools_row(self):
|
||||||
|
with gr.Row(elem_id=f"{self.id_part}_tools"):
|
||||||
|
from modules.ui import paste_symbol, clear_prompt_symbol, restore_progress_symbol
|
||||||
|
|
||||||
|
self.paste = ToolButton(value=paste_symbol, elem_id="paste", tooltip="Read generation parameters from prompt or last generation if prompt is empty into user interface.")
|
||||||
|
self.clear_prompt_button = ToolButton(value=clear_prompt_symbol, elem_id=f"{self.id_part}_clear_prompt", tooltip="Clear prompt")
|
||||||
|
self.apply_styles = ToolButton(value=ui_prompt_styles.styles_materialize_symbol, elem_id=f"{self.id_part}_style_apply", tooltip="Apply all selected styles to prompts.")
|
||||||
|
|
||||||
|
if self.is_img2img:
|
||||||
|
self.button_interrogate = ToolButton('📎', tooltip='Interrogate CLIP - use CLIP neural network to create a text describing the image, and put it into the prompt field', elem_id="interrogate")
|
||||||
|
self.button_deepbooru = ToolButton('📦', tooltip='Interrogate DeepBooru - use DeepBooru neural network to create a text describing the image, and put it into the prompt field', elem_id="deepbooru")
|
||||||
|
|
||||||
|
self.restore_progress_button = ToolButton(value=restore_progress_symbol, elem_id=f"{self.id_part}_restore_progress", visible=False, tooltip="Restore progress")
|
||||||
|
|
||||||
|
self.token_counter = gr.HTML(value="<span>0/75</span>", elem_id=f"{self.id_part}_token_counter", elem_classes=["token-counter"])
|
||||||
|
self.token_button = gr.Button(visible=False, elem_id=f"{self.id_part}_token_button")
|
||||||
|
self.negative_token_counter = gr.HTML(value="<span>0/75</span>", elem_id=f"{self.id_part}_negative_token_counter", elem_classes=["token-counter"])
|
||||||
|
self.negative_token_button = gr.Button(visible=False, elem_id=f"{self.id_part}_negative_token_button")
|
||||||
|
|
||||||
|
self.clear_prompt_button.click(
|
||||||
|
fn=lambda *x: x,
|
||||||
|
_js="confirm_clear_prompt",
|
||||||
|
inputs=[self.prompt, self.negative_prompt],
|
||||||
|
outputs=[self.prompt, self.negative_prompt],
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_styles_ui(self):
|
||||||
|
self.ui_styles = ui_prompt_styles.UiPromptStyles(self.id_part, self.prompt, self.negative_prompt)
|
||||||
|
self.ui_styles.setup_apply_button(self.apply_styles)
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
from transformers import BertPreTrainedModel,BertConfig
|
||||||
|
import torch.nn as nn
|
||||||
|
import torch
|
||||||
|
from transformers.models.xlm_roberta.configuration_xlm_roberta import XLMRobertaConfig
|
||||||
|
from transformers import XLMRobertaModel,XLMRobertaTokenizer
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class BertSeriesConfig(BertConfig):
|
||||||
|
def __init__(self, vocab_size=30522, hidden_size=768, num_hidden_layers=12, num_attention_heads=12, intermediate_size=3072, hidden_act="gelu", hidden_dropout_prob=0.1, attention_probs_dropout_prob=0.1, max_position_embeddings=512, type_vocab_size=2, initializer_range=0.02, layer_norm_eps=1e-12, pad_token_id=0, position_embedding_type="absolute", use_cache=True, classifier_dropout=None,project_dim=512, pooler_fn="average",learn_encoder=False,model_type='bert',**kwargs):
|
||||||
|
|
||||||
|
super().__init__(vocab_size, hidden_size, num_hidden_layers, num_attention_heads, intermediate_size, hidden_act, hidden_dropout_prob, attention_probs_dropout_prob, max_position_embeddings, type_vocab_size, initializer_range, layer_norm_eps, pad_token_id, position_embedding_type, use_cache, classifier_dropout, **kwargs)
|
||||||
|
self.project_dim = project_dim
|
||||||
|
self.pooler_fn = pooler_fn
|
||||||
|
self.learn_encoder = learn_encoder
|
||||||
|
|
||||||
|
class RobertaSeriesConfig(XLMRobertaConfig):
|
||||||
|
def __init__(self, pad_token_id=1, bos_token_id=0, eos_token_id=2,project_dim=512,pooler_fn='cls',learn_encoder=False, **kwargs):
|
||||||
|
super().__init__(pad_token_id=pad_token_id, bos_token_id=bos_token_id, eos_token_id=eos_token_id, **kwargs)
|
||||||
|
self.project_dim = project_dim
|
||||||
|
self.pooler_fn = pooler_fn
|
||||||
|
self.learn_encoder = learn_encoder
|
||||||
|
|
||||||
|
|
||||||
|
class BertSeriesModelWithTransformation(BertPreTrainedModel):
|
||||||
|
|
||||||
|
_keys_to_ignore_on_load_unexpected = [r"pooler"]
|
||||||
|
_keys_to_ignore_on_load_missing = [r"position_ids", r"predictions.decoder.bias"]
|
||||||
|
config_class = BertSeriesConfig
|
||||||
|
|
||||||
|
def __init__(self, config=None, **kargs):
|
||||||
|
# modify initialization for autoloading
|
||||||
|
if config is None:
|
||||||
|
config = XLMRobertaConfig()
|
||||||
|
config.attention_probs_dropout_prob= 0.1
|
||||||
|
config.bos_token_id=0
|
||||||
|
config.eos_token_id=2
|
||||||
|
config.hidden_act='gelu'
|
||||||
|
config.hidden_dropout_prob=0.1
|
||||||
|
config.hidden_size=1024
|
||||||
|
config.initializer_range=0.02
|
||||||
|
config.intermediate_size=4096
|
||||||
|
config.layer_norm_eps=1e-05
|
||||||
|
config.max_position_embeddings=514
|
||||||
|
|
||||||
|
config.num_attention_heads=16
|
||||||
|
config.num_hidden_layers=24
|
||||||
|
config.output_past=True
|
||||||
|
config.pad_token_id=1
|
||||||
|
config.position_embedding_type= "absolute"
|
||||||
|
|
||||||
|
config.type_vocab_size= 1
|
||||||
|
config.use_cache=True
|
||||||
|
config.vocab_size= 250002
|
||||||
|
config.project_dim = 1024
|
||||||
|
config.learn_encoder = False
|
||||||
|
super().__init__(config)
|
||||||
|
self.roberta = XLMRobertaModel(config)
|
||||||
|
self.transformation = nn.Linear(config.hidden_size,config.project_dim)
|
||||||
|
# self.pre_LN=nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
||||||
|
self.tokenizer = XLMRobertaTokenizer.from_pretrained('xlm-roberta-large')
|
||||||
|
# self.pooler = lambda x: x[:,0]
|
||||||
|
# self.post_init()
|
||||||
|
|
||||||
|
self.has_pre_transformation = True
|
||||||
|
if self.has_pre_transformation:
|
||||||
|
self.transformation_pre = nn.Linear(config.hidden_size, config.project_dim)
|
||||||
|
self.pre_LN = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
||||||
|
self.post_init()
|
||||||
|
|
||||||
|
def encode(self,c):
|
||||||
|
device = next(self.parameters()).device
|
||||||
|
text = self.tokenizer(c,
|
||||||
|
truncation=True,
|
||||||
|
max_length=77,
|
||||||
|
return_length=False,
|
||||||
|
return_overflowing_tokens=False,
|
||||||
|
padding="max_length",
|
||||||
|
return_tensors="pt")
|
||||||
|
text["input_ids"] = torch.tensor(text["input_ids"]).to(device)
|
||||||
|
text["attention_mask"] = torch.tensor(
|
||||||
|
text['attention_mask']).to(device)
|
||||||
|
features = self(**text)
|
||||||
|
return features['projection_state']
|
||||||
|
|
||||||
|
def forward(
|
||||||
|
self,
|
||||||
|
input_ids: Optional[torch.Tensor] = None,
|
||||||
|
attention_mask: Optional[torch.Tensor] = None,
|
||||||
|
token_type_ids: Optional[torch.Tensor] = None,
|
||||||
|
position_ids: Optional[torch.Tensor] = None,
|
||||||
|
head_mask: Optional[torch.Tensor] = None,
|
||||||
|
inputs_embeds: Optional[torch.Tensor] = None,
|
||||||
|
encoder_hidden_states: Optional[torch.Tensor] = None,
|
||||||
|
encoder_attention_mask: Optional[torch.Tensor] = None,
|
||||||
|
output_attentions: Optional[bool] = None,
|
||||||
|
return_dict: Optional[bool] = None,
|
||||||
|
output_hidden_states: Optional[bool] = None,
|
||||||
|
) :
|
||||||
|
r"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
||||||
|
|
||||||
|
|
||||||
|
outputs = self.roberta(
|
||||||
|
input_ids=input_ids,
|
||||||
|
attention_mask=attention_mask,
|
||||||
|
token_type_ids=token_type_ids,
|
||||||
|
position_ids=position_ids,
|
||||||
|
head_mask=head_mask,
|
||||||
|
inputs_embeds=inputs_embeds,
|
||||||
|
encoder_hidden_states=encoder_hidden_states,
|
||||||
|
encoder_attention_mask=encoder_attention_mask,
|
||||||
|
output_attentions=output_attentions,
|
||||||
|
output_hidden_states=True,
|
||||||
|
return_dict=return_dict,
|
||||||
|
)
|
||||||
|
|
||||||
|
# # last module outputs
|
||||||
|
# sequence_output = outputs[0]
|
||||||
|
|
||||||
|
|
||||||
|
# # project every module
|
||||||
|
# sequence_output_ln = self.pre_LN(sequence_output)
|
||||||
|
|
||||||
|
# # pooler
|
||||||
|
# pooler_output = self.pooler(sequence_output_ln)
|
||||||
|
# pooler_output = self.transformation(pooler_output)
|
||||||
|
# projection_state = self.transformation(outputs.last_hidden_state)
|
||||||
|
|
||||||
|
if self.has_pre_transformation:
|
||||||
|
sequence_output2 = outputs["hidden_states"][-2]
|
||||||
|
sequence_output2 = self.pre_LN(sequence_output2)
|
||||||
|
projection_state2 = self.transformation_pre(sequence_output2)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"projection_state": projection_state2,
|
||||||
|
"last_hidden_state": outputs.last_hidden_state,
|
||||||
|
"hidden_states": outputs.hidden_states,
|
||||||
|
"attentions": outputs.attentions,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
projection_state = self.transformation(outputs.last_hidden_state)
|
||||||
|
return {
|
||||||
|
"projection_state": projection_state,
|
||||||
|
"last_hidden_state": outputs.last_hidden_state,
|
||||||
|
"hidden_states": outputs.hidden_states,
|
||||||
|
"attentions": outputs.attentions,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# return {
|
||||||
|
# 'pooler_output':pooler_output,
|
||||||
|
# 'last_hidden_state':outputs.last_hidden_state,
|
||||||
|
# 'hidden_states':outputs.hidden_states,
|
||||||
|
# 'attentions':outputs.attentions,
|
||||||
|
# 'projection_state':projection_state,
|
||||||
|
# 'sequence_out': sequence_output
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
class RobertaSeriesModelWithTransformation(BertSeriesModelWithTransformation):
|
||||||
|
base_model_prefix = 'roberta'
|
||||||
|
config_class= RobertaSeriesConfig
|
||||||
@@ -32,3 +32,5 @@ torch
|
|||||||
torchdiffeq
|
torchdiffeq
|
||||||
torchsde
|
torchsde
|
||||||
transformers==4.30.2
|
transformers==4.30.2
|
||||||
|
|
||||||
|
git+https://github.com/openai/consistencydecoder.git
|
||||||
|
|||||||
@@ -29,3 +29,5 @@ torch
|
|||||||
torchdiffeq==0.2.3
|
torchdiffeq==0.2.3
|
||||||
torchsde==0.2.6
|
torchsde==0.2.6
|
||||||
transformers==4.30.2
|
transformers==4.30.2
|
||||||
|
httpx==0.24.1
|
||||||
|
git+https://github.com/openai/consistencydecoder.git
|
||||||
|
|||||||
@@ -124,16 +124,20 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||||||
* Add a ctrl+enter as a shortcut to start a generation
|
* Add a ctrl+enter as a shortcut to start a generation
|
||||||
*/
|
*/
|
||||||
document.addEventListener('keydown', function(e) {
|
document.addEventListener('keydown', function(e) {
|
||||||
var handled = false;
|
const isEnter = e.key === 'Enter' || e.keyCode === 13;
|
||||||
if (e.key !== undefined) {
|
const isModifierKey = e.metaKey || e.ctrlKey || e.altKey;
|
||||||
if ((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
|
|
||||||
} else if (e.keyCode !== undefined) {
|
const interruptButton = get_uiCurrentTabContent().querySelector('button[id$=_interrupt]');
|
||||||
if ((e.keyCode == 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
|
const generateButton = get_uiCurrentTabContent().querySelector('button[id$=_generate]');
|
||||||
}
|
|
||||||
if (handled) {
|
if (isEnter && isModifierKey) {
|
||||||
var button = get_uiCurrentTabContent().querySelector('button[id$=_generate]');
|
if (interruptButton.style.display === 'block') {
|
||||||
if (button) {
|
interruptButton.click();
|
||||||
button.click();
|
setTimeout(function() {
|
||||||
|
generateButton.click();
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
generateButton.click();
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ class Script(scripts.Script):
|
|||||||
def ui(self, is_img2img):
|
def ui(self, is_img2img):
|
||||||
checkbox_iterate = gr.Checkbox(label="Iterate seed every line", value=False, elem_id=self.elem_id("checkbox_iterate"))
|
checkbox_iterate = gr.Checkbox(label="Iterate seed every line", value=False, elem_id=self.elem_id("checkbox_iterate"))
|
||||||
checkbox_iterate_batch = gr.Checkbox(label="Use same random seed for all lines", value=False, elem_id=self.elem_id("checkbox_iterate_batch"))
|
checkbox_iterate_batch = gr.Checkbox(label="Use same random seed for all lines", value=False, elem_id=self.elem_id("checkbox_iterate_batch"))
|
||||||
|
prompt_position = gr.Radio(["start", "end"], label="Insert prompts at the", elem_id=self.elem_id("prompt_position"), value="start")
|
||||||
|
|
||||||
prompt_txt = gr.Textbox(label="List of prompt inputs", lines=1, elem_id=self.elem_id("prompt_txt"))
|
prompt_txt = gr.Textbox(label="List of prompt inputs", lines=1, elem_id=self.elem_id("prompt_txt"))
|
||||||
file = gr.File(label="Upload prompt inputs", type='binary', elem_id=self.elem_id("file"))
|
file = gr.File(label="Upload prompt inputs", type='binary', elem_id=self.elem_id("file"))
|
||||||
@@ -124,9 +125,9 @@ class Script(scripts.Script):
|
|||||||
# We don't shrink back to 1, because that causes the control to ignore [enter], and it may
|
# We don't shrink back to 1, because that causes the control to ignore [enter], and it may
|
||||||
# be unclear to the user that shift-enter is needed.
|
# be unclear to the user that shift-enter is needed.
|
||||||
prompt_txt.change(lambda tb: gr.update(lines=7) if ("\n" in tb) else gr.update(lines=2), inputs=[prompt_txt], outputs=[prompt_txt], show_progress=False)
|
prompt_txt.change(lambda tb: gr.update(lines=7) if ("\n" in tb) else gr.update(lines=2), inputs=[prompt_txt], outputs=[prompt_txt], show_progress=False)
|
||||||
return [checkbox_iterate, checkbox_iterate_batch, prompt_txt]
|
return [checkbox_iterate, checkbox_iterate_batch, prompt_position, prompt_txt]
|
||||||
|
|
||||||
def run(self, p, checkbox_iterate, checkbox_iterate_batch, prompt_txt: str):
|
def run(self, p, checkbox_iterate, checkbox_iterate_batch, prompt_position, prompt_txt: str):
|
||||||
lines = [x for x in (x.strip() for x in prompt_txt.splitlines()) if x]
|
lines = [x for x in (x.strip() for x in prompt_txt.splitlines()) if x]
|
||||||
|
|
||||||
p.do_not_save_grid = True
|
p.do_not_save_grid = True
|
||||||
@@ -167,6 +168,18 @@ class Script(scripts.Script):
|
|||||||
else:
|
else:
|
||||||
setattr(copy_p, k, v)
|
setattr(copy_p, k, v)
|
||||||
|
|
||||||
|
if args.get("prompt") and p.prompt:
|
||||||
|
if prompt_position == "start":
|
||||||
|
copy_p.prompt = args.get("prompt") + " " + p.prompt
|
||||||
|
else:
|
||||||
|
copy_p.prompt = p.prompt + " " + args.get("prompt")
|
||||||
|
|
||||||
|
if args.get("negative_prompt") and p.negative_prompt:
|
||||||
|
if prompt_position == "start":
|
||||||
|
copy_p.negative_prompt = args.get("negative_prompt") + " " + p.negative_prompt
|
||||||
|
else:
|
||||||
|
copy_p.negative_prompt = p.negative_prompt + " " + args.get("negative_prompt")
|
||||||
|
|
||||||
proc = process_images(copy_p)
|
proc = process_images(copy_p)
|
||||||
images += proc.images
|
images += proc.images
|
||||||
|
|
||||||
|
|||||||
@@ -204,6 +204,11 @@ div.block.gradio-accordion {
|
|||||||
padding: 8px 8px;
|
padding: 8px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"].input-accordion-checkbox{
|
||||||
|
vertical-align: sub;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* txt2img/img2img specific */
|
/* txt2img/img2img specific */
|
||||||
|
|
||||||
@@ -291,6 +296,13 @@ div.block.gradio-accordion {
|
|||||||
min-height: 4.5em;
|
min-height: 4.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#txt2img_generate, #img2img_generate {
|
||||||
|
min-height: 4.5em;
|
||||||
|
}
|
||||||
|
.generate-box-compact #txt2img_generate, .generate-box-compact #img2img_generate {
|
||||||
|
min-height: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 2500px) {
|
@media screen and (min-width: 2500px) {
|
||||||
#txt2img_gallery, #img2img_gallery {
|
#txt2img_gallery, #img2img_gallery {
|
||||||
min-height: 768px;
|
min-height: 768px;
|
||||||
@@ -398,6 +410,15 @@ div#extras_scale_to_tab div.form{
|
|||||||
min-width: 0.5em;
|
min-width: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.toprow-compact-stylerow{
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.toprow-compact-tools{
|
||||||
|
min-width: fit-content !important;
|
||||||
|
max-width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
/* settings */
|
/* settings */
|
||||||
#quicksettings {
|
#quicksettings {
|
||||||
align-items: end;
|
align-items: end;
|
||||||
@@ -520,7 +541,8 @@ table.popup-table .link{
|
|||||||
height: 20px;
|
height: 20px;
|
||||||
background: #b4c0cc;
|
background: #b4c0cc;
|
||||||
border-radius: 3px !important;
|
border-radius: 3px !important;
|
||||||
top: -20px;
|
top: -14px;
|
||||||
|
left: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -818,6 +840,10 @@ footer {
|
|||||||
|
|
||||||
/* extra networks UI */
|
/* extra networks UI */
|
||||||
|
|
||||||
|
.extra-page .prompt{
|
||||||
|
margin: 0 0 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
.extra-network-cards{
|
.extra-network-cards{
|
||||||
height: calc(100vh - 24rem);
|
height: calc(100vh - 24rem);
|
||||||
overflow: clip scroll;
|
overflow: clip scroll;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
|
if exist webui.settings.bat (
|
||||||
|
call webui.settings.bat
|
||||||
|
)
|
||||||
|
|
||||||
if not defined PYTHON (set PYTHON=python)
|
if not defined PYTHON (set PYTHON=python)
|
||||||
if defined GIT (set "GIT_PYTHON_GIT_EXECUTABLE=%GIT%")
|
if defined GIT (set "GIT_PYTHON_GIT_EXECUTABLE=%GIT%")
|
||||||
if not defined VENV_DIR (set "VENV_DIR=%~dp0%venv")
|
if not defined VENV_DIR (set "VENV_DIR=%~dp0%venv")
|
||||||
|
|||||||
Reference in New Issue
Block a user