diff --git a/CHANGELOG.md b/CHANGELOG.md index f413163e7..0f6259408 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ # Change Log for SD.Next -## Update for 2026-02-17 +## Update for 2026-02-18 -### Highlights for 2026-02-17 +### Highlights for 2026-02-18 TBD -### Details for 2026-02-17 +### Details for 2026-02-18 - **Models** - [FireRed Image Edit](https://huggingface.co/FireRedTeam/FireRed-Image-Edit-1.0) @@ -28,6 +28,10 @@ TBD - **nunchaku** models are now listed in networks tab as reference models instead of being used implicitly via quantization, thanks @CalamitousFelicitousness - removed: old `codeformer` and `gfpgan` face restorers, thanks @CalamitousFelicitousness +- **Compute** + - **ROCm** support for additional AMD GPUs: `gfx103X`, thanks @crashingalexsan + - **Cuda** `torch==2.10` removed support for `rtx1000` series, use following before first startup: + > set TORCH_COMMAND='torch==2.9.1 torchvision==0.24.1 torchaudio==2.9.1 --index-url https://download.pytorch.org/whl/cu126' - **UI** - ui: **localization** improved translation quality and new translations locales: *en, en1, en2, en3, en4, hr, es, it, fr, de, pt, ru, zh, ja, ko, hi, ar, bn, ur, id, vi, tr, sr, po, he, xx, yy, qq, tlh* @@ -39,7 +43,10 @@ TBD - **Internal** - `python==3.14` initial support see [docs](https://vladmandic.github.io/sdnext-docs/Python/) for details - - remove hard-dependnecies: `clip`, `numba`, `skimage`, `torchsde` + - remove hard-dependnecies: + `clip, numba, skimage, torchsde, omegaconf, antlr, patch-ng, patch-ng, astunparse, addict, inflection, jsonmerge, kornia`, + `resize-right, voluptuous, yapf, sqlalchemy, invisible-watermark, pi-heif, ftfy, blendmodes, PyWavelets` + these are now installed on-demand when needed - refactor: to/from image/tensor logic, thanks @CalamitousFelicitousness - refactor: switch to `pyproject.toml` for tool configs - refactor: reorganize `cli` scripts diff --git a/cli/api-pulid.js b/cli/api-pulid.js index 23e4eb094..22dc605a7 100755 --- a/cli/api-pulid.js +++ b/cli/api-pulid.js @@ -81,7 +81,7 @@ async function main() { } else { const json = await res.json(); console.log('result:', json.info); - for (const i in json.images) { // eslint-disable-line guard-for-in + for (const i in json.images) { const file = args.output || `/tmp/test-${i}.jpg`; const data = atob(json.images[i]); fs.writeFileSync(file, data, 'binary'); diff --git a/cli/api-txt2img.js b/cli/api-txt2img.js index 093943c53..5531bc3af 100755 --- a/cli/api-txt2img.js +++ b/cli/api-txt2img.js @@ -41,7 +41,7 @@ async function main() { } else { const json = await res.json(); console.log('result:', json.info); - for (const i in json.images) { // eslint-disable-line guard-for-in + for (const i in json.images) { const f = `/tmp/test-${i}.jpg`; fs.writeFileSync(f, atob(json.images[i]), 'binary'); console.log('image saved:', f); diff --git a/cli/process.py b/cli/process.py index 591b7c694..3461e8f04 100644 --- a/cli/process.py +++ b/cli/process.py @@ -6,7 +6,6 @@ import base64 import numpy as np import mediapipe as mp from PIL import Image, ImageOps -from pi_heif import register_heif_opener from skimage.metrics import structural_similarity as ssim from scipy.stats import beta @@ -261,7 +260,6 @@ def file(filename: str, folder: str, tag = None, requested = []): res = Result(fn = filename, typ='unknown', tag=tag, requested = requested) # open image try: - register_heif_opener() res.image = Image.open(filename) if res.image.mode == 'RGBA': res.image = res.image.convert('RGB') diff --git a/html/locale_ar.json b/html/locale_ar.json index d6b2dd6ed..25c1667a3 100644 --- a/html/locale_ar.json +++ b/html/locale_ar.json @@ -11071,4 +11071,4 @@ "hint": "استخراج خريطة العمق باستخدام نموذج Zoe" } ] -} \ No newline at end of file +} diff --git a/html/locale_bn.json b/html/locale_bn.json index 558d57f67..5cb6ef568 100644 --- a/html/locale_bn.json +++ b/html/locale_bn.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_de.json b/html/locale_de.json index 05733fdde..6b724eda3 100644 --- a/html/locale_de.json +++ b/html/locale_de.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_en.json b/html/locale_en.json index 8bc99ff6c..e4ee61e99 100644 --- a/html/locale_en.json +++ b/html/locale_en.json @@ -1654,4 +1654,4 @@ {"id":"","label":"Z values","localized":"","hint":"Separate values for Z axis using commas","ui":"script_xyz_grid_script"}, {"id":"","label":"Zoe Depth","localized":"","hint":"","ui":"control"} ] -} \ No newline at end of file +} diff --git a/html/locale_es.json b/html/locale_es.json index c206132df..668715d3f 100644 --- a/html/locale_es.json +++ b/html/locale_es.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_fr.json b/html/locale_fr.json index 025a07f26..41454562c 100644 --- a/html/locale_fr.json +++ b/html/locale_fr.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_he.json b/html/locale_he.json index 78e78c901..8afdbf5a1 100644 --- a/html/locale_he.json +++ b/html/locale_he.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_hi.json b/html/locale_hi.json index f71262a2c..f5530078e 100644 --- a/html/locale_hi.json +++ b/html/locale_hi.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_hr.json b/html/locale_hr.json index f252f25d4..da3d82add 100644 --- a/html/locale_hr.json +++ b/html/locale_hr.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_id.json b/html/locale_id.json index 4e4ee6db0..ddcb62732 100644 --- a/html/locale_id.json +++ b/html/locale_id.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_it.json b/html/locale_it.json index 7ae8b1979..3fd26f471 100644 --- a/html/locale_it.json +++ b/html/locale_it.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_ja.json b/html/locale_ja.json index 236539fae..d84ef2315 100644 --- a/html/locale_ja.json +++ b/html/locale_ja.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_ko.json b/html/locale_ko.json index 3fdf4e164..0beaba6de 100644 --- a/html/locale_ko.json +++ b/html/locale_ko.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_nb.json b/html/locale_nb.json index 1c4a604f5..f6a33d083 100644 --- a/html/locale_nb.json +++ b/html/locale_nb.json @@ -11071,4 +11071,4 @@ "hint": "Utilizes the Zoe model for estimating relative depth from a single 2D image for ControlNet." } ] -} \ No newline at end of file +} diff --git a/html/locale_po.json b/html/locale_po.json index 1c1006e1d..855b8f8ba 100644 --- a/html/locale_po.json +++ b/html/locale_po.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_pt.json b/html/locale_pt.json index f273271e5..12d010051 100644 --- a/html/locale_pt.json +++ b/html/locale_pt.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_qq.json b/html/locale_qq.json index 97d5f4ff3..f3c3030fc 100644 --- a/html/locale_qq.json +++ b/html/locale_qq.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_ru.json b/html/locale_ru.json index 3e622369b..26edab984 100644 --- a/html/locale_ru.json +++ b/html/locale_ru.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_sr.json b/html/locale_sr.json index f38a05363..32d6ce2ed 100644 --- a/html/locale_sr.json +++ b/html/locale_sr.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_tb.json b/html/locale_tb.json index 23ab0001e..97707a3d7 100644 --- a/html/locale_tb.json +++ b/html/locale_tb.json @@ -11071,4 +11071,4 @@ "hint": "Utilizes the Zoe neural heuristic to compute a monochromatic spatial depth-parallax map." } ] -} \ No newline at end of file +} diff --git a/html/locale_tlh.json b/html/locale_tlh.json index 1f5e2cdb4..fd46975aa 100644 --- a/html/locale_tlh.json +++ b/html/locale_tlh.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_tr.json b/html/locale_tr.json index 59bfd5a88..edfb76061 100644 --- a/html/locale_tr.json +++ b/html/locale_tr.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_ur.json b/html/locale_ur.json index b3c4db030..9b5db7931 100644 --- a/html/locale_ur.json +++ b/html/locale_ur.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_vi.json b/html/locale_vi.json index bbf974c49..ead28e7ea 100644 --- a/html/locale_vi.json +++ b/html/locale_vi.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_xx.json b/html/locale_xx.json index 375935dc2..ac474cb1c 100644 --- a/html/locale_xx.json +++ b/html/locale_xx.json @@ -11071,4 +11071,4 @@ "hint": "" } ] -} \ No newline at end of file +} diff --git a/html/locale_zh.json b/html/locale_zh.json index 57f5393b5..a903fefb0 100644 --- a/html/locale_zh.json +++ b/html/locale_zh.json @@ -11071,4 +11071,4 @@ "hint": "Zoe 深度图估计模型" } ] -} \ No newline at end of file +} diff --git a/installer.py b/installer.py index caed75769..9639fe8de 100644 --- a/installer.py +++ b/installer.py @@ -698,9 +698,9 @@ def check_diffusers(): current = opts.get('diffusers_version', '') if minor > -1 else '' if (minor == -1) or ((current != target_commit) and (not args.experimental)): if minor == -1: - log.info(f'Diffusers install: commit={target_commit}') + log.info(f'Install: package="diffusers" commit={target_commit}') else: - log.info(f'Diffusers update: current={pkg.version} hash={current} target={target_commit}') + log.info(f'Update: package="diffusers" current={pkg.version} hash={current} target={target_commit}') pip('uninstall --yes diffusers', ignore=True, quiet=True, uv=False) if args.skip_git: log.warning('Git: marked as not available but required for diffusers installation') @@ -728,9 +728,9 @@ def check_transformers(): target_tokenizers = '0.22.2' if (pkg_transformers is None) or ((pkg_transformers.version != target_transformers) or (pkg_tokenizers is None) or ((pkg_tokenizers.version != target_tokenizers) and (not args.experimental))): if pkg_transformers is None: - log.info(f'Transformers install: version={target_transformers}') + log.info(f'Install: package="transformers" version={target_transformers}') else: - log.info(f'Transformers update: current={pkg_transformers.version} target={target_transformers}') + log.info(f'Update: package="transformers" current={pkg_transformers.version} target={target_transformers}') pip('uninstall --yes transformers', ignore=True, quiet=True, uv=False) pip(f'install --upgrade tokenizers=={target_tokenizers}', ignore=False, quiet=True, uv=False) pip(f'install --upgrade transformers=={target_transformers}', ignore=False, quiet=True, uv=False) @@ -961,7 +961,7 @@ def check_cudnn(): # check torch version def check_torch(): - log.info('Verifying torch installation') + log.info('Torch: verifying installation') t_start = time.time() if args.skip_torch: log.info('Torch: skip tests') @@ -1030,7 +1030,7 @@ def check_torch(): if 'torch' in torch_command: if not installed('torch'): - log.info(f'Torch: download and install in progress... cmd="{torch_command}"') + log.info(f'Install: package="torch" download and install in progress... cmd="{torch_command}"') install('--upgrade pip', 'pip', reinstall=True) # pytorch rocm is too large for older pip install(torch_command, 'torch torchvision', quiet=True) @@ -1366,6 +1366,9 @@ def install_insightface(): def install_optional(): t_start = time.time() log.info('Installing optional requirements...') + install('pi-heif') + install('addict') + install('yapf') install('--no-build-isolation git+https://github.com/Disty0/BasicSR@23c1fb6f5c559ef5ce7ad657f2fa56e41b121754', 'basicsr', ignore=True, quiet=True) install('av', ignore=True, quiet=True) install('beautifulsoup4', ignore=True, quiet=True) diff --git a/javascript/civitai.js b/javascript/civitai.js index cf86c069c..d08fb6f28 100644 --- a/javascript/civitai.js +++ b/javascript/civitai.js @@ -1,7 +1,7 @@ String.prototype.format = function (args) { // eslint-disable-line no-extend-native, func-names let thisString = ''; for (let charPos = 0; charPos < this.length; charPos++) thisString += this[charPos]; - for (const key in args) { // eslint-disable-line guard-for-in + for (const key in args) { const stringKey = `{${key}}`; thisString = thisString.replace(new RegExp(stringKey, 'g'), args[key]); } diff --git a/modules/api/models.py b/modules/api/models.py index 915ad15ec..b1425d267 100644 --- a/modules/api/models.py +++ b/modules/api/models.py @@ -1,7 +1,7 @@ +import re import inspect from typing import Any, Optional, Dict, List, Type, Callable, Union from pydantic import BaseModel, Field, create_model # pylint: disable=no-name-in-module -from inflection import underscore from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img import modules.shared as shared @@ -29,6 +29,12 @@ if not hasattr(BaseModel, "__config__"): BaseModel.__config__ = DummyConfig +def underscore(name: str) -> str: # Convert CamelCase or PascalCase string to underscore_case (snake_case). + # use instead of inflection.underscore + s1 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name) + s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) + return s2.lower() + class PydanticModelGenerator: def __init__( self, diff --git a/modules/cfgzero/wan_t2v_pipeline.py b/modules/cfgzero/wan_t2v_pipeline.py index 7912ea3aa..9cc0fa529 100644 --- a/modules/cfgzero/wan_t2v_pipeline.py +++ b/modules/cfgzero/wan_t2v_pipeline.py @@ -15,7 +15,6 @@ import html from typing import Any, Callable, Dict, List, Optional, Union -import ftfy import regex as re import torch from transformers import AutoTokenizer, UMT5EncoderModel @@ -86,6 +85,9 @@ def optimized_scale(positive_flat, negative_flat): return st_star def basic_clean(text): + from installer import install + install('ftfy') + import ftfy text = ftfy.fix_text(text) text = html.unescape(html.unescape(text)) return text.strip() diff --git a/modules/extras.py b/modules/extras.py index dfcee94c8..221bbe6a0 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -33,7 +33,7 @@ def run_modelmerger(id_task, **kwargs): # pylint: disable=unused-argument from installer import install install('tensordict', quiet=True) try: - from tensordict import TensorDict + from tensordict import TensorDict # pylint: disable=unused-import except Exception as e: shared.log.error(f"Merge: {e}") return [*[gr.update() for _ in range(4)], "tensordict not available"] diff --git a/modules/face/faceid.py b/modules/face/faceid.py index bbb53f729..8986e92b1 100644 --- a/modules/face/faceid.py +++ b/modules/face/faceid.py @@ -70,7 +70,7 @@ def face_id( shared.prompt_styles.apply_styles_to_extra(p) if shared.opts.cuda_compile_backend == 'none': - token_merge.apply_token_merging(p.sd_model) + token_merge.apply_token_merging(shared.sd_model) sd_hijack_freeu.apply_freeu(p) script_callbacks.before_process_callback(p) diff --git a/modules/image/save.py b/modules/image/save.py index 8b592bd62..42dd751bf 100644 --- a/modules/image/save.py +++ b/modules/image/save.py @@ -13,11 +13,6 @@ from modules.image.watermark import set_watermark debug = errors.log.trace if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None debug_save = errors.log.trace if os.environ.get('SD_SAVE_DEBUG', None) is not None else lambda *args, **kwargs: None -try: - from pi_heif import register_heif_opener - register_heif_opener() -except Exception: - pass def sanitize_filename_part(text, replace_spaces=True): diff --git a/modules/postprocess/realesrgan_model.py b/modules/postprocess/realesrgan_model.py index 0e779d603..08bf4a01f 100644 --- a/modules/postprocess/realesrgan_model.py +++ b/modules/postprocess/realesrgan_model.py @@ -9,6 +9,8 @@ from modules import devices class UpscalerRealESRGAN(Upscaler): def __init__(self, dirname): from installer import install + install('addict') + install('yapf') install('--no-build-isolation git+https://github.com/Disty0/BasicSR@23c1fb6f5c559ef5ce7ad657f2fa56e41b121754', 'basicsr', ignore=True, quiet=True) from basicsr.archs.rrdbnet_arch import RRDBNet self.name = "RealESRGAN" diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 7f0525780..5bb170557 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -75,7 +75,7 @@ def process_pre(p: processing.StableDiffusionProcessing): # apply-with-unapply sd_models_compile.check_deepcache(enable=True) ipadapter.apply(shared.sd_model, p) - token_merge.apply_token_merging(p.sd_model) + token_merge.apply_token_merging(shared.sd_model) hidiffusion.apply(p, shared.sd_model_type) ras.apply(shared.sd_model, p) pag.apply(p) @@ -117,7 +117,7 @@ def process_post(p: processing.StableDiffusionProcessing): try: sd_models_compile.check_deepcache(enable=False) ipadapter.unapply(shared.sd_model, unload=getattr(p, 'ip_adapter_unload', False)) - token_merge.remove_token_merging(p.sd_model) + token_merge.remove_token_merging(shared.sd_model) hidiffusion.unapply() ras.unapply(shared.sd_model) pag.unapply() diff --git a/modules/processing_helpers.py b/modules/processing_helpers.py index d46648529..8477b2218 100644 --- a/modules/processing_helpers.py +++ b/modules/processing_helpers.py @@ -7,7 +7,6 @@ import torch import numpy as np import cv2 from PIL import Image -from blendmodes.blend import blendLayers, BlendType from modules import shared, devices, images, sd_models, sd_samplers, sd_vae, sd_hijack_hypertile, processing_vae, timer from modules.api import helpers @@ -38,7 +37,9 @@ def setup_color_correction(image): def apply_color_correction(correction, original_image): from installer import install install('scikit-image', quiet=True) + install('blendmodes', quiet=True) from skimage import exposure + from blendmodes.blend import blendLayers, BlendType shared.log.debug(f"Applying color correction: correction={correction.shape} image={original_image}") np_image = np.asarray(original_image) np_recolor = cv2.cvtColor(np_image, cv2.COLOR_RGB2LAB) diff --git a/modules/rocm.py b/modules/rocm.py index dab5aa2d9..c0b8b8df1 100644 --- a/modules/rocm.py +++ b/modules/rocm.py @@ -129,7 +129,7 @@ class Agent: return "v2-staging/gfx1152" if self.gfx_version == 0x1153: return "v2-staging/gfx1153" - if self.gfx_version in (0x1030, 0x1032,): + if self.gfx_version in (0x1030, 0x1031, 0x1032, 0x1034,): return "v2-staging/gfx103X-dgpu" #if (self.gfx_version & 0xFFF0) == 0x1010: # return "gfx101X-dgpu" diff --git a/modules/seedvr/src/common/config.py b/modules/seedvr/src/common/config.py index 58c4e71f8..5b8780bc7 100644 --- a/modules/seedvr/src/common/config.py +++ b/modules/seedvr/src/common/config.py @@ -1,7 +1,12 @@ import importlib from typing import Any, Callable, List, Union -from omegaconf import DictConfig, ListConfig, OmegaConf +try: + from installer import install + install('omegaconf') + from omegaconf import DictConfig, ListConfig, OmegaConf +except Exception as e: + raise ImportError(f"Failed to import omegaconf. Error: {e}") from e try: OmegaConf.register_new_resolver("eval", eval) @@ -10,7 +15,7 @@ except Exception as e: raise -def load_config(path: str, argv: List[str] = None) -> Union[DictConfig, ListConfig]: +def load_config(path: str, argv: List[str] = None): """ Load a configuration. Will resolve inheritance. """ @@ -25,7 +30,7 @@ def load_config(path: str, argv: List[str] = None) -> Union[DictConfig, ListConf def resolve_recursive( config: Any, - resolver: Callable[[Union[DictConfig, ListConfig]], Union[DictConfig, ListConfig]], + resolver: Callable[[Any], Any], ) -> Any: config = resolver(config) if isinstance(config, DictConfig): @@ -41,7 +46,7 @@ def resolve_recursive( return config -def resolve_inheritance(config: Union[DictConfig, ListConfig]) -> Any: +def resolve_inheritance(config: Any) -> Any: """ Recursively resolve inheritance if the config contains: __inherit__: path/to/parent.yaml or a ListConfig of such paths. @@ -104,7 +109,7 @@ def import_item(path: Union[str, List[str]], name: str) -> Any: raise ValueError(f"Path must be string or list of strings, got: {type(path)}") -def create_object(config: DictConfig) -> Any: +def create_object(config: Any) -> Any: """ Create an object from config. The config is expected to contains the following: diff --git a/modules/seedvr/src/common/diffusion/config.py b/modules/seedvr/src/common/diffusion/config.py index 0a7183584..6e635b90d 100644 --- a/modules/seedvr/src/common/diffusion/config.py +++ b/modules/seedvr/src/common/diffusion/config.py @@ -17,7 +17,6 @@ Utility functions for creating schedules and samplers from config. """ import torch -from omegaconf import DictConfig from .samplers.base import Sampler from .samplers.euler import EulerSampler @@ -28,7 +27,7 @@ from .timesteps.sampling.trailing import UniformTrailingSamplingTimesteps def create_schedule_from_config( - config: DictConfig, + config, ) -> Schedule: """ Create a schedule from configuration. @@ -40,7 +39,7 @@ def create_schedule_from_config( def create_sampler_from_config( - config: DictConfig, + config, schedule: Schedule, timesteps: SamplingTimesteps, ) -> Sampler: @@ -57,7 +56,7 @@ def create_sampler_from_config( def create_sampling_timesteps_from_config( - config: DictConfig, + config, schedule: Schedule, device: torch.device, ) -> SamplingTimesteps: diff --git a/modules/seedvr/src/core/infer.py b/modules/seedvr/src/core/infer.py index 7882d3a61..5be430316 100644 --- a/modules/seedvr/src/core/infer.py +++ b/modules/seedvr/src/core/infer.py @@ -1,7 +1,6 @@ from typing import List, Optional, Tuple, Union import torch from einops import rearrange -from omegaconf import DictConfig, ListConfig from ..common.diffusion import classifier_free_guidance_dispatcher, create_sampler_from_config, create_sampling_timesteps_from_config, create_schedule_from_config from ..models.dit_v2 import na @@ -40,7 +39,9 @@ def optimized_channels_to_second(tensor): class VideoDiffusionInfer(): - def __init__(self, config: DictConfig, device: str, dtype: torch.dtype): + def __init__(self, config, device: str, dtype: torch.dtype): + from installer import install + install('omegaconf') self.config = config self.device = device self.dtype = dtype @@ -48,6 +49,7 @@ class VideoDiffusionInfer(): self.dit = None self.sampler = None self.schedule = None + def get_condition(self, latent: torch.Tensor, latent_blur: torch.Tensor, task: str) -> torch.Tensor: t, h, w, c = latent.shape cond = torch.zeros([t, h, w, c + 1], device=latent.device, dtype=latent.dtype) @@ -93,6 +95,7 @@ class VideoDiffusionInfer(): @torch.no_grad() def vae_encode(self, samples: List[torch.Tensor]) -> List[torch.Tensor]: + from omegaconf import ListConfig use_sample = self.config.vae.get("use_sample", True) latents = [] if len(samples) > 0: @@ -138,6 +141,7 @@ class VideoDiffusionInfer(): @torch.no_grad() def vae_decode(self, latents: List[torch.Tensor], target_dtype: torch.dtype = None) -> List[torch.Tensor]: """🚀 VAE decode optimisé - décodage direct sans chunking, compatible avec autocast externe""" + from omegaconf import ListConfig samples = [] if len(latents) > 0: device = self.device diff --git a/modules/seedvr/src/core/model_manager.py b/modules/seedvr/src/core/model_manager.py index 3abade938..3625af263 100644 --- a/modules/seedvr/src/core/model_manager.py +++ b/modules/seedvr/src/core/model_manager.py @@ -1,6 +1,5 @@ import os import torch -from omegaconf import OmegaConf from safetensors.torch import load_file as load_safetensors_file from huggingface_hub import hf_hub_download from ..optimization.memory_manager import preinitialize_rope_cache @@ -9,6 +8,10 @@ from ..core.infer import VideoDiffusionInfer def configure_runner(model_name, cache_dir, device:str='cpu', dtype:torch.dtype=None): + from installer import install + install('omegaconf') + from omegaconf import OmegaConf + repo_id = "vladmandic/SeedVR2" script_directory = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) config_path = os.path.join(script_directory, './config_7b.yaml') if "7b" in model_name else os.path.join(script_directory, './config_3b.yaml') diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index 62b97c6c7..68204650e 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -437,7 +437,7 @@ class ExtraNetworksPage: files = list(files_cache.list_files(reference_path, ext_filter=exts, recursive=False)) if shared.opts.diffusers_dir in path: path = os.path.relpath(path, shared.opts.diffusers_dir) - fn = os.path.join(reference_path, path.replace('models--', '').replace('\\', '/').split('/')[0]) + fn = os.path.join(reference_path, path.replace('models--', '').replace('\\', '/').split('/')[0]) # pylint: disable=use-maxsplit-arg else: fn = os.path.splitext(path)[0] files += list(files_cache.list_files(os.path.dirname(path), ext_filter=exts, recursive=False)) diff --git a/package.json b/package.json index f31c9053e..2f6cfe69c 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,9 @@ "eslint-ui": "cd extensions-builtin/sdnext-modernui && eslint . javascript/", "ruff": ". venv/bin/activate && ruff check", "ruff-win": "venv\\scripts\\activate && ruff check", - "pylint": ". venv/bin/activate && pylint --disable=W0511 *.py modules/ pipelines/ scripts/ extensions-builtin/ | grep -v '^*'", - "pylint-win": "venv\\scripts\\activate && pylint --disable=W0511 *.py modules/ pipelines/ scripts/ extensions-builtin/", - "lint": "npm run format && npm run eslint && npm run eslint-ui && npm run ruff && npm run pylint | grep -v TODO", + "pylint": ". venv/bin/activate && pylint *.py modules/ pipelines/ scripts/ extensions-builtin/ | grep -v '^*'", + "pylint-win": "venv\\scripts\\activate && pylint *.py modules/ pipelines/ scripts/ extensions-builtin/", + "lint": "npm run format && npm run eslint && npm run eslint-ui && npm run ruff && npm run pylint", "lint-win": "npm run format-win && npm run eslint && npm run eslint-ui && npm run ruff-win && npm run pylint-win", "test": ". venv/bin/activate; python launch.py --debug --test", "todo": "grep -oIPR 'TODO.*' *.py modules/ pipelines/ | sort -u", diff --git a/pipelines/hdm/hdm/utils/__init__.py b/pipelines/hdm/hdm/utils/__init__.py index e590bbd2c..f6507e2f5 100644 --- a/pipelines/hdm/hdm/utils/__init__.py +++ b/pipelines/hdm/hdm/utils/__init__.py @@ -1,5 +1,4 @@ import importlib -import omegaconf from inspect import isfunction from random import shuffle @@ -16,6 +15,9 @@ def get_obj_from_str(string, reload=False): def instantiate(obj): + from installer import install + install('omegaconf') + import omegaconf if isinstance(obj, omegaconf.DictConfig): obj = dict(**obj) if isinstance(obj, dict) and "class" in obj: diff --git a/pipelines/hdm/hdm/utils/config.py b/pipelines/hdm/hdm/utils/config.py index 4fa2e6636..454b7d532 100644 --- a/pipelines/hdm/hdm/utils/config.py +++ b/pipelines/hdm/hdm/utils/config.py @@ -1,9 +1,13 @@ import os -import toml -import omegaconf def load_train_config(file): + from installer import install + install('omegaconf') + install('toml') + import omegaconf + import toml + config = toml.load(file) model = config["model"] diff --git a/pipelines/model_google.py b/pipelines/model_google.py index 627003fd6..9c0637cf2 100644 --- a/pipelines/model_google.py +++ b/pipelines/model_google.py @@ -56,7 +56,7 @@ class GoogleNanoBananaPipeline(): ) def img2img(self, prompt, image): - from google import genai + from google import genai # pylint: disable=no-name-in-module image_bytes = io.BytesIO() image.save(image_bytes, format='JPEG') return self.client.models.generate_content( @@ -109,7 +109,7 @@ class GoogleNanoBananaPipeline(): return args def __call__(self, prompt: list[str], width: int, height: int, image: Image.Image = None): - from google import genai + from google import genai # pylint: disable=no-name-in-module if self.client is None: args = self.get_args() if args is None: diff --git a/pyproject.toml b/pyproject.toml index 2e08e03ba..53c963c93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,6 +81,7 @@ ignore = [ "B006", # Do not use mutable data structures for argument defaults "B008", # Do not perform function call in argument defaults "B905", # Strict zip() usage + "ASYNC240", # Async functions should not use os.path methods "C420", # Unnecessary dict comprehension for iterable; use `dict.fromkeys` instead "C408", # Unnecessary `dict` call "I001", # Import block is un-sorted or un-formatted @@ -194,7 +195,7 @@ main.ignore-patterns=[ ".*_model_arch_v2.py$", ] main.ignored-modules="" -main.jobs=8 +main.jobs=4 main.limit-inference-results=100 main.load-plugins="" main.persistent=false @@ -334,15 +335,15 @@ similarities.ignore-imports=true similarities.ignore-signatures=true similarities.min-similarity-lines=4 spelling.max-spelling-suggestions=4 -# spelling.dict="" -# spelling.ignore-comment-directives=["fmt: on","fmt: off","noqa:","noqa","nosec","isort:skip","mypy:"] -# spelling.ignore-words="" -# spelling.private-dict-file="" -# spelling.store-unknown-words=false string.check-quote-consistency=false string.check-str-concat-over-line-jumps=false typecheck.contextmanager-decorators="contextlib.contextmanager" -typecheck.generated-members=["numpy.*","logging.*","torch.*","cv2.*"] +typecheck.generated-members=[ + "numpy.*", + "logging.*", + "torch.*", + "cv2.*", + ] typecheck.ignore-none=true typecheck.ignore-on-opaque-inference=true typecheck.ignored-checks-for-mixins=["no-member","not-async-context-manager","not-context-manager","attribute-defined-outside-init"] diff --git a/requirements.txt b/requirements.txt index 5996db4c2..3c15c6d53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,35 +3,19 @@ setuptools==69.5.1 wheel # standard -patch-ng anyio -addict -astunparse filetype future GitPython -httpcore -inflection -jsonmerge -kornia lark -omegaconf piexif mpmath psutil pyyaml -resize-right toml voluptuous -yapf fasteners orjson -sqlalchemy -invisible-watermark -PyWavelets -pi-heif -ftfy -blendmodes # versioned fastapi==0.124.4 @@ -40,13 +24,11 @@ safetensors==0.7.0 peft==0.18.1 httpx==0.28.1 compel==2.2.1 -antlr4-python3-runtime==4.9.3 requests==2.32.3 tqdm==4.67.3 accelerate==1.12.0 einops==0.8.1 huggingface_hub==0.36.2 -numexpr==2.11.0 numpy==2.1.2 pandas==2.3.1 protobuf==4.25.3 diff --git a/scripts/pulid/eva_clip/tokenizer.py b/scripts/pulid/eva_clip/tokenizer.py index 8184c5f7e..b76e2a3aa 100644 --- a/scripts/pulid/eva_clip/tokenizer.py +++ b/scripts/pulid/eva_clip/tokenizer.py @@ -8,7 +8,6 @@ import os from functools import lru_cache from typing import Union, List -import ftfy import regex as re import torch @@ -58,6 +57,9 @@ def get_pairs(word): def basic_clean(text): + from installer import install + install('ftfy') + import ftfy text = ftfy.fix_text(text) text = html.unescape(html.unescape(text)) return text.strip() diff --git a/scripts/pulid/pulid_sdxl.py b/scripts/pulid/pulid_sdxl.py index 821622a2a..2fc38373b 100644 --- a/scripts/pulid/pulid_sdxl.py +++ b/scripts/pulid/pulid_sdxl.py @@ -14,11 +14,12 @@ from torchvision.transforms import InterpolationMode from torchvision.transforms.functional import normalize, resize import insightface -from basicsr.utils import img2tensor, tensor2img from facexlib.parsing import init_parsing_model from facexlib.utils.face_restoration_helper import FaceRestoreHelper from insightface.app import FaceAnalysis +from .pulid_utils import img2tensor, tensor2img + from eva_clip import create_model_and_transforms from eva_clip.constants import OPENAI_DATASET_MEAN, OPENAI_DATASET_STD from encoders_transformer import IDFormer, IDEncoder diff --git a/wiki b/wiki index c0924688d..51a98c9e3 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit c0924688d04e3b41399f2cbd8e6050d937bebc06 +Subproject commit 51a98c9e39bc8a226987a10c54eaaba36bfa8e8e