Upload 5 files
Browse files- .github/FUNDING.yml +13 -0
- .gitignore +3 -0
- README.md +556 -0
- scripts/Roboto-Regular.ttf +0 -0
- scripts/lora_block_weight.py +1266 -0
.github/FUNDING.yml
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# These are supported funding model platforms
|
2 |
+
|
3 |
+
github:[hako-mikan] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
4 |
+
patreon: # Replace with a single Patreon username
|
5 |
+
open_collective: # Replace with a single Open Collective username
|
6 |
+
ko_fi: # Replace with a single Ko-fi username
|
7 |
+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
8 |
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
9 |
+
liberapay: # Replace with a single Liberapay username
|
10 |
+
issuehunt: # Replace with a single IssueHunt username
|
11 |
+
otechie: # Replace with a single Otechie username
|
12 |
+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
13 |
+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
.gitignore
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
scripts/__pycache__/
|
2 |
+
scripts/elempresets.txt
|
3 |
+
scripts/lbwpresets.txt
|
README.md
ADDED
@@ -0,0 +1,556 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# LoRA Block Weight
|
2 |
+
- custom script for [AUTOMATIC1111's stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
|
3 |
+
- When applying Lora, strength can be set block by block.
|
4 |
+
|
5 |
+
- [AUTOMATIC1111's stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) 用のスクリプトです
|
6 |
+
- Loraを適用する際、強さを階層ごとに設定できます
|
7 |
+
|
8 |
+
[<img src="https://img.shields.io/badge/lang-Egnlish-red.svg?style=plastic" height="25" />](#overview)
|
9 |
+
[<img src="https://img.shields.io/badge/言語-日本語-green.svg?style=plastic" height="25" />](#概要)
|
10 |
+
[<img src="https://img.shields.io/badge/Support-%E2%99%A5-magenta.svg?logo=github&style=plastic" height="25" />](https://github.com/sponsors/hako-mikan)
|
11 |
+
|
12 |
+
> [!IMPORTANT]
|
13 |
+
> If you have an error :`ValueError: could not convert string to float`
|
14 |
+
> use new syntax`<lora:"lora name":1:lbw=IN02>`
|
15 |
+
|
16 |
+
|
17 |
+
## Updates/更新情報
|
18 |
+
### 2024.04.06.0000(JST)
|
19 |
+
- add [new UI](#make-weights): make weights
|
20 |
+
- ウェイトを作成する[新しいUI](#ウェイトの作成)を追加
|
21 |
+
|
22 |
+
### 2023.11.22.2000(JST)
|
23 |
+
- bugfix
|
24 |
+
- added new feature:start in steps
|
25 |
+
- 機能追加:LoRAの途中開始
|
26 |
+
|
27 |
+
### 2023.11.21.1930(JST)
|
28 |
+
- added new feature:stop in steps
|
29 |
+
- 機能追加:LoRAの途中停止
|
30 |
+
By specifying `<lora:"lora name":lbw=ALL:stop=10>`, you can disable the effect of LoRA at the specified step. In the case of character or composition LoRA, a sufficient effect is achieved in about 10 steps, and by cutting it off at this point, it is possible to minimize the impact on the style of the painting
|
31 |
+
`<lora:"lora name":lbw=ALL:stop=10>`と指定することで指定したstepでLoRAの効果を無くします。キャラクターや構図LoRAの場合には10 step程度で十分な効果があり、ここで切ることで画風への影響を抑えることが可能です。
|
32 |
+
|
33 |
+
# Overview
|
34 |
+
Lora is a powerful tool, but it is sometimes difficult to use and can affect areas that you do not want it to affect. This script allows you to set the weights block-by-block. Using this script, you may be able to get the image you want.
|
35 |
+
|
36 |
+
## Usage
|
37 |
+
Place lora_block_weight.py in the script folder.
|
38 |
+
Or you can install from Extentions tab in web-ui. When installing, please restart web-ui.bat.
|
39 |
+
|
40 |
+
### Active
|
41 |
+
Check this box to activate it.
|
42 |
+
|
43 |
+
### Prompt
|
44 |
+
In the prompt box, enter the Lora you wish to use as usual. Enter the weight or identifier by typing ":" after the strength value. The identifier can be edited in the Weights setting.
|
45 |
+
```
|
46 |
+
<lora:"lora name":1:0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0>.
|
47 |
+
<lora:"lora name":1:0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>. (a1111-sd-webui-locon, etc.)
|
48 |
+
<lyco:"lora name":1:1:lbw=IN02> (a1111-sd-webui-lycoris, web-ui 1.5 or later)
|
49 |
+
<lyco:"lora name":1:1:lbw=1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0> (a1111-sd-webui-lycoris, web-ui 1.5 or later)
|
50 |
+
```
|
51 |
+
For LyCORIS using a1111-sd-webui-lycoris, syntax is different.
|
52 |
+
`lbw=IN02` is used and follow lycoirs syntax for others such as unet or else.
|
53 |
+
a1111-sd-webui-lycoris is under under development, so this syntax might be changed.
|
54 |
+
|
55 |
+
Lora strength is in effect and applies to the entire Blocks.
|
56 |
+
It is case-sensitive.
|
57 |
+
For LyCORIS, full-model blobks used,so you need to input 26 weights.
|
58 |
+
You can use weight for LoRA, in this case, the weight of blocks not in LoRA is set to 0.
|
59 |
+
If the above format is not used, the preset will treat it as a comment line.
|
60 |
+
|
61 |
+
### start, stop step
|
62 |
+
By specifying `<lora:"lora name":lbw=ALL:start=10>`, the effect of LoRA appears from the designated step. By specifying `<lora:"lora name":lbw=ALL:stop=10>`, the effect of LoRA is eliminated at the specified step. In the case of character or composition LoRA, a significant effect is achieved in about 10 steps, and by cutting it off at this point, it is possible to minimize the influence on the style of the painting. By specifying `<lora:"lora name":lbw=ALL:step=5-10>`, LoRA is activated only between steps 5-10."
|
63 |
+
|
64 |
+
### Weights Setting
|
65 |
+
Enter the identifier and weights.
|
66 |
+
Unlike the full model, Lora is divided into 17 blocks, including the encoder. Therefore, enter 17 values.
|
67 |
+
BASE, IN, OUT, etc. are the blocks equivalent to the full model.
|
68 |
+
Due to various formats such as Full Model and LyCORIS and SDXL, script currently accept weights for 12, 17, 20, and 26. Generally, even if weights in incompatible formats are inputted, the system will still function. However, any layers not provided will be treated as having a weight of 0.
|
69 |
+
|
70 |
+
LoRA(17)
|
71 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|
|
72 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|
73 |
+
|BASE|IN01|IN02|IN04|IN05|IN07|IN08|MID|OUT03|OUT04|OUT05|OUT06|OUT07|OUT08|OUT09|OUT10|OUT11|
|
74 |
+
|
75 |
+
LyCORIS, etc. (26)
|
76 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
|
77 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|
78 |
+
|BASE|IN00|IN01|IN02|IN03|IN04|IN05|IN06|IN07|IN08|IN09|IN10|IN11|MID|OUT00|OUT01|OUT02|OUT03|OUT04|OUT05|OUT06|OUT07|OUT08|OUT09|OUT10|OUT11|
|
79 |
+
|
80 |
+
SDXL LoRA(12)
|
81 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|
|
82 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|
|
83 |
+
|BASE|IN04|IN05|IN07|IN08|MID|OUT0|OUT1|OUT2|OUT3|OUT4|OUT05|
|
84 |
+
|
85 |
+
SDXL - LyCORIS/LoCon(20)
|
86 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|
|
87 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|
88 |
+
|BASE|IN00|IN01|IN02|IN03|IN04|IN05|IN06|IN07|IN08||MID|OUT00|OUT01|OUT02|OUT03|OUT04|OUT05|OUT06|OUT07|OUT08|
|
89 |
+
|
90 |
+
### Special Values (Random)
|
91 |
+
Basically, a numerical value must be entered to work correctly, but by entering `R` and `U`, a random value will be entered.
|
92 |
+
R : Numerical value with 3 decimal places from 0~1
|
93 |
+
U : 3 decimal places from -1.5 to 1.5
|
94 |
+
|
95 |
+
For example, if ROUT:1,1,1,1,1,1,1,1,R,R,R,R,R,R,R,R,R
|
96 |
+
Only the OUT blocks is randomized.
|
97 |
+
The randomized values will be displayed on the command prompt screen when the image is generated.
|
98 |
+
|
99 |
+
### Special Values (Dynamic)
|
100 |
+
The special value `X` may also be included to use a dynamic weight specified in the LoRA syntax. This is activated by including an additional weight value after the specified `Original Weight`.
|
101 |
+
|
102 |
+
For example, if ROUT:X,1,1,1,1,1,1,1,1,1,1,1,X,X,X,X,X and you had a prompt containing \<lora:my_lore:0.5:ROUT:0.7\>. The `X` weights in ROUT would be replaced with `0.7` at runtime.
|
103 |
+
|
104 |
+
> NOTE: If you select an `Original Weight` tag that has a dynamic weight (`X`) and you do not specify a value in the LoRA syntax, it will default to `1`.
|
105 |
+
|
106 |
+
### Save Presets
|
107 |
+
|
108 |
+
The "Save Presets" button saves the text in the current text box. It is better to use a text editor, so use the "Open TextEditor" button to open a text editor, edit the text, and reload it.
|
109 |
+
The text box above the Weights setting is a list of currently available identifiers, useful for copying and pasting into an XY plot. 17 identifiers are required to appear in the list.
|
110 |
+
|
111 |
+
### Fun Usage
|
112 |
+
Used in conjunction with the XY plot, it is possible to examine the impact of each level of the hierarchy.
|
113 |
+

|
114 |
+
|
115 |
+
The setting values are as follows.
|
116 |
+
NOT:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
117 |
+
ALL:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
118 |
+
INS:1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
119 |
+
IND:1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0
|
120 |
+
INALL:1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0
|
121 |
+
MIDD:1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0
|
122 |
+
OUTD:1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0
|
123 |
+
OUTS:1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1
|
124 |
+
OUTALL:1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1
|
125 |
+
|
126 |
+
## XYZ Plotting Function
|
127 |
+
The optimal value can be searched by changing the value of each layer individually.
|
128 |
+
### Usage
|
129 |
+
Check "Active" to activate the function. If Script (such as XYZ plot in Automatic1111) is enabled, it will take precedence.
|
130 |
+
Hires. fix is not supported. batch size is fixed to 1. batch count should be set to 1.
|
131 |
+
Enter XYZ as the identifier of the LoRA that you want to change. It will work even if you do not enter a value corresponding to XYZ in the preset. If a value corresponding to XYZ is entered, that value will be used as the initial value.
|
132 |
+
Inputting ZYX, inverted value will be automatically inputted.
|
133 |
+
This feature enables to match weights of two LoRAs.
|
134 |
+
Inputing XYZ for LoRA1 and ZYX for LoRA2, you get,
|
135 |
+
LoRA1 1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0
|
136 |
+
LoRA2 0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1
|
137 |
+
### Axis type
|
138 |
+
#### values
|
139 |
+
Sets the weight of the hierarchy to be changed. Enter the values separated by commas. 0,0.25,0.5,0.75,1", etc.
|
140 |
+
|
141 |
+
#### Block ID
|
142 |
+
If a block ID is entered, only that block will change to the value specified by value. As with the other types, use commas to separate them. Multiple blocks can be changed at the same time by separating them with a space or hyphen. The initial NOT will invert the change, so NOT IN09-OUT02 will change all blocks except IN09-OUT02.
|
143 |
+
|
144 |
+
#### seed
|
145 |
+
Seed changes, and is intended to be specified on the Z-axis.
|
146 |
+
|
147 |
+
#### Original Weights
|
148 |
+
Specify the initial value to change the weight of each block. If Original Weight is enabled, the value entered for XYZ is ignored.
|
149 |
+
|
150 |
+
### Input example
|
151 |
+
X : value, value : 1,0.25,0.5,0.75,1
|
152 |
+
Y : Block ID, value : BASE,IN01-IN08,IN05-OUT05,OUT03-OUT11,NOT OUT03-OUT11
|
153 |
+
Z : Original Weights, Value : NONE,ALL0.5,ALL
|
154 |
+
|
155 |
+
In this case, an XY plot is created corresponding to the initial values NONE,ALL0.5,ALL.
|
156 |
+
If you select Seed for Z and enter -1,-1,-1, the XY plot will be created 3 times with different seeds.
|
157 |
+
|
158 |
+
### Original Weights Combined XY Plot
|
159 |
+
If both X and Y are set to Original Weights then an XY plot is made by combining the weights. If both X and Y have a weight in the same block then the Y case is set to zero before adding the arrays, this value will be used during the YX case where X's value is then set to zero. The intended usage is without overlapping blocks.
|
160 |
+
|
161 |
+
Given these names and values in the "Weights setting":
|
162 |
+
INS:1,1,1,0,0,0,0,0,0,0,0,0
|
163 |
+
MID:1,0,0,0,0,1,0,0,0,0,0,0
|
164 |
+
OUTD:1,0,0,0,0,0,1,1,1,0,0,0
|
165 |
+
|
166 |
+
With:
|
167 |
+
X : Original Weights, value: INS,MID,OUTD
|
168 |
+
Y : Original Weights, value: INS,MID,OUTD
|
169 |
+
Z : none
|
170 |
+
|
171 |
+
An XY plot is made with 9 elements. The diagonal is the X values: INS,MID,OUTD unchanged. So we have for the first row:
|
172 |
+
```
|
173 |
+
INS+INS = 1,1,1,0,0,0,0,0,0,0,0,0 (Just INS unchanged, first image on the diagonal)
|
174 |
+
MID+INS = 1,1,1,0,0,1,0,0,0,0,0,0 (second column of first row)
|
175 |
+
OUTD+INS = 1,1,1,0,0,0,1,1,1,0,0,0 (third column of first row)
|
176 |
+
```
|
177 |
+
|
178 |
+
Then the next row is INS+MID, MID+MID, OUTD+MID, and so on. Example image [here](https://user-images.githubusercontent.com/55250869/270830887-dff65f45-823a-4dbd-94c5-34d37c84a84f.jpg)
|
179 |
+
|
180 |
+
### Effective Block Analyzer
|
181 |
+
This function check which layers are working well. The effect of the block is visualized and quantified by setting the intensity of the other bocks to 1, decreasing the intensity of the block you want to examine, and taking the difference.
|
182 |
+
#### Range
|
183 |
+
If you enter 0.5, 1, all initial values are set to 1, and only the target block is calculated as 0.5. Normally, 0.5 will make a difference, but some LoRAs may have difficulty making a difference, in which case, set 0.5 to 0 or a negative value.
|
184 |
+
|
185 |
+
#### settings
|
186 |
+
##### diff color
|
187 |
+
Specify the background color of the diff file.
|
188 |
+
|
189 |
+
##### chnage X-Y
|
190 |
+
Swaps the X and Y axes. By default, Block is assigned to the Y axis.
|
191 |
+
|
192 |
+
##### Threshold
|
193 |
+
Sets the threshold at which a change is recognized when calculating the difference. Basically, the default value is fine, but if you want to detect subtle differences in color, etc., lower the value.
|
194 |
+
|
195 |
+
#### Blocks
|
196 |
+
Enter the blocks to be examined, using the same format as for XYZ plots.
|
197 |
+
|
198 |
+
Here is the English translation in Markdown format:
|
199 |
+
|
200 |
+
### Guide for API users
|
201 |
+
#### Regular Usage
|
202 |
+
By default, Active is checked in the initial settings, so you can use it simply by installing it. You can use it by entering the format as instructed in the prompt. If executed, the phrase "LoRA Block Weight" will appear on the command prompt screen. If for some reason Active is not enabled, you can make it active by entering a value in the API for `"alwayson_scripts"`.
|
203 |
+
When you enable API mode and use the UI, two extensions will appear. Please use the one on the bottom.
|
204 |
+
The default presets can be used for presets. If you want to use your own presets, you can either edit the preset file or use the following format for the data passed to the API.
|
205 |
+
|
206 |
+
The code that can be used when passing to the API in json format is as follows. The presets you enter here will become available. If you want to use multiple presets, please separate them with `\n`.
|
207 |
+
|
208 |
+
```json
|
209 |
+
"prompt": "myprompt, <lora:mylora:1:MYSETS>",
|
210 |
+
"alwayson_scripts": {
|
211 |
+
"LoRA Block Weight": {
|
212 |
+
"args": ["MYSETS:1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nYOURSETS:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1", true, 1 ,"","","","","","","","","","","","","",""]
|
213 |
+
}
|
214 |
+
}
|
215 |
+
```
|
216 |
+
#### XYZ Plot
|
217 |
+
Please use the format below. Please delete `"alwayson_scripts"` as it will cause an error.
|
218 |
+
|
219 |
+
```json
|
220 |
+
"prompt": "myprompt, <lora:mylora:1:XYZ>",
|
221 |
+
"script_name":"LoRA Block Weight",
|
222 |
+
"script_args": ["XYZ:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", true, 1 ,"seed","-1,-1","","","","","","","","","","","",""]
|
223 |
+
```
|
224 |
+
In this case, the six following `True,1` correspond to `xtype,xvalues,ytype,yvalues,ztype,zvalues`. It will be ignored if left blank. Please follow the instructions in the XYZ plot section for entering values. Even numbers should be enclosed in `""`.
|
225 |
+
|
226 |
+
The following types are available.
|
227 |
+
|
228 |
+
```json
|
229 |
+
"none","Block ID","values","seed","Original Weights","elements"
|
230 |
+
```
|
231 |
+
#### Effective Block Analyzer
|
232 |
+
It can be used by using the following format.
|
233 |
+
|
234 |
+
```json
|
235 |
+
"prompt": "myprompt, <lora:mylora:1:XYZ>",
|
236 |
+
"script_name":"LoRA Block Weight",
|
237 |
+
"script_args": ["XYZ:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", true, 2 ,"","","","","","","0,1","17ALL",1,"white",20,true,"",""]
|
238 |
+
```
|
239 |
+
For `"0,1"`, specify the weight. If you specify `"17ALL"`, it will examine all the layers of the normal LoRA. If you want to specify individually, please write like `"BASE,IN00,IN01,IN02"`. Specify whether to reverse XY for `True` in the `"1"` for the number of times you want to check (if it is 2 or more, multiple seeds will be set), and `white` for the background color.
|
240 |
+
|
241 |
+
#### Make Weights
|
242 |
+
In "make weights," you can create a weight list from a slider. When you press the "add to preset" button, the weight specified by the identifier is added to the end of the preset. If a preset with the same name already exists, it will be overwritten. The "add to preset and save" button allows you to save the preset simultaneously.
|
243 |
+

|
244 |
+
|
245 |
+
# 概要
|
246 |
+
Loraは強力なツールですが、時に扱いが難しく、影響してほしくないところにまで影響がでたりします。このスクリプトではLoraを適用する際、適用度合いをU-Netの階層ごとに設定することができます。これを使用することで求める画像に近づけることができるかもしれません。
|
247 |
+
|
248 |
+
## 使い方
|
249 |
+
インストール時はWeb-ui.batを再起動をしてください。
|
250 |
+
|
251 |
+
### Active
|
252 |
+
ここにチェックを入れることで動作します。
|
253 |
+
|
254 |
+
### プロンプト
|
255 |
+
プロンプト画面では通常通り使用したいLoraを記入してください。その際、強さの値の次に「:」を入力しウェイトか識別子を入力します。識別子はWeights setting で編集します。
|
256 |
+
```
|
257 |
+
<lora:"lora name":1:0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0>.
|
258 |
+
<lora:"lora name":1:0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>. (a1111-sd-webui-locon, etc.)
|
259 |
+
<lora:"lora name":1:1:lbw=IN02> (a1111-sd-webui-lycoris, web-ui 1.5 or later)
|
260 |
+
<lora:"lora name":1:1:lbw=1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0> (a1111-sd-webui-lycoris, web-ui 1.5 or later)
|
261 |
+
<lora:"lora name":1:1:lbw=IN02:stop=10>
|
262 |
+
```
|
263 |
+
Loraの強さは有効で、階層全体にかかります。大文字と小文字は区別されます。
|
264 |
+
LyCORISに対してLoRAのプリセットも使用できますが、その場合LoRAで使われていない階層のウェイトは0に設定されます。
|
265 |
+
上記の形式になっていない場合プリセットではコメント行として扱われます。
|
266 |
+
a1111-sd-webui-lycoris版のLyCORISや、ver1.5以降のweb-uiを使用する場合構文が異なります。`lbw=IN02`を使って下さい。順番は問いません。その他の書式はlycorisの書式にしたがって下さい。詳しくはLyCORISのドキュメントを参照して下さい。識別子を入力して下さい。a1111-sd-webui-lycoris版は開発途中のためこの構文は変更される可能性があります。
|
267 |
+
### start, stop step
|
268 |
+
`<lora:"lora name":lbw=ALL:start=10>`と指定すると、指定したstepからLoRAの効果が現れます。
|
269 |
+
`<lora:"lora name":lbw=ALL:stop=10>`と指定することで指定したstepでLoRAの効果を無くします。キャラクターや構図LoRAの場合には10 step程度で十分な効果があり、ここで切ることで画風への影響を抑えることが可能です。
|
270 |
+
`<lora:"lora name":lbw=ALL:step=5-10>`と指定するとstep 5-10の間のみLoRAが有効化します。
|
271 |
+
|
272 |
+
### Weights setting
|
273 |
+
識別子とウェイトを入力します。
|
274 |
+
フルモデルと異なり、Loraではエンコーダーを含め17のブロックに分かれています。よって、17個の数値を入力してください。
|
275 |
+
BASE,IN,OUTなどはフルモデル相当の階層です。
|
276 |
+
フルモデルやLyCORIS、SDXLなど様々な形式があるため、現状では12,17,20,26のウェイトを受け付けます。基本的に形式が合わないウェイトを入力しても動作しますが、未入力の層は0として扱われます。
|
277 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|
|
278 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|
279 |
+
|BASE|IN01|IN02|IN04|IN05|IN07|IN08|MID|OUT03|OUT04|OUT05|OUT06|OUT07|OUT08|OUT09|OUT10|OUT11|
|
280 |
+
|
281 |
+
LyCORISなどの場合(26)
|
282 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
|
283 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|
284 |
+
|BASE|IN00|IN01|IN02|IN03|IN04|IN05|IN06|IN07|IN08|IN09|IN10|IN11|MID|OUT00|OUT01|OUT02|OUT03|OUT04|OUT05|OUT06|OUT07|OUT08|OUT09|OUT10|OUT11|
|
285 |
+
|
286 |
+
SDXL LoRAの場合(12)
|
287 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|
|
288 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|
|
289 |
+
|BASE|IN04|IN05|IN07|IN08|MID|OUT0|OUT1|OUT2|OUT3|OUT4|OUT05|
|
290 |
+
|
291 |
+
SDXL - LyCORISの場合(20)
|
292 |
+
|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|
|
293 |
+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|
294 |
+
|BASE|IN00|IN01|IN02|IN03|IN04|IN05|IN06|IN07|IN08||MID|OUT00|OUT01|OUT02|OUT03|OUT04|OUT05|OUT06|OUT07|OUT08|
|
295 |
+
|
296 |
+
### 特別な値
|
297 |
+
基本的には数値を入れないと正しく動きませんが R および U を入力することでランダムな数値が入力されます。
|
298 |
+
R : 0~1までの小数点3桁の数値
|
299 |
+
U : -1.5~1.5までの小数点3桁の数値
|
300 |
+
|
301 |
+
例えば ROUT:1,1,1,1,1,1,1,1,R,R,R,R,R,R,R,R,R とすると
|
302 |
+
OUT層のみダンダム化されます
|
303 |
+
ランダム化された数値は画像生成時にコマンドプロンプト画面に表示されます
|
304 |
+
|
305 |
+
saveボタンで現在のテキストボックスのテキストを保存できます。テキストエディタを使った方がいいので、open Texteditorボタンでテキストエディタ開き、編集後reloadしてください。
|
306 |
+
Weights settingの上にあるテキストボックスは現在使用できる識別子の一覧です。XYプロットにコピペするのに便利です。17個ないと一覧に表示されません。
|
307 |
+
|
308 |
+
### 楽しい使い方
|
309 |
+
XY plotと併用することで各階層の影響を調べることが可能になります。
|
310 |
+

|
311 |
+
|
312 |
+
設定値は以下の通りです。
|
313 |
+
NOT:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
314 |
+
ALL:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
|
315 |
+
INS:1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0
|
316 |
+
IND:1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0
|
317 |
+
INALL:1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0
|
318 |
+
MIDD:1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0
|
319 |
+
OUTD:1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0
|
320 |
+
OUTS:1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1
|
321 |
+
OUTALL:1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1
|
322 |
+
|
323 |
+
## XYZ プロット機能
|
324 |
+
各層の値を個別に変化させることで最適値を総当たりに探せます。
|
325 |
+
### 使い方
|
326 |
+
Activeをチェックすることで動作します。 Script(Automatic1111本体のXYZプロットなど)が有効になっている場合そちらが優先されます。noneを選択してください。
|
327 |
+
Hires. fixには対応していません。Batch sizeは1に固定されます。Batch countは1に設定してください。
|
328 |
+
変化させたいLoRAの識別子にXYZと入力します\<lora:"lora名":1:XYZ>。 プリセットにXYZに対応する値を入力していなくても動作します。その場合すべてのウェイトが0の状態からスタートします。XYZに対応する値が入力されている場合はその値が初期値になります。
|
329 |
+
ZYXと入力するとXYZとは反対の値が入力されます。これはふたつのLoRAのウェイトを合わせる際に有効です。
|
330 |
+
例えばLoRA1にXYZ,LoRA2にZYXと入力すると、
|
331 |
+
LoRA1 1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0
|
332 |
+
LoRA2 0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1
|
333 |
+
となります。
|
334 |
+
### 軸タイプ
|
335 |
+
#### values
|
336 |
+
変化させる階層のウェイトを設定します。カンマ区切りで入力してください。「0,0.25,0.5,0.75,1」など。
|
337 |
+
|
338 |
+
#### Block ID
|
339 |
+
ブロックIDを入力すると、そのブロックのみvalueで指定した値に変わります。他のタイプと同様にカンマで区切ります。スペースまたはハイフンで区切ることで複数のブロックを同時に変化させることもできます。最初にNOTをつけることで変化対象が反転します。NOT IN09-OUT02とすると、IN09-OUT02以外が変化します。NOTは最初に入力しないと効果がありません。IN08-M00-OUT03は繋がっています。
|
340 |
+
|
341 |
+
#### Seed
|
342 |
+
シードが変わります。Z軸に指定することを想定しています。
|
343 |
+
|
344 |
+
#### Original Weights
|
345 |
+
各ブロックのウェイトを変化させる初期値を指定します。プリセットに登録されている識別子を入力してください。Original Weightが有効になっている場合XYZに入力された値は無視されます。
|
346 |
+
|
347 |
+
### Original Weightsの合算
|
348 |
+
もしXとYが両方ともOriginal Weightsに設定されている場合、その重みを組み合わせてXYプロットが作成されます。XとYの両方が同じブロックに重みがある場合、配列を加算する前にYケースはゼロに設定されます。この値は、Xの値がゼロに設定されるYXケースで使用されます。意図されている使用方法は、重複するブロックなしでのものです。
|
349 |
+
|
350 |
+
"Weights setting"に以下の名前と値が与えられているとします:
|
351 |
+
INS:1,1,1,0,0,0,0,0,0,0,0,0
|
352 |
+
MID:1,0,0,0,0,1,0,0,0,0,0,0
|
353 |
+
OUTD:1,0,0,0,0,0,1,1,1,0,0,0
|
354 |
+
|
355 |
+
以下の設定で:
|
356 |
+
X : Original Weights, 値: INS,MID,OUTD
|
357 |
+
Y : Original Weights, 値: INS,MID,OUTD
|
358 |
+
Z : なし
|
359 |
+
|
360 |
+
9つの要素を持つXYプロットが作成されます。対角線上は、変更されていないXの値:INS,MID,OUTDです。したがって、最初の行は以下のようになります:
|
361 |
+
```
|
362 |
+
INS+INS = 1,1,1,0,0,0,0,0,0,0,0,0 (変更されていないINSだけ、対角線上の最初の画像)
|
363 |
+
MID+INS = 1,1,1,0,0,1,0,0,0,0,0,0 (最初の行の第2列)
|
364 |
+
OUTD+INS = 1,1,1,0,0,0,1,1,1,0,0,0 (最初の行の第3列)
|
365 |
+
```
|
366 |
+
|
367 |
+
次の行は、INS+MID、MID+MID、OUTD+MIDなどです。例の画像は[こちら](https://user-images.githubusercontent.com/55250869/270830887-dff65f45-823a-4dbd-94c5-34d37c84a84f.jpg)です。
|
368 |
+
|
369 |
+
### 入力例
|
370 |
+
X : value, 値 : 1,0.25,0.5,0.75,1
|
371 |
+
Y : Block ID, 値 : BASE,IN01-IN08,IN05-OUT05,OUT03-OUT11,NOT OUT03-OUT11
|
372 |
+
Z : Original Weights, 値 : NONE,ALL0.5,ALL
|
373 |
+
|
374 |
+
この場合、初期値NONE,ALL0.5,ALLに対応したXY plotが作製されます。
|
375 |
+
ZにSeedを選び、-1,-1,-1を入力すると、異なるseedでXY plotを3回作製します。
|
376 |
+
|
377 |
+
### Effective Block Analyzer
|
378 |
+
どの階層が良く効いているかを判別する機能です。対象の階層以外の強度を1にして、調べたい階層の強度を下げ、差分を取ることで階層の効果を可視化・数値化します。
|
379 |
+
#### Range
|
380 |
+
0.5, 1 と入力した場合、初期値がすべて1になり、対象のブロックのみ0.5として計算が行われます。普通は0.5で差がでますが、LoRAによっては差が出にくい場合があるので、その場合は0.5を0あるいはマイナスの値に設定してください。
|
381 |
+
|
382 |
+
#### 設定
|
383 |
+
##### diff color
|
384 |
+
差分ファイルの背景カラーを指定します。
|
385 |
+
|
386 |
+
##### chnage X-Y
|
387 |
+
X軸とY軸を入れ替えます。デフォルトではY軸にBlockが割り当てられています。
|
388 |
+
|
389 |
+
##### Threshold
|
390 |
+
差分を計算する際の変化したと認識される閾値を設定します。基本的にはデフォルト値で問題ありませんが、微妙な色の違いなどを検出したい場合は値を下げて下さい。
|
391 |
+
|
392 |
+
#### Blocks
|
393 |
+
調べたい階層を入力します。XYZプロットと同じ書式が使用可��です。
|
394 |
+
|
395 |
+
階層別マージについては下記を参照してください
|
396 |
+
|
397 |
+
### elemental
|
398 |
+
詳細は[こちら](https://github.com/hako-mikan/sd-webui-supermerger/blob/main/elemental_ja.md)を参照して下さい。
|
399 |
+
#### 使い方
|
400 |
+
Elementaタブにて階層指定と同じように識別子を設定します。識別子は階層の識別子の後に入力します。
|
401 |
+
\<lora:"lora名":1:IN04:ATTNON>
|
402 |
+
ATTNON:
|
403 |
+
|
404 |
+
書式は
|
405 |
+
識別子:階層指定:要素指定:ウェイト
|
406 |
+
のように指定します。要素は部分一致で判定されます。attn1ならattn1のみ、attnならattn1及びattn2が反応します。階層、要素共に空白で区切ると複数指定できます。
|
407 |
+
print changeをオンにすると反応した要素がコマンドプロンプト上に表示されます。
|
408 |
+
|
409 |
+
ALL0:::0
|
410 |
+
はすべての要素のウェイトをゼロに設定します。
|
411 |
+
IN1:IN00-IN11::1
|
412 |
+
はINのすべての要素を1にします
|
413 |
+
ATTNON::attn:1
|
414 |
+
はすべての階層のattnを1にします。
|
415 |
+
|
416 |
+
#### XYZプロット
|
417 |
+
XYZプロットのelementsの項ではカンマ区切りでXYZプロットが可能になります。
|
418 |
+
その場合は
|
419 |
+
\<lora:"lora名":1:XYZ:XYZ>
|
420 |
+
と指定して下さい。
|
421 |
+
elements
|
422 |
+
の項に
|
423 |
+
IN05-OUT05:attn:0,IN05-OUT05:attn:0.5,IN05-OUT05:attn:1
|
424 |
+
と入力して走らせるとIN05からOUT05までのattnのみを変化させることができます。
|
425 |
+
この際、XYZの値を変更することで初期値を変更できます。デフォルトではelementalのXYZはXYZ:::1となっており、これは全階層、全要素を1にしますが、ここをXYZ:encoder::1とするとテキストエンコーダーのみを有効にした状態で評価ができます。
|
426 |
+
|
427 |
+
#### ウェイトの作成
|
428 |
+
make weightsではスライダーからウェイトリストを作成できます。
|
429 |
+
add to presetボタンを押すと、identiferで指定されたウェイトがプリセットの末尾に追加されます。
|
430 |
+
すでに同じ名前のプリセットが存在する場合、上書きされます。
|
431 |
+
add to preset and saveボタンでは同時にプリセットの保存が行われます。
|
432 |
+

|
433 |
+
|
434 |
+
### APIを通しての利用について
|
435 |
+
#### 通常利用
|
436 |
+
初期設定でActiveはチェックされているのでインストールするだけで利用可能になります。
|
437 |
+
プロンプトに書式通りに入力することで利用できます。実行された場合にはコマンドプロンプト画面に「LoRA Block Weight」の文字が現れます。
|
438 |
+
何らかの理由でActiveになっていない場合にはAPIに投げる値のうち、`"alwayson_scripts"`に値を入力することでActiveにできます。
|
439 |
+
APIモードを有効にしてUIを使うとき、拡張がふたつ表示されます。下の方を使って下さい。
|
440 |
+
プリセットはデフォルトのプリセットが利用できます。独自のプリセットを利用したい場合にはプリセットファイルを編集するか、APIに受け渡すデータに対して下記の書式を利用して下さい。
|
441 |
+
json形式でAPIに受け渡すときに使用できるコードです。ここで入力したプリセットが利用可能になります。複数のプリセットを利用したい場合には`\n`で区切って下さい。
|
442 |
+
|
443 |
+
"prompt": "myprompt, <lora:mylora:1:MYSETS>",
|
444 |
+
"alwayson_scripts": {
|
445 |
+
"LoRA Block Weight": {
|
446 |
+
"args": ["MYSETS:1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\nYOURSETS:0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1", True, 1 ,"","","","","","","","","","","","","",""]
|
447 |
+
}
|
448 |
+
}
|
449 |
+
|
450 |
+
#### XYZ plot
|
451 |
+
下記の書式を利用して下さい。`"alwayson_scripts"`は消して下さいエラーになります。
|
452 |
+
```
|
453 |
+
"prompt": "myprompt, <lora:mylora:1:XYZ>",
|
454 |
+
"script_name":"LoRA Block Weight",
|
455 |
+
"script_args": ["XYZ:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", True, 1 ,"seed","-1,-1","","","","","","","","","","","",""]
|
456 |
+
|
457 |
+
```
|
458 |
+
この際、`True,1`に続く6個が`xtype,xvalues,ytype,yvalues,ztype,zvalues`に対応します。空白だと無視されます。入力する値などはXYZ plotの項に従って下さい。数字でもすべて`""`で囲って下さい。
|
459 |
+
使用できるタイプは次の通りです。
|
460 |
+
```
|
461 |
+
"none","Block ID","values","seed","Original Weights","elements"
|
462 |
+
```
|
463 |
+
#### Effective Block Analyzer
|
464 |
+
下記のような書式を使うことで使用できます。
|
465 |
+
```
|
466 |
+
"prompt": "myprompt, <lora:mylora:1:XYZ>",
|
467 |
+
"script_name":"LoRA Block Weight",
|
468 |
+
"script_args": ["XYZ:1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", True, 2 ,"","","","","","","0,1","17ALL",1,"white",20,True,"",""]
|
469 |
+
|
470 |
+
```
|
471 |
+
`"0,1"`にはウェイト。`"17ALL"`を指定すると普通のLoRAすべての階層を調べます。個別に指定したい場合は`"BASE,IN00,IN01,IN02"`のように記述して下さい。`1`には調べたい回数(2以上だと複数のシードを設定します),`white`には背景色,`True`にはXYを反転するかどうかを指定して下さい。
|
472 |
+
|
473 |
+
### updates/更新情報
|
474 |
+
### 2023.10.26.2000(JST)
|
475 |
+
- bugfix:Effective block checker does not work correctly.
|
476 |
+
- bugfix:Does not work correctly when lora in memory is set to a value other than 0.
|
477 |
+
|
478 |
+
### 2023.10.04.2000(JST)
|
479 |
+
XYZ plotに[新たな機能](#Original-Weightsの合算)が追加されました。[sometimesacoder](https://github.com/sometimesacoder)氏に感謝します。
|
480 |
+
A [new feature](#Original-Weights-Combined-XY-Plot) was added to the XYZ plot. Many thanks to [sometimesacoder](https://github.com/sometimesacoder).
|
481 |
+
|
482 |
+
### 2023.07.22.0030(JST)
|
483 |
+
- support SDXL
|
484 |
+
- support web-ui 1.5
|
485 |
+
- support no buildin-LoRA system(lycoris required)
|
486 |
+
|
487 |
+
to use with web-ui 1.5/web-ui1.5で使うときは
|
488 |
+
```
|
489 |
+
<lora:"lora name":1:1:lbw=IN02>
|
490 |
+
<lora:"lora name":1:1:lbw=1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0>
|
491 |
+
```
|
492 |
+
|
493 |
+
### 2023.07.14.2000(JST)
|
494 |
+
- APIでXYZプロットが利用可能になりました
|
495 |
+
- [APIの利用方法](#apiを通しての利用について)を追記しました
|
496 |
+
- XYZ plot can be used in API
|
497 |
+
- Added [guide for API users](#guide-for-api-users)
|
498 |
+
|
499 |
+
### 2023.5.24.2000(JST)
|
500 |
+
- changed directory for presets(extentions/sd-webui-lora-block-weight/scripts/)
|
501 |
+
- プリセットの保存フォルダがextentions/sd-webui-lora-block-weight/scripts/に変更になりました。
|
502 |
+
|
503 |
+
### 2023.5.12.2100(JST)
|
504 |
+
- changed syntax of lycoris
|
505 |
+
- lycorisの書式を変更しました
|
506 |
+
|
507 |
+
### 2023.04.14.2000(JST)
|
508 |
+
- support LyCORIS(a1111-sd-webui-lycoris)
|
509 |
+
- LyCORIS(a1111-sd-webui-lycoris)に対応
|
510 |
+
|
511 |
+
### 2023.03.20.2030(JST)
|
512 |
+
- Comment lines can now be added to presets
|
513 |
+
- プリセットにコメント行を追加できるようになりました
|
514 |
+
- support XYZ plot hires.fix
|
515 |
+
- XYZプロットがhires.fixに対応しました
|
516 |
+
|
517 |
+
### 2023.03.16.2030(JST)
|
518 |
+
- [LyCORIS](https://github.com/KohakuBlueleaf/LyCORIS)に対応しました
|
519 |
+
- Support [LyCORIS](https://github.com/KohakuBlueleaf/LyCORIS)
|
520 |
+
|
521 |
+
別途[LyCORIS Extention](https://github.com/KohakuBlueleaf/a1111-sd-webui-locon)が必要です。
|
522 |
+
For use LyCORIS, [Extension](https://github.com/KohakuBlueleaf/a1111-sd-webui-locon) for LyCORIS needed.
|
523 |
+
|
524 |
+
### 2023.02.07 1250(JST)
|
525 |
+
- Changed behavior when XYZ plot Active (Script of the main UI is prioritized).
|
526 |
+
|
527 |
+
### 2023.02.06 2000(JST)
|
528 |
+
- Feature added: XYZ plotting is added.
|
529 |
+
|
530 |
+
### 2023.01.31 0200(JST)
|
531 |
+
- Feature added: Random feature is added
|
532 |
+
- Fixed: Weighting now works for negative values.
|
533 |
+
|
534 |
+
### 2023.02.16 2040(JST)
|
535 |
+
- Original Weight をxやyに設定できない問題を解決しました
|
536 |
+
- Effective Weight Analyzer選択時にXYZのXやYがValuesとBlockIdになっていないとエラーになる問題を解決しました
|
537 |
+
|
538 |
+
### 2023.02.08 2120(JST)
|
539 |
+
- 階層適応した後通常使用する際、階層適応が残る問題を解決しました
|
540 |
+
- 効果のある階層をワンクリックで判別する機能を追加しました
|
541 |
+
|
542 |
+
### 2023.02.08 0050(JST)
|
543 |
+
- 一部環境でseedが固定されない問題を解決しました
|
544 |
+
|
545 |
+
### 2023.02.07 2015(JST)
|
546 |
+
- マイナスのウェイトが正常に働かない問題を修正しました
|
547 |
+
|
548 |
+
### 2023.02.07 1250(JST)
|
549 |
+
- XYZプロットActive時の動作を変更しました(本体のScriptが優先されるようになります)
|
550 |
+
|
551 |
+
### 2023.02.06 2000(JST)
|
552 |
+
- 機能追加:XYZプロット機能を追加しました
|
553 |
+
|
554 |
+
### 2023.01.31 0200(JST)
|
555 |
+
- 機能追加:ランダム機能を追加しました
|
556 |
+
- 機能修正:ウェイトがマイナスにも効くようになりました
|
scripts/Roboto-Regular.ttf
ADDED
Binary file (306 kB). View file
|
|
scripts/lora_block_weight.py
ADDED
@@ -0,0 +1,1266 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import json
|
3 |
+
import os
|
4 |
+
import gc
|
5 |
+
import re
|
6 |
+
import sys
|
7 |
+
import torch
|
8 |
+
import shutil
|
9 |
+
import math
|
10 |
+
import importlib
|
11 |
+
import numpy as np
|
12 |
+
import gradio as gr
|
13 |
+
import os.path
|
14 |
+
import random
|
15 |
+
from pprint import pprint
|
16 |
+
import modules.ui
|
17 |
+
import modules.scripts as scripts
|
18 |
+
from PIL import Image, ImageFont, ImageDraw
|
19 |
+
import modules.shared as shared
|
20 |
+
from modules import devices, sd_models, images,cmd_args, extra_networks, sd_hijack
|
21 |
+
from modules.shared import cmd_opts, opts, state
|
22 |
+
from modules.processing import process_images, Processed
|
23 |
+
from modules.script_callbacks import CFGDenoiserParams, on_cfg_denoiser
|
24 |
+
|
25 |
+
LBW_T = "customscript/lora_block_weight.py/txt2img/Active/value"
|
26 |
+
LBW_I = "customscript/lora_block_weight.py/img2img/Active/value"
|
27 |
+
|
28 |
+
if os.path.exists(cmd_opts.ui_config_file):
|
29 |
+
with open(cmd_opts.ui_config_file, 'r', encoding="utf-8") as json_file:
|
30 |
+
ui_config = json.load(json_file)
|
31 |
+
else:
|
32 |
+
print("ui config file not found, using default values")
|
33 |
+
ui_config = {}
|
34 |
+
|
35 |
+
startup_t = ui_config[LBW_T] if LBW_T in ui_config else None
|
36 |
+
startup_i = ui_config[LBW_I] if LBW_I in ui_config else None
|
37 |
+
active_t = "Active" if startup_t else "Not Active"
|
38 |
+
active_i = "Active" if startup_i else "Not Active"
|
39 |
+
|
40 |
+
lxyz = ""
|
41 |
+
lzyx = ""
|
42 |
+
prompts = ""
|
43 |
+
xyelem = ""
|
44 |
+
princ = False
|
45 |
+
|
46 |
+
try:
|
47 |
+
from ldm_patched.modules import model_management
|
48 |
+
forge = True
|
49 |
+
except:
|
50 |
+
forge = False
|
51 |
+
|
52 |
+
BLOCKID26=["BASE","IN00","IN01","IN02","IN03","IN04","IN05","IN06","IN07","IN08","IN09","IN10","IN11","M00","OUT00","OUT01","OUT02","OUT03","OUT04","OUT05","OUT06","OUT07","OUT08","OUT09","OUT10","OUT11"]
|
53 |
+
BLOCKID17=["BASE","IN01","IN02","IN04","IN05","IN07","IN08","M00","OUT03","OUT04","OUT05","OUT06","OUT07","OUT08","OUT09","OUT10","OUT11"]
|
54 |
+
BLOCKID12=["BASE","IN04","IN05","IN07","IN08","M00","OUT00","OUT01","OUT02","OUT03","OUT04","OUT05"]
|
55 |
+
BLOCKID20=["BASE","IN00","IN01","IN02","IN03","IN04","IN05","IN06","IN07","IN08","M00","OUT00","OUT01","OUT02","OUT03","OUT04","OUT05","OUT06","OUT07","OUT08"]
|
56 |
+
BLOCKNUMS = [12,17,20,26]
|
57 |
+
BLOCKIDS=[BLOCKID12,BLOCKID17,BLOCKID20,BLOCKID26]
|
58 |
+
|
59 |
+
BLOCKS=["encoder",
|
60 |
+
"diffusion_model_input_blocks_0_",
|
61 |
+
"diffusion_model_input_blocks_1_",
|
62 |
+
"diffusion_model_input_blocks_2_",
|
63 |
+
"diffusion_model_input_blocks_3_",
|
64 |
+
"diffusion_model_input_blocks_4_",
|
65 |
+
"diffusion_model_input_blocks_5_",
|
66 |
+
"diffusion_model_input_blocks_6_",
|
67 |
+
"diffusion_model_input_blocks_7_",
|
68 |
+
"diffusion_model_input_blocks_8_",
|
69 |
+
"diffusion_model_input_blocks_9_",
|
70 |
+
"diffusion_model_input_blocks_10_",
|
71 |
+
"diffusion_model_input_blocks_11_",
|
72 |
+
"diffusion_model_middle_block_",
|
73 |
+
"diffusion_model_output_blocks_0_",
|
74 |
+
"diffusion_model_output_blocks_1_",
|
75 |
+
"diffusion_model_output_blocks_2_",
|
76 |
+
"diffusion_model_output_blocks_3_",
|
77 |
+
"diffusion_model_output_blocks_4_",
|
78 |
+
"diffusion_model_output_blocks_5_",
|
79 |
+
"diffusion_model_output_blocks_6_",
|
80 |
+
"diffusion_model_output_blocks_7_",
|
81 |
+
"diffusion_model_output_blocks_8_",
|
82 |
+
"diffusion_model_output_blocks_9_",
|
83 |
+
"diffusion_model_output_blocks_10_",
|
84 |
+
"diffusion_model_output_blocks_11_",
|
85 |
+
"embedders",
|
86 |
+
"transformer_resblocks"]
|
87 |
+
|
88 |
+
loopstopper = True
|
89 |
+
|
90 |
+
ATYPES =["none","Block ID","values","seed","Original Weights","elements"]
|
91 |
+
|
92 |
+
DEF_WEIGHT_PRESET = "\
|
93 |
+
NOT:0,0,0,0,0,0,0,0,0,0,0,0\n\
|
94 |
+
ALL:1,1,1,1,1,1,1,1,1,1,1,1\n\
|
95 |
+
INS:1,1,1,0,0,0,0,0,0,0,0,0\n\
|
96 |
+
IND:1,0,0,1,1,0,0,0,0,0,0,0\n\
|
97 |
+
INALL:1,1,1,1,1,0,0,0,0,0,0,0\n\
|
98 |
+
MIDD:1,0,0,1,1,1,1,1,1,0,0,0\n\
|
99 |
+
OUTD:1,0,0,0,0,0,1,1,1,0,0,0\n\
|
100 |
+
OUTS:1,0,0,0,0,0,0,0,0,1,1,1\n\
|
101 |
+
OUTALL:1,0,0,0,0,0,1,1,1,1,1,1\n\
|
102 |
+
BASE:1,0,0,0,0,0,0,0,0,0,0,0\n\
|
103 |
+
IN04:1,1,0,0,0,0,0,0,0,0,0,0\n\
|
104 |
+
IN05:1,0,1,0,0,0,0,0,0,0,0,0\n\
|
105 |
+
IN07:1,0,0,1,0,0,0,0,0,0,0,0\n\
|
106 |
+
IN08:1,0,0,0,1,0,0,0,0,0,0,0\n\
|
107 |
+
MID:1,0,0,0,0,1,0,0,0,0,0,0\n\
|
108 |
+
OUT00:1,0,0,0,0,0,1,0,0,0,0,0\n\
|
109 |
+
OUT01:1,0,0,0,0,0,0,1,0,0,0,0\n\
|
110 |
+
OUT02:1,0,0,0,0,0,0,0,1,0,0,0\n\
|
111 |
+
OUT03:1,0,0,0,0,0,0,0,0,1,0,0\n\
|
112 |
+
OUT04:1,0,0,0,0,0,0,0,0,0,1,0\n\
|
113 |
+
OUT05:1,0,0,0,0,0,0,0,0,0,0,1"
|
114 |
+
|
115 |
+
scriptpath = os.path.dirname(os.path.abspath(__file__))
|
116 |
+
|
117 |
+
class Script(modules.scripts.Script):
|
118 |
+
def __init__(self):
|
119 |
+
self.log = {}
|
120 |
+
self.stops = {}
|
121 |
+
self.starts = {}
|
122 |
+
self.active = False
|
123 |
+
self.lora = {}
|
124 |
+
self.lycoris = {}
|
125 |
+
self.networks = {}
|
126 |
+
|
127 |
+
self.stopsf = []
|
128 |
+
self.startsf = []
|
129 |
+
self.uf = []
|
130 |
+
self.lf = []
|
131 |
+
self.ef = []
|
132 |
+
|
133 |
+
def title(self):
|
134 |
+
return "LoRA Block Weight"
|
135 |
+
|
136 |
+
def show(self, is_img2img):
|
137 |
+
return modules.scripts.AlwaysVisible
|
138 |
+
|
139 |
+
def ui(self, is_img2img):
|
140 |
+
LWEIGHTSPRESETS = DEF_WEIGHT_PRESET
|
141 |
+
|
142 |
+
runorigin = scripts.scripts_txt2img.run
|
143 |
+
runorigini = scripts.scripts_img2img.run
|
144 |
+
|
145 |
+
scriptpath = os.path.dirname(os.path.abspath(__file__))
|
146 |
+
path_root = scripts.basedir()
|
147 |
+
|
148 |
+
extpath = os.path.join(scriptpath, "lbwpresets.txt")
|
149 |
+
extpathe = os.path.join(scriptpath, "elempresets.txt")
|
150 |
+
filepath = os.path.join(path_root,"scripts", "lbwpresets.txt")
|
151 |
+
filepathe = os.path.join(path_root,"scripts", "elempresets.txt")
|
152 |
+
|
153 |
+
if os.path.isfile(filepath) and not os.path.isfile(extpath):
|
154 |
+
shutil.move(filepath,extpath)
|
155 |
+
|
156 |
+
if os.path.isfile(filepathe) and not os.path.isfile(extpathe):
|
157 |
+
shutil.move(filepathe,extpathe)
|
158 |
+
|
159 |
+
lbwpresets=""
|
160 |
+
|
161 |
+
try:
|
162 |
+
with open(extpath,encoding="utf-8") as f:
|
163 |
+
lbwpresets = f.read()
|
164 |
+
except OSError as e:
|
165 |
+
lbwpresets=LWEIGHTSPRESETS
|
166 |
+
if not os.path.isfile(extpath):
|
167 |
+
try:
|
168 |
+
with open(extpath,mode = 'w',encoding="utf-8") as f:
|
169 |
+
f.write(lbwpresets)
|
170 |
+
except:
|
171 |
+
pass
|
172 |
+
|
173 |
+
try:
|
174 |
+
with open(extpathe,encoding="utf-8") as f:
|
175 |
+
elempresets = f.read()
|
176 |
+
except OSError as e:
|
177 |
+
elempresets=ELEMPRESETS
|
178 |
+
if not os.path.isfile(extpathe):
|
179 |
+
try:
|
180 |
+
with open(extpathe,mode = 'w',encoding="utf-8") as f:
|
181 |
+
f.write(elempresets)
|
182 |
+
except:
|
183 |
+
pass
|
184 |
+
|
185 |
+
loraratios=lbwpresets.splitlines()
|
186 |
+
lratios={}
|
187 |
+
for i,l in enumerate(loraratios):
|
188 |
+
if checkloadcond(l) : continue
|
189 |
+
lratios[l.split(":")[0]]=l.split(":")[1]
|
190 |
+
ratiostags = [k for k in lratios.keys()]
|
191 |
+
ratiostags = ",".join(ratiostags)
|
192 |
+
|
193 |
+
if os.environ.get('IGNORE_CMD_ARGS_ERRORS', None) is None:
|
194 |
+
args = cmd_args.parser.parse_args()
|
195 |
+
else:
|
196 |
+
args, _ = cmd_args.parser.parse_known_args()
|
197 |
+
if args.api:
|
198 |
+
register()
|
199 |
+
|
200 |
+
with gr.Accordion(f"LoRA Block Weight : {active_i if is_img2img else active_t}",open = False) as acc:
|
201 |
+
with gr.Row():
|
202 |
+
with gr.Column(min_width = 50, scale=1):
|
203 |
+
lbw_useblocks = gr.Checkbox(value = True,label="Active",interactive =True,elem_id="lbw_active")
|
204 |
+
debug = gr.Checkbox(value = False,label="Debug",interactive =True,elem_id="lbw_debug")
|
205 |
+
with gr.Column(scale=5):
|
206 |
+
bw_ratiotags= gr.TextArea(label="",value=ratiostags,visible =True,interactive =True,elem_id="lbw_ratios")
|
207 |
+
with gr.Accordion("XYZ plot",open = False):
|
208 |
+
gr.HTML(value='<p style= "word-wrap:break-word;">changeable blocks : BASE,IN00,IN01,IN02,IN03,IN04,IN05,IN06,IN07,IN08,IN09,IN10,IN11,M00,OUT00,OUT01,OUT02,OUT03,OUT04,OUT05,OUT06,OUT07,OUT08,OUT09,OUT10,OUT11</p>')
|
209 |
+
xyzsetting = gr.Radio(label = "Active",choices = ["Disable","XYZ plot","Effective Block Analyzer"], value ="Disable",type = "index")
|
210 |
+
with gr.Row(visible = False) as esets:
|
211 |
+
diffcol = gr.Radio(label = "diff image color",choices = ["black","white"], value ="black",type = "value",interactive =True)
|
212 |
+
revxy = gr.Checkbox(value = False,label="change X-Y",interactive =True,elem_id="lbw_changexy")
|
213 |
+
thresh = gr.Textbox(label="difference threshold",lines=1,value="20",interactive =True,elem_id="diff_thr")
|
214 |
+
xtype = gr.Dropdown(label="X Types", choices=[x for x in ATYPES], value=ATYPES [2],interactive =True,elem_id="lbw_xtype")
|
215 |
+
xmen = gr.Textbox(label="X Values",lines=1,value="0,0.25,0.5,0.75,1",interactive =True,elem_id="lbw_xmen")
|
216 |
+
ytype = gr.Dropdown(label="Y Types", choices=[y for y in ATYPES], value=ATYPES [1],interactive =True,elem_id="lbw_ytype")
|
217 |
+
ymen = gr.Textbox(label="Y Values" ,lines=1,value="IN05-OUT05",interactive =True,elem_id="lbw_ymen")
|
218 |
+
ztype = gr.Dropdown(label="Z type", choices=[z for z in ATYPES], value=ATYPES[0],interactive =True,elem_id="lbw_ztype")
|
219 |
+
zmen = gr.Textbox(label="Z values",lines=1,value="",interactive =True,elem_id="lbw_zmen")
|
220 |
+
|
221 |
+
exmen = gr.Textbox(label="Range",lines=1,value="0.5,1",interactive =True,elem_id="lbw_exmen",visible = False)
|
222 |
+
eymen = gr.Textbox(label="Blocks (12ALL,17ALL,20ALL,26ALL also can be used)" ,lines=1,value="BASE,IN00,IN01,IN02,IN03,IN04,IN05,IN06,IN07,IN08,IN09,IN10,IN11,M00,OUT00,OUT01,OUT02,OUT03,OUT04,OUT05,OUT06,OUT07,OUT08,OUT09,OUT10,OUT11",interactive =True,elem_id="lbw_eymen",visible = False)
|
223 |
+
ecount = gr.Number(value=1, label="number of seed", interactive=True, visible = True)
|
224 |
+
|
225 |
+
with gr.Accordion("Weights setting",open = True):
|
226 |
+
with gr.Row():
|
227 |
+
reloadtext = gr.Button(value="Reload Presets",variant='primary',elem_id="lbw_reload")
|
228 |
+
reloadtags = gr.Button(value="Reload Tags",variant='primary',elem_id="lbw_reload")
|
229 |
+
savetext = gr.Button(value="Save Presets",variant='primary',elem_id="lbw_savetext")
|
230 |
+
openeditor = gr.Button(value="Open TextEditor",variant='primary',elem_id="lbw_openeditor")
|
231 |
+
lbw_loraratios = gr.TextArea(label="",value=lbwpresets,visible =True,interactive = True,elem_id="lbw_ratiospreset")
|
232 |
+
|
233 |
+
with gr.Accordion("Elemental",open = False):
|
234 |
+
with gr.Row():
|
235 |
+
e_reloadtext = gr.Button(value="Reload Presets",variant='primary',elem_id="lbw_reload")
|
236 |
+
e_savetext = gr.Button(value="Save Presets",variant='primary',elem_id="lbw_savetext")
|
237 |
+
e_openeditor = gr.Button(value="Open TextEditor",variant='primary',elem_id="lbw_openeditor")
|
238 |
+
elemsets = gr.Checkbox(value = False,label="print change",interactive =True,elem_id="lbw_print_change")
|
239 |
+
elemental = gr.TextArea(label="Identifer:BlockID:Elements:Ratio,...,separated by empty line ",value = elempresets,interactive =True,elem_id="element")
|
240 |
+
|
241 |
+
d_true = gr.Checkbox(value = True,visible = False)
|
242 |
+
d_false = gr.Checkbox(value = False,visible = False)
|
243 |
+
|
244 |
+
with gr.Accordion("Make Weights",open = False):
|
245 |
+
with gr.Row():
|
246 |
+
m_text = gr.Textbox(value="",label="Weights")
|
247 |
+
with gr.Row():
|
248 |
+
m_add = gr.Button(value="Add to presets",size="sm",variant='primary')
|
249 |
+
m_add_save = gr.Button(value="Add to presets and Save",size="sm",variant='primary')
|
250 |
+
m_name = gr.Textbox(value="",label="Identifier")
|
251 |
+
with gr.Row():
|
252 |
+
m_type = gr.Radio(label="Weights type",choices=["17(1.X/2.X)", "26(1.X/2.X full)", "12(XL)","20(XL full)"], value="17(1.X/2.X)")
|
253 |
+
with gr.Row():
|
254 |
+
m_set_0 = gr.Button(value="Set All 0",variant='primary')
|
255 |
+
m_set_1 = gr.Button(value="Set All 1",variant='primary')
|
256 |
+
m_custom = gr.Button(value="Set custom",variant='primary')
|
257 |
+
m_custom_v = gr.Slider(show_label=False, minimum=-1.0, maximum=1, step=0.1, value=0, interactive=True)
|
258 |
+
with gr.Row():
|
259 |
+
with gr.Column(scale=1, min_width=100):
|
260 |
+
gr.Slider(visible=False)
|
261 |
+
with gr.Column(scale=2, min_width=200):
|
262 |
+
base = gr.Slider(label="BASE", minimum=-1, maximum=1, step=0.1, value=0.0)
|
263 |
+
with gr.Column(scale=1, min_width=100):
|
264 |
+
gr.Slider(visible=False)
|
265 |
+
with gr.Row():
|
266 |
+
with gr.Column(scale=2, min_width=200):
|
267 |
+
ins = [gr.Slider(label=block, minimum=-1.0, maximum=1, step=0.1, value=0, interactive=True) for block in BLOCKID26[1:13]]
|
268 |
+
with gr.Column(scale=2, min_width=200):
|
269 |
+
outs = [gr.Slider(label=block, minimum=-1.0, maximum=1, step=0.1, value=0, interactive=True) for block in reversed(BLOCKID26[14:])]
|
270 |
+
with gr.Row():
|
271 |
+
with gr.Column(scale=1, min_width=100):
|
272 |
+
gr.Slider(visible=False)
|
273 |
+
with gr.Column(scale=2, min_width=200):
|
274 |
+
m00 = gr.Slider(label="M00", minimum=-1, maximum=1, step=0.1, value=0.0)
|
275 |
+
with gr.Column(scale=1, min_width=100):
|
276 |
+
gr.Slider(visible=False)
|
277 |
+
|
278 |
+
blocks = [base] + ins + [m00] + outs[::-1]
|
279 |
+
for block in blocks:
|
280 |
+
if block.label not in BLOCKID17:
|
281 |
+
block.visible = False
|
282 |
+
|
283 |
+
m_set_0.click(fn=lambda x:[0]*26 + [",".join(["0"]*int(x[:2]))],inputs=[m_type],outputs=blocks + [m_text])
|
284 |
+
m_set_1.click(fn=lambda x:[1]*26 + [",".join(["1"]*int(x[:2]))],inputs=[m_type],outputs=blocks + [m_text])
|
285 |
+
m_custom.click(fn=lambda x,y:[x]*26 + [",".join([str(x)]*int(y[:2]))],inputs=[m_custom_v,m_type],outputs=blocks + [m_text])
|
286 |
+
|
287 |
+
def addweights(weights, id, presets, save = False):
|
288 |
+
if id == "":id = "NONAME"
|
289 |
+
lines = presets.strip().split("\n")
|
290 |
+
id_found = False
|
291 |
+
for i, line in enumerate(lines):
|
292 |
+
if line.startswith("#"):
|
293 |
+
continue
|
294 |
+
if line.split(":")[0] == id:
|
295 |
+
lines[i] = f"{id}:{weights}"
|
296 |
+
id_found = True
|
297 |
+
break
|
298 |
+
if not id_found:
|
299 |
+
lines.append(f"{id}:{weights}")
|
300 |
+
|
301 |
+
if save:
|
302 |
+
with open(extpath,mode = 'w',encoding="utf-8") as f:
|
303 |
+
f.write("\n".join(lines))
|
304 |
+
|
305 |
+
return "\n".join(lines)
|
306 |
+
|
307 |
+
def changetheblocks(sdver,*blocks):
|
308 |
+
sdver = int(sdver[:2])
|
309 |
+
output = []
|
310 |
+
targ_blocks = BLOCKIDS[BLOCKNUMS.index(sdver)]
|
311 |
+
for i, block in enumerate(BLOCKID26):
|
312 |
+
if block in targ_blocks:
|
313 |
+
output.append(str(blocks[i]))
|
314 |
+
return [",".join(output)] + [gr.update(visible = True if block in targ_blocks else False) for block in BLOCKID26]
|
315 |
+
|
316 |
+
m_add.click(fn=addweights, inputs=[m_text,m_name,lbw_loraratios],outputs=[lbw_loraratios])
|
317 |
+
m_add_save.click(fn=addweights, inputs=[m_text,m_name,lbw_loraratios, d_true],outputs=[lbw_loraratios])
|
318 |
+
m_type.change(fn=changetheblocks, inputs=[m_type] + blocks,outputs=[m_text] + blocks)
|
319 |
+
|
320 |
+
d_true = gr.Checkbox(value = True,visible = False)
|
321 |
+
d_false = gr.Checkbox(value = False,visible = False)
|
322 |
+
|
323 |
+
lbw_useblocks.change(fn=lambda x:gr.update(label = f"LoRA Block Weight : {'Active' if x else 'Not Active'}"),inputs=lbw_useblocks, outputs=[acc])
|
324 |
+
|
325 |
+
def makeweights(sdver, *blocks):
|
326 |
+
sdver = int(sdver[:2])
|
327 |
+
output = []
|
328 |
+
targ_blocks = BLOCKIDS[BLOCKNUMS.index(sdver)]
|
329 |
+
for i, block in enumerate(BLOCKID26):
|
330 |
+
if block in targ_blocks:
|
331 |
+
output.append(str(blocks[i]))
|
332 |
+
return ",".join(output)
|
333 |
+
|
334 |
+
changes = [b.release(fn=makeweights,inputs=[m_type] + blocks,outputs=[m_text]) for b in blocks]
|
335 |
+
|
336 |
+
import subprocess
|
337 |
+
def openeditors(b):
|
338 |
+
path = extpath if b else extpathe
|
339 |
+
subprocess.Popen(['start', path], shell=True)
|
340 |
+
|
341 |
+
def reloadpresets(isweight):
|
342 |
+
if isweight:
|
343 |
+
try:
|
344 |
+
with open(extpath,encoding="utf-8") as f:
|
345 |
+
return f.read()
|
346 |
+
except OSError as e:
|
347 |
+
pass
|
348 |
+
else:
|
349 |
+
try:
|
350 |
+
with open(extpath,encoding="utf-8") as f:
|
351 |
+
return f.read()
|
352 |
+
except OSError as e:
|
353 |
+
pass
|
354 |
+
|
355 |
+
def tagdicter(presets):
|
356 |
+
presets=presets.splitlines()
|
357 |
+
wdict={}
|
358 |
+
for l in presets:
|
359 |
+
if checkloadcond(l) : continue
|
360 |
+
w=[]
|
361 |
+
if ":" in l :
|
362 |
+
key = l.split(":",1)[0]
|
363 |
+
w = l.split(":",1)[1]
|
364 |
+
if any(len([w for w in w.split(",")]) == x for x in BLOCKNUMS):
|
365 |
+
wdict[key.strip()]=w
|
366 |
+
return ",".join(list(wdict.keys()))
|
367 |
+
|
368 |
+
def savepresets(text,isweight):
|
369 |
+
if isweight:
|
370 |
+
with open(extpath,mode = 'w',encoding="utf-8") as f:
|
371 |
+
f.write(text)
|
372 |
+
else:
|
373 |
+
with open(extpathe,mode = 'w',encoding="utf-8") as f:
|
374 |
+
f.write(text)
|
375 |
+
|
376 |
+
reloadtext.click(fn=reloadpresets,inputs=[d_true],outputs=[lbw_loraratios])
|
377 |
+
reloadtags.click(fn=tagdicter,inputs=[lbw_loraratios],outputs=[bw_ratiotags])
|
378 |
+
savetext.click(fn=savepresets,inputs=[lbw_loraratios,d_true],outputs=[])
|
379 |
+
openeditor.click(fn=openeditors,inputs=[d_true],outputs=[])
|
380 |
+
|
381 |
+
e_reloadtext.click(fn=reloadpresets,inputs=[d_false],outputs=[elemental])
|
382 |
+
e_savetext.click(fn=savepresets,inputs=[elemental,d_false],outputs=[])
|
383 |
+
e_openeditor.click(fn=openeditors,inputs=[d_false],outputs=[])
|
384 |
+
|
385 |
+
def urawaza(active):
|
386 |
+
if active > 0:
|
387 |
+
register()
|
388 |
+
scripts.scripts_txt2img.run = newrun
|
389 |
+
scripts.scripts_img2img.run = newrun
|
390 |
+
if active == 1:return [*[gr.update(visible = True) for x in range(6)],*[gr.update(visible = False) for x in range(4)]]
|
391 |
+
else:return [*[gr.update(visible = False) for x in range(6)],*[gr.update(visible = True) for x in range(4)]]
|
392 |
+
else:
|
393 |
+
scripts.scripts_txt2img.run = runorigin
|
394 |
+
scripts.scripts_img2img.run = runorigini
|
395 |
+
return [*[gr.update(visible = True) for x in range(6)],*[gr.update(visible = False) for x in range(4)]]
|
396 |
+
|
397 |
+
xyzsetting.change(fn=urawaza,inputs=[xyzsetting],outputs =[xtype,xmen,ytype,ymen,ztype,zmen,exmen,eymen,ecount,esets])
|
398 |
+
|
399 |
+
return lbw_loraratios,lbw_useblocks,xyzsetting,xtype,xmen,ytype,ymen,ztype,zmen,exmen,eymen,ecount,diffcol,thresh,revxy,elemental,elemsets,debug
|
400 |
+
|
401 |
+
def process(self, p, loraratios,useblocks,xyzsetting,xtype,xmen,ytype,ymen,ztype,zmen,exmen,eymen,ecount,diffcol,thresh,revxy,elemental,elemsets,debug):
|
402 |
+
#print("self =",self,"p =",p,"presets =",loraratios,"useblocks =",useblocks,"xyzsettings =",xyzsetting,"xtype =",xtype,"xmen =",xmen,"ytype =",ytype,"ymen =",ymen,"ztype =",ztype,"zmen =",zmen)
|
403 |
+
#Note that this does not use the default arg syntax because the default args are supposed to be at the end of the function
|
404 |
+
if(loraratios == None):
|
405 |
+
loraratios = DEF_WEIGHT_PRESET
|
406 |
+
if(useblocks == None):
|
407 |
+
useblocks = True
|
408 |
+
|
409 |
+
lorachecker(self)
|
410 |
+
self.log["enable LBW"] = useblocks
|
411 |
+
self.log["registerd"] = registerd
|
412 |
+
|
413 |
+
if useblocks:
|
414 |
+
self.active = True
|
415 |
+
loraratios=loraratios.splitlines()
|
416 |
+
elemental = elemental.split("\n\n") if elemental is not None else []
|
417 |
+
lratios={}
|
418 |
+
elementals={}
|
419 |
+
for l in loraratios:
|
420 |
+
if checkloadcond(l) : continue
|
421 |
+
l0=l.split(":",1)[0]
|
422 |
+
lratios[l0.strip()]=l.split(":",1)[1]
|
423 |
+
for e in elemental:
|
424 |
+
if ":" not in e: continue
|
425 |
+
e0=e.split(":",1)[0]
|
426 |
+
elementals[e0.strip()]=e.split(":",1)[1]
|
427 |
+
if elemsets : print(xyelem)
|
428 |
+
if xyzsetting and "XYZ" in p.prompt:
|
429 |
+
lratios["XYZ"] = lxyz
|
430 |
+
lratios["ZYX"] = lzyx
|
431 |
+
if xyelem != "":
|
432 |
+
if "XYZ" in elementals.keys():
|
433 |
+
elementals["XYZ"] = elementals["XYZ"] + ","+ xyelem
|
434 |
+
else:
|
435 |
+
elementals["XYZ"] = xyelem
|
436 |
+
self.lratios = lratios
|
437 |
+
self.elementals = elementals
|
438 |
+
global princ
|
439 |
+
princ = elemsets
|
440 |
+
|
441 |
+
if not hasattr(self,"lbt_dr_callbacks"):
|
442 |
+
self.lbt_dr_callbacks = on_cfg_denoiser(self.denoiser_callback)
|
443 |
+
|
444 |
+
def denoiser_callback(self, params: CFGDenoiserParams):
|
445 |
+
def setparams(self, key, te, u ,sets):
|
446 |
+
for dicts in [self.lora,self.lycoris,self.networks]:
|
447 |
+
for lora in dicts:
|
448 |
+
if lora.name.split("_in_LBW_")[0] == key:
|
449 |
+
lora.te_multiplier = te
|
450 |
+
lora.unet_multiplier = u
|
451 |
+
sets.append(key)
|
452 |
+
|
453 |
+
if forge and self.active:
|
454 |
+
if params.sampling_step in self.startsf:
|
455 |
+
shared.sd_model.forge_objects.unet.unpatch_model(device_to=devices.device)
|
456 |
+
for key, vals in shared.sd_model.forge_objects.unet.patches.items():
|
457 |
+
n_vals = []
|
458 |
+
lvals = [val for val in vals if val[1][0] in LORAS]
|
459 |
+
for s, v, m, l, e in zip(self.startsf, lvals, self.uf, self.lf, self.ef):
|
460 |
+
if s is not None and s == params.sampling_step:
|
461 |
+
ratio, errormodules = ratiodealer(key.replace(".","_"), l, e)
|
462 |
+
n_vals.append((ratio * m, *v[1:]))
|
463 |
+
else:
|
464 |
+
n_vals.append(v)
|
465 |
+
shared.sd_model.forge_objects.unet.patches[key] = n_vals
|
466 |
+
shared.sd_model.forge_objects.unet.patch_model()
|
467 |
+
|
468 |
+
if params.sampling_step in self.stopsf:
|
469 |
+
shared.sd_model.forge_objects.unet.unpatch_model(device_to=devices.device)
|
470 |
+
for key, vals in shared.sd_model.forge_objects.unet.patches.items():
|
471 |
+
n_vals = []
|
472 |
+
lvals = [val for val in vals if val[1][0] in LORAS]
|
473 |
+
for s, v, m, l, e in zip(self.stopsf, lvals, self.uf, self.lf, self.ef):
|
474 |
+
if s is not None and s == params.sampling_step:
|
475 |
+
n_vals.append((0, *v[1:]))
|
476 |
+
else:
|
477 |
+
n_vals.append(v)
|
478 |
+
shared.sd_model.forge_objects.unet.patches[key] = n_vals
|
479 |
+
shared.sd_model.forge_objects.unet.patch_model()
|
480 |
+
|
481 |
+
elif self.active:
|
482 |
+
if self.starts and params.sampling_step == 0:
|
483 |
+
for key, step_te_u in self.starts.items():
|
484 |
+
setparams(self, key, 0, 0, [])
|
485 |
+
#print("\nstart 0", self, key, 0, 0, [])
|
486 |
+
|
487 |
+
if self.starts:
|
488 |
+
sets = []
|
489 |
+
for key, step_te_u in self.starts.items():
|
490 |
+
step, te, u = step_te_u
|
491 |
+
if params.sampling_step > step - 2:
|
492 |
+
setparams(self, key, te, u, sets)
|
493 |
+
#print("\nstart", self, key, u, te, sets)
|
494 |
+
for key in sets:
|
495 |
+
if key in self.starts:
|
496 |
+
del self.starts[key]
|
497 |
+
|
498 |
+
if self.stops:
|
499 |
+
sets = []
|
500 |
+
for key, step in self.stops.items():
|
501 |
+
if params.sampling_step > step - 2:
|
502 |
+
setparams(self, key, 0, 0, sets)
|
503 |
+
#print("\nstop", self, key, 0, 0, sets)
|
504 |
+
for key in sets:
|
505 |
+
if key in self.stops:
|
506 |
+
del self.stops[key]
|
507 |
+
|
508 |
+
def before_process_batch(self, p, loraratios,useblocks,*args,**kwargs):
|
509 |
+
if useblocks:
|
510 |
+
resetmemory()
|
511 |
+
if not self.isnet: p.disable_extra_networks = False
|
512 |
+
global prompts
|
513 |
+
prompts = kwargs["prompts"].copy()
|
514 |
+
|
515 |
+
def process_batch(self, p, loraratios,useblocks,*args,**kwargs):
|
516 |
+
if useblocks:
|
517 |
+
if not self.isnet: p.disable_extra_networks = True
|
518 |
+
|
519 |
+
o_prompts = [p.prompt]
|
520 |
+
for prompt in prompts:
|
521 |
+
if "<lora" in prompt or "<lyco" in prompt:
|
522 |
+
o_prompts = prompts.copy()
|
523 |
+
if not self.isnet: loradealer(self, o_prompts ,self.lratios,self.elementals)
|
524 |
+
|
525 |
+
def postprocess(self, p, processed, presets,useblocks,xyzsetting,xtype,xmen,ytype,ymen,ztype,zmen,exmen,eymen,ecount,diffcol,thresh,revxy,elemental,elemsets,debug,*args):
|
526 |
+
if not useblocks:
|
527 |
+
return
|
528 |
+
lora = importer(self)
|
529 |
+
emb_db = sd_hijack.model_hijack.embedding_db
|
530 |
+
|
531 |
+
for net in lora.loaded_loras:
|
532 |
+
if hasattr(net,"bundle_embeddings"):
|
533 |
+
for emb_name, embedding in net.bundle_embeddings.items():
|
534 |
+
if embedding.loaded:
|
535 |
+
emb_db.register_embedding_by_name(None, shared.sd_model, emb_name)
|
536 |
+
|
537 |
+
lora.loaded_loras.clear()
|
538 |
+
|
539 |
+
if forge:
|
540 |
+
sd_models.model_data.get_sd_model().current_lora_hash = None
|
541 |
+
shared.sd_model.forge_objects_after_applying_lora.unet.unpatch_model()
|
542 |
+
shared.sd_model.forge_objects_after_applying_lora.clip.patcher.unpatch_model()
|
543 |
+
|
544 |
+
global lxyz,lzyx,xyelem
|
545 |
+
lxyz = lzyx = xyelem = ""
|
546 |
+
if debug:
|
547 |
+
print(self.log)
|
548 |
+
gc.collect()
|
549 |
+
|
550 |
+
def after_extra_networks_activate(self, p, presets,useblocks, *args, **kwargs):
|
551 |
+
if useblocks:
|
552 |
+
loradealer(self, kwargs["prompts"] ,self.lratios,self.elementals,kwargs["extra_network_data"])
|
553 |
+
|
554 |
+
def run(self,p,presets,useblocks,xyzsetting,xtype,xmen,ytype,ymen,ztype,zmen,exmen,eymen,ecount,diffcol,thresh,revxy,elemental,elemsets,debug):
|
555 |
+
if not useblocks:
|
556 |
+
return
|
557 |
+
self.__init__()
|
558 |
+
self.log["pass XYZ"] = True
|
559 |
+
self.log["XYZsets"] = xyzsetting
|
560 |
+
self.log["enable LBW"] = useblocks
|
561 |
+
|
562 |
+
if xyzsetting >0:
|
563 |
+
lorachecker(self)
|
564 |
+
lora = importer(self)
|
565 |
+
loraratios=presets.splitlines()
|
566 |
+
lratios={}
|
567 |
+
for l in loraratios:
|
568 |
+
if checkloadcond(l) : continue
|
569 |
+
l0=l.split(":",1)[0]
|
570 |
+
lratios[l0.strip()]=l.split(":",1)[1]
|
571 |
+
|
572 |
+
if "XYZ" in p.prompt:
|
573 |
+
base = lratios["XYZ"] if "XYZ" in lratios.keys() else "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"
|
574 |
+
else: return
|
575 |
+
|
576 |
+
for i, all in enumerate(["12ALL","17ALL","20ALL","26ALL"]):
|
577 |
+
if eymen == all:
|
578 |
+
eymen = ",".join(BLOCKIDS[i])
|
579 |
+
|
580 |
+
if xyzsetting > 1:
|
581 |
+
xmen,ymen = exmen,eymen
|
582 |
+
xtype,ytype = "values","ID"
|
583 |
+
ebase = xmen.split(",")[1]
|
584 |
+
ebase = [ebase.strip()]*26
|
585 |
+
base = ",".join(ebase)
|
586 |
+
ztype = ""
|
587 |
+
if ecount > 1:
|
588 |
+
ztype = "seed"
|
589 |
+
zmen = ",".join([str(random.randrange(4294967294)) for x in range(int(ecount))])
|
590 |
+
|
591 |
+
#ATYPES =["none","Block ID","values","seed","Base Weights"]
|
592 |
+
|
593 |
+
def dicedealer(am):
|
594 |
+
for i,a in enumerate(am):
|
595 |
+
if a =="-1": am[i] = str(random.randrange(4294967294))
|
596 |
+
print(f"the die was thrown : {am}")
|
597 |
+
|
598 |
+
if p.seed == -1: p.seed = str(random.randrange(4294967294))
|
599 |
+
|
600 |
+
#print(f"xs:{xmen},ys:{ymen},zs:{zmen}")
|
601 |
+
|
602 |
+
def adjuster(a,at):
|
603 |
+
if "none" in at:a = ""
|
604 |
+
a = [a.strip() for a in a.split(',')]
|
605 |
+
if "seed" in at:dicedealer(a)
|
606 |
+
return a
|
607 |
+
|
608 |
+
xs = adjuster(xmen,xtype)
|
609 |
+
ys = adjuster(ymen,ytype)
|
610 |
+
zs = adjuster(zmen,ztype)
|
611 |
+
|
612 |
+
ids = alpha =seed = ""
|
613 |
+
p.batch_size = 1
|
614 |
+
|
615 |
+
print(f"xs:{xs},ys:{ys},zs:{zs}")
|
616 |
+
|
617 |
+
images = []
|
618 |
+
|
619 |
+
def weightsdealer(alpha,ids,base):
|
620 |
+
#print(f"weights from : {base}")
|
621 |
+
ids = [z.strip() for z in ids.split(' ')]
|
622 |
+
weights_t = [w.strip() for w in base.split(',')]
|
623 |
+
blockid = BLOCKIDS[BLOCKNUMS.index(len(weights_t))]
|
624 |
+
if ids[0]!="NOT":
|
625 |
+
flagger=[False]*len(weights_t)
|
626 |
+
changer = True
|
627 |
+
else:
|
628 |
+
flagger=[True]*len(weights_t)
|
629 |
+
changer = False
|
630 |
+
for id in ids:
|
631 |
+
if id =="NOT":continue
|
632 |
+
if "-" in id:
|
633 |
+
it = [it.strip() for it in id.split('-')]
|
634 |
+
if blockid.index(it[1]) > blockid.index(it[0]):
|
635 |
+
flagger[blockid.index(it[0]):blockid.index(it[1])+1] = [changer]*(blockid.index(it[1])-blockid.index(it[0])+1)
|
636 |
+
else:
|
637 |
+
flagger[blockid.index(it[1]):blockid.index(it[0])+1] = [changer]*(blockid.index(it[0])-blockid.index(it[1])+1)
|
638 |
+
else:
|
639 |
+
flagger[blockid.index(id)] =changer
|
640 |
+
for i,f in enumerate(flagger):
|
641 |
+
if f:weights_t[i]=alpha
|
642 |
+
outext = ",".join(weights_t)
|
643 |
+
#print(f"weights changed: {outext}")
|
644 |
+
return outext
|
645 |
+
|
646 |
+
generatedbases=[]
|
647 |
+
def xyzdealer(a,at):
|
648 |
+
nonlocal ids,alpha,p,base,c_base,generatedbases
|
649 |
+
if "ID" in at:return
|
650 |
+
if "values" in at:alpha = a
|
651 |
+
if "seed" in at:
|
652 |
+
p.seed = int(a)
|
653 |
+
generatedbases=[]
|
654 |
+
if "Weights" in at:base =c_base = lratios[a]
|
655 |
+
if "elements" in at:
|
656 |
+
global xyelem
|
657 |
+
xyelem = a
|
658 |
+
|
659 |
+
def imagedupewatcher(baselist,basetocheck,currentiteration):
|
660 |
+
for idx,alreadygenerated in enumerate(baselist):
|
661 |
+
if (basetocheck == alreadygenerated):
|
662 |
+
# E.g., we already generated IND+OUTS and this is now OUTS+IND with identical weights.
|
663 |
+
baselist.insert(currentiteration-1, basetocheck)
|
664 |
+
return idx
|
665 |
+
return -1
|
666 |
+
|
667 |
+
def strThree(someNumber): # Returns 1.12345 as 1.123 and 1.0000 as 1
|
668 |
+
return format(someNumber, ".3f").rstrip('0').rstrip('.')
|
669 |
+
|
670 |
+
# Adds X and Y together using array addition.
|
671 |
+
# If both X and Y have a value in the same block then Y's is set to 0;
|
672 |
+
# both values are used due to both XY and YX being generated, but the diagonal then only show the first value.
|
673 |
+
# imagedupwatcher prevents duplicate images from being generated;
|
674 |
+
# when X and Y have non-overlapping blocks then the upper triangular images are identical to the lower ones.
|
675 |
+
def xyoriginalweightsdealer(x,y):
|
676 |
+
xweights = np.asarray(lratios[x].split(','), dtype=np.float32) # np array easier to add later
|
677 |
+
yweights = np.asarray(lratios[y].split(','), dtype=np.float32)
|
678 |
+
for idx,xval in np.ndenumerate(xweights):
|
679 |
+
yval = yweights[idx]
|
680 |
+
if xval != 0 and yval != 0:
|
681 |
+
yweights[idx] = 0
|
682 |
+
# Add xweights to yweights, round to 3 places,
|
683 |
+
# map floats to string with format of 3 decimals trailing zeroes and decimal stripped
|
684 |
+
baseListToStrings = list(map(strThree, np.around(np.add(xweights,yweights,),3).tolist()))
|
685 |
+
return ",".join(baseListToStrings)
|
686 |
+
|
687 |
+
grids = []
|
688 |
+
images =[]
|
689 |
+
|
690 |
+
totalcount = len(xs)*len(ys)*len(zs) if xyzsetting < 2 else len(xs)*len(ys)*len(zs) //2 +1
|
691 |
+
shared.total_tqdm.updateTotal(totalcount)
|
692 |
+
xc = yc =zc = 0
|
693 |
+
state.job_count = totalcount
|
694 |
+
totalcount = len(xs)*len(ys)*len(zs)
|
695 |
+
c_base = base
|
696 |
+
|
697 |
+
for z in zs:
|
698 |
+
generatedbases=[]
|
699 |
+
images = []
|
700 |
+
yc = 0
|
701 |
+
xyzdealer(z,ztype)
|
702 |
+
for y in ys:
|
703 |
+
xc = 0
|
704 |
+
xyzdealer(y,ytype)
|
705 |
+
for x in xs:
|
706 |
+
xyzdealer(x,xtype)
|
707 |
+
if "Weights" in xtype and "Weights" in ytype:
|
708 |
+
c_base = xyoriginalweightsdealer(x,y)
|
709 |
+
else:
|
710 |
+
if "ID" in xtype:
|
711 |
+
if "values" in ytype:c_base = weightsdealer(y,x,base)
|
712 |
+
if "values" in ztype:c_base = weightsdealer(z,x,base)
|
713 |
+
if "ID" in ytype:
|
714 |
+
if "values" in xtype:c_base = weightsdealer(x,y,base)
|
715 |
+
if "values" in ztype:c_base = weightsdealer(z,y,base)
|
716 |
+
if "ID" in ztype:
|
717 |
+
if "values" in xtype:c_base = weightsdealer(x,z,base)
|
718 |
+
if "values" in ytype:c_base = weightsdealer(y,z,base)
|
719 |
+
|
720 |
+
iteration = len(xs)*len(ys)*zc + yc*len(xs) +xc +1
|
721 |
+
print(f"X:{xtype}, {x},Y: {ytype},{y}, Z:{ztype},{z}, base:{c_base} ({iteration}/{totalcount})")
|
722 |
+
|
723 |
+
dupe_index = imagedupewatcher(generatedbases,c_base,iteration)
|
724 |
+
if dupe_index > -1:
|
725 |
+
print(f"Skipping generation of duplicate base:{c_base}")
|
726 |
+
images.append(images[dupe_index].copy())
|
727 |
+
xc += 1
|
728 |
+
continue
|
729 |
+
|
730 |
+
global lxyz,lzyx
|
731 |
+
lxyz = c_base
|
732 |
+
|
733 |
+
cr_base = c_base.split(",")
|
734 |
+
cr_base_t=[]
|
735 |
+
for x in cr_base:
|
736 |
+
if not identifier(x):
|
737 |
+
cr_base_t.append(str(1-float(x)))
|
738 |
+
else:
|
739 |
+
cr_base_t.append(x)
|
740 |
+
lzyx = ",".join(cr_base_t)
|
741 |
+
|
742 |
+
if not(xc == 1 and not (yc ==0 ) and xyzsetting >1):
|
743 |
+
lora.loaded_loras.clear()
|
744 |
+
p.cached_c = [None,None]
|
745 |
+
p.cached_uc = [None,None]
|
746 |
+
p.cached_hr_c = [None, None]
|
747 |
+
p.cached_hr_uc = [None, None]
|
748 |
+
processed:Processed = process_images(p)
|
749 |
+
images.append(processed.images[0])
|
750 |
+
generatedbases.insert(iteration-1, c_base)
|
751 |
+
xc += 1
|
752 |
+
yc += 1
|
753 |
+
zc += 1
|
754 |
+
origin = loranames(processed.all_prompts) + ", "+ znamer(ztype,z,base)
|
755 |
+
images,xst,yst = effectivechecker(images,xs.copy(),ys.copy(),diffcol,thresh,revxy) if xyzsetting >1 else (images,xs.copy(),ys.copy())
|
756 |
+
grids.append(smakegrid(images,xst,yst,origin,p))
|
757 |
+
processed.images= grids
|
758 |
+
lora.loaded_loras.clear()
|
759 |
+
return processed
|
760 |
+
|
761 |
+
def identifier(char):
|
762 |
+
return char[0] in ["R", "U", "X"]
|
763 |
+
|
764 |
+
def znamer(at,a,base):
|
765 |
+
if "ID" in at:return f"Block : {a}"
|
766 |
+
if "values" in at:return f"value : {a}"
|
767 |
+
if "seed" in at:return f"seed : {a}"
|
768 |
+
if "Weights" in at:return f"original weights :\n {base}"
|
769 |
+
else: return ""
|
770 |
+
|
771 |
+
def loranames(all_prompts):
|
772 |
+
_, extra_network_data = extra_networks.parse_prompts(all_prompts[0:1])
|
773 |
+
calledloras = extra_network_data["lora"] if "lyco" not in extra_network_data.keys() else extra_network_data["lyco"]
|
774 |
+
names = ""
|
775 |
+
for called in calledloras:
|
776 |
+
if len(called.items) <3:continue
|
777 |
+
names += called.items[0]
|
778 |
+
return names
|
779 |
+
|
780 |
+
def lorachecker(self):
|
781 |
+
try:
|
782 |
+
import networks
|
783 |
+
self.isnet = True
|
784 |
+
self.layer_name = "network_layer_name"
|
785 |
+
except:
|
786 |
+
self.isnet = False
|
787 |
+
self.layer_name = "lora_layer_name"
|
788 |
+
try:
|
789 |
+
import lora
|
790 |
+
self.islora = True
|
791 |
+
except:
|
792 |
+
pass
|
793 |
+
try:
|
794 |
+
import lycoris
|
795 |
+
self.islyco = True
|
796 |
+
except:
|
797 |
+
pass
|
798 |
+
self.onlyco = (not self.islora) and self.islyco
|
799 |
+
self.isxl = hasattr(shared.sd_model,"conditioner")
|
800 |
+
|
801 |
+
self.log["isnet"] = self.isnet
|
802 |
+
self.log["isxl"] = self.isxl
|
803 |
+
self.log["islora"] = self.islora
|
804 |
+
|
805 |
+
def resetmemory():
|
806 |
+
try:
|
807 |
+
import networks as nets
|
808 |
+
nets.networks_in_memory = {}
|
809 |
+
gc.collect()
|
810 |
+
|
811 |
+
except:
|
812 |
+
pass
|
813 |
+
|
814 |
+
def importer(self):
|
815 |
+
if self.onlyco:
|
816 |
+
# lycorisモジュールを動的にインポート
|
817 |
+
lora_module = importlib.import_module("lycoris")
|
818 |
+
return lora_module
|
819 |
+
else:
|
820 |
+
# loraモジュールを動的にインポート
|
821 |
+
lora_module = importlib.import_module("lora")
|
822 |
+
return lora_module
|
823 |
+
|
824 |
+
def loradealer(self, prompts,lratios,elementals, extra_network_data = None):
|
825 |
+
if extra_network_data is None:
|
826 |
+
_, extra_network_data = extra_networks.parse_prompts(prompts)
|
827 |
+
moduletypes = extra_network_data.keys()
|
828 |
+
|
829 |
+
for ltype in moduletypes:
|
830 |
+
lorans = []
|
831 |
+
lorars = []
|
832 |
+
te_multipliers = []
|
833 |
+
unet_multipliers = []
|
834 |
+
elements = []
|
835 |
+
starts = []
|
836 |
+
stops = []
|
837 |
+
fparams = []
|
838 |
+
load = False
|
839 |
+
go_lbw = False
|
840 |
+
|
841 |
+
if not (ltype == "lora" or ltype == "lyco") : continue
|
842 |
+
for called in extra_network_data[ltype]:
|
843 |
+
items = called.items
|
844 |
+
setnow = False
|
845 |
+
name = items[0]
|
846 |
+
te = syntaxdealer(items,"te=",1)
|
847 |
+
unet = syntaxdealer(items,"unet=",2)
|
848 |
+
te,unet = multidealer(te,unet)
|
849 |
+
|
850 |
+
weights = syntaxdealer(items,"lbw=",2) if syntaxdealer(items,"lbw=",2) is not None else syntaxdealer(items,"w=",2)
|
851 |
+
elem = syntaxdealer(items, "lbwe=",3)
|
852 |
+
start = syntaxdealer(items,"start=",None)
|
853 |
+
stop = syntaxdealer(items,"stop=",None)
|
854 |
+
start, stop = stepsdealer(syntaxdealer(items,"step=",None), start, stop)
|
855 |
+
|
856 |
+
if weights is not None and (weights in lratios or any(weights.count(",") == x - 1 for x in BLOCKNUMS)):
|
857 |
+
wei = lratios[weights] if weights in lratios else weights
|
858 |
+
ratios = [w.strip() for w in wei.split(",")]
|
859 |
+
for i,r in enumerate(ratios):
|
860 |
+
if r =="R":
|
861 |
+
ratios[i] = round(random.random(),3)
|
862 |
+
elif r == "U":
|
863 |
+
ratios[i] = round(random.uniform(-0.5,1.5),3)
|
864 |
+
elif r[0] == "X":
|
865 |
+
base = syntaxdealer(items,"x=", 3) if len(items) >= 4 else 1
|
866 |
+
ratios[i] = getinheritedweight(base, r)
|
867 |
+
else:
|
868 |
+
ratios[i] = float(r)
|
869 |
+
|
870 |
+
if len(ratios) != 26:
|
871 |
+
ratios = to26(ratios)
|
872 |
+
setnow = True
|
873 |
+
else:
|
874 |
+
ratios = [1] * 26
|
875 |
+
|
876 |
+
if elem in elementals:
|
877 |
+
setnow = True
|
878 |
+
elem = elementals[elem]
|
879 |
+
else:
|
880 |
+
elem = ""
|
881 |
+
|
882 |
+
if setnow:
|
883 |
+
print(f"LoRA Block weight ({ltype}): {name}: (Te:{te},Unet:{unet}) x {ratios}")
|
884 |
+
go_lbw = True
|
885 |
+
fparams.append([unet,ratios,elem])
|
886 |
+
settolist([lorans,te_multipliers,unet_multipliers,lorars,elements,starts,stops],[name,te,unet,ratios,elem,start,stop])
|
887 |
+
|
888 |
+
if start:
|
889 |
+
self.starts[name] = [int(start),te,unet]
|
890 |
+
self.log["starts"] = load = True
|
891 |
+
|
892 |
+
if stop:
|
893 |
+
self.stops[name] = int(stop)
|
894 |
+
self.log["stops"] = load = True
|
895 |
+
|
896 |
+
self.startsf = [int(s) if s is not None else None for s in starts]
|
897 |
+
self.stopsf = [int(s) if s is not None else None for s in stops]
|
898 |
+
self.uf = unet_multipliers
|
899 |
+
self.lf = lorars
|
900 |
+
self.ef = elements
|
901 |
+
|
902 |
+
if self.isnet: ltype = "nets"
|
903 |
+
if forge: ltype = "forge"
|
904 |
+
if go_lbw or load: load_loras_blocks(self, lorans,lorars,te_multipliers,unet_multipliers,elements,ltype, starts=starts)
|
905 |
+
|
906 |
+
def stepsdealer(step, start, stop):
|
907 |
+
if step is None or "-" not in step:
|
908 |
+
return start, stop
|
909 |
+
return step.split("-")
|
910 |
+
|
911 |
+
def settolist(ls,vs):
|
912 |
+
for l, v in zip(ls,vs):
|
913 |
+
l.append(v)
|
914 |
+
|
915 |
+
def syntaxdealer(items,target,index): #type "unet=", "x=", "lwbe="
|
916 |
+
for item in items:
|
917 |
+
if target in item:
|
918 |
+
return item.replace(target,"")
|
919 |
+
if index is None or index + 1> len(items): return None
|
920 |
+
if "=" in items[index]:return None
|
921 |
+
return items[index] if "@" not in items[index] else 1
|
922 |
+
|
923 |
+
def isfloat(t):
|
924 |
+
try:
|
925 |
+
float(t)
|
926 |
+
return True
|
927 |
+
except:
|
928 |
+
return False
|
929 |
+
|
930 |
+
def multidealer(t, u):
|
931 |
+
if t is None and u is None:
|
932 |
+
return 1,1
|
933 |
+
elif t is None:
|
934 |
+
return float(u),float(u)
|
935 |
+
elif u is None:
|
936 |
+
return float(t), float(t)
|
937 |
+
else:
|
938 |
+
return float(t),float(u)
|
939 |
+
|
940 |
+
re_inherited_weight = re.compile(r"X([+-])?([\d.]+)?")
|
941 |
+
|
942 |
+
def getinheritedweight(weight, offset):
|
943 |
+
match = re_inherited_weight.search(offset)
|
944 |
+
if match.group(1) == "+":
|
945 |
+
return float(weight) + float(match.group(2))
|
946 |
+
elif match.group(1) == "-":
|
947 |
+
return float(weight) - float(match.group(2))
|
948 |
+
else:
|
949 |
+
return float(weight)
|
950 |
+
|
951 |
+
def load_loras_blocks(self, names, lwei,te,unet,elements,ltype = "lora", starts = None):
|
952 |
+
oldnew=[]
|
953 |
+
if "lora" == ltype:
|
954 |
+
lora = importer(self)
|
955 |
+
self.lora = lora.loaded_loras
|
956 |
+
for loaded in lora.loaded_loras:
|
957 |
+
for n, name in enumerate(names):
|
958 |
+
if name == loaded.name:
|
959 |
+
if lwei[n] == [1] * 26 and elements[n] == "": continue
|
960 |
+
lbw(loaded,lwei[n],elements[n])
|
961 |
+
setall(loaded,te[n],unet[n])
|
962 |
+
newname = loaded.name +"_in_LBW_"+ str(round(random.random(),3))
|
963 |
+
oldname = loaded.name
|
964 |
+
loaded.name = newname
|
965 |
+
oldnew.append([oldname,newname])
|
966 |
+
|
967 |
+
elif "lyco" == ltype:
|
968 |
+
import lycoris as lycomo
|
969 |
+
self.lycoris = lycomo.loaded_lycos
|
970 |
+
for loaded in lycomo.loaded_lycos:
|
971 |
+
for n, name in enumerate(names):
|
972 |
+
if name == loaded.name:
|
973 |
+
lbw(loaded,lwei[n],elements[n])
|
974 |
+
setall(loaded,te[n],unet[n])
|
975 |
+
|
976 |
+
elif "nets" == ltype:
|
977 |
+
import networks as nets
|
978 |
+
self.networks = nets.loaded_networks
|
979 |
+
for loaded in nets.loaded_networks:
|
980 |
+
for n, name in enumerate(names):
|
981 |
+
if name == loaded.name:
|
982 |
+
lbw(loaded,lwei[n],elements[n])
|
983 |
+
setall(loaded,te[n],unet[n])
|
984 |
+
|
985 |
+
elif "forge" == ltype:
|
986 |
+
lbwf(te, unet, lwei, elements, starts)
|
987 |
+
|
988 |
+
try:
|
989 |
+
import lora_ctl_network as ctl
|
990 |
+
for old,new in oldnew:
|
991 |
+
if old in ctl.lora_weights.keys():
|
992 |
+
ctl.lora_weights[new] = ctl.lora_weights[old]
|
993 |
+
except:
|
994 |
+
pass
|
995 |
+
|
996 |
+
def setall(m,te,unet):
|
997 |
+
m.name = m.name + "_in_LBW_"+ str(round(random.random(),3))
|
998 |
+
m.te_multiplier = te
|
999 |
+
m.unet_multiplier = unet
|
1000 |
+
m.multiplier = unet
|
1001 |
+
|
1002 |
+
def smakegrid(imgs,xs,ys,currentmodel,p):
|
1003 |
+
ver_texts = [[images.GridAnnotation(y)] for y in ys]
|
1004 |
+
hor_texts = [[images.GridAnnotation(x)] for x in xs]
|
1005 |
+
|
1006 |
+
w, h = imgs[0].size
|
1007 |
+
grid = Image.new('RGB', size=(len(xs) * w, len(ys) * h), color='black')
|
1008 |
+
|
1009 |
+
for i, img in enumerate(imgs):
|
1010 |
+
grid.paste(img, box=(i % len(xs) * w, i // len(xs) * h))
|
1011 |
+
|
1012 |
+
grid = images.draw_grid_annotations(grid,w, h, hor_texts, ver_texts)
|
1013 |
+
grid = draw_origin(grid, currentmodel,w*len(xs),h*len(ys),w)
|
1014 |
+
if opts.grid_save:
|
1015 |
+
images.save_image(grid, opts.outdir_txt2img_grids, "xy_grid", extension=opts.grid_format, prompt=p.prompt, seed=p.seed, grid=True, p=p)
|
1016 |
+
|
1017 |
+
return grid
|
1018 |
+
|
1019 |
+
def get_font(fontsize):
|
1020 |
+
fontpath = os.path.join(scriptpath, "Roboto-Regular.ttf")
|
1021 |
+
try:
|
1022 |
+
return ImageFont.truetype(opts.font or fontpath, fontsize)
|
1023 |
+
except Exception:
|
1024 |
+
return ImageFont.truetype(fontpath, fontsize)
|
1025 |
+
|
1026 |
+
def draw_origin(grid, text,width,height,width_one):
|
1027 |
+
grid_d= Image.new("RGB", (grid.width,grid.height), "white")
|
1028 |
+
grid_d.paste(grid,(0,0))
|
1029 |
+
|
1030 |
+
d= ImageDraw.Draw(grid_d)
|
1031 |
+
color_active = (0, 0, 0)
|
1032 |
+
fontsize = (width+height)//25
|
1033 |
+
fnt = get_font(fontsize)
|
1034 |
+
|
1035 |
+
if grid.width != width_one:
|
1036 |
+
while d.multiline_textsize(text, font=fnt)[0] > width_one*0.75 and fontsize > 0:
|
1037 |
+
fontsize -=1
|
1038 |
+
fnt = get_font(fontsize)
|
1039 |
+
d.multiline_text((0,0), text, font=fnt, fill=color_active,align="center")
|
1040 |
+
return grid_d
|
1041 |
+
|
1042 |
+
def newrun(p, *args):
|
1043 |
+
script_index = args[0]
|
1044 |
+
|
1045 |
+
if args[0] ==0:
|
1046 |
+
script = None
|
1047 |
+
for obj in scripts.scripts_txt2img.alwayson_scripts:
|
1048 |
+
if "lora_block_weight" in obj.filename:
|
1049 |
+
script = obj
|
1050 |
+
script_args = args[script.args_from:script.args_to]
|
1051 |
+
else:
|
1052 |
+
script = scripts.scripts_txt2img.selectable_scripts[script_index-1]
|
1053 |
+
|
1054 |
+
if script is None:
|
1055 |
+
return None
|
1056 |
+
|
1057 |
+
script_args = args[script.args_from:script.args_to]
|
1058 |
+
|
1059 |
+
processed = script.run(p, *script_args)
|
1060 |
+
|
1061 |
+
shared.total_tqdm.clear()
|
1062 |
+
|
1063 |
+
return processed
|
1064 |
+
|
1065 |
+
registerd = False
|
1066 |
+
|
1067 |
+
def register():
|
1068 |
+
global registerd
|
1069 |
+
registerd = True
|
1070 |
+
for obj in scripts.scripts_txt2img.alwayson_scripts:
|
1071 |
+
if "lora_block_weight" in obj.filename:
|
1072 |
+
if obj not in scripts.scripts_txt2img.selectable_scripts:
|
1073 |
+
scripts.scripts_txt2img.selectable_scripts.append(obj)
|
1074 |
+
scripts.scripts_txt2img.titles.append("LoRA Block Weight")
|
1075 |
+
for obj in scripts.scripts_img2img.alwayson_scripts:
|
1076 |
+
if "lora_block_weight" in obj.filename:
|
1077 |
+
if obj not in scripts.scripts_img2img.selectable_scripts:
|
1078 |
+
scripts.scripts_img2img.selectable_scripts.append(obj)
|
1079 |
+
scripts.scripts_img2img.titles.append("LoRA Block Weight")
|
1080 |
+
|
1081 |
+
def effectivechecker(imgs,ss,ls,diffcol,thresh,revxy):
|
1082 |
+
orig = imgs[1]
|
1083 |
+
imgs = imgs[::2]
|
1084 |
+
diffs = []
|
1085 |
+
outnum =[]
|
1086 |
+
|
1087 |
+
for img in imgs:
|
1088 |
+
abs_diff = cv2.absdiff(np.array(img) , np.array(orig))
|
1089 |
+
|
1090 |
+
abs_diff_t = cv2.threshold(abs_diff, int(thresh), 255, cv2.THRESH_BINARY)[1]
|
1091 |
+
res = abs_diff_t.astype(np.uint8)
|
1092 |
+
percentage = (np.count_nonzero(res) * 100)/ res.size
|
1093 |
+
if "white" in diffcol: abs_diff = cv2.bitwise_not(abs_diff)
|
1094 |
+
outnum.append(percentage)
|
1095 |
+
|
1096 |
+
abs_diff = Image.fromarray(abs_diff)
|
1097 |
+
|
1098 |
+
diffs.append(abs_diff)
|
1099 |
+
|
1100 |
+
outs = []
|
1101 |
+
for i in range(len(ls)):
|
1102 |
+
ls[i] = ls[i] + "\n Diff : " + str(round(outnum[i],3)) + "%"
|
1103 |
+
|
1104 |
+
if not revxy:
|
1105 |
+
for diff,img in zip(diffs,imgs):
|
1106 |
+
outs.append(diff)
|
1107 |
+
outs.append(img)
|
1108 |
+
outs.append(orig)
|
1109 |
+
ss = ["diff",ss[0],"source"]
|
1110 |
+
return outs,ss,ls
|
1111 |
+
else:
|
1112 |
+
outs = [orig]*len(diffs) + imgs + diffs
|
1113 |
+
ss = ["source",ss[0],"diff"]
|
1114 |
+
return outs,ls,ss
|
1115 |
+
|
1116 |
+
def lbw(lora,lwei,elemental):
|
1117 |
+
elemental = elemental.split(",")
|
1118 |
+
errormodules = []
|
1119 |
+
for key in lora.modules.keys():
|
1120 |
+
ratio, errormodule = ratiodealer(key, lwei, elemental)
|
1121 |
+
if errormodule:
|
1122 |
+
errormodules.append(errormodule)
|
1123 |
+
|
1124 |
+
ltype = type(lora.modules[key]).__name__
|
1125 |
+
set = False
|
1126 |
+
if ltype in LORAANDSOON.keys():
|
1127 |
+
if "OFT" not in ltype:
|
1128 |
+
setattr(lora.modules[key],LORAANDSOON[ltype],torch.nn.Parameter(getattr(lora.modules[key],LORAANDSOON[ltype]) * ratio))
|
1129 |
+
else:
|
1130 |
+
setattr(lora.modules[key],LORAANDSOON[ltype],getattr(lora.modules[key],LORAANDSOON[ltype]) * ratio)
|
1131 |
+
set = True
|
1132 |
+
else:
|
1133 |
+
if hasattr(lora.modules[key],"up_model"):
|
1134 |
+
lora.modules[key].up_model.weight= torch.nn.Parameter(lora.modules[key].up_model.weight *ratio)
|
1135 |
+
#print("LoRA using LoCON")
|
1136 |
+
set = True
|
1137 |
+
else:
|
1138 |
+
lora.modules[key].up.weight= torch.nn.Parameter(lora.modules[key].up.weight *ratio)
|
1139 |
+
#print("LoRA")
|
1140 |
+
set = True
|
1141 |
+
if not set :
|
1142 |
+
print("unkwon LoRA")
|
1143 |
+
|
1144 |
+
if len(errormodules) > 0:
|
1145 |
+
print(errormodules)
|
1146 |
+
return lora
|
1147 |
+
|
1148 |
+
LORAS = ["lora", "loha", "lokr"]
|
1149 |
+
|
1150 |
+
def lbwf(mt, mu, lwei, elemental, starts):
|
1151 |
+
for key, vals in shared.sd_model.forge_objects_after_applying_lora.unet.patches.items():
|
1152 |
+
n_vals = []
|
1153 |
+
errormodules = []
|
1154 |
+
lvals = [val for val in vals if val[1][0] in LORAS]
|
1155 |
+
for v, m, l, e ,s in zip(lvals, mu, lwei, elemental, starts):
|
1156 |
+
ratio, errormodule = ratiodealer(key.replace(".","_"), l, e)
|
1157 |
+
n_vals.append((ratio * m if s is None else 0, *v[1:]))
|
1158 |
+
if errormodule:errormodules.append(errormodule)
|
1159 |
+
shared.sd_model.forge_objects_after_applying_lora.unet.patches[key] = n_vals
|
1160 |
+
|
1161 |
+
for key, vals in shared.sd_model.forge_objects_after_applying_lora.clip.patcher.patches.items():
|
1162 |
+
n_vals = []
|
1163 |
+
lvals = [val for val in vals if val[1][0] in LORAS]
|
1164 |
+
for v, m, l, e in zip(lvals, mt, lwei, elemental):
|
1165 |
+
ratio, errormodule = ratiodealer(key.replace(".","_"), l, e)
|
1166 |
+
n_vals.append((ratio * m, *v[1:]))
|
1167 |
+
if errormodule:errormodules.append(errormodule)
|
1168 |
+
shared.sd_model.forge_objects_after_applying_lora.clip.patcher.patches[key] = n_vals
|
1169 |
+
|
1170 |
+
if len(errormodules) > 0:
|
1171 |
+
print("Unknown modules:",errormodules)
|
1172 |
+
|
1173 |
+
def ratiodealer(key, lwei, elemental):
|
1174 |
+
ratio = 1
|
1175 |
+
picked = False
|
1176 |
+
errormodules = []
|
1177 |
+
currentblock = 0
|
1178 |
+
|
1179 |
+
for i,block in enumerate(BLOCKS):
|
1180 |
+
if block in key:
|
1181 |
+
if i == 26 or i == 27:
|
1182 |
+
i = 0
|
1183 |
+
ratio = lwei[i]
|
1184 |
+
picked = True
|
1185 |
+
currentblock = i
|
1186 |
+
|
1187 |
+
if not picked:
|
1188 |
+
errormodules.append(key)
|
1189 |
+
|
1190 |
+
if len(elemental) > 0:
|
1191 |
+
skey = key + BLOCKID26[currentblock]
|
1192 |
+
for d in elemental:
|
1193 |
+
if d.count(":") != 2 :continue
|
1194 |
+
dbs,dws,dr = (hyphener(d.split(":")[0]),d.split(":")[1],d.split(":")[2])
|
1195 |
+
dbs,dws = (dbs.split(" "), dws.split(" "))
|
1196 |
+
dbn,dbs = (True,dbs[1:]) if dbs[0] == "NOT" else (False,dbs)
|
1197 |
+
dwn,dws = (True,dws[1:]) if dws[0] == "NOT" else (False,dws)
|
1198 |
+
flag = dbn
|
1199 |
+
for db in dbs:
|
1200 |
+
if db in skey:
|
1201 |
+
flag = not dbn
|
1202 |
+
if flag:flag = dwn
|
1203 |
+
else:continue
|
1204 |
+
for dw in dws:
|
1205 |
+
if dw in skey:
|
1206 |
+
flag = not dwn
|
1207 |
+
if flag:
|
1208 |
+
dr = float(dr)
|
1209 |
+
if princ :print(dbs,dws,key,dr)
|
1210 |
+
ratio = dr
|
1211 |
+
|
1212 |
+
return ratio, errormodules
|
1213 |
+
|
1214 |
+
LORAANDSOON = {
|
1215 |
+
"LoraHadaModule" : "w1a",
|
1216 |
+
"LycoHadaModule" : "w1a",
|
1217 |
+
"NetworkModuleHada": "w1a",
|
1218 |
+
"FullModule" : "weight",
|
1219 |
+
"NetworkModuleFull": "weight",
|
1220 |
+
"IA3Module" : "w",
|
1221 |
+
"NetworkModuleIa3" : "w",
|
1222 |
+
"LoraKronModule" : "w1",
|
1223 |
+
"LycoKronModule" : "w1",
|
1224 |
+
"NetworkModuleLokr": "w1",
|
1225 |
+
"NetworkModuleGLora": "w1a",
|
1226 |
+
"NetworkModuleNorm": "w_norm",
|
1227 |
+
"NetworkModuleOFT": "scale"
|
1228 |
+
}
|
1229 |
+
|
1230 |
+
def hyphener(t):
|
1231 |
+
t = t.split(" ")
|
1232 |
+
for i,e in enumerate(t):
|
1233 |
+
if "-" in e:
|
1234 |
+
e = e.split("-")
|
1235 |
+
if BLOCKID26.index(e[1]) > BLOCKID26.index(e[0]):
|
1236 |
+
t[i] = " ".join(BLOCKID26[BLOCKID26.index(e[0]):BLOCKID26.index(e[1])+1])
|
1237 |
+
else:
|
1238 |
+
t[i] = " ".join(BLOCKID26[BLOCKID26.index(e[1]):BLOCKID26.index(e[0])+1])
|
1239 |
+
return " ".join(t)
|
1240 |
+
|
1241 |
+
ELEMPRESETS="\
|
1242 |
+
ATTNDEEPON:IN05-OUT05:attn:1\n\n\
|
1243 |
+
ATTNDEEPOFF:IN05-OUT05:attn:0\n\n\
|
1244 |
+
PROJDEEPOFF:IN05-OUT05:proj:0\n\n\
|
1245 |
+
XYZ:::1"
|
1246 |
+
|
1247 |
+
def to26(ratios):
|
1248 |
+
ids = BLOCKIDS[BLOCKNUMS.index(len(ratios))]
|
1249 |
+
output = [0]*26
|
1250 |
+
for i, id in enumerate(ids):
|
1251 |
+
output[BLOCKID26.index(id)] = ratios[i]
|
1252 |
+
return output
|
1253 |
+
|
1254 |
+
def checkloadcond(l:str)->bool:
|
1255 |
+
# ここの条件分岐は読み込んだ行がBlock Waightの書式にあっているかを確認している。
|
1256 |
+
# [:]が含まれ、16個(LoRa)か25個(LyCORIS),11,19(XL),のカンマが含まれる形式であるうえ、
|
1257 |
+
# それがコメントアウト行(# foobar)でないことが求められている。
|
1258 |
+
# 逆に言うとコメントアウトしたいなら絶対"# "から始めることを要求している。
|
1259 |
+
|
1260 |
+
# This conditional branch is checking whether the loaded line conforms to the Block Weight format.
|
1261 |
+
# It is required that "[:]" is included, and the format contains either 16 commas (for LoRa) or 25 commas (for LyCORIS),
|
1262 |
+
# and it's not a comment line (e.g., "# foobar").
|
1263 |
+
# Conversely, if you want to comment out, it requires that it absolutely starts with "# ".
|
1264 |
+
res=(":" not in l) or (not any(l.count(",") == x - 1 for x in BLOCKNUMS)) or ("#" in l)
|
1265 |
+
#print("[debug]", res,repr(l))
|
1266 |
+
return res
|