mirror of
https://github.com/vladmandic/automatic
synced 2026-09-04 12:00:46 +02:00
Merge branch 'master' of https://github.com/vladmandic/automatic
This commit is contained in:
@@ -5,10 +5,9 @@
|
||||
Stuff to be fixed...
|
||||
|
||||
- ClipSkip not updated on read gen info
|
||||
- Usage of `sd_vae` in quick settings
|
||||
- Run VAE with hires at 1280
|
||||
- Make TensorFlow optional
|
||||
|
||||
- Transformers version
|
||||
- Move Restart Server from WebUI to Launch and reload modules
|
||||
|
||||
## Features
|
||||
|
||||
@@ -16,7 +15,6 @@ Stuff to be added...
|
||||
|
||||
- Add Gradio theme maker
|
||||
- Create new GitHub hooks/actions for CI/CD
|
||||
- Move Restart Server from WebUI to Launch and reload modules
|
||||
- Redo Extensions tab: see <https://vladmandic.github.io/sd-extension-manager/pages/extensions.html>
|
||||
- Stream-load models as option for slow storage
|
||||
- Autodetect nVidia and AMD: `nvidia-smi` vs `rocm-smi`
|
||||
@@ -58,11 +56,9 @@ Tech that can be integrated as part of the core workflow...
|
||||
|
||||
### Pending Code Updates
|
||||
|
||||
- fix VAE dtype
|
||||
should fix most issues with NaN or black images
|
||||
- add built-in Gradio themes
|
||||
- fix setup race conditions
|
||||
- reduce requirements
|
||||
- more AMD specific work
|
||||
- initial work on Apple platform support
|
||||
- additional PR merges
|
||||
- use samples format for live preview
|
||||
- identify race condition where generate locks up while fetching preview
|
||||
- use **Approx NN** for live preview
|
||||
- create default `styles.csv`
|
||||
- fix setup not installing `tensorflow` dependencies
|
||||
- update default git flags to reduce number of warnings
|
||||
|
||||
@@ -89,7 +89,7 @@ class UpscalerSwinIR(Upscaler):
|
||||
|
||||
with progress.open(filename, 'rb', description=f'Loading weights: [cyan]{filename}', auto_refresh=True) as f:
|
||||
pretrained_model = torch.load(filename)
|
||||
if params is not None:
|
||||
if params is not None and params in pretrained_model:
|
||||
model.load_state_dict(pretrained_model[params], strict=True)
|
||||
else:
|
||||
model.load_state_dict(pretrained_model, strict=True)
|
||||
|
||||
@@ -17,6 +17,7 @@ parser.add_argument("--lowram", action='store_true', help="Load checkpoint weigh
|
||||
parser.add_argument("--ckpt", type=str, default=sd_model_file, help="Path to checkpoint of stable diffusion model to load immediately",)
|
||||
parser.add_argument('--vae', type=str, help='Path to checkpoint of stable diffusion VAE model to load immediately', default=None)
|
||||
parser.add_argument("--data-dir", type=str, default=os.path.dirname(os.path.dirname(os.path.realpath(__file__))), help="Base path where all user data is stored")
|
||||
parser.add_argument("--models-dir", type=str, default="models", help="Nase path where all models are stored",)
|
||||
|
||||
parser.add_argument("--allow-code", action='store_true', help="Allow custom script execution")
|
||||
parser.add_argument("--share", action='store_true', help="Enable to make the UI accessible through Gradio site")
|
||||
@@ -43,6 +44,7 @@ parser.add_argument("--no-hashing", action='store_true', help="Disable sha256 ha
|
||||
parser.add_argument("--no-download-sd-model", action='store_true', help="Disable download of default model even if no model is found", default=False)
|
||||
parser.add_argument("--profile", action='store_true', help="Run profiler, default: %(default)s")
|
||||
parser.add_argument("--disable-queue", action='store_true', help="Disable Gradio queues and force use of HTTP instead of WebSockets, default: %(default)s")
|
||||
parser.add_argument("--rollback-vae", action='store_true', help="trying to roll back vae when produced nan image, need to enable nan check", default=False)
|
||||
parser.add_argument("--token-merging", action='store_true', help="Provides speed and memory improvements by merging redundant tokens. This has a more pronounced effect on higher resolutions.", default=False)
|
||||
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import io
|
||||
import os
|
||||
import re
|
||||
|
||||
from PIL import Image
|
||||
import gradio as gr
|
||||
from modules.paths import data_path
|
||||
from modules import shared, ui_tempdir, script_callbacks
|
||||
from PIL import Image
|
||||
|
||||
re_param_code = r'\s*([\w ]+):\s*("(?:\\"[^,]|\\"|\\|[^\"])+"|[^,]*)(?:,|$)'
|
||||
re_param = re.compile(re_param_code)
|
||||
@@ -251,7 +251,7 @@ Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model
|
||||
lines.append(lastline)
|
||||
lastline = ''
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
for _i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
if line.startswith("Negative prompt:"):
|
||||
done_with_prompt = True
|
||||
@@ -382,6 +382,8 @@ def connect_paste(button, paste_fields, input_comp, override_settings_component,
|
||||
if os.path.exists(filename):
|
||||
with open(filename, "r", encoding="utf8") as file:
|
||||
prompt = file.read()
|
||||
else:
|
||||
prompt = ''
|
||||
|
||||
params = parse_generation_parameters(prompt)
|
||||
script_callbacks.infotext_pasted_callback(prompt, params)
|
||||
|
||||
@@ -15,7 +15,6 @@ parser_pre.add_argument("--data-dir", type=str, default=os.path.dirname(os.path.
|
||||
parser_pre.add_argument("--models-dir", type=str, default="models", help="base path where all models are stored",)
|
||||
cmd_opts_pre = parser_pre.parse_known_args()[0]
|
||||
data_path = cmd_opts_pre.data_dir
|
||||
|
||||
models_path = os.path.join(data_path, cmd_opts_pre.models_dir)
|
||||
extensions_dir = os.path.join(data_path, "extensions")
|
||||
extensions_builtin_dir = os.path.join(script_path, "extensions-builtin")
|
||||
|
||||
+15
-4
@@ -442,9 +442,8 @@ def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, see
|
||||
|
||||
|
||||
def decode_first_stage(model, x):
|
||||
with devices.autocast(disable=x.dtype == devices.dtype_vae):
|
||||
with devices.autocast(disable = x.dtype==devices.dtype_vae):
|
||||
x = model.decode_first_stage(x)
|
||||
|
||||
return x
|
||||
|
||||
|
||||
@@ -690,8 +689,20 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
samples_ddim = p.sample(conditioning=c, unconditional_conditioning=uc, seeds=seeds, subseeds=subseeds, subseed_strength=p.subseed_strength, prompts=prompts)
|
||||
|
||||
x_samples_ddim = [decode_first_stage(p.sd_model, samples_ddim[i:i+1].to(dtype=devices.dtype_vae))[0].cpu() for i in range(samples_ddim.size(0))]
|
||||
for x in x_samples_ddim:
|
||||
devices.test_for_nans(x, "vae")
|
||||
try:
|
||||
for x in x_samples_ddim:
|
||||
devices.test_for_nans(x, "vae")
|
||||
except devices.NansException as e:
|
||||
if not shared.cmd_opts.no_half and not shared.cmd_opts.no_half_vae and shared.cmd_opts.rollback_vae:
|
||||
print('\nA tensor with all NaNs was produced in VAE, try converting to bf16.')
|
||||
devices.dtype_vae = torch.bfloat16
|
||||
vae_file, vae_source = sd_vae.resolve_vae(p.sd_model.sd_model_checkpoint)
|
||||
sd_vae.load_vae(p.sd_model, vae_file, vae_source)
|
||||
x_samples_ddim = [decode_first_stage(p.sd_model, samples_ddim[i:i+1].to(dtype=devices.dtype_vae))[0].cpu() for i in range(samples_ddim.size(0))]
|
||||
for x in x_samples_ddim:
|
||||
devices.test_for_nans(x, "vae")
|
||||
else:
|
||||
raise e
|
||||
|
||||
x_samples_ddim = torch.stack(x_samples_ddim).float()
|
||||
x_samples_ddim = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
|
||||
|
||||
+7
-22
@@ -1,11 +1,7 @@
|
||||
import base64
|
||||
import io
|
||||
import time
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from modules.shared import opts
|
||||
|
||||
from pydantic import BaseModel, Field # pylint: disable=no-name-in-module
|
||||
import modules.shared as shared
|
||||
|
||||
|
||||
@@ -15,18 +11,15 @@ finished_tasks = []
|
||||
|
||||
|
||||
def start_task(id_task):
|
||||
global current_task
|
||||
|
||||
global current_task # pylint: disable=global-statement
|
||||
current_task = id_task
|
||||
pending_tasks.pop(id_task, None)
|
||||
|
||||
|
||||
def finish_task(id_task):
|
||||
global current_task
|
||||
|
||||
global current_task # pylint: disable=global-statement
|
||||
if current_task == id_task:
|
||||
current_task = None
|
||||
|
||||
finished_tasks.append(id_task)
|
||||
if len(finished_tasks) > 16:
|
||||
finished_tasks.pop(0)
|
||||
@@ -60,39 +53,31 @@ def progressapi(req: ProgressRequest):
|
||||
active = req.id_task == current_task
|
||||
queued = req.id_task in pending_tasks
|
||||
completed = req.id_task in finished_tasks
|
||||
|
||||
if not active:
|
||||
return ProgressResponse(active=active, queued=queued, completed=completed, id_live_preview=-1, textinfo="In queue..." if queued else "Waiting...")
|
||||
|
||||
progress = 0
|
||||
|
||||
job_count, job_no = shared.state.job_count, shared.state.job_no
|
||||
sampling_steps, sampling_step = shared.state.sampling_steps, shared.state.sampling_step
|
||||
|
||||
if job_count > 0:
|
||||
progress += job_no / job_count
|
||||
if sampling_steps > 0 and job_count > 0:
|
||||
progress += 1 / job_count * sampling_step / sampling_steps
|
||||
|
||||
progress = min(progress, 1)
|
||||
|
||||
elapsed_since_start = time.time() - shared.state.time_start
|
||||
predicted_duration = elapsed_since_start / progress if progress > 0 else None
|
||||
eta = predicted_duration - elapsed_since_start if predicted_duration is not None else None
|
||||
|
||||
id_live_preview = req.id_live_preview
|
||||
shared.state.set_current_image()
|
||||
if opts.live_previews_enable and shared.state.id_live_preview != req.id_live_preview:
|
||||
if shared.opts.live_previews_enable and shared.state.id_live_preview != req.id_live_preview:
|
||||
image = shared.state.current_image
|
||||
if image is not None:
|
||||
buffered = io.BytesIO()
|
||||
image.save(buffered, format="png")
|
||||
live_preview = 'data:image/png;base64,' + base64.b64encode(buffered.getvalue()).decode("ascii")
|
||||
fmt = 'jpeg' if shared.opts.samples_format == 'jpg' else shared.opts.samples_format
|
||||
image.save(buffered, format=fmt)
|
||||
live_preview = f'data:image/{fmt};base64,{base64.b64encode(buffered.getvalue()).decode("ascii")}'
|
||||
id_live_preview = shared.state.id_live_preview
|
||||
else:
|
||||
live_preview = None
|
||||
else:
|
||||
live_preview = None
|
||||
|
||||
return ProgressResponse(active=active, queued=queued, completed=completed, progress=progress, eta=eta, live_preview=live_preview, id_live_preview=id_live_preview, textinfo=shared.state.textinfo)
|
||||
|
||||
|
||||
@@ -28,14 +28,12 @@ approximation_indexes = {"Full": 0, "Approx NN": 1, "Approx cheap": 2}
|
||||
def single_sample_to_image(sample, approximation=None):
|
||||
if approximation is None:
|
||||
approximation = approximation_indexes.get(opts.show_progress_type, 0)
|
||||
|
||||
if approximation == 2:
|
||||
x_sample = sd_vae_approx.cheap_approximation(sample)
|
||||
elif approximation == 1:
|
||||
x_sample = sd_vae_approx.model()(sample.to(devices.device, devices.dtype).unsqueeze(0))[0].detach()
|
||||
else:
|
||||
x_sample = processing.decode_first_stage(shared.sd_model, sample.unsqueeze(0))[0]
|
||||
|
||||
x_sample = torch.clamp((x_sample + 1.0) / 2.0, min=0.0, max=1.0)
|
||||
x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
|
||||
x_sample = x_sample.astype(np.uint8)
|
||||
|
||||
@@ -197,6 +197,8 @@ def reload_vae_weights(sd_model=None, vae_file=unspecified):
|
||||
sd_model.to(devices.cpu)
|
||||
|
||||
sd_hijack.model_hijack.undo_hijack(sd_model)
|
||||
if shared.cmd_opts.rollback_vae and devices.dtype_vae == torch.bfloat16:
|
||||
devices.dtype_vae = torch.float16
|
||||
|
||||
load_vae(sd_model, vae_file, vae_source)
|
||||
|
||||
|
||||
+2
-6
@@ -112,7 +112,6 @@ class State:
|
||||
"sampling_step": self.sampling_step,
|
||||
"sampling_steps": self.sampling_steps,
|
||||
}
|
||||
|
||||
return obj
|
||||
|
||||
def begin(self):
|
||||
@@ -142,20 +141,17 @@ class State:
|
||||
"""sets self.current_image from self.current_latent if enough sampling steps have been made after the last call to this"""
|
||||
if not parallel_processing_allowed:
|
||||
return
|
||||
|
||||
if self.sampling_step - self.current_image_sampling_step >= opts.show_progress_every_n_steps and opts.live_previews_enable and opts.show_progress_every_n_steps != -1:
|
||||
self.do_set_current_image()
|
||||
|
||||
def do_set_current_image(self):
|
||||
if self.current_latent is None:
|
||||
return
|
||||
|
||||
import modules.sd_samplers # pylint: disable=W0621
|
||||
if opts.show_progress_grid:
|
||||
self.assign_current_image(modules.sd_samplers.samples_to_image_grid(self.current_latent))
|
||||
else:
|
||||
self.assign_current_image(modules.sd_samplers.sample_to_image(self.current_latent))
|
||||
|
||||
self.current_image_sampling_step = self.sampling_step
|
||||
|
||||
def assign_current_image(self, image):
|
||||
@@ -425,8 +421,8 @@ options_templates.update(options_section(('ui', "Live previews"), {
|
||||
"show_progressbar": OptionInfo(True, "Show progressbar"),
|
||||
"live_previews_enable": OptionInfo(True, "Show live previews of the created image"),
|
||||
"show_progress_grid": OptionInfo(True, "Show previews of all images generated in a batch as a grid"),
|
||||
"show_progress_every_n_steps": OptionInfo(-1, "Show new live preview image every N sampling steps. Set to -1 to show after completion of batch.", gr.Slider, {"minimum": -1, "maximum": 32, "step": 1}),
|
||||
"show_progress_type": OptionInfo("Full", "Image creation progress preview mode", gr.Radio, {"choices": ["Full", "Approx NN", "Approx cheap"]}),
|
||||
"show_progress_every_n_steps": OptionInfo(1, "Show new live preview image every N sampling steps. Set to -1 to show after completion of batch.", gr.Slider, {"minimum": -1, "maximum": 32, "step": 1}),
|
||||
"show_progress_type": OptionInfo("Approx NN", "Image creation progress preview mode", gr.Radio, {"choices": ["Full", "Approx NN", "Approx cheap"]}),
|
||||
"live_preview_content": OptionInfo("Combined", "Live preview subject", gr.Radio, {"choices": ["Combined", "Prompt", "Negative prompt"]}),
|
||||
"live_preview_refresh_period": OptionInfo(250, "Progressbar/preview update period, in milliseconds")
|
||||
}))
|
||||
|
||||
+3
-6
@@ -49,7 +49,8 @@ class StyleDatabase:
|
||||
self.styles.clear()
|
||||
|
||||
if not os.path.exists(self.path):
|
||||
return
|
||||
print(f'Creating styles database: {self.path}')
|
||||
self.save_styles(self.path)
|
||||
|
||||
with open(self.path, "r", encoding="utf-8-sig", newline='') as file:
|
||||
reader = csv.DictReader(file)
|
||||
@@ -79,9 +80,5 @@ class StyleDatabase:
|
||||
# and collections.NamedTuple has explicit documentation for accessing _fields. Same goes for _asdict()
|
||||
writer = csv.DictWriter(file, fieldnames=PromptStyle._fields)
|
||||
writer.writeheader()
|
||||
writer.writerows(style._asdict() for k, style in self.styles.items())
|
||||
|
||||
# Always keep a backup file around
|
||||
if os.path.exists(path):
|
||||
shutil.move(path, path + ".bak")
|
||||
writer.writerows(style._asdict() for k, style in self.styles.items())
|
||||
shutil.move(temp_path, path)
|
||||
|
||||
@@ -49,7 +49,6 @@ tqdm
|
||||
voluptuous
|
||||
yapf
|
||||
scikit-image
|
||||
|
||||
accelerate==0.18.0
|
||||
opencv-python==4.7.0.72
|
||||
diffusers==0.15.0
|
||||
|
||||
+50
-21
@@ -374,16 +374,19 @@ class Script(scripts.Script):
|
||||
with gr.Row():
|
||||
x_type = gr.Dropdown(label="X type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[1].label, type="index", elem_id=self.elem_id("x_type"))
|
||||
x_values = gr.Textbox(label="X values", lines=1, elem_id=self.elem_id("x_values"))
|
||||
x_values_dropdown = gr.Dropdown(label="X values",visible=False,multiselect=True,interactive=True)
|
||||
fill_x_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_x_tool_button", visible=False)
|
||||
|
||||
with gr.Row():
|
||||
y_type = gr.Dropdown(label="Y type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("y_type"))
|
||||
y_values = gr.Textbox(label="Y values", lines=1, elem_id=self.elem_id("y_values"))
|
||||
y_values_dropdown = gr.Dropdown(label="Y values",visible=False,multiselect=True,interactive=True)
|
||||
fill_y_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_y_tool_button", visible=False)
|
||||
|
||||
with gr.Row():
|
||||
z_type = gr.Dropdown(label="Z type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("z_type"))
|
||||
z_values = gr.Textbox(label="Z values", lines=1, elem_id=self.elem_id("z_values"))
|
||||
z_values_dropdown = gr.Dropdown(label="Z values",visible=False,multiselect=True,interactive=True)
|
||||
fill_z_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_z_tool_button", visible=False)
|
||||
|
||||
with gr.Row(variant="compact", elem_id="axis_options"):
|
||||
@@ -401,54 +404,74 @@ class Script(scripts.Script):
|
||||
swap_yz_axes_button = gr.Button(value="Swap Y/Z axes", elem_id="yz_grid_swap_axes_button")
|
||||
swap_xz_axes_button = gr.Button(value="Swap X/Z axes", elem_id="xz_grid_swap_axes_button")
|
||||
|
||||
def swap_axes(axis1_type, axis1_values, axis2_type, axis2_values):
|
||||
return self.current_axis_options[axis2_type].label, axis2_values, self.current_axis_options[axis1_type].label, axis1_values
|
||||
def swap_axes(axis1_type, axis1_values, axis1_values_dropdown, axis2_type, axis2_values, axis2_values_dropdown):
|
||||
return self.current_axis_options[axis2_type].label, axis2_values, axis2_values_dropdown, self.current_axis_options[axis1_type].label, axis1_values, axis1_values_dropdown
|
||||
|
||||
xy_swap_args = [x_type, x_values, y_type, y_values]
|
||||
xy_swap_args = [x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown]
|
||||
swap_xy_axes_button.click(swap_axes, inputs=xy_swap_args, outputs=xy_swap_args)
|
||||
yz_swap_args = [y_type, y_values, z_type, z_values]
|
||||
yz_swap_args = [y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown]
|
||||
swap_yz_axes_button.click(swap_axes, inputs=yz_swap_args, outputs=yz_swap_args)
|
||||
xz_swap_args = [x_type, x_values, z_type, z_values]
|
||||
xz_swap_args = [x_type, x_values, x_values_dropdown, z_type, z_values, z_values_dropdown]
|
||||
swap_xz_axes_button.click(swap_axes, inputs=xz_swap_args, outputs=xz_swap_args)
|
||||
|
||||
def fill(x_type):
|
||||
axis = self.current_axis_options[x_type]
|
||||
return ", ".join(axis.choices()) if axis.choices else gr.update()
|
||||
return axis.choices() if axis.choices else gr.update()
|
||||
|
||||
fill_x_button.click(fn=fill, inputs=[x_type], outputs=[x_values])
|
||||
fill_y_button.click(fn=fill, inputs=[y_type], outputs=[y_values])
|
||||
fill_z_button.click(fn=fill, inputs=[z_type], outputs=[z_values])
|
||||
fill_x_button.click(fn=fill, inputs=[x_type], outputs=[x_values_dropdown])
|
||||
fill_y_button.click(fn=fill, inputs=[y_type], outputs=[y_values_dropdown])
|
||||
fill_z_button.click(fn=fill, inputs=[z_type], outputs=[z_values_dropdown])
|
||||
|
||||
def select_axis(x_type):
|
||||
return gr.Button.update(visible=self.current_axis_options[x_type].choices is not None)
|
||||
def select_axis(axis_type,axis_values_dropdown):
|
||||
choices = self.current_axis_options[axis_type].choices
|
||||
has_choices = choices is not None
|
||||
current_values = axis_values_dropdown
|
||||
if has_choices:
|
||||
choices = choices()
|
||||
if isinstance(current_values,str):
|
||||
current_values = current_values.split(",")
|
||||
current_values = list(filter(lambda x: x in choices, current_values))
|
||||
return gr.Button.update(visible=has_choices),gr.Textbox.update(visible=not has_choices),gr.update(choices=choices if has_choices else None,visible=has_choices,value=current_values)
|
||||
|
||||
x_type.change(fn=select_axis, inputs=[x_type], outputs=[fill_x_button])
|
||||
y_type.change(fn=select_axis, inputs=[y_type], outputs=[fill_y_button])
|
||||
z_type.change(fn=select_axis, inputs=[z_type], outputs=[fill_z_button])
|
||||
x_type.change(fn=select_axis, inputs=[x_type,x_values_dropdown], outputs=[fill_x_button,x_values,x_values_dropdown])
|
||||
y_type.change(fn=select_axis, inputs=[y_type,y_values_dropdown], outputs=[fill_y_button,y_values,y_values_dropdown])
|
||||
z_type.change(fn=select_axis, inputs=[z_type,z_values_dropdown], outputs=[fill_z_button,z_values,z_values_dropdown])
|
||||
|
||||
def get_dropdown_update_from_params(axis,params):
|
||||
val_key = axis + " Values"
|
||||
vals = params.get(val_key,"")
|
||||
valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals))) if x]
|
||||
return gr.update(value = valslist)
|
||||
|
||||
self.infotext_fields = (
|
||||
(x_type, "X Type"),
|
||||
(x_values, "X Values"),
|
||||
(x_values_dropdown, lambda params:get_dropdown_update_from_params("X",params)),
|
||||
(y_type, "Y Type"),
|
||||
(y_values, "Y Values"),
|
||||
(y_values_dropdown, lambda params:get_dropdown_update_from_params("Y",params)),
|
||||
(z_type, "Z Type"),
|
||||
(z_values, "Z Values"),
|
||||
(z_values_dropdown, lambda params:get_dropdown_update_from_params("Z",params)),
|
||||
)
|
||||
|
||||
return [x_type, x_values, y_type, y_values, z_type, z_values, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, margin_size]
|
||||
return [x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, margin_size]
|
||||
|
||||
def run(self, p, x_type, x_values, y_type, y_values, z_type, z_values, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, margin_size):
|
||||
def run(self, p, x_type, x_values, x_values_dropdown, y_type, y_values, y_values_dropdown, z_type, z_values, z_values_dropdown, draw_legend, include_lone_images, include_sub_grids, no_fixed_seeds, margin_size):
|
||||
if not no_fixed_seeds:
|
||||
modules.processing.fix_seed(p)
|
||||
|
||||
if not opts.return_grid:
|
||||
p.batch_size = 1
|
||||
|
||||
def process_axis(opt, vals):
|
||||
def process_axis(opt, vals, vals_dropdown):
|
||||
if opt.label == 'Nothing':
|
||||
return [0]
|
||||
|
||||
valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals)))]
|
||||
if opt.choices is not None:
|
||||
valslist = vals_dropdown
|
||||
else:
|
||||
valslist = [x.strip() for x in chain.from_iterable(csv.reader(StringIO(vals))) if x]
|
||||
|
||||
if opt.type == int:
|
||||
valslist_ext = []
|
||||
@@ -506,13 +529,19 @@ class Script(scripts.Script):
|
||||
return valslist
|
||||
|
||||
x_opt = self.current_axis_options[x_type]
|
||||
xs = process_axis(x_opt, x_values)
|
||||
if x_opt.choices is not None:
|
||||
x_values = ",".join(x_values_dropdown)
|
||||
xs = process_axis(x_opt, x_values, x_values_dropdown)
|
||||
|
||||
y_opt = self.current_axis_options[y_type]
|
||||
ys = process_axis(y_opt, y_values)
|
||||
if y_opt.choices is not None:
|
||||
y_values = ",".join(y_values_dropdown)
|
||||
ys = process_axis(y_opt, y_values, y_values_dropdown)
|
||||
|
||||
z_opt = self.current_axis_options[z_type]
|
||||
zs = process_axis(z_opt, z_values)
|
||||
if z_opt.choices is not None:
|
||||
z_values = ",".join(z_values_dropdown)
|
||||
zs = process_axis(z_opt, z_values, z_values_dropdown)
|
||||
|
||||
# this could be moved to common code, but unlikely to be ever triggered anywhere else
|
||||
Image.MAX_IMAGE_PIXELS = None # disable check in Pillow and rely on check below to allow large custom image sizes
|
||||
|
||||
@@ -140,7 +140,7 @@ def update(folder):
|
||||
git('checkout master', folder)
|
||||
else:
|
||||
log.warning(f'Unknown branch for: {folder}')
|
||||
git('pull --rebase --autostash', folder)
|
||||
git('pull --autostash', folder)
|
||||
branch = git('branch', folder)
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ def check_torch():
|
||||
log.debug(f'Cannot install xformers package: {e}')
|
||||
try:
|
||||
tensorflow_package = os.environ.get('TENSORFLOW_PACKAGE', 'tensorflow==2.12.0')
|
||||
install(f'--no-deps {tensorflow_package}', ignore=True)
|
||||
install(tensorflow_package, ignore=True)
|
||||
except Exception as e:
|
||||
log.debug(f'Cannot install tensorflow package: {e}')
|
||||
|
||||
@@ -237,7 +237,6 @@ def install_packages():
|
||||
def install_repositories():
|
||||
def d(name):
|
||||
return os.path.join(os.path.dirname(__file__), 'repositories', name)
|
||||
|
||||
log.info('Installing repositories')
|
||||
os.makedirs(os.path.join(os.path.dirname(__file__), 'repositories'), exist_ok=True)
|
||||
stable_diffusion_repo = os.environ.get('STABLE_DIFFUSION_REPO', "https://github.com/Stability-AI/stablediffusion.git")
|
||||
@@ -263,7 +262,7 @@ def run_extension_installer(folder):
|
||||
if not os.path.isfile(path_installer):
|
||||
return
|
||||
try:
|
||||
log.debug(f"Running extension installer: {path_installer}")
|
||||
log.debug(f"Running extension installer: {folder} / {path_installer}")
|
||||
env = os.environ.copy()
|
||||
env['PYTHONPATH'] = os.path.abspath(".")
|
||||
result = subprocess.run(f'"{sys.executable}" "{path_installer}"', shell=True, env=env, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=folder)
|
||||
@@ -334,7 +333,7 @@ def install_submodules():
|
||||
|
||||
def ensure_package(pkg):
|
||||
try:
|
||||
import pkg
|
||||
import pkg # type: ignore
|
||||
except ImportError:
|
||||
install(pkg)
|
||||
|
||||
@@ -394,6 +393,13 @@ def check_extensions():
|
||||
|
||||
# check version of the main repo and optionally upgrade it
|
||||
def check_version():
|
||||
if not os.path.exists('.git'):
|
||||
log.error('Not a git repository')
|
||||
exit(1)
|
||||
status = git('status')
|
||||
if 'branch' not in status:
|
||||
log.error('Cannot get git repository status')
|
||||
exit(1)
|
||||
ver = git('log -1 --pretty=format:"%h %ad"')
|
||||
log.info(f'Version: {ver}')
|
||||
commit = git('rev-parse HEAD')
|
||||
@@ -420,17 +426,20 @@ def check_version():
|
||||
log.error('Error upgrading repository')
|
||||
else:
|
||||
log.info(f'Latest published version: {commits["commit"]["sha"]} {commits["commit"]["commit"]["author"]["date"]}')
|
||||
if not args.noupdate:
|
||||
log.info('Updating Wiki')
|
||||
try:
|
||||
update(os.path.join(os.path.dirname(__file__), "wiki"))
|
||||
update(os.path.join(os.path.dirname(__file__), "wiki", "origin-wiki"))
|
||||
except:
|
||||
log.error('Error updating wiki')
|
||||
except Exception as e:
|
||||
log.error(f'Failed to check version: {e} {commits}')
|
||||
|
||||
|
||||
def update_wiki():
|
||||
if not args.noupdate:
|
||||
log.info('Updating Wiki')
|
||||
try:
|
||||
update(os.path.join(os.path.dirname(__file__), "wiki"))
|
||||
update(os.path.join(os.path.dirname(__file__), "wiki", "origin-wiki"))
|
||||
except:
|
||||
log.error('Error updating wiki')
|
||||
|
||||
|
||||
# check if we can run setup in quick mode
|
||||
def check_timestamp():
|
||||
if not quick_allowed or not os.path.isfile('setup.log'):
|
||||
@@ -535,6 +544,7 @@ def run_setup():
|
||||
install_repositories()
|
||||
install_submodules()
|
||||
install_extensions()
|
||||
update_wiki()
|
||||
if errors == 0:
|
||||
log.debug(f'Setup complete without errors: {round(time.time())}')
|
||||
else:
|
||||
|
||||
@@ -64,7 +64,19 @@ else:
|
||||
server_name = "0.0.0.0" if cmd_opts.listen else None
|
||||
|
||||
|
||||
def check_rollback_vae():
|
||||
if shared.cmd_opts.rollback_vae:
|
||||
if version.parse(torch.__version__) < version.parse('2.1'):
|
||||
print("If your PyTorch version is lower than PyTorch 2.1, Rollback VAE will not work.")
|
||||
shared.cmd_opts.rollback_vae = False
|
||||
elif 0 < torch.cuda.get_device_capability()[0] < 8:
|
||||
print('Rollback VAE will not work because your device does not support it.')
|
||||
shared.cmd_opts.rollback_vae = False
|
||||
|
||||
|
||||
def initialize():
|
||||
check_rollback_vae()
|
||||
|
||||
extensions.list_extensions()
|
||||
startup_timer.record("extensions")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user