diff --git a/modules/sd_models.py b/modules/sd_models.py index e123a64b2..433d44558 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -676,7 +676,7 @@ def detect_pipeline(f: str, op: str = 'model', warning=True): return pipeline, guess -def set_diffuser_options(sd_model, vae, op: str): +def set_diffuser_options(sd_model, vae = None, op: str = 'model'): if sd_model is None: shared.log.warning(f'{op} is not loaded') return @@ -1049,6 +1049,9 @@ def set_diffuser_pipe(pipe, new_pipe_type): new_pipe.sd_model_hash = sd_model_hash new_pipe.has_accelerate = has_accelerate new_pipe.embedding_db = embedding_db + new_pipe.is_sdxl = True # pylint: disable=attribute-defined-outside-init # a1111 compatibility item + new_pipe.is_sd2 = False # pylint: disable=attribute-defined-outside-init + new_pipe.is_sd1 = False # pylint: disable=attribute-defined-outside-init shared.log.debug(f"Pipeline class change: original={pipe.__class__.__name__} target={new_pipe.__class__.__name__}") pipe = new_pipe return pipe diff --git a/scripts/demofusion.py b/scripts/demofusion.py index 0d655b413..d37552996 100644 --- a/scripts/demofusion.py +++ b/scripts/demofusion.py @@ -1267,12 +1267,6 @@ class Script(scripts.Script): scheduler=shared.sd_model.scheduler, force_zeros_for_empty_prompt=shared.opts.diffusers_force_zeros, ) - new_pipe.sd_checkpoint_info = shared.sd_model.sd_checkpoint_info # pylint: disable=attribute-defined-outside-init - new_pipe.sd_model_hash = shared.sd_model.sd_model_hash # pylint: disable=attribute-defined-outside-init - new_pipe.sd_model_checkpoint = shared.sd_model.sd_checkpoint_info.filename # pylint: disable=attribute-defined-outside-init - new_pipe.is_sdxl = True # pylint: disable=attribute-defined-outside-init - new_pipe.is_sd2 = False # pylint: disable=attribute-defined-outside-init - new_pipe.is_sd1 = False # pylint: disable=attribute-defined-outside-init shared.sd_model = new_pipe if not ((shared.opts.diffusers_model_cpu_offload or shared.cmd_opts.medvram) or (shared.opts.diffusers_seq_cpu_offload or shared.cmd_opts.lowvram)): shared.sd_model.to(shared.device) diff --git a/scripts/example.py b/scripts/example.py new file mode 100644 index 000000000..a8209492f --- /dev/null +++ b/scripts/example.py @@ -0,0 +1,132 @@ +import gradio as gr +from diffusers.pipelines import StableDiffusionPipeline, StableDiffusionXLPipeline # pylint: disable=unused-import +from modules import shared, scripts, processing, sd_models + +""" +Author:: +- Your details + +Credits: +- Link to original implementation and author + +Contributions: +- Submit a PR on SD.Next GitHub repo to be included in /scripts +- Before submitting a PR, make sure to test your script thoroughly and that it passes code quality checks + Lint rules are part of SD.Next CI/CD pipeline + > pip install ruff pylint + > ruff scripts/example.py + > pylint scriptts/example.py +""" + +## Config + +# script title +title = 'Example' + +# is script available in txt2img tab +txt2img = False + +# is script available in img2img tab +img2img = False + +# is pipeline ok to run in pure latent mode without implicit conversions +# recommended so entire ecosystem can be used as-is, but requires that latent is in format that sdnext can understand +# some pipelines may not support this, in which case set to false and pipeline will implicitly do things like vae encode/decode on its own +latent = True + +# class from which this pipeline is derived, most commonly 'StableDiffusionPipeline' or 'StableDiffusionXLPipeline' +pipeline_base = 'StableDiffusionPipeline' + +# class definition for this pipeline +# for built-in diffuser pipelines, simply import it from diffusers.pipelines above +# for example only, its set to same as base pipeline +# for community pipelines, copy class definition from community source code +# in which case only class definition code and required imports needs to be copied, not the entire source code +pipeline_class = StableDiffusionPipeline + +# pipeline args values are defined in ui method below, here we need to define their exact names +# they also have to be in the exact order as they are defined in ui +# note: variable names should be exactly as defined in pipeline_class.__call__ method +# if pipeline requires a param and its not provided, it will result in runtime error +# if you provide param that is not defined by pipeline, sdnext will strip it +params = ['test1', 'test2', 'test3', 'test4'] + + +### Script definition + +class Script(scripts.Script): + def title(self): + return title + + def show(self, is_img2img): + if shared.backend == shared.Backend.DIFFUSERS: + return img2img if is_img2img else txt2img + return False + + # Define UI for pipeline + def ui(self, _is_img2img): + ui_controls = [] + with gr.Row(): + ui_controls.append(gr.Slider(minimum=0, maximum=1, step=0.1, value=0.5, label="Test1")) + ui_controls.append(gr.Slider(minimum=0, maximum=10, step=1, value=5, label="Test2")) + with gr.Row(): + ui_controls.append(gr.Checkbox(label="Test3", value=True)) + with gr.Row(): + ui_controls.append(gr.Textbox(label="Test4", value="", placeholder="enter text here")) + with gr.Row(): + gr.HTML(' TypeError: StableDiffusionPipeline.__init__() missing 2 required positional arguments: 'safety_checker' and 'feature_extractor' + vae = shared.sd_model.vae, + text_encoder=shared.sd_model.text_encoder, + tokenizer=shared.sd_model.tokenizer, + unet=shared.sd_model.unet, + scheduler=shared.sd_model.scheduler, + safety_checker=shared.sd_model.safety_checker, + feature_extractor=shared.sd_model.feature_extractor, + ) + if not ((shared.opts.diffusers_model_cpu_offload or shared.cmd_opts.medvram) or (shared.opts.diffusers_seq_cpu_offload or shared.cmd_opts.lowvram)): + shared.sd_model.to(shared.device) # move pipeline if needed, but don't touch if its under automatic managment + sd_models.set_diffuser_options(shared.sd_model) # set all model options such as fp16, offload, etc. + + # if pipeline also needs a specific type, you can set it here, but not commonly needed + # shared.sd_model = sd_models.set_diffuser_pipe(shared.sd_model, sd_models.DiffusersTaskType.IMAGE_2_IMAGE) + + # prepare params + # all pipeline params go into p.task_args and are automatically handled by sdnext from there + for i in range(len(args)): + p.task_args[params[i]] = args[i] + + # you can also re-use existing params from `p` object if pipeline wants them, but under a different name + # for example, if pipeline expects 'image' param, but you want to use 'init_images' instead which is what img2img tab uses + # p.task_args['image'] = p.init_images[0] + + if not latent: + p.task_args['output_type'] = 'np' + shared.log.debug(f'{c}: args={p.task_args}') + + # if you need to run any preprocessing, this is the place to do it + + # run processing + processed: processing.Processed = processing.process_images(p) + + # if you need to run any postprocessing, this is the place to do it + # you dont need to handle saving, metadata, etc - sdnext will do it for you + + # restore original pipeline + shared.sd_model = orig_pipepeline + return processed diff --git a/wiki b/wiki index 06a89abd7..8bdd1dfb1 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 06a89abd7c2db4608f52b11c9fbf2186a2cfac2b +Subproject commit 8bdd1dfb154a1dd4f1cbafd85a60a5135b478bb9