diff --git a/.github/skills/analyze-model/SKILL.md b/.github/skills/analyze-model/SKILL.md index 2f9df43ff..02c0fed01 100644 --- a/.github/skills/analyze-model/SKILL.md +++ b/.github/skills/analyze-model/SKILL.md @@ -130,4 +130,4 @@ If critical information is missing, explicitly list unknowns and what to inspect - Prefer concrete evidence from repository files and model card over assumptions. - If source suggests multiple possible paths, compare at least two and state why one is preferred. -- Keep recommendations aligned with the conventions defined in the port-model skill. \ No newline at end of file +- Keep recommendations aligned with the conventions defined in the port-model skill. diff --git a/.github/skills/check-models/SKILL.md b/.github/skills/check-models/SKILL.md index 88414134e..8fa9d0fde 100644 --- a/.github/skills/check-models/SKILL.md +++ b/.github/skills/check-models/SKILL.md @@ -148,4 +148,4 @@ A full pass requires all of the following in audited scope: - reference entries are valid, categorized correctly, and have preview files - custom pipeline contracts are consistent with actual model behavior -If any area is intentionally out of scope, mark as partial pass with explicit exclusions. \ No newline at end of file +If any area is intentionally out of scope, mark as partial pass with explicit exclusions. diff --git a/.github/skills/check-schedulers/SKILL.md b/.github/skills/check-schedulers/SKILL.md index 472c9a35f..db1b41260 100644 --- a/.github/skills/check-schedulers/SKILL.md +++ b/.github/skills/check-schedulers/SKILL.md @@ -146,4 +146,4 @@ The check passes only if all are true: - each `SamplerData` entry is correctly mapped and usable - no blocking runtime or compile-path failures in validated scope -If scope is partial due to environment limitations, report pass with explicit limitations, not a full pass. \ No newline at end of file +If scope is partial due to environment limitations, report pass with explicit limitations, not a full pass. diff --git a/.github/skills/debug-model/SKILL.md b/.github/skills/debug-model/SKILL.md index 57ec7317f..709c05392 100644 --- a/.github/skills/debug-model/SKILL.md +++ b/.github/skills/debug-model/SKILL.md @@ -214,4 +214,4 @@ When closing the task, report which of these were completed: - "The new model port fails in from_pretrained" - "SD.Next detects my custom pipeline as the wrong model type" - "The loader works but generation returns black images" -- "This standalone-script port loads weights but crashes in attention" \ No newline at end of file +- "This standalone-script port loads weights but crashes in attention" diff --git a/.github/skills/fix-lint/SKILL.md b/.github/skills/fix-lint/SKILL.md index 222dfe501..2bfb725de 100644 --- a/.github/skills/fix-lint/SKILL.md +++ b/.github/skills/fix-lint/SKILL.md @@ -29,8 +29,8 @@ If activation fails, report the blocker and stop before running Python-based too Run tools in this exact sequence: 1. `pre-commit run --all-files` -2. `eslint . javascript/` -3. `cd extensions-builtin/sdnext-modernui && eslint . javascript/` +2. `{PROJECT_ROOT}/node_modules/.bin/eslint . javascript/` +3. `cd extensions-builtin/sdnext-modernui && {PROJECT_ROOT}/node_modules/.bin/eslint . javascript/` 4. `ruff check` 5. `pylint *.py` 6. `pylint modules/` @@ -38,6 +38,8 @@ Run tools in this exact sequence: 8. `pylint scripts/` 9. `pylint extensions-builtin/` +Note that `pylint` can run for considerable time, so run with no timeouts. + ## Fix Policy - Fix issues reported by each tool before moving on. diff --git a/.github/skills/github-issues/SKILL.md b/.github/skills/github-issues/SKILL.md index befbb4bfb..4e929fa5b 100644 --- a/.github/skills/github-issues/SKILL.md +++ b/.github/skills/github-issues/SKILL.md @@ -6,12 +6,12 @@ argument-hint: "Optionally specify state (open/closed/all), max issues, and whet # Summarize SD.Next [Issues] GitHub Issues -Fetch issues from the SD.Next GitHub repository that contain `[Issues]` in the title, then produce a concise markdown report with one entry per issue. +Fetch issues from the SD.Next GitHub repository that contain `[Issue]` in the title, then produce a concise markdown report with one entry per issue. ## When To Use - The user asks for periodic issue triage summaries -- You need an actionable status report for `[Issues]` tracker items +- You need an actionable status report for `[Issue]` tracker items - You want suggested next actions for each matching issue ## Repository diff --git a/.github/skills/port-model/SKILL.md b/.github/skills/port-model/SKILL.md index 7d13fa517..b79812544 100644 --- a/.github/skills/port-model/SKILL.md +++ b/.github/skills/port-model/SKILL.md @@ -244,4 +244,4 @@ When using this skill, the final implementation should usually include: - "Port this standalone inference script into an SD.Next Diffusers pipeline" - "Add support for this Hugging Face model repo to SD.Next" - "Wire this upstream Diffusers pipeline into SD.Next autodetect and loading" -- "Convert this single-file checkpoint model into a custom Diffusers pipeline for SD.Next" \ No newline at end of file +- "Convert this single-file checkpoint model into a custom Diffusers pipeline for SD.Next" diff --git a/TODO.md b/TODO.md index 609a4af8f..b770608ab 100644 --- a/TODO.md +++ b/TODO.md @@ -135,7 +135,6 @@ installer.py:TODO rocm: switch to pytorch source when it becomes available modules/control/run.py:TODO modernui: monkey-patch for missing tabs.select event modules/history.py:TODO: apply metadata, preview, load/save modules/image/resize.py:TODO resize image: enable full VAE mode for resize-latent -modules/lora/lora_apply.py:TODO lora: add other quantization types modules/lora/lora_apply.py:TODO lora: maybe force imediate quantization modules/lora/lora_extract.py:TODO: lora: support pre-quantized flux modules/lora/lora_load.py:TODO lora: add t5 key support for sd35/f1 diff --git a/modules/lora/lora_apply.py b/modules/lora/lora_apply.py index 0cd33e851..21f26ea2c 100644 --- a/modules/lora/lora_apply.py +++ b/modules/lora/lora_apply.py @@ -161,7 +161,6 @@ def network_add_weights(self: torch.nn.Conv2d | torch.nn.Linear | torch.nn.Group if model_weights is None: # weights are used if provided-from-backup else use self.weight model_weights = self.weight weight, new_weight = None, None - # TODO lora: add other quantization types if self.__class__.__name__ == 'Linear4bit' and bnb is not None: try: dequant_weight = bnb.functional.dequantize_4bit(model_weights.to(devices.device), quant_state=self.quant_state, quant_type=self.quant_type, blocksize=self.blocksize) diff --git a/modules/lora/lora_extract.py b/modules/lora/lora_extract.py index 27f379c43..e1536198a 100644 --- a/modules/lora/lora_extract.py +++ b/modules/lora/lora_extract.py @@ -186,19 +186,6 @@ def make_lora(fn, maxrank, auto_rank, rank_ratio, modules, overwrite): progress.remove_task(task) t3 = time.time() - # TODO: lora: support pre-quantized flux - # if 'te' in modules and getattr(shared.sd_model, 'transformer', None) is not None: - # for name, module in shared.sd_model.transformer.named_modules(): - # if "norm" in name and "linear" not in name: - # continue - # weights_backup = getattr(module, "network_weights_backup", None) - # if weights_backup is None: - # continue - # module.svdhandler = SVDHandler() - # module.svdhandler.network_name = "lora_transformer_" + name.replace(".", "_") - # module.svdhandler.decompose(module.weight, weights_backup) - # module.svdhandler.findrank(rank, rank_ratio) - lora_state_dict = {} for sub in ['text_encoder', 'text_encoder_2', 'unet', 'transformer']: submodel = getattr(shared.sd_model, sub, None) diff --git a/scripts/custom_code.py b/scripts/custom_code.py index 7c45d2f7c..1701cdf8b 100644 --- a/scripts/custom_code.py +++ b/scripts/custom_code.py @@ -40,10 +40,10 @@ class CustomCodeScript(scripts_manager.Script): def title(self): return "Custom code" - def show(self, is_img2img): + def show(self, _is_img2img): return cmd_opts.allow_code - def ui(self, is_img2img): + def ui(self, _is_img2img): example = """from modules.processing import process_images p.width = 768 diff --git a/scripts/hdr.py b/scripts/hdr.py index 651527449..82a4a5c5f 100644 --- a/scripts/hdr.py +++ b/scripts/hdr.py @@ -13,10 +13,10 @@ class HDRScript(scripts_manager.Script): def title(self): return "HDR: High Dynamic Range" - def show(self, is_img2img): + def show(self, _is_img2img): return True - def ui(self, is_img2img): + def ui(self, _is_img2img): with gr.Row(): gr.HTML("  HDR: High Dynamic Range
") with gr.Row(): diff --git a/scripts/init_latents.py b/scripts/init_latents.py index 9925eb070..309abe72a 100644 --- a/scripts/init_latents.py +++ b/scripts/init_latents.py @@ -8,7 +8,7 @@ class InitLatentsScript(scripts_manager.Script): def title(self): return 'Init Latents' - def show(self, is_img2img): + def show(self, _is_img2img): return scripts_manager.AlwaysVisible @staticmethod @@ -29,7 +29,7 @@ class InitLatentsScript(scripts_manager.Script): p.init_latent = slerp(p.subseed_strength, latents, var_latents) if p.subseed_strength < 1 else var_latents p.generator = generator if p.subseed_strength <= 0.5 else var_generator - def process_batch(self, p: processing.StableDiffusionProcessing, *args, **kwargs): # pylint: disable=arguments-differ + def process_batch(self, p: processing.StableDiffusionProcessing, *args, **_kwargs): # pylint: disable=arguments-differ if not shared.sd_loaded or not hasattr(shared.sd_model, 'unet'): return from modules.processing_helpers import create_random_tensors diff --git a/scripts/ipadapter.py b/scripts/ipadapter.py index 0bb866dad..25f22866b 100644 --- a/scripts/ipadapter.py +++ b/scripts/ipadapter.py @@ -14,7 +14,7 @@ class IPAdapterScript(scripts_manager.Script): def title(self): return 'IP Adapters' - def show(self, is_img2img): + def show(self, _is_img2img): return scripts_manager.AlwaysVisible def load_images(self, files): diff --git a/scripts/loopback.py b/scripts/loopback.py index 31c2af7a8..e3df383b9 100644 --- a/scripts/loopback.py +++ b/scripts/loopback.py @@ -11,10 +11,10 @@ class LoopbackScript(scripts_manager.Script): def title(self): return "Loopback" - def show(self, is_img2img): + def show(self, _is_img2img): return True - def ui(self, is_img2img): + def ui(self, _is_img2img): with gr.Row(): gr.HTML("  Loopback
") with gr.Row(): diff --git a/scripts/mulan.py b/scripts/mulan.py index b8e8a8c68..baf7bf923 100644 --- a/scripts/mulan.py +++ b/scripts/mulan.py @@ -49,7 +49,7 @@ class MuLanScript(scripts_manager.Script): def title(self): return 'MuLan: Multi Language Prompts' - def show(self, is_img2img): + def show(self, _is_img2img): return True def ui(self, _is_img2img): diff --git a/scripts/prompt_enhance.py b/scripts/prompt_enhance.py index f74b49c91..e8c9f6b53 100644 --- a/scripts/prompt_enhance.py +++ b/scripts/prompt_enhance.py @@ -936,7 +936,7 @@ class PromptEnhanceScript(scripts_manager.Script): apply_btn.click(fn=self.apply, inputs=[self.prompt, self.image, apply_prompt, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, top_k, top_p, thinking_mode, nsfw_mode, use_vision, prefill_text, keep_prefill, keep_thinking], outputs=[prompt_output, self.prompt]) return [self.prompt, self.image, apply_auto, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, top_k, top_p, thinking_mode, nsfw_mode, use_vision, prefill_text, keep_prefill, keep_thinking] - def after_component(self, component, **kwargs): # searching for actual ui prompt components + def after_component(self, component, **_kwargs): # searching for actual ui prompt components if getattr(component, 'elem_id', '') in ['txt2img_prompt', 'img2img_prompt', 'control_prompt', 'video_prompt']: self.prompt = component self.prompt.use_original = True diff --git a/scripts/prompt_matrix.py b/scripts/prompt_matrix.py index 2b758b0d3..7df52598e 100644 --- a/scripts/prompt_matrix.py +++ b/scripts/prompt_matrix.py @@ -10,7 +10,7 @@ class PromptMatrixScript(scripts_manager.Script): def title(self): return "Prompt matrix" - def ui(self, is_img2img): + def ui(self, _is_img2img): with gr.Row(): gr.HTML('  Prompt matrix
') with gr.Row(): diff --git a/scripts/prompts_from_file.py b/scripts/prompts_from_file.py index 0ec86998a..fb192253b 100644 --- a/scripts/prompts_from_file.py +++ b/scripts/prompts_from_file.py @@ -97,7 +97,7 @@ class PromptsFromFileScript(scripts_manager.Script): def title(self): return "Prompts from file" - def ui(self, is_img2img): + def ui(self, _is_img2img): with gr.Row(): gr.HTML('  Prompt from file
') with gr.Row(): diff --git a/scripts/sd_upscale.py b/scripts/sd_upscale.py index e6f614d41..2b1b87f81 100644 --- a/scripts/sd_upscale.py +++ b/scripts/sd_upscale.py @@ -15,7 +15,7 @@ class SDUpscaleScript(scripts_manager.Script): def show(self, is_img2img): return is_img2img - def ui(self, is_img2img): + def ui(self, _is_img2img): with gr.Row(): info = gr.HTML("  SD Upscale
") with gr.Row(): diff --git a/scripts/skip_layer_guidance.py b/scripts/skip_layer_guidance.py index b50608d88..833023487 100644 --- a/scripts/skip_layer_guidance.py +++ b/scripts/skip_layer_guidance.py @@ -15,7 +15,7 @@ class SLGScript(scripts_manager.Script): def title(self): return 'SLG: Skip Layer Guidance' - def show(self, is_img2img): + def show(self, _is_img2img): return True # return signature is array of gradio components diff --git a/scripts/style_aligned_ext.py b/scripts/style_aligned_ext.py index 6236dac9e..c64d811a8 100644 --- a/scripts/style_aligned_ext.py +++ b/scripts/style_aligned_ext.py @@ -16,7 +16,7 @@ class StyleAlignedScript(scripts_manager.Script): def title(self): return 'Style Aligned Image Generation' - def show(self, is_img2img): + def show(self, _is_img2img): return True def reset(self): diff --git a/scripts/text2video.py b/scripts/text2video.py index 42543bfd5..8cea90dba 100644 --- a/scripts/text2video.py +++ b/scripts/text2video.py @@ -1,9 +1,6 @@ """ Additional params for Text-to-Video - -TODO text2video items: -- Video-to-Video upscaling: , """ import gradio as gr diff --git a/scripts/tiling.py b/scripts/tiling.py index 57d50c8a9..037f67d06 100644 --- a/scripts/tiling.py +++ b/scripts/tiling.py @@ -32,7 +32,7 @@ class TilingScript(scripts_manager.Script): def title(self): return 'Asymmetric Tiling' - def show(self, is_img2img): + def show(self, _is_img2img): return True def ui(self, _is_img2img): # ui elements diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index 19e41b695..d86e22af6 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -25,6 +25,10 @@ debug = log.trace if os.environ.get('SD_XYZ_DEBUG', None) is not None else lambd class XYZGridScript(scripts_manager.Script): current_axis_options = [] + def __init__(self): + super().__init__() + self.infotext_fields = () + def title(self): return "XYZ Grid Script" diff --git a/scripts/xyz_grid_on.py b/scripts/xyz_grid_on.py index bac0ad8ea..992208ebe 100644 --- a/scripts/xyz_grid_on.py +++ b/scripts/xyz_grid_on.py @@ -26,7 +26,11 @@ debug = log.trace if os.environ.get('SD_XYZ_DEBUG', None) is not None else lambd class XYZGridScript(scripts_manager.Script): current_axis_options = [] - def show(self, is_img2img): + def __init__(self): + super().__init__() + self.infotext_fields = () + + def show(self, _is_img2img): return scripts_manager.AlwaysVisible def title(self):