@@ -1,138 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"html",
|
||||
"json"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"airbnb-base",
|
||||
"plugin:css/recommended",
|
||||
"plugin:json/recommended",
|
||||
"plugin:node/recommended"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"commonjs": true,
|
||||
"node": true,
|
||||
"jquery": true,
|
||||
"es2024": true
|
||||
},
|
||||
"rules": {
|
||||
"max-len": [1, 275, 3],
|
||||
"camelcase":"off",
|
||||
"default-case":"off",
|
||||
"no-await-in-loop":"off",
|
||||
"no-bitwise":"off",
|
||||
"no-continue":"off",
|
||||
"no-confusing-arrow":"off",
|
||||
"no-console":"off",
|
||||
"no-empty":"off",
|
||||
"no-loop-func":"off",
|
||||
"no-mixed-operators":"off",
|
||||
"no-param-reassign":"off",
|
||||
"no-process-exit":"off",
|
||||
"no-plusplus":"off",
|
||||
"no-restricted-globals":"off",
|
||||
"no-restricted-syntax":"off",
|
||||
"no-return-assign":"off",
|
||||
"no-unused-vars":"off",
|
||||
"no-useless-escape":"off",
|
||||
"object-curly-newline":"off",
|
||||
"prefer-rest-params":"off",
|
||||
"prefer-destructuring":"off",
|
||||
"radix":"off",
|
||||
"node/shebang": "off"
|
||||
},
|
||||
"globals": {
|
||||
"panzoom": "readonly",
|
||||
"authFetch": "readonly",
|
||||
"log": "readonly",
|
||||
"debug": "readonly",
|
||||
"error": "readonly",
|
||||
"xhrGet": "readonly",
|
||||
"xhrPost": "readonly",
|
||||
"gradioApp": "readonly",
|
||||
"executeCallbacks": "readonly",
|
||||
"onAfterUiUpdate": "readonly",
|
||||
"onOptionsChanged": "readonly",
|
||||
"optionsChangedCallbacks": "readonly",
|
||||
"onUiLoaded": "readonly",
|
||||
"onUiUpdate": "readonly",
|
||||
"onUiTabChange": "readonly",
|
||||
"onUiReady": "readonly",
|
||||
"uiCurrentTab": "writable",
|
||||
"uiElementIsVisible": "readonly",
|
||||
"uiElementInSight": "readonly",
|
||||
"getUICurrentTabContent": "readonly",
|
||||
"waitForFlag": "readonly",
|
||||
"logFn": "readonly",
|
||||
"generateForever": "readonly",
|
||||
"showContributors": "readonly",
|
||||
"opts": "writable",
|
||||
"sortUIElements": "readonly",
|
||||
"all_gallery_buttons": "readonly",
|
||||
"selected_gallery_button": "readonly",
|
||||
"selected_gallery_index": "readonly",
|
||||
"switch_to_txt2img": "readonly",
|
||||
"switch_to_img2img_tab": "readonly",
|
||||
"switch_to_img2img": "readonly",
|
||||
"switch_to_sketch": "readonly",
|
||||
"switch_to_inpaint": "readonly",
|
||||
"witch_to_inpaint_sketch": "readonly",
|
||||
"switch_to_extras": "readonly",
|
||||
"get_tab_index": "readonly",
|
||||
"create_submit_args": "readonly",
|
||||
"restartReload": "readonly",
|
||||
"markSelectedCards": "readonly",
|
||||
"updateInput": "readonly",
|
||||
"toggleCompact": "readonly",
|
||||
"setFontSize": "readonly",
|
||||
"setTheme": "readonly",
|
||||
"registerDragDrop": "readonly",
|
||||
"getToken": "readonly",
|
||||
"getENActiveTab": "readonly",
|
||||
"quickApplyStyle": "readonly",
|
||||
"quickSaveStyle": "readonly",
|
||||
"setupExtraNetworks": "readonly",
|
||||
"showNetworks": "readonly",
|
||||
"localization": "readonly",
|
||||
"randomId": "readonly",
|
||||
"requestProgress": "readonly",
|
||||
"setRefreshInterval": "readonly",
|
||||
"modalPrevImage": "readonly",
|
||||
"modalNextImage": "readonly",
|
||||
"galleryClickEventHandler": "readonly",
|
||||
"getExif": "readonly",
|
||||
"jobStatusEl": "readonly",
|
||||
"removeSplash": "readonly",
|
||||
"initGPU": "readonly",
|
||||
"startGPU": "readonly",
|
||||
"disableNVML": "readonly",
|
||||
"idbGet": "readonly",
|
||||
"idbPut": "readonly",
|
||||
"idbDel": "readonly",
|
||||
"idbAdd": "readonly",
|
||||
"idbCount": "readonly",
|
||||
"idbFolderCleanup": "readonly",
|
||||
"initChangelog": "readonly",
|
||||
"sendNotification": "readonly",
|
||||
"monitorConnection": "readonly"
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"node_modules",
|
||||
"extensions",
|
||||
"repositories",
|
||||
"venv",
|
||||
"panzoom.js",
|
||||
"split.js",
|
||||
"exifr.js",
|
||||
"jquery.js",
|
||||
"sparkline.js",
|
||||
"iframeResizer.min.js"
|
||||
]
|
||||
}
|
||||
@@ -2,5 +2,14 @@
|
||||
"python.analysis.extraPaths": [".", "./modules", "./scripts", "./pipelines"],
|
||||
"python.analysis.typeCheckingMode": "off",
|
||||
"editor.formatOnSave": false,
|
||||
"python.REPL.enableREPLSmartSend": false
|
||||
"python.REPL.enableREPLSmartSend": false,
|
||||
"eslint.enable": true,
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"typescript",
|
||||
"html",
|
||||
"css",
|
||||
"json",
|
||||
"markdown"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,115 @@
|
||||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2025-01-20
|
||||
|
||||
### Highlights for 2025-01-20
|
||||
|
||||
First release of 2026 brings quite a few new models: **Flux.2-Klein, Qwen-Image-2512, LTX-2-Dev, GLM-Image**
|
||||
There are also improvements to *SDNQ* quantization engine, updated *Prompt Enhance*, *Image Preview* and many others.
|
||||
Plus some significant under-the-hood changes to improve code coverage and quality which resulted in more than usual levels of bug-fixes and some ~330 commits!
|
||||
For full list of changes, see full changelog.
|
||||
|
||||
[ReadMe](https://github.com/vladmandic/automatic/blob/master/README.md) | [ChangeLog](https://github.com/vladmandic/automatic/blob/master/CHANGELOG.md) | [Docs](https://vladmandic.github.io/sdnext-docs/) | [WiKi](https://github.com/vladmandic/automatic/wiki) | [Discord](https://discord.com/invite/sd-next-federal-batch-inspectors-1101998836328697867) | [Sponsor](https://github.com/sponsors/vladmandic)
|
||||
|
||||
### Details for 2025-01-20
|
||||
|
||||
- **Models**
|
||||
- [Flux.2 Klein](https://bfl.ai/blog/flux2-klein-towards-interactive-visual-intelligence)
|
||||
Flux.2-Klein is a new family of compact models from BFL in *4B and 9B sizes* and avaialable as *destilled and base* variants
|
||||
also includes are *sdnq prequantized variants*
|
||||
*note*: 9B variant is [gated](https://vladmandic.github.io/sdnext-docs/Gated/)
|
||||
- [Qwen-Image-2512](https://qwen.ai/blog?id=qwen-image-2512)
|
||||
Qwen-Image successor, significantly reduces the AI-generated look and adds finer natural detailils and improved text rendering
|
||||
available in both *original*, *sdnq-svd prequantized* and *sdnq-dynamic prequantized* variants
|
||||
thanks @CalamitousFelicitousness
|
||||
- [LTX-2 19B Dev](https://ltx.io/model/ltx-2)
|
||||
LTX-2 is a new very large 19B parameter video generation model from Lightricks using Gemma-3 text encoder
|
||||
available for T2I/I2I workflows in original and sdnq prequantized variants
|
||||
*note*: model is very sensitive to input params and will result in errors otherwise
|
||||
- [GLM-Image](https://z.ai/blog/glm-image)
|
||||
GLM-image is a new image generation model that adopts a hybrid autoregressive with diffusion decoder architecture
|
||||
available in both *original* and *sdnq-dynamic prequantized* variants
|
||||
thanks @CalamitousFelicitousness
|
||||
*note*: model requires pre-release versions of `transformers` package:
|
||||
> pip install --upgrade git+https://github.com/huggingface/transformers.git
|
||||
> ./webui.sh --experimental
|
||||
- [Nunchaku Z-Image Turbo](https://huggingface.co/nunchaku-tech/nunchaku-z-image-turbo)
|
||||
nunchaku optimized z-image turbo
|
||||
- **Feaures**
|
||||
- **SDNQ**: add *dynamic* quantization method
|
||||
sdnq can dynamically determine best quantization method for each module layer
|
||||
slower to quantize on-the-fly, but results in better quality with minimal resource usage
|
||||
- **SDNQ** now has *19 int* based and *69 float* based quantization types
|
||||
*note*: not all are exposed via ui purely for simplicity, but all are available via api and scripts
|
||||
- **wildcards**: allow weights, thanks @Tillerz
|
||||
- **sampler**: add laplace beta schedule
|
||||
results in better prompt adherence and smoother infills
|
||||
- **prompt enhance**: improve handling and refresh ui, thanks @CalamitousFelicitousness
|
||||
new models such moondream-3 and xiaomo-mimo
|
||||
add support for *thinking* mode where model can reason about the prompt
|
||||
add support for *vision* processing where prompt enhance can also optionally analyze input image
|
||||
add support for *pre-fill* mode where prompt enhance can continue from existing caption
|
||||
- **chroma**: add inpaint pipeline support
|
||||
- **taesd preview**: support for more models, thanks @alerikaisattera
|
||||
- **image ouput paths**: better handling of relative/absolute paths, thanks @CalamitousFelicitousness
|
||||
- **UI**
|
||||
- kanvas add send-to functionality
|
||||
- kanvas improve support for standardui
|
||||
- improve extensions tab layout and behavior, thanks @awsr
|
||||
- indicate collapsed/hidden sections
|
||||
- persistent panel minimize/maximize state
|
||||
- gallery improve sorting behavior
|
||||
- gallery implement prev/next navigation in full screen viewer, thanks @ryanmeador
|
||||
- **Internal**
|
||||
- **lora** native support by default will now skip text-encoder
|
||||
can be enabled in *settings -> networks*
|
||||
- update core js linting to `eslint9`, thanks @awsr
|
||||
- update modernui js linting to `eslint9`, thanks @awsr
|
||||
- update kanvas js linting to `eslint9`, thanks @awsr
|
||||
- update strong typing checks, thanks @awsr
|
||||
- update reference models previews, thanks @liutyi
|
||||
- update models specs page, thanks @alerikaisattera
|
||||
- sdnq improvements
|
||||
- startup sequence optimizations
|
||||
- rocm/hip/hipblast detection and initialization improvements
|
||||
- zluda detection and initialization improvements
|
||||
- new env variable `SD_VAE_DEFAULT` to force default vae processing
|
||||
- update `nunchaku==1.1.0`
|
||||
- lora switch logic from force-diffusers to allow-native
|
||||
- split `reference.json`
|
||||
- print system env on startup
|
||||
- disable fallback on models with custom loaders
|
||||
- refactor triggering of prompt parser and set secondary prompts when needed
|
||||
- refactor handling of seeds
|
||||
- allow unsafe ssl context for downloads
|
||||
- **Fixes**
|
||||
- controlnet: controlnet with non-english ui locales
|
||||
- core: add skip_keys to offloading logic, fixes wan frames mismatch, thanks @ryanmeador
|
||||
- core: force model move on offload=none
|
||||
- core: hidiffusion tracing
|
||||
- core: hip device name detection
|
||||
- core: reduce triton test verbosity
|
||||
- core: switch processing class not restoring params
|
||||
- extension tab: update checker, date handling, formatting etc., thanks @awsr
|
||||
- lora force unapply on change
|
||||
- lora handle null description, thanks @CalamitousFelicitousness
|
||||
- lora loading when using torch without distributed support
|
||||
- lora skip with strength zero
|
||||
- lora: generate slowdown when consequtive lora-diffusers enabled
|
||||
- model: google-genai auth, thanks @CalamitousFelicitousness
|
||||
- model: improve qwen i2i handling
|
||||
- model: kandinsky-5 image and video on non-cuda platforms
|
||||
- model: meituan-longca-image-edit missing image param
|
||||
- model: wan 2.2 i2v
|
||||
- model: z-image single-file loader
|
||||
- other: update civitai base models, thanks @trojaner
|
||||
- ui: gallery save/delete
|
||||
- ui: mobile auto-collapse when using side panel, thanks @awsr
|
||||
- ui: networks filter by model type
|
||||
- ui: networks icon/list view type switch, thanks @awsr
|
||||
- vae: force align width/height to vae scale factor
|
||||
- wildards with folder specification
|
||||
|
||||
## Update for 2025-12-26
|
||||
|
||||
### Highlights for 2025-12-26
|
||||
|
||||
@@ -1,52 +1,54 @@
|
||||
# TODO
|
||||
|
||||
## Known issues
|
||||
|
||||
- z-image-turbo controlnet device mismatch: <https://github.com/huggingface/diffusers/pull/12886>
|
||||
- z-image-turbo safetensors loader: <https://github.com/huggingface/diffusers/issues/12887>
|
||||
- kandinsky-image-5 hardcoded cuda: <https://github.com/huggingface/diffusers/pull/12814>
|
||||
- peft lora with torch-rocm-windows: <https://github.com/huggingface/peft/pull/2963>
|
||||
|
||||
## Project Board
|
||||
|
||||
- <https://github.com/users/vladmandic/projects>
|
||||
|
||||
## Internal
|
||||
|
||||
- Reimplement `llama` remover for kanvas
|
||||
- Deploy: Create executable for SD.Next
|
||||
- Feature: Integrate natural language image search
|
||||
[ImageDB](https://github.com/vladmandic/imagedb)
|
||||
- Feature: Transformers unified cache handler
|
||||
- Feature: Remote Text-Encoder support
|
||||
- Refactor: [Modular pipelines and guiders](https://github.com/huggingface/diffusers/issues/11915)
|
||||
- Refactor: move sampler options to settings to config
|
||||
- Refactor: [GGUF](https://huggingface.co/docs/diffusers/main/en/quantization/gguf)
|
||||
- Feature: LoRA add OMI format support for SD35/FLUX.1
|
||||
- Feature: Move `nunchaku` models to refernce instead of internal decision
|
||||
- Update: `transformers==5.0.0`
|
||||
- Feature: Unify *huggingface* and *diffusers* model folders
|
||||
- Reimplement `llama` remover for Kanvas
|
||||
- Deploy: Create executable for SD.Next
|
||||
- Feature: Integrate natural language image search
|
||||
[ImageDB](https://github.com/vladmandic/imagedb)
|
||||
- Feature: Remote Text-Encoder support
|
||||
- Refactor: move sampler options to settings to config
|
||||
- Refactor: [GGUF](https://huggingface.co/docs/diffusers/main/en/quantization/gguf)
|
||||
- Feature: LoRA add OMI format support for SD35/FLUX.1
|
||||
- Refactor: remove `CodeFormer`
|
||||
- Refactor: remove `GFPGAN`
|
||||
- UI: Lite vs Expert mode
|
||||
- Video tab: add full API support
|
||||
- Control tab: add overrides handling
|
||||
- Refactor: remove `GFPGAN`
|
||||
- UI: Lite vs Expert mode
|
||||
- Video tab: add full API support
|
||||
- Control tab: add overrides handling
|
||||
- Engine: `TensorRT` acceleration
|
||||
- Engine: [mmgp](https://github.com/deepbeepmeep/mmgp)
|
||||
- Engine: [sharpfin](https://github.com/drhead/sharpfin) instead of `torchvision`
|
||||
|
||||
## Modular
|
||||
|
||||
- Switch to modular pipelines
|
||||
- Feature: Transformers unified cache handler
|
||||
- Refactor: [Modular pipelines and guiders](https://github.com/huggingface/diffusers/issues/11915)
|
||||
- [MagCache](https://github.com/lllyasviel/FramePack/pull/673/files)
|
||||
- [SmoothCache](https://github.com/huggingface/diffusers/issues/11135)
|
||||
|
||||
## Features
|
||||
|
||||
- [Flux.2 TinyVAE](https://huggingface.co/fal/FLUX.2-Tiny-AutoEncoder)
|
||||
- [IPAdapter composition](https://huggingface.co/ostris/ip-composition-adapter)
|
||||
- [IPAdapter negative guidance](https://github.com/huggingface/diffusers/discussions/7167)
|
||||
- [MagCache](https://github.com/lllyasviel/FramePack/pull/673/files)
|
||||
- [SmoothCache](https://github.com/huggingface/diffusers/issues/11135)
|
||||
- [STG](https://github.com/huggingface/diffusers/blob/main/examples/community/README.md#spatiotemporal-skip-guidance)
|
||||
- [IPAdapter composition](https://huggingface.co/ostris/ip-composition-adapter)
|
||||
- [IPAdapter negative guidance](https://github.com/huggingface/diffusers/discussions/7167)
|
||||
- [STG](https://github.com/huggingface/diffusers/blob/main/examples/community/README.md#spatiotemporal-skip-guidance)
|
||||
- [Video Inpaint Pipeline](https://github.com/huggingface/diffusers/pull/12506)
|
||||
- [Sonic Inpaint](https://github.com/ubc-vision/sonic)
|
||||
|
||||
### New models / Pipelines
|
||||
|
||||
TODO: *Prioritize*!
|
||||
TODO: Investigate which models are diffusers-compatible and prioritize!
|
||||
|
||||
- [Bria FiboEdit](https://github.com/huggingface/diffusers/commit/d7a1c31f4f85bae5a9e01cdce49bd7346bd8ccd6)
|
||||
- [LTXVideo 0.98 LongMulti](https://github.com/huggingface/diffusers/pull/12614)
|
||||
- [Cosmos-Predict-2.5](https://huggingface.co/nvidia/Cosmos-Predict2.5-2B)
|
||||
- [NewBie Image Exp0.1](https://github.com/huggingface/diffusers/pull/12803)
|
||||
- [Sana-I2V](https://github.com/huggingface/diffusers/pull/12634#issuecomment-3540534268)
|
||||
@@ -54,7 +56,8 @@ TODO: *Prioritize*!
|
||||
- [Bytedance Lynx](https://github.com/bytedance/lynx)
|
||||
- [ByteDance OneReward](https://github.com/bytedance/OneReward)
|
||||
- [ByteDance USO](https://github.com/bytedance/USO)
|
||||
- [Chroma1 Radiance](https://huggingface.co/lodestones/Chroma1-Radiance)
|
||||
- [Chroma Radiance](https://huggingface.co/lodestones/Chroma1-Radiance)
|
||||
- [Chroma Zeta](https://huggingface.co/lodestones/Zeta-Chroma)
|
||||
- [DiffSynth Studio](https://github.com/modelscope/DiffSynth-Studio)
|
||||
- [DiffusionForcing](https://github.com/kwsong0113/diffusion-forcing-transformer)
|
||||
- [Dream0 guidance](https://huggingface.co/ByteDance/DreamO)
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
// simple nodejs script to test sdnext api
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const process = require('process');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const argparse = require('argparse');
|
||||
|
||||
const sd_url = process.env.SDAPI_URL || 'http://127.0.0.1:7860';
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
// simple nodejs script to test sdnext api
|
||||
|
||||
const fs = require('fs'); // eslint-disable-line no-undef
|
||||
const process = require('process'); // eslint-disable-line no-undef
|
||||
const fs = require('node:fs');
|
||||
|
||||
const sd_url = process.env.SDAPI_URL || 'http://127.0.0.1:7860';
|
||||
const sd_username = process.env.SDAPI_USR;
|
||||
|
||||
@@ -40,7 +40,6 @@ def download_urllib(args):
|
||||
fn = ''
|
||||
req = urllib.request.Request(args.url, headers=headers)
|
||||
res = urllib.request.urlopen(req)
|
||||
res.getheader('content-length')
|
||||
content_length = int(res.getheader('content-length') or 0)
|
||||
fn = get_filename(args, res)
|
||||
print(f'downloading: url={args.url} file={fn} size={content_length if content_length > 0 else "unknown"} lib=urllib block={args.block}')
|
||||
|
||||
@@ -9,10 +9,19 @@ if __name__ == "__main__":
|
||||
keyword = sys.argv[0] if len(sys.argv) > 0 else ''
|
||||
hf.logging.set_verbosity_info()
|
||||
hf_api = hf.HfApi()
|
||||
res = hf_api.list_models(model_name=keyword, full=True, limit=100, sort="downloads", direction=-1)
|
||||
res = hf_api.list_models(
|
||||
model_name=keyword,
|
||||
full=True,
|
||||
limit=100,
|
||||
sort="downloads",
|
||||
direction=-1,
|
||||
)
|
||||
res = sorted(res, key=lambda x: x.id)
|
||||
exact = [m for m in res if keyword.lower() in m.id.lower()]
|
||||
if len(exact) > 0:
|
||||
res = exact
|
||||
for m in res:
|
||||
meta = hf_api.model_info(m.id, files_metadata=True)
|
||||
m.files = [f.rfilename for f in meta.siblings if f.rfilename.endswith('.bin') or f.rfilename.endswith('.safetensors')]
|
||||
m.size = sum([f.size for f in meta.siblings]) / 1024 / 1024 / 1024 # in GB
|
||||
print({ 'name': m.id, 'files': len(m.files), 'size': m.size, 'downloads': m.downloads, 'mtime': m.lastModified, 'url': f'https://huggingface.co/{m.id}', 'pipeline': m.pipeline_tag })
|
||||
m.size = round(sum([f.size for f in meta.siblings]) / 1024 / 1024 / 1024, 2)
|
||||
print({ 'name': m.id, 'files': len(m.files), 'size': m.size, 'downloads': m.downloads, 'ctime': m.created_at.isoformat(), 'url': f'https://huggingface.co/{m.id}', 'pipeline': m.pipeline_tag })
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
// script used to localize sdnext ui and hints to multiple languages using google gemini ai
|
||||
|
||||
const fs = require('fs');
|
||||
const process = require('process');
|
||||
const fs = require('node:fs');
|
||||
|
||||
const { GoogleGenerativeAI } = require('@google/generative-ai');
|
||||
|
||||
const api_key = process.env.GOOGLE_AI_API_KEY;
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { includeIgnoreFile } from '@eslint/compat';
|
||||
import css from '@eslint/css';
|
||||
import js from '@eslint/js';
|
||||
import json from '@eslint/json';
|
||||
import markdown from '@eslint/markdown';
|
||||
import html from '@html-eslint/eslint-plugin';
|
||||
import { configs, helpers, plugins, rules } from 'eslint-config-airbnb-extended';
|
||||
import pluginPromise from 'eslint-plugin-promise';
|
||||
import { defineConfig, globalIgnores } from 'eslint/config';
|
||||
import globals from 'globals';
|
||||
|
||||
const gitignorePath = path.resolve('.', '.gitignore');
|
||||
|
||||
const jsConfig = defineConfig([
|
||||
// ESLint recommended config
|
||||
{
|
||||
name: 'js/config',
|
||||
files: helpers.extensions.allFiles,
|
||||
...js.configs.recommended,
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
},
|
||||
globals: { // Set per project
|
||||
...globals.builtin,
|
||||
...globals.browser,
|
||||
...globals.jquery,
|
||||
panzoom: 'readonly',
|
||||
authFetch: 'readonly',
|
||||
log: 'readonly',
|
||||
debug: 'readonly',
|
||||
error: 'readonly',
|
||||
xhrGet: 'readonly',
|
||||
xhrPost: 'readonly',
|
||||
gradioApp: 'readonly',
|
||||
executeCallbacks: 'readonly',
|
||||
onAfterUiUpdate: 'readonly',
|
||||
onOptionsChanged: 'readonly',
|
||||
optionsChangedCallbacks: 'readonly',
|
||||
onUiLoaded: 'readonly',
|
||||
onUiUpdate: 'readonly',
|
||||
onUiTabChange: 'readonly',
|
||||
onUiReady: 'readonly',
|
||||
uiCurrentTab: 'writable',
|
||||
uiElementIsVisible: 'readonly',
|
||||
uiElementInSight: 'readonly',
|
||||
getUICurrentTabContent: 'readonly',
|
||||
waitForFlag: 'readonly',
|
||||
logFn: 'readonly',
|
||||
generateForever: 'readonly',
|
||||
showContributors: 'readonly',
|
||||
opts: 'writable',
|
||||
sortUIElements: 'readonly',
|
||||
all_gallery_buttons: 'readonly',
|
||||
selected_gallery_button: 'readonly',
|
||||
selected_gallery_index: 'readonly',
|
||||
switch_to_txt2img: 'readonly',
|
||||
switch_to_img2img_tab: 'readonly',
|
||||
switch_to_img2img: 'readonly',
|
||||
switch_to_sketch: 'readonly',
|
||||
switch_to_inpaint: 'readonly',
|
||||
witch_to_inpaint_sketch: 'readonly',
|
||||
switch_to_extras: 'readonly',
|
||||
get_tab_index: 'readonly',
|
||||
create_submit_args: 'readonly',
|
||||
restartReload: 'readonly',
|
||||
markSelectedCards: 'readonly',
|
||||
updateInput: 'readonly',
|
||||
toggleCompact: 'readonly',
|
||||
setFontSize: 'readonly',
|
||||
setTheme: 'readonly',
|
||||
registerDragDrop: 'readonly',
|
||||
getToken: 'readonly',
|
||||
getENActiveTab: 'readonly',
|
||||
quickApplyStyle: 'readonly',
|
||||
quickSaveStyle: 'readonly',
|
||||
setupExtraNetworks: 'readonly',
|
||||
showNetworks: 'readonly',
|
||||
localization: 'readonly',
|
||||
randomId: 'readonly',
|
||||
requestProgress: 'readonly',
|
||||
setRefreshInterval: 'readonly',
|
||||
modalPrevImage: 'readonly',
|
||||
modalNextImage: 'readonly',
|
||||
galleryClickEventHandler: 'readonly',
|
||||
getExif: 'readonly',
|
||||
jobStatusEl: 'readonly',
|
||||
removeSplash: 'readonly',
|
||||
initGPU: 'readonly',
|
||||
startGPU: 'readonly',
|
||||
disableNVML: 'readonly',
|
||||
idbGet: 'readonly',
|
||||
idbPut: 'readonly',
|
||||
idbDel: 'readonly',
|
||||
idbAdd: 'readonly',
|
||||
idbCount: 'readonly',
|
||||
idbFolderCleanup: 'readonly',
|
||||
initChangelog: 'readonly',
|
||||
sendNotification: 'readonly',
|
||||
monitorConnection: 'readonly',
|
||||
},
|
||||
},
|
||||
},
|
||||
pluginPromise.configs['flat/recommended'],
|
||||
// Stylistic plugin
|
||||
plugins.stylistic,
|
||||
// Import X plugin
|
||||
plugins.importX,
|
||||
// Airbnb base recommended config
|
||||
...configs.base.recommended,
|
||||
{
|
||||
name: 'sdnext/js',
|
||||
files: helpers.extensions.allFiles,
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
camelcase: 'off',
|
||||
'default-case': 'off',
|
||||
'max-classes-per-file': 'warn',
|
||||
'no-await-in-loop': 'off',
|
||||
'no-bitwise': 'off',
|
||||
'no-continue': 'off',
|
||||
'no-console': 'off',
|
||||
'no-loop-func': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'no-plusplus': 'off',
|
||||
'no-redeclare': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-use-before-define': 'warn',
|
||||
'no-useless-escape': 'warn',
|
||||
'prefer-destructuring': 'off',
|
||||
'prefer-rest-params': 'off',
|
||||
'prefer-template': 'warn',
|
||||
'promise/no-nesting': 'off',
|
||||
radix: 'off',
|
||||
'@stylistic/brace-style': [
|
||||
'error',
|
||||
'1tbs',
|
||||
{
|
||||
allowSingleLine: true,
|
||||
},
|
||||
],
|
||||
'@stylistic/indent': ['error', 2],
|
||||
'@stylistic/lines-between-class-members': [
|
||||
'error',
|
||||
'always',
|
||||
{
|
||||
exceptAfterSingleLine: true,
|
||||
},
|
||||
],
|
||||
'@stylistic/max-len': [
|
||||
'warn',
|
||||
{
|
||||
code: 275,
|
||||
tabWidth: 2,
|
||||
},
|
||||
],
|
||||
'@stylistic/max-statements-per-line': 'off',
|
||||
'@stylistic/no-mixed-operators': 'off',
|
||||
'@stylistic/object-curly-newline': [
|
||||
'error',
|
||||
{
|
||||
multiline: true,
|
||||
consistent: true,
|
||||
},
|
||||
],
|
||||
'@stylistic/quotes': [
|
||||
'error',
|
||||
'single',
|
||||
{
|
||||
avoidEscape: true,
|
||||
},
|
||||
],
|
||||
'@stylistic/semi': [
|
||||
'error',
|
||||
'always',
|
||||
{
|
||||
omitLastInOneLineBlock: false,
|
||||
},
|
||||
],
|
||||
'promise/always-return': 'off',
|
||||
'promise/catch-or-return': 'off',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// const typescriptConfig = defineConfig([
|
||||
// // TypeScript ESLint plugin
|
||||
// plugins.typescriptEslint,
|
||||
// // Airbnb base TypeScript config
|
||||
// ...configs.base.typescript,
|
||||
// {
|
||||
// name: 'sdnext/typescript',
|
||||
// files: helpers.extensions.tsFiles,
|
||||
// rules: {
|
||||
// '@typescript-eslint/ban-ts-comment': 'off',
|
||||
// '@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
// '@typescript-eslint/no-shadow': 'error',
|
||||
// '@typescript-eslint/no-var-requires': 'off',
|
||||
// },
|
||||
// },
|
||||
// ]);
|
||||
|
||||
const nodeConfig = defineConfig([
|
||||
// Node plugin
|
||||
plugins.node,
|
||||
{
|
||||
name: 'sdnext/node',
|
||||
files: ['**/cli/*.js'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
// Import as rule sets to override the `files` setting from default config
|
||||
...rules.node.base.rules,
|
||||
...rules.node.globals.rules,
|
||||
...rules.node.noUnsupportedFeatures.rules,
|
||||
...rules.node.promises.rules,
|
||||
'n/no-sync': 'off',
|
||||
'n/no-process-exit': 'off',
|
||||
'n/hashbang': 'off',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const jsonConfig = defineConfig([
|
||||
{
|
||||
files: ['**/*.json'],
|
||||
ignores: ['package-lock.json'],
|
||||
plugins: { json },
|
||||
language: 'json/json',
|
||||
extends: ['json/recommended'],
|
||||
},
|
||||
]);
|
||||
|
||||
const markdownConfig = defineConfig([
|
||||
{
|
||||
files: ['**/*.md'],
|
||||
plugins: { markdown },
|
||||
language: 'markdown/gfm',
|
||||
processor: 'markdown/markdown',
|
||||
extends: ['markdown/recommended'],
|
||||
},
|
||||
]);
|
||||
|
||||
const cssConfig = defineConfig([
|
||||
{
|
||||
files: ['**/*.css'],
|
||||
language: 'css/css',
|
||||
plugins: { css },
|
||||
extends: ['css/recommended'],
|
||||
// languageOptions: {
|
||||
// tolerant: true,
|
||||
// },
|
||||
rules: {
|
||||
'css/font-family-fallbacks': 'off',
|
||||
'css/no-invalid-properties': [
|
||||
'error',
|
||||
{
|
||||
allowUnknownVariables: true,
|
||||
},
|
||||
],
|
||||
'css/no-important': 'off',
|
||||
'css/use-baseline': 'off',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const htmlConfig = defineConfig([
|
||||
{
|
||||
files: ['**/*.html'],
|
||||
plugins: {
|
||||
html,
|
||||
},
|
||||
extends: ['html/recommended'],
|
||||
language: 'html/html',
|
||||
rules: {
|
||||
'html/attrs-newline': 'off',
|
||||
'html/element-newline': 'off',
|
||||
'html/indent': [
|
||||
'warn',
|
||||
2,
|
||||
],
|
||||
'html/no-duplicate-class': 'error',
|
||||
'html/no-extra-spacing-attrs': [
|
||||
'error',
|
||||
{
|
||||
enforceBeforeSelfClose: true,
|
||||
disallowMissing: true,
|
||||
disallowTabs: true,
|
||||
disallowInAssignment: true,
|
||||
},
|
||||
],
|
||||
'html/require-closing-tags': [
|
||||
'error',
|
||||
{
|
||||
selfClosing: 'always',
|
||||
},
|
||||
],
|
||||
'html/use-baseline': 'off',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
export default defineConfig([
|
||||
// Ignore files and folders listed in .gitignore
|
||||
includeIgnoreFile(gitignorePath),
|
||||
globalIgnores([
|
||||
'**/node_modules',
|
||||
'**/extensions',
|
||||
'**/extensions-builtin',
|
||||
'**/repositories',
|
||||
'**/venv',
|
||||
'**/panZoom.js',
|
||||
'**/split.js',
|
||||
'**/exifr.js',
|
||||
'**/jquery.js',
|
||||
'**/sparkline.js',
|
||||
'**/iframeResizer.min.js',
|
||||
]),
|
||||
...jsConfig,
|
||||
// ...typescriptConfig,
|
||||
...nodeConfig,
|
||||
...jsonConfig,
|
||||
...markdownConfig,
|
||||
...cssConfig,
|
||||
...htmlConfig,
|
||||
]);
|
||||
@@ -97,8 +97,11 @@
|
||||
{"id":"","label":"Build info on first access","localized":"","reload":"","hint":"Prevents server from building EN page on server startup and instead build it when requested"},
|
||||
{"id":"","label":"Show reference styles","localized":"","reload":"","hint":"Show or hide build-it styles"},
|
||||
{"id":"","label":"LoRA load using Diffusers method","localized":"","reload":"","hint":"Alternative method uses diffusers built-in LoRA capabilities instead of native SD.Next implementation (may reduce LoRA compatibility)"},
|
||||
{"id":"","label":"LoRA fuse directly to model","localized":"","reload":"","hint":"When loading LoRAs, immediately merge weights with underlying model instead of applying them on-the-fly"},
|
||||
{"id":"","label":"LoRA native fuse with model","localized":"","reload":"","hint":"Merge LoRA into the model for lower memory usage.<br><br><b style=\"color: #ef4444\">Warning:</b> After removing or switching a LoRA, you may still see its style in generated images. To get a clean model, reload it from the model selector."},
|
||||
{"id":"","label":"LoRA memory cache","localized":"","reload":"","hint":"How many LoRAs to keep in network for future use before requiring reloading from storage"},
|
||||
{"id":"","label":"LoRA force reload always","localized":"","reload":"","hint":"Forces LoRA networks to reload from storage on every generation, even if already cached.<br>Useful for debugging or when LoRA files are being modified externally.<br>Disable for normal use to benefit from caching."},
|
||||
{"id":"","label":"LoRA diffusers fuse with model","localized":"","reload":"","hint":"Merge LoRA into the model for lower memory usage and torch.compile compatibility.<br><br><b style=\"color: #ef4444\">Warning:</b> After removing or switching a LoRA, you may still see its style in generated images. To get a clean model, reload it from the model selector."},
|
||||
{"id":"","label":"LoRA precision when quantized","localized":"","reload":"","hint":"When using a BnB 4-bit model, LoRA is applied by decompressing the weights, adding the LoRA, then recompressing. This controls the format used for recompression.<br><br>Only affects BnB 4-bit models. SDNQ models keep their original format."},
|
||||
{"id":"","label":"Local","localized":"","reload":"","hint":"Models that are downlaoded and ready to use"},
|
||||
{"id":"","label":"Gallery","localized":"","reload":"","hint":"Image gallery"},
|
||||
{"id":"","label":"Reference","localized":"","reload":"","hint":"List of reference models that can be automatically downloaded on first use"},
|
||||
@@ -156,7 +159,7 @@
|
||||
{"id":"","label":"HDR Maximize","localized":"","reload":"","hint":"Calculates a 'normalization factor' by dividing the maximum tensor value by the specified range multiplied by 4. This factor is then used to shift the channels within the given boundary, ensuring maximum dynamic range for subsequent processing. The objective is to optimize dynamic range for external applications like Photoshop, particularly for adjusting levels, contrast, and brightness"},
|
||||
{"id":"","label":"Enable refine pass","localized":"","reload":"","hint":"Use a similar process as image to image to upscale and/or add detail to the final image. Optionally uses refiner model to enhance image details."},
|
||||
{"id":"","label":"Enable detailer pass","localized":"","reload":"","hint":"Detect target objects such as face and reprocess it at higher resolution"},
|
||||
{"id":"","label":"Include detection results","localized":"","reload":"","hint":"Include original image with detected areas marked"},
|
||||
{"id":"","label":"Include detections","localized":"","reload":"","hint":"Include original image with detected areas marked"},
|
||||
{"id":"","label":"Sort detections","localized":"","reload":"","hint":"Sort detected areas by from left to right instead of detection score"},
|
||||
{"id":"","label":"Denoising strength","localized":"","reload":"","hint":"Determines how little respect the algorithm should have for image's content. At 0, nothing will change, and at 1 you'll get an unrelated image. With values below 1.0, processing will take less steps than the Sampling Steps slider specifies"},
|
||||
{"id":"","label":"Denoise start","localized":"","reload":"","hint":"Override denoise strength by stating how early base model should finish and when refiner should start. Only applicable to refiner usage. If set to 0 or 1, denoising strength will be used"},
|
||||
@@ -241,6 +244,21 @@
|
||||
{"id":"","label":"Sort by","localized":"","reload":"","hint":"Sort by"},
|
||||
{"id":"","label":"Nudenet","localized":"","reload":"","hint":"Flexible extension that can detect and obfustate nudity in images"},
|
||||
{"id":"","label":"Prompt enhance","localized":"","reload":"","hint":"Extension that can use different LLMs to rewrite prompt for improved results"},
|
||||
{"id":"","label":"Enhance now","localized":"","reload":"","hint":"Run prompt enhancement using the selected LLM model"},
|
||||
{"id":"","label":"Apply to prompt","localized":"","reload":"","hint":"Automatically copy enhanced result to the prompt input box"},
|
||||
{"id":"","label":"Auto enhance","localized":"","reload":"","hint":"Automatically enhance prompt before every image generation"},
|
||||
{"id":"","label":"Use vision","localized":"","reload":"","hint":"Include input image when enhancing prompt.<br><br>Only available for vision-capable models, marked with \uf06e icon."},
|
||||
{"id":"","label":"LLM model","localized":"","reload":"","hint":"Select the language model to use for prompt enhancement.<br><br>Models supporting vision are marked with \uf06e icon.<br>Models supporting thinking mode are marked with \uf0eb icon."},
|
||||
{"id":"","label":"Model repo","localized":"","reload":"","hint":"HuggingFace repository ID for the model"},
|
||||
{"id":"","label":"Model gguf","localized":"","reload":"","hint":"Optional GGUF quantized model repository on HuggingFace"},
|
||||
{"id":"","label":"Model type","localized":"","reload":"","hint":"Optional GGUF model quantization type"},
|
||||
{"id":"","label":"Model file","localized":"","reload":"","hint":"Optional specific GGUF model file inside the repository"},
|
||||
{"id":"","label":"Load custom model","localized":"","reload":"","hint":"Load a custom model with the specified configuration"},
|
||||
{"id":"","label":"NSFW allowed","localized":"","reload":"","hint":"Allow the model to generate adult content in enhanced prompts"},
|
||||
{"id":"","label":"Prompt prefix","localized":"","reload":"","hint":"Text prepended at the beginning of the enhanced prompt result.<br><br>Useful for adding prompt elements which need to be copied to the image prompt unchanged, like quality tags 'masterpiece, best quality' or artist names, which would otherwise be rewritten by the LLM."},
|
||||
{"id":"","label":"Prompt suffix","localized":"","reload":"","hint":"Text appended to the end of the enhanced prompt result.<br><br>Useful for adding prompt elements which need to be copied to the image prompt unchanged, which would otherwise be rewritten by the LLM."},
|
||||
{"id":"","label":"Enhanced prompt","localized":"","reload":"","hint":"The enhanced prompt output from the LLM"},
|
||||
{"id":"","label":"Set prompt","localized":"","reload":"","hint":"Copy the enhanced prompt to the main prompt input"},
|
||||
{"id":"","label":"Manage extensions","localized":"","reload":"","hint":"Manage extensions"},
|
||||
{"id":"","label":"Manual install","localized":"","reload":"","hint":"Manually install extension"},
|
||||
{"id":"","label":"Extension GIT repository URL","localized":"","reload":"","hint":"Specify extension repository URL on GitHub"},
|
||||
@@ -876,8 +894,8 @@
|
||||
{"id":"","label":"loaded lora","localized":"","reload":"","hint":"loaded lora"},
|
||||
{"id":"","label":"logsnr","localized":"","reload":"","hint":"logsnr"},
|
||||
{"id":"","label":"loop","localized":"","reload":"","hint":"loop"},
|
||||
{"id":"","label":"lora add hash info to metadata","localized":"","reload":"","hint":"lora add hash info to metadata"},
|
||||
{"id":"","label":"lora auto-apply tags","localized":"","reload":"","hint":"lora auto-apply tags"},
|
||||
{"id":"","label":"LoRA add hash info to metadata","localized":"","reload":"","hint":"Include LoRA file hashes in generated image metadata.<br>Useful for reproducibility and tracking which exact LoRA versions were used."},
|
||||
{"id":"","label":"LoRA auto-apply tags","localized":"","reload":"","hint":"Automatically add trigger words/tags from LoRA metadata to your prompt.<br>Set to the number of tags to auto-apply, e.g., 3 = add top 3 trigger tags.<br>Set to 0 to disable, -1 to add all available tags."},
|
||||
{"id":"","label":"lora load using diffusers method for selected models","localized":"","reload":"","hint":"lora load using diffusers method for selected models"},
|
||||
{"id":"","label":"lora load using legacy method","localized":"","reload":"","hint":"lora load using legacy method"},
|
||||
{"id":"","label":"lora target filename","localized":"","reload":"","hint":"lora target filename"},
|
||||
@@ -1209,7 +1227,7 @@
|
||||
{"id":"","label":"tdd","localized":"","reload":"","hint":"tdd"},
|
||||
{"id":"","label":"te","localized":"","reload":"","hint":"te"},
|
||||
{"id":"","label":"temperature","localized":"","reload":"","hint":"Controls randomness in token selection by reshaping the probability distribution.<br>Like adjusting a dial between cautious predictability (low values ~0.4) and creative exploration (higher values ~1). Higher temperatures increase willingness to choose less obvious options, but makes outputs more unpredictable.<br><br>Set to 0 to disable, resulting in silent switch to greedy decoding, disabling sampling."},
|
||||
{"id":"","label":"Thinking mode","localized":"","reload":"","hint":"Enables thinking/reasoning, allowing the model to take more time to generate responses.<br>This can lead to more thoughtful and detailed answers, but will increase response time.<br>This setting affects both hybrid and thinking-only models, and in some may result in lower overall quality than expected. For thinking-only models like Qwen3-VL this setting might have to be combined with prefill to guarantee preventing thinking.<br><br>Models supporting this feature are marked with an \uf0eb icon."},
|
||||
{"id":"","label":"Thinking Mode","localized":"","reload":"","hint":"Enables thinking/reasoning, allowing the model to take more time to generate responses.<br>This can lead to more thoughtful and detailed answers, but will increase response time.<br>This setting affects both hybrid and thinking-only models, and in some may result in lower overall quality than expected. For thinking-only models like Qwen3-VL this setting might have to be combined with prefill to guarantee preventing thinking.<br><br>Models supporting this feature are marked with an \uf0eb icon."},
|
||||
{"id":"","label":"Repetition penalty","localized":"","reload":"","hint":"Discourages reusing tokens that already appear in the prompt or output by penalizing their probabilities.<br>Like adding friction to revisiting previous choices. Helps break repetitive loops but may reduce coherence at aggressive values.<br><br>Set to 1 to disable."},
|
||||
{"id":"","label":"text guidance scale","localized":"","reload":"","hint":"text guidance scale"},
|
||||
{"id":"","label":"template","localized":"","reload":"","hint":"template"},
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"Google Gemini 2.5 Flash Nano Banana": {
|
||||
"path": "gemini-2.5-flash-image",
|
||||
"desc": "Gemini can generate and process images conversationally. You can prompt Gemini with text, images, or a combination of both allowing you to create, edit, and iterate on visuals with unprecedented control.",
|
||||
"preview": "gemini-2.5-flash-image.jpg",
|
||||
"tags": "cloud",
|
||||
"skip": true
|
||||
},
|
||||
"Google Gemini 3.0 Pro Nano Banana": {
|
||||
"path": "gemini-3-pro-image-preview",
|
||||
"desc": "Built on Gemini 3. Create and edit images with studio-quality levels of precision and control",
|
||||
"preview": "gemini-3-pro-image-preview.jpg",
|
||||
"tags": "cloud",
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"Tempest-by-Vlad XL": {
|
||||
"path": "tempestByVlad_baseV01.safetensors@https://civitai.com/api/download/models/1301775",
|
||||
"preview": "tempestByVlad_baseV01.jpg",
|
||||
"desc": "Flexible SDXL model with custom encoder and finetuned for larger landscape resolutions with high details and high contrast.",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 January",
|
||||
"extras": ""
|
||||
},
|
||||
"Tempest-by-Vlad XL Hyper": {
|
||||
"path": "tempestByVlad_hyperV01.safetensors@https://civitai.com/api/download/models/1343512",
|
||||
"preview": "tempestByVlad_hyperV01.jpg",
|
||||
"desc": "Custom distilled variant with goal to get as-normal-as-possible model that works with low steps and guidance-free",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 January",
|
||||
"extras": ""
|
||||
},
|
||||
"Juggernaut XL XI": {
|
||||
"path": "juggernautXL_juggXIByRundiffusion.safetensors@https://civitai.com/api/download/models/782002",
|
||||
"preview": "juggernautXL_juggXIByRundiffusion.jpg",
|
||||
"desc": "Showcase finetuned model based on Stable diffusion XL",
|
||||
"date": "2024 August",
|
||||
"size": 6.94,
|
||||
"tags": "community",
|
||||
"extras": "sampler: DEIS, steps: 20, cfg_scale: 6.0"
|
||||
},
|
||||
"Juggernaut XL XI Lightning": {
|
||||
"path": "juggernautXL_juggXILightningByRD.safetensors@https://civitai.com/api/download/models/920957",
|
||||
"preview": "juggernautXL_juggXILightningByRD.jpg",
|
||||
"desc": "Showcase finetuned model based on Stable diffusion XL",
|
||||
"date": "2024 August",
|
||||
"size": 6.94,
|
||||
"tags": "community",
|
||||
"extras": "sampler: DPM SDE, steps: 6, cfg_scale: 2.0"
|
||||
},
|
||||
"Juggernaut SD Reborn": {
|
||||
"original": true,
|
||||
"path": "juggernaut_reborn.safetensors@https://civitai.com/api/download/models/274039",
|
||||
"preview": "juggernaut_reborn.jpg",
|
||||
"desc": "Showcase finetuned model based on Stable diffusion 1.5",
|
||||
"date": "2023 December",
|
||||
"size": 2.28,
|
||||
"tags": "community",
|
||||
"extras": "width: 512, height: 512, sampler: DEIS, steps: 20, cfg_scale: 6.0"
|
||||
},
|
||||
"WAI Illustrious XL v15": {
|
||||
"path": "waiIllustriousSDXL_v150.safetensors@https://civitai.com/api/download/models/2167369",
|
||||
"preview": "waiIllustriousSDXL_v150.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 August",
|
||||
"extras": ""
|
||||
},
|
||||
"Pony Realism XL v2.3": {
|
||||
"path": "ponyRealism_V23.safetensors@https://civitai.com/api/download/models/1763661",
|
||||
"preview": "ponyRealism_V23.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 May",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI XL 1.0 V-Pred": {
|
||||
"path": "noobaiXLNAIXL_vPred10Version.safetensors@https://huggingface.co/Laxhar/noobai-XL-Vpred-1.0/resolve/main/NoobAI-XL-Vpred-v1.0.safetensors",
|
||||
"preview": "noobaiXLNAIXL_vPred10Version.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2024 December",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI XL 1.1 Epsilon": {
|
||||
"path": "noobaiXLNAIXL_epsilonPred11Version.safetensors@https://huggingface.co/Laxhar/noobai-XL-1.1/resolve/main/NoobAI-XL-v1.1.safetensors",
|
||||
"preview": "noobaiXLNAIXL_epsilonPred11Version.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2024 November",
|
||||
"extras": ""
|
||||
},
|
||||
"WAI-Ani-Pony XL v14": {
|
||||
"path": "waiANIPONYXL_v140.safetensors.safetensors@https://civitai.com/api/download/models/1767402",
|
||||
"preview": "waiANIPONYXL_v140.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 May",
|
||||
"extras": ""
|
||||
},
|
||||
"Tiwaz CenKreChro": {
|
||||
"path": "Tiwaz/CenKreChro",
|
||||
"preview": "Tiwaz--CenKreChro.jpg",
|
||||
"skip": true,
|
||||
"desc": "Based Centerfold Flux 5, trying to merge in Chroma and Krea.",
|
||||
"extras": "",
|
||||
"tags": "community",
|
||||
"date": "2025 September"
|
||||
},
|
||||
"purplesmartai Pony 7": {
|
||||
"path": "purplesmartai/pony-v7-base",
|
||||
"preview": "purplesmartai--pony-v7-base.jpg",
|
||||
"skip": true,
|
||||
"desc": "Pony V7 is a versatile character generation model based on AuraFlow architecture. It supports a wide range of styles and species types (humanoid, anthro, feral, and more) and handles character interactions through natural language prompts.",
|
||||
"extras": "",
|
||||
"tags": "community",
|
||||
"date": "October September"
|
||||
},
|
||||
"ShuttleAI Shuttle 3.0 Diffusion": {
|
||||
"path": "shuttleai/shuttle-3-diffusion",
|
||||
"desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition",
|
||||
"preview": "shuttleai--shuttle-3-diffusion.jpg",
|
||||
"tags": "community",
|
||||
"skip": true
|
||||
},
|
||||
"ShuttleAI Shuttle 3.1 Aesthetic": {
|
||||
"path": "shuttleai/shuttle-3.1-aesthetic",
|
||||
"desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition",
|
||||
"preview": "shuttleai--shuttle-3_1-aestetic.jpg",
|
||||
"tags": "community",
|
||||
"skip": true
|
||||
},
|
||||
"ShuttleAI Shuttle Jaguar": {
|
||||
"path": "shuttleai/shuttle-jaguar",
|
||||
"desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition",
|
||||
"preview": "shuttleai--shuttle-jaguar.jpg",
|
||||
"tags": "community",
|
||||
"skip": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
{
|
||||
"StabilityAI StableDiffusion XL Turbo": {
|
||||
"path": "stabilityai/sdxl-turbo",
|
||||
"preview": "stabilityai--sdxl-turbo.jpg",
|
||||
"desc": "SDXL-Turbo is a fast generative text-to-image model that can synthesize photorealistic images from a text prompt in a 1-4 steps.",
|
||||
"skip": true,
|
||||
"variant": "fp16",
|
||||
"tags": "distilled",
|
||||
"extras": "steps: 4, cfg_scale: 0.0"
|
||||
},
|
||||
"StabilityAI Stable Cascade Lite": {
|
||||
"path": "huggingface/stabilityai/stable-cascade-lite",
|
||||
"skip": true,
|
||||
"variant": "bf16",
|
||||
"desc": "Stable Cascade is a diffusion model built upon the Würstchen architecture and its main difference to other models like Stable Diffusion is that it is working at a much smaller latent space. Why is this important? The smaller the latent space, the faster you can run inference and the cheaper the training becomes. How small is the latent space? Stable Diffusion uses a compression factor of 8, resulting in a 1024x1024 image being encoded to 128x128. Stable Cascade achieves a compression factor of 42, meaning that it is possible to encode a 1024x1024 image to 24x24, while maintaining crisp reconstructions. The text-conditional model is then trained in the highly compressed latent space. Previous versions of this architecture, achieved a 16x cost reduction over Stable Diffusion 1.5",
|
||||
"preview": "stabilityai--stable-cascade-lite.jpg",
|
||||
"extras": "sampler: Default, cfg_scale: 4.0, image_cfg_scale: 1.0",
|
||||
"size": 4.97,
|
||||
"tags": "distilled",
|
||||
"date": "2024 February"
|
||||
},
|
||||
"StabilityAI Stable Diffusion 3.5 Turbo": {
|
||||
"path": "stabilityai/stable-diffusion-3.5-large-turbo",
|
||||
"skip": true,
|
||||
"variant": "fp16",
|
||||
"desc": "Stable Diffusion 3.5 Large Turbo is a Multimodal Diffusion Transformer (MMDiT) text-to-image model with Adversarial Diffusion Distillation (ADD) that features improved performance in image quality, typography, complex prompt understanding, and resource-efficiency, with a focus on fewer inference steps.",
|
||||
"preview": "stabilityai--stable-diffusion-3_5-large-turbo.jpg",
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 7.0"
|
||||
},
|
||||
"Tencent FLUX.1 Dev SRPO": {
|
||||
"path": "vladmandic/flux.1-dev-SRPO",
|
||||
"preview": "vladmandic--flux.1-dev-SRPO.jpg",
|
||||
"desc": "FLUX.1 Dev SRPO is Tencent trained with specific technique: Directly Aligning the Full Diffusion Trajectory with Fine-Grained Human Preference",
|
||||
"tags": "distilled",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 4.5"
|
||||
},
|
||||
"Qwen-Image-Lightning": {
|
||||
"path": "vladmandic/Qwen-Lightning",
|
||||
"preview": "vladmandic--Qwen-Lightning.jpg",
|
||||
"desc": "Qwen-Lightning is step-distilled from Qwen-Image to allow for generation in 8 steps.",
|
||||
"skip": true,
|
||||
"extras": "steps: 8",
|
||||
"size": 56.1,
|
||||
"tags": "distilled",
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Qwen-Image-Distill": {
|
||||
"path": "SahilCarterr/Qwen-Image-Distill-Full",
|
||||
"preview": "SahilCarterr--Qwen-Image-Distill-Full.jpg",
|
||||
"desc": "Qwen-Image-Distill is a distilled and accelerated version of Qwen-Image by DiffSynth-Studio.",
|
||||
"skip": true,
|
||||
"extras": "steps: 15",
|
||||
"size": 56.1,
|
||||
"tags": "distilled",
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Qwen-Image-Lightning-Edit": {
|
||||
"path": "vladmandic/Qwen-Lightning-Edit",
|
||||
"preview": "vladmandic--Qwen-Lightning-Edit.jpg",
|
||||
"desc": "Qwen-Lightning-Edit is step-distilled from Qwen-Image-Edit to allow for generation in 8 steps.",
|
||||
"skip": true,
|
||||
"extras": "steps: 8",
|
||||
"size": 56.1,
|
||||
"tags": "distilled",
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Qwen-Image Pruning-12B": {
|
||||
"path": "OPPOer/Qwen-Image-Pruning",
|
||||
"subfolder": "Qwen-Image-12B-8steps",
|
||||
"preview": "OPPOer--Qwen-Image-Pruning.jpg",
|
||||
"desc": "This open-source project is based on Qwen-Image and has attempted model pruning, removing 20 layers while retaining the weights of 40 layers, resulting in a model size of 12B parameters.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"date": "2025 Ocotober"
|
||||
},
|
||||
"Qwen-Image-Edit Pruning-13B": {
|
||||
"path": "OPPOer/Qwen-Image-Edit-Pruning",
|
||||
"subfolder": "Qwen-Image-Edit-13B-4steps",
|
||||
"preview": "OPPOer--Qwen-Image-Edit-Pruning.jpg",
|
||||
"desc": "This open-source project is based on Qwen-Image-Edit and has attempted model pruning, removing 20 layers while retaining the weights of 40 layers, resulting in a model size of 13.6B parameters.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"date": "2025 Ocotober"
|
||||
},
|
||||
"Qwen-Image-Edit-2509 Pruning-13B": {
|
||||
"path": "OPPOer/Qwen-Image-Edit-2509-Pruning",
|
||||
"subfolder": "Qwen-Image-Edit-2509-13B-4steps",
|
||||
"preview": "OPPOer--Qwen-Image-Edit-2509-Pruning.jpg",
|
||||
"desc": "This open-source project is based on Qwen-Image-Edit and has attempted model pruning, removing 20 layers while retaining the weights of 40 layers, resulting in a model size of 13.6B parameters.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"date": "2025 Ocotober"
|
||||
},
|
||||
"lodestones Chroma1 Flash": {
|
||||
"path": "lodestones/Chroma1-Flash",
|
||||
"preview": "lodestones--Chroma1-Flash.jpg",
|
||||
"desc": "Chroma is a 8.9B parameter model based on FLUX.1-schnell. It’s fully Apache 2.0 licensed, ensuring that anyone can use, modify, and build on top of it—no corporate gatekeeping. A fine-tuned version of the Chroma1-Base made to find the best way to make these flow matching models faster.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 26.84,
|
||||
"tags": "distilled",
|
||||
"date": "2025 July"
|
||||
},
|
||||
"SDXL Flash Mini": {
|
||||
"path": "SDXL-Flash_Mini.safetensors@https://huggingface.co/sd-community/sdxl-flash-mini/resolve/main/SDXL-Flash_Mini.safetensors?download=true",
|
||||
"preview": "SDXL-Flash_Mini.jpg",
|
||||
"desc": "Introducing the new fast model SDXL Flash (Mini), we learned that all fast XL models work fast, but the quality decreases, and we also made a fast model, but it is not as fast as LCM, Turbo, Lightning and Hyper, but the quality is higher.",
|
||||
"extras": "width: 2048, height: 1024, sampler: DEIS, steps: 40, cfg_scale: 6.0",
|
||||
"tags": "distilled",
|
||||
"experimental": true
|
||||
},
|
||||
"NVLabs Sana 1.5 1.6B 1k Sprint": {
|
||||
"path": "Efficient-Large-Model/Sana_Sprint_1.6B_1024px_diffusers",
|
||||
"desc": "SANA-Sprint is an ultra-efficient diffusion model for text-to-image (T2I) generation, reducing inference steps from 20 to 1-4 while achieving state-of-the-art performance.",
|
||||
"preview": "Efficient-Large-Model--Sana15_Sprint_1600M_1024px_diffusers.jpg",
|
||||
"tags": "distilled",
|
||||
"skip": true
|
||||
},
|
||||
"Segmind SSD-1B": {
|
||||
"path": "huggingface/segmind/SSD-1B",
|
||||
"preview": "segmind--SSD-1B.jpg",
|
||||
"desc": "The Segmind Stable Diffusion Model (SSD-1B) offers a compact, efficient, and distilled version of the SDXL model. At 50% smaller and 60% faster than Stable Diffusion XL (SDXL), it provides quick and seamless performance without sacrificing image quality.",
|
||||
"variant": "fp16",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 9.0",
|
||||
"size": 8.72,
|
||||
"tags": "distilled",
|
||||
"date": "2023 October"
|
||||
},
|
||||
"Segmind Tiny": {
|
||||
"path": "segmind/tiny-sd",
|
||||
"preview": "segmind--tiny-sd.jpg",
|
||||
"desc": "Segmind's Tiny-SD offers a compact, efficient, and distilled version of Realistic Vision 4.0 and is up to 80% faster than SD1.5",
|
||||
"extras": "width: 512, height: 512, sampler: Default, cfg_scale: 9.0",
|
||||
"size": 1.03,
|
||||
"tags": "distilled",
|
||||
"date": "2023 July"
|
||||
},
|
||||
"Tencent HunyuanImage 2.1 Distilled": {
|
||||
"path": "hunyuanvideo-community/HunyuanImage-2.1-Distilled-Diffusers",
|
||||
"desc": "HunyuanImage-2.1, a highly efficient text-to-image model that is capable of generating 2K (2048 × 2048) resolution images.",
|
||||
"preview": "hunyuanvideo-community--HunyuanImage-2.1-Distilled-Diffusers.jpg",
|
||||
"extras": "",
|
||||
"tags": "distilled",
|
||||
"skip": true,
|
||||
"size": 0,
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Tencent HunyuanDiT 1.2 Distilled": {
|
||||
"path": "Tencent-Hunyuan/HunyuanDiT-v1.2-Diffusers-Distilled",
|
||||
"desc": "Hunyuan-DiT : A Powerful Multi-Resolution Diffusion Transformer with Fine-Grained Chinese Understanding.",
|
||||
"preview": "Tencent-Hunyuan--HunyuanDiT-v1.2-Diffusers-Distilled.jpg",
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 2.0"
|
||||
},
|
||||
"Tencent HunyuanDiT 1.1 Distilled": {
|
||||
"path": "Tencent-Hunyuan/HunyuanDiT-v1.1-Diffusers-Distilled",
|
||||
"desc": "Hunyuan-DiT : A Powerful Multi-Resolution Diffusion Transformer with Fine-Grained Chinese Understanding.",
|
||||
"preview": "Tencent-Hunyuan--HunyuanDiT-v1.1-Diffusers-Distilled.jpg",
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 2.0"
|
||||
},
|
||||
"Black Forest Labs FLUX.2 Klein 4B": {
|
||||
"path": "black-forest-labs/FLUX.2-klein-4B",
|
||||
"preview": "black-forest-labs--FLUX.2-klein-4B.jpg",
|
||||
"desc": "FLUX.2-klein-4B is a 4 billion parameter size-distilled version of FLUX.2-dev optimized for consumer GPUs. Achieves sub-second inference with 4 steps. Supports both text-to-image generation and multi-reference image editing. Apache 2.0 licensed.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 1.0, steps: 4",
|
||||
"size": 8.5,
|
||||
"date": "2025 January"
|
||||
},
|
||||
"Black Forest Labs FLUX.2 Klein 9B": {
|
||||
"path": "black-forest-labs/FLUX.2-klein-9B",
|
||||
"preview": "black-forest-labs--FLUX.2-klein-9B.jpg",
|
||||
"desc": "FLUX.2-klein-9B is a 9 billion parameter size-distilled version of FLUX.2-dev. Higher quality than 4B variant with sub-second inference using 4 steps. Supports text-to-image and multi-reference editing. Non-commercial license.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 1.0, steps: 4",
|
||||
"size": 18.5,
|
||||
"date": "2025 January"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
{
|
||||
"FLUX.1-Dev sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.1-Schnell sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-schnell-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-schnell-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-schnell using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.1-Dev Krea sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-Krea-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-Krea-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-Krea-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.1-Dev Kontext sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-Kontext-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-Kontext-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-Kontext-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.2 Dev sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.2-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.2-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.2-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"extras": "",
|
||||
"size": 31.58,
|
||||
"date": "2025 November"
|
||||
},
|
||||
"Black Forest Labs FLUX.2 Klein 4B sdnq-uint4-dynamic": {
|
||||
"path": "Disty0/FLUX.2-klein-4B-SDNQ-4bit-dynamic",
|
||||
"preview": "Disty0--FLUX.2-klein-4B-SDNQ-4bit-dynamic.jpg",
|
||||
"desc": "Dynamic 4-bit quantization of black-forest-labs/FLUX.2-klein-4B using SDNQ.",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 1.0, steps: 4",
|
||||
"tags": "quantized",
|
||||
"size": 5.1,
|
||||
"date": "2026 January"
|
||||
},
|
||||
"Black Forest Labs FLUX.2 Klein 9B sdnq-uint4-dynamic-svd": {
|
||||
"path": "Disty0/FLUX.2-klein-9B-SDNQ-4bit-dynamic-svd-r32",
|
||||
"preview": "Disty0--FLUX.2-klein-9B-SDNQ-4bit-dynamic-svd-r32.jpg",
|
||||
"desc": "Dynamic 4-bit quantization of black-forest-labs/FLUX.2-klein-9B using SDNQ with SVD rank 32.",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 1.0, steps: 4",
|
||||
"tags": "quantized",
|
||||
"size": 11.7,
|
||||
"date": "2026 January"
|
||||
},
|
||||
"Chroma1-HD sdnq-svd-uint4": {
|
||||
"path": "Disty0/Chroma1-HD-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Chroma1-HD-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of lodestones/Chroma1-HD using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 11.89,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"Wan-AI Wan2.2 A14B T2I sdnq-svd-uint4": {
|
||||
"path": "Disty0/Wan2.2-T2V-A14B-SDNQ-uint4-svd-r32",
|
||||
"preview": "Wan-AI--Wan2.2-T2V-A14B-Diffusers.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 23.54,
|
||||
"extras": ""
|
||||
},
|
||||
"Wan-AI Wan2.2 A14B I2I sdnq-svd-uint4": {
|
||||
"path": "Disty0/Wan2.2-I2V-A14B-SDNQ-uint4-svd-r32",
|
||||
"preview": "Wan-AI--Wan2.2-T2V-A14B-Diffusers.jpg",
|
||||
"desc": "Quantization of Laxhar/noobai-XL-1.1 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 23.55,
|
||||
"extras": ""
|
||||
},
|
||||
"Z-Image-Turbo sdnq-svd-uint4": {
|
||||
"path": "Disty0/Z-Image-Turbo-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Z-Image-Turbo-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of Tongyi-MAI/Z-Image-Turbo using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"extras": "sampler: Default, cfg_scale: 1.0, steps: 9",
|
||||
"size": 6.5,
|
||||
"date": "2025 November"
|
||||
},
|
||||
"Qwen-Image sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 16.09,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-2512 sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-2512-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Qwen-Image-2512-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-2512 using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"extras": "",
|
||||
"size": 16.10,
|
||||
"date": "2025 December"
|
||||
},
|
||||
"Qwen-Image-2512 sdnq-dynamic-uint4": {
|
||||
"path": "Disty0/Qwen-Image-2512-SDNQ-4bit-dynamic",
|
||||
"preview": "Disty0--Qwen-Image-2512-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-2512 using SDNQ: sdnq-dynamic 4-bit uint",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"extras": "",
|
||||
"size": 17.2,
|
||||
"date": "2026 January"
|
||||
},
|
||||
"Qwen-Image-Edit sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Edit-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image-Edit.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Edit using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-Edit-2509 sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Edit-2509-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image-Edit-2509.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Edit-2509 using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-Edit-2511 sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Edit-2511-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Qwen-Image-Edit-2511-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Edit-2511 using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 December",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-Layered sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Layered-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Qwen-Image-Layered-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Layered using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 December",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"nVidia ChronoEdit sdnq-svd-uint4": {
|
||||
"path": "Disty0/ChronoEdit-14B-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--ChronoEdit-14B-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of nvidia/ChronoEdit-14B-Diffusers using SDNQ: sdnq-svd 4-bit uint with svd rank 32.",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 18.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Tencent HunyuanImage 3.0 sdnq-svd-uint4": {
|
||||
"path": "Disty0/HunyuanImage3-SDNQ-uint4-svd-r32",
|
||||
"desc": "Quantization of tencent/HunyuanImage-3.0 using SDNQ: sdnq-svd 4-bit uint with svd rank 32.",
|
||||
"preview": "Disty0--HunyuanImage3-SDNQ-uint4-svd-r32.jpg",
|
||||
"extras": "",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 57.06,
|
||||
"date": "2025 September"
|
||||
},
|
||||
"Tempest-by-Vlad XL sdnq-svd-uint4": {
|
||||
"path": "vladmandic/tempestByVlad_baseV01-SDNQ-uint4-svd",
|
||||
"preview": "vladmandic--tempestByVlad_baseV01-SDNQ-uint4-svd.jpg",
|
||||
"desc": "Quantization of vladmandic/tempestByVlad_baseV01 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"tags": "quantized",
|
||||
"size": 3.37,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI-XL v1.1 epsilon sdnq-svd-uint4": {
|
||||
"path": "Disty0/NoobAI-XL-v1.1-SDNQ-uint4-svd-r128",
|
||||
"preview": "Disty0--NoobAI-XL-v1.1-SDNQ-uint4-svd-r128.jpg",
|
||||
"desc": "Quantization of Laxhar/noobai-XL-1.1 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"tags": "quantized",
|
||||
"size": 3.37,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI-XL v1.0 v-pred sdnq-svd-uint4": {
|
||||
"path": "Disty0/NoobAI-XL-Vpred-v1.0-SDNQ-uint4-svd-r128",
|
||||
"preview": "Disty0--NoobAI-XL-Vpred-v1.0-SDNQ-uint4-svd-r128.jpg",
|
||||
"desc": "Quantization of Laxhar/noobai-XL-Vpred-1.0 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"tags": "quantized",
|
||||
"size": 3.37,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"ZAI GLM-Image sdnq-dynamic-uint4": {
|
||||
"path": "Disty0/GLM-Image-SDNQ-4bit-dynamic",
|
||||
"preview": "zai-org--GLM-Image.jpg",
|
||||
"desc": "Quantization of ZAI GLM-Image using SDNQ: sdnq-dynamic 4-bit uint",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 1.5, steps: 50",
|
||||
"size": 11.6,
|
||||
"tags": "quantized",
|
||||
"date": "2026 January"
|
||||
}
|
||||
}
|
||||
@@ -38,15 +38,6 @@
|
||||
"size": 6.94,
|
||||
"date": "2023 July"
|
||||
},
|
||||
"StabilityAI StableDiffusion XL Turbo": {
|
||||
"path": "stabilityai/sdxl-turbo",
|
||||
"preview": "stabilityai--sdxl-turbo.jpg",
|
||||
"desc": "SDXL-Turbo is a fast generative text-to-image model that can synthesize photorealistic images from a text prompt in a 1-4 steps.",
|
||||
"skip": true,
|
||||
"variant": "fp16",
|
||||
"tags": "distilled",
|
||||
"extras": "steps: 4, cfg_scale: 0.0"
|
||||
},
|
||||
"StabilityAI Stable Cascade": {
|
||||
"path": "huggingface/stabilityai/stable-cascade",
|
||||
"skip": true,
|
||||
@@ -57,17 +48,6 @@
|
||||
"size": 11.82,
|
||||
"date": "2024 February"
|
||||
},
|
||||
"StabilityAI Stable Cascade Lite": {
|
||||
"path": "huggingface/stabilityai/stable-cascade-lite",
|
||||
"skip": true,
|
||||
"variant": "bf16",
|
||||
"desc": "Stable Cascade is a diffusion model built upon the Würstchen architecture and its main difference to other models like Stable Diffusion is that it is working at a much smaller latent space. Why is this important? The smaller the latent space, the faster you can run inference and the cheaper the training becomes. How small is the latent space? Stable Diffusion uses a compression factor of 8, resulting in a 1024x1024 image being encoded to 128x128. Stable Cascade achieves a compression factor of 42, meaning that it is possible to encode a 1024x1024 image to 24x24, while maintaining crisp reconstructions. The text-conditional model is then trained in the highly compressed latent space. Previous versions of this architecture, achieved a 16x cost reduction over Stable Diffusion 1.5",
|
||||
"preview": "stabilityai--stable-cascade-lite.jpg",
|
||||
"extras": "sampler: Default, cfg_scale: 4.0, image_cfg_scale: 1.0",
|
||||
"size": 4.97,
|
||||
"tags": "distilled",
|
||||
"date": "2024 February"
|
||||
},
|
||||
"StabilityAI Stable Diffusion 3.0 Medium": {
|
||||
"path": "stabilityai/stable-diffusion-3-medium-diffusers",
|
||||
"skip": true,
|
||||
@@ -98,15 +78,6 @@
|
||||
"size": 26.98,
|
||||
"date": "2024 October"
|
||||
},
|
||||
"StabilityAI Stable Diffusion 3.5 Turbo": {
|
||||
"path": "stabilityai/stable-diffusion-3.5-large-turbo",
|
||||
"skip": true,
|
||||
"variant": "fp16",
|
||||
"desc": "Stable Diffusion 3.5 Large Turbo is a Multimodal Diffusion Transformer (MMDiT) text-to-image model with Adversarial Diffusion Distillation (ADD) that features improved performance in image quality, typography, complex prompt understanding, and resource-efficiency, with a focus on fewer inference steps.",
|
||||
"preview": "stabilityai--stable-diffusion-3_5-large-turbo.jpg",
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 7.0"
|
||||
},
|
||||
|
||||
"Black Forest Labs FLUX.1 Dev": {
|
||||
"path": "black-forest-labs/FLUX.1-dev",
|
||||
@@ -153,20 +124,29 @@
|
||||
"size": 104.74,
|
||||
"date": "2025 November"
|
||||
},
|
||||
"Tencent FLUX.1 Dev SRPO": {
|
||||
"path": "vladmandic/flux.1-dev-SRPO",
|
||||
"preview": "vladmandic--flux.1-dev-SRPO.jpg",
|
||||
"desc": "FLUX.1 Dev SRPO is Tencent trained with specific technique: Directly Aligning the Full Diffusion Trajectory with Fine-Grained Human Preference",
|
||||
"tags": "distilled",
|
||||
"Black Forest Labs FLUX.2 Klein Base 4B": {
|
||||
"path": "black-forest-labs/FLUX.2-klein-base-4B",
|
||||
"preview": "black-forest-labs--FLUX.2-klein-base-4B.jpg",
|
||||
"desc": "FLUX.2-klein-base-4B is the undistilled 4 billion parameter base model of FLUX.2-klein. Requires 50 inference steps for full quality but offers flexibility for fine-tuning. Supports text-to-image and multi-reference editing. Apache 2.0 licensed.",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 4.5"
|
||||
"extras": "sampler: Default, cfg_scale: 4.0, steps: 50",
|
||||
"size": 8.5,
|
||||
"date": "2025 January"
|
||||
},
|
||||
"Black Forest Labs FLUX.2 Klein Base 9B": {
|
||||
"path": "black-forest-labs/FLUX.2-klein-base-9B",
|
||||
"preview": "black-forest-labs--FLUX.2-klein-base-9B.jpg",
|
||||
"desc": "FLUX.2-klein-base-9B is the undistilled 9 billion parameter base model of FLUX.2-klein. Requires 50 inference steps for full quality but offers flexibility for fine-tuning. Supports text-to-image and multi-reference editing. Non-commercial license.",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 4.0, steps: 50",
|
||||
"size": 18.5,
|
||||
"date": "2025 January"
|
||||
},
|
||||
|
||||
"Z-Image-Turbo": {
|
||||
"path": "Tongyi-MAI/Z-Image-Turbo",
|
||||
"preview": "Tongyi-MAI--Z-Image-Turbo.jpg",
|
||||
"desc": "Z-Image-Turbo, a distilled version of Z-Image that matches or exceeds leading competitors with only 8 NFEs (Number of Function Evaluations). It offers sub-second inference latency on enterprise-grade H800 GPUs and fits comfortably within 16G VRAM consumer devices. It excels in photorealistic image generation, bilingual text rendering (English & Chinese), and robust instruction adherence.",
|
||||
"tags": "distilled",
|
||||
"desc": "Z-Image-Turbo, a distilled version of Z-Image that matches or exceeds leading competitors with only 8 NFEs (Number of Function Evaluations). It excels in photorealistic image generation, bilingual text rendering (English & Chinese), and robust instruction adherence.",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 1.0, steps: 9",
|
||||
"size": 20.3,
|
||||
@@ -182,6 +162,15 @@
|
||||
"size": 56.1,
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Qwen-Image-2512": {
|
||||
"path": "Qwen/Qwen-Image-2512",
|
||||
"preview": "Qwen--Qwen-Image-2512.jpg",
|
||||
"desc": "Qwen-Image-2512 is an Qwen Image successor, that significantly reduces the AI-generated look, got finer natural detailils and improved text rendering.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 53.7,
|
||||
"date": "2025 December"
|
||||
},
|
||||
"Qwen-Image-Edit": {
|
||||
"path": "Qwen/Qwen-Image-Edit",
|
||||
"preview": "Qwen--Qwen-Image-Edit.jpg",
|
||||
@@ -202,7 +191,7 @@
|
||||
},
|
||||
"Qwen-Image-Edit-2511": {
|
||||
"path": "Qwen/Qwen-Image-Edit-2511",
|
||||
"preview": "Qwen--Qwen-Image-Edit-2509.jpg",
|
||||
"preview": "Qwen--Qwen-Image-Edit-2511.jpg",
|
||||
"desc": "Key enhancements: mitigate image drift, improved character consistency, enhanced industrial design generation, and strengthened geometric reasoning ability.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
@@ -211,74 +200,17 @@
|
||||
},
|
||||
"Qwen-Image-Layered": {
|
||||
"path": "Qwen/Qwen-Image-Layered",
|
||||
"preview": "Qwen--Qwen-Image-Edit-2509.jpg",
|
||||
"preview": "Qwen--Qwen-Image-Layered.jpg",
|
||||
"desc": "Qwen-Image-Layered, a model capable of decomposing an image into multiple RGBA layers",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 53.7,
|
||||
"date": "2025 December"
|
||||
},
|
||||
"Qwen-Image-Lightning": {
|
||||
"path": "vladmandic/Qwen-Lightning",
|
||||
"preview": "vladmandic--Qwen-Lightning.jpg",
|
||||
"desc": "Qwen-Lightning is step-distilled from Qwen-Image to allow for generation in 8 steps.",
|
||||
"skip": true,
|
||||
"extras": "steps: 8",
|
||||
"size": 56.1,
|
||||
"tags": "distilled",
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Qwen-Image-Distill": {
|
||||
"path": "SahilCarterr/Qwen-Image-Distill-Full",
|
||||
"preview": "SahilCarterr--Qwen-Image-Distill-Full.jpg",
|
||||
"desc": "Qwen-Image-Distill is a distilled and accelerated version of Qwen-Image by DiffSynth-Studio.",
|
||||
"skip": true,
|
||||
"extras": "steps: 15",
|
||||
"size": 56.1,
|
||||
"tags": "distilled",
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Qwen-Image-Lightning-Edit": {
|
||||
"path": "vladmandic/Qwen-Lightning-Edit",
|
||||
"preview": "vladmandic--Qwen-Lightning-Edit.jpg",
|
||||
"desc": "Qwen-Lightning-Edit is step-distilled from Qwen-Image-Edit to allow for generation in 8 steps.",
|
||||
"skip": true,
|
||||
"extras": "steps: 8",
|
||||
"size": 56.1,
|
||||
"tags": "distilled",
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Qwen-Image Pruning-12B": {
|
||||
"path": "OPPOer/Qwen-Image-Pruning",
|
||||
"subfolder": "Qwen-Image-12B-8steps",
|
||||
"preview": "OPPOer--Qwen-Image-Pruning.jpg",
|
||||
"desc": "This open-source project is based on Qwen-Image and has attempted model pruning, removing 20 layers while retaining the weights of 40 layers, resulting in a model size of 12B parameters.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"date": "2025 Ocotober"
|
||||
},
|
||||
"Qwen-Image-Edit Pruning-13B": {
|
||||
"path": "OPPOer/Qwen-Image-Edit-Pruning",
|
||||
"subfolder": "Qwen-Image-Edit-13B-4steps",
|
||||
"preview": "OPPOer--Qwen-Image-Edit-Pruning.jpg",
|
||||
"desc": "This open-source project is based on Qwen-Image-Edit and has attempted model pruning, removing 20 layers while retaining the weights of 40 layers, resulting in a model size of 13.6B parameters.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"date": "2025 Ocotober"
|
||||
},
|
||||
"Qwen-Image-Edit-2509 Pruning-13B": {
|
||||
"path": "OPPOer/Qwen-Image-Edit-2509-Pruning",
|
||||
"subfolder": "Qwen-Image-Edit-2509-13B-4steps",
|
||||
"preview": "OPPOer--Qwen-Image-Edit-2509-Pruning.jpg",
|
||||
"desc": "This open-source project is based on Qwen-Image-Edit and has attempted model pruning, removing 20 layers while retaining the weights of 40 layers, resulting in a model size of 13.6B parameters.",
|
||||
"skip": true,
|
||||
"tags": "distilled",
|
||||
"date": "2025 Ocotober"
|
||||
},
|
||||
|
||||
"lodestones Chroma1 HD": {
|
||||
"path": "lodestones/Chroma1-HD",
|
||||
"preview": "lodestones--Chroma-HD.jpg",
|
||||
"preview": "lodestones--Chroma1-HD.jpg",
|
||||
"desc": "Chroma is a 8.9B parameter model based on FLUX.1-schnell. It’s fully Apache 2.0 licensed, ensuring that anyone can use, modify, and build on top of it—no corporate gatekeeping. This is the high-res fine-tune of the Chroma1-Base at a 1024x1024 resolution.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
@@ -287,50 +219,22 @@
|
||||
},
|
||||
"lodestones Chroma1 Base": {
|
||||
"path": "lodestones/Chroma1-Base",
|
||||
"preview": "lodestones--Chroma-Base.jpg",
|
||||
"preview": "lodestones--Chroma1-Base.jpg",
|
||||
"desc": "Chroma is a 8.9B parameter model based on FLUX.1-schnell. It’s fully Apache 2.0 licensed, ensuring that anyone can use, modify, and build on top of it—no corporate gatekeeping. This is the core 512x512 model. It's a solid, all-around foundation for pretty much any creative project.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 26.84,
|
||||
"date": "2025 July"
|
||||
},
|
||||
"lodestones Chroma1 Flash": {
|
||||
"path": "lodestones/Chroma1-Flash",
|
||||
"preview": "lodestones--Chroma-flash.jpg",
|
||||
"desc": "Chroma is a 8.9B parameter model based on FLUX.1-schnell. It’s fully Apache 2.0 licensed, ensuring that anyone can use, modify, and build on top of it—no corporate gatekeeping. A fine-tuned version of the Chroma1-Base made to find the best way to make these flow matching models faster.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 26.84,
|
||||
"tags": "distilled",
|
||||
"date": "2025 July"
|
||||
},
|
||||
"lodestones Chroma1 v50 Preview Annealed": {
|
||||
"path": "vladmandic/chroma-unlocked-v50-annealed",
|
||||
"preview": "lodestones--Chroma-annealed.jpg",
|
||||
"preview": "vladmandic--chroma-unlocked-v50-annealed.jpg",
|
||||
"desc": "Chroma is a 8.9B parameter model based on FLUX.1-schnell. It’s fully Apache 2.0 licensed, ensuring that anyone can use, modify, and build on top of it—no corporate gatekeeping. Re-tweaked variant with extra noise added.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 26.84,
|
||||
"date": "2025 July"
|
||||
},
|
||||
"lodestones Chroma1 v48 Preview": {
|
||||
"path": "vladmandic/chroma-unlocked-v48",
|
||||
"preview": "lodestones--Chroma.jpg",
|
||||
"desc": "Chroma is a 8.9B parameter model based on FLUX.1-schnell. It’s fully Apache 2.0 licensed, ensuring that anyone can use, modify, and build on top of it—no corporate gatekeeping. Last raw version of Chroma before final finetuning.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 26.84,
|
||||
"date": "2025 July"
|
||||
},
|
||||
"lodestones Chroma1 v48 Preview Calibrated": {
|
||||
"path": "vladmandic/chroma-unlocked-v48-detail-calibrated",
|
||||
"preview": "lodestones--Chroma-detail.jpg",
|
||||
"desc": "Chroma is a 8.9B parameter model based on FLUX.1-schnell. It’s fully Apache 2.0 licensed, ensuring that anyone can use, modify, and build on top of it—no corporate gatekeeping. Last raw version of Chroma before final finetuning but with some detail calibration.",
|
||||
"skip": true,
|
||||
"extras": "",
|
||||
"size": 26.84,
|
||||
"date": "2025 July"
|
||||
},
|
||||
|
||||
"Meituan LongCat Image": {
|
||||
"path": "meituan-longcat/LongCat-Image",
|
||||
@@ -451,14 +355,6 @@
|
||||
"desc": "SDXS: Real-Time One-Step Latent Diffusion Models with Image Conditions",
|
||||
"extras": "width: 512, height: 512, sampler: CMSI, steps: 1, cfg_scale: 0.0"
|
||||
},
|
||||
"SDXL Flash Mini": {
|
||||
"path": "SDXL-Flash_Mini.safetensors@https://huggingface.co/sd-community/sdxl-flash-mini/resolve/main/SDXL-Flash_Mini.safetensors?download=true",
|
||||
"preview": "SDXL-Flash_Mini.jpg",
|
||||
"desc": "Introducing the new fast model SDXL Flash (Mini), we learned that all fast XL models work fast, but the quality decreases, and we also made a fast model, but it is not as fast as LCM, Turbo, Lightning and Hyper, but the quality is higher.",
|
||||
"extras": "width: 2048, height: 1024, sampler: DEIS, steps: 40, cfg_scale: 6.0",
|
||||
"tags": "distilled",
|
||||
"experimental": true
|
||||
},
|
||||
|
||||
"NVLabs Sana 1.5 1.6B 1k": {
|
||||
"path": "Efficient-Large-Model/SANA1.5_1.6B_1024px_diffusers",
|
||||
@@ -476,13 +372,6 @@
|
||||
"size": 15.58,
|
||||
"date": "2025 March"
|
||||
},
|
||||
"NVLabs Sana 1.5 1.6B 1k Sprint": {
|
||||
"path": "Efficient-Large-Model/Sana_Sprint_1.6B_1024px_diffusers",
|
||||
"desc": "SANA-Sprint is an ultra-efficient diffusion model for text-to-image (T2I) generation, reducing inference steps from 20 to 1-4 while achieving state-of-the-art performance.",
|
||||
"preview": "Efficient-Large-Model--Sana15_Sprint_1600M_1024px_diffusers.jpg",
|
||||
"tags": "distilled",
|
||||
"skip": true
|
||||
},
|
||||
"NVLabs Sana 1.0 1.6B 4k": {
|
||||
"path": "Efficient-Large-Model/Sana_1600M_4Kpx_BF16_diffusers",
|
||||
"desc": "Sana is a text-to-image framework that can efficiently generate images up to 4096 × 4096 resolution. Sana can synthesize high-resolution, high-quality images with strong text-image alignment at a remarkably fast speed, deployable on laptop GPU.",
|
||||
@@ -593,26 +482,6 @@
|
||||
"size": 6.43,
|
||||
"date": "2023 November"
|
||||
},
|
||||
"Segmind SSD-1B": {
|
||||
"path": "huggingface/segmind/SSD-1B",
|
||||
"preview": "segmind--SSD-1B.jpg",
|
||||
"desc": "The Segmind Stable Diffusion Model (SSD-1B) offers a compact, efficient, and distilled version of the SDXL model. At 50% smaller and 60% faster than Stable Diffusion XL (SDXL), it provides quick and seamless performance without sacrificing image quality.",
|
||||
"variant": "fp16",
|
||||
"skip": true,
|
||||
"extras": "sampler: Default, cfg_scale: 9.0",
|
||||
"size": 8.72,
|
||||
"tags": "distilled",
|
||||
"date": "2023 October"
|
||||
},
|
||||
"Segmind Tiny": {
|
||||
"path": "segmind/tiny-sd",
|
||||
"preview": "segmind--tiny-sd.jpg",
|
||||
"desc": "Segmind's Tiny-SD offers a compact, efficient, and distilled version of Realistic Vision 4.0 and is up to 80% faster than SD1.5",
|
||||
"extras": "width: 512, height: 512, sampler: Default, cfg_scale: 9.0",
|
||||
"size": 1.03,
|
||||
"tags": "distilled",
|
||||
"date": "2023 July"
|
||||
},
|
||||
"Segmind SegMoE SD 4x2": {
|
||||
"path": "segmind/SegMoE-SD-4x2-v0",
|
||||
"preview": "segmind--SegMoE-SD-4x2-v0.jpg",
|
||||
@@ -672,16 +541,6 @@
|
||||
"size": 0,
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Tencent HunyuanImage 2.1 Distilled": {
|
||||
"path": "hunyuanvideo-community/HunyuanImage-2.1-Distilled-Diffusers",
|
||||
"desc": "HunyuanImage-2.1, a highly efficient text-to-image model that is capable of generating 2K (2048 × 2048) resolution images.",
|
||||
"preview": "hunyuanvideo-community--HunyuanImage-2.1-Distilled-Diffusers.jpg",
|
||||
"extras": "",
|
||||
"tags": "distilled",
|
||||
"skip": true,
|
||||
"size": 0,
|
||||
"date": "2025 August"
|
||||
},
|
||||
"Tencent HunyuanImage 2.1 Refiner": {
|
||||
"path": "hunyuanvideo-community/HunyuanImage-2.1-Refiner-Diffusers",
|
||||
"desc": "HunyuanImage-2.1, a highly efficient text-to-image model that is capable of generating 2K (2048 × 2048) resolution images.",
|
||||
@@ -699,26 +558,12 @@
|
||||
"size": 14.09,
|
||||
"date": "2024 May"
|
||||
},
|
||||
"Tencent HunyuanDiT 1.2 Distilled": {
|
||||
"path": "Tencent-Hunyuan/HunyuanDiT-v1.2-Diffusers-Distilled",
|
||||
"desc": "Hunyuan-DiT : A Powerful Multi-Resolution Diffusion Transformer with Fine-Grained Chinese Understanding.",
|
||||
"preview": "Tencent-Hunyuan--HunyuanDiT-v1.2-Diffusers-Distilled.jpg",
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 2.0"
|
||||
},
|
||||
"Tencent HunyuanDiT 1.1": {
|
||||
"path": "Tencent-Hunyuan/HunyuanDiT-v1.1-Diffusers",
|
||||
"desc": "Hunyuan-DiT : A Powerful Multi-Resolution Diffusion Transformer with Fine-Grained Chinese Understanding.",
|
||||
"preview": "Tencent-Hunyuan--HunyuanDiT-v1.1-Diffusers.jpg",
|
||||
"extras": "sampler: Default, cfg_scale: 2.0"
|
||||
},
|
||||
"Tencent HunyuanDiT 1.1 Distilled": {
|
||||
"path": "Tencent-Hunyuan/HunyuanDiT-v1.1-Diffusers-Distilled",
|
||||
"desc": "Hunyuan-DiT : A Powerful Multi-Resolution Diffusion Transformer with Fine-Grained Chinese Understanding.",
|
||||
"preview": "Tencent-Hunyuan--HunyuanDiT-v1.1-Diffusers-Distilled.jpg",
|
||||
"tags": "distilled",
|
||||
"extras": "sampler: Default, cfg_scale: 2.0"
|
||||
},
|
||||
|
||||
"AlphaVLLM Lumina Next SFT": {
|
||||
"path": "Alpha-VLLM/Lumina-Next-SFT-diffusers",
|
||||
@@ -1002,338 +847,14 @@
|
||||
"skip": true
|
||||
},
|
||||
|
||||
"FLUX.1-Dev sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"ZAI GLM-Image": {
|
||||
"path": "zai-org/GLM-Image",
|
||||
"preview": "zai-org--GLM-Image.jpg",
|
||||
"desc": "GLM-Image is a two-stage image generation model combining autoregressive token generation (9B vision-language encoder) with diffusion refinement (7B DiT transformer). Features strong text rendering and compositional capabilities.",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.1-Schnell sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-schnell-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-schnell-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-schnell using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.1-Dev Krea sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-Krea-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-Krea-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-Krea-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.1-Dev Kontext sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.1-Kontext-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.1-Kontext-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-Kontext-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 12.60,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"FLUX.2 Dev sdnq-svd-uint4": {
|
||||
"path": "Disty0/FLUX.2-dev-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--FLUX.2-dev-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.2-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"extras": "",
|
||||
"size": 31.58,
|
||||
"date": "2025 November"
|
||||
},
|
||||
"Chroma1-HD sdnq-svd-uint4": {
|
||||
"path": "Disty0/Chroma1-HD-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Chroma1-HD-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of lodestones/Chroma1-HD using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 11.89,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"Wan-AI Wan2.2 A14B T2I sdnq-svd-uint4": {
|
||||
"path": "Disty0/Wan2.2-T2V-A14B-SDNQ-uint4-svd-r32",
|
||||
"preview": "Wan-AI--Wan2.2-T2V-A14B-Diffusers.jpg",
|
||||
"desc": "Quantization of black-forest-labs/FLUX.1-dev using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 23.54,
|
||||
"extras": ""
|
||||
},
|
||||
"Wan-AI Wan2.2 A14B I2I sdnq-svd-uint4": {
|
||||
"path": "Disty0/Wan2.2-I2V-A14B-SDNQ-uint4-svd-r32",
|
||||
"preview": "Wan-AI--Wan2.2-T2V-A14B-Diffusers.jpg",
|
||||
"desc": "Quantization of Laxhar/noobai-XL-1.1 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 23.55,
|
||||
"extras": ""
|
||||
},
|
||||
"Z-Image-Turbo sdnq-svd-uint4": {
|
||||
"path": "Disty0/Z-Image-Turbo-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--Z-Image-Turbo-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of Tongyi-MAI/Z-Image-Turbo using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"extras": "sampler: Default, cfg_scale: 1.0, steps: 9",
|
||||
"size": 6.5,
|
||||
"date": "2025 November"
|
||||
},
|
||||
"Qwen-Image sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 16.09,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-Edit sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Edit-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image-Edit.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Edit using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-Edit-2509 sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Edit-2509-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image-Edit-2509.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Edit-2509 using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-Edit-2511 sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Edit-2511-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image-Edit-2509.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Edit-2511 using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 December",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Qwen-Image-Layered sdnq-svd-uint4": {
|
||||
"path": "Disty0/Qwen-Image-Layered-SDNQ-uint4-svd-r32",
|
||||
"preview": "Qwen--Qwen-Image-Edit-2509.jpg",
|
||||
"desc": "Quantization of Qwen/Qwen-Image-Layered using SDNQ: sdnq-svd 4-bit uint with svd rank 32",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 December",
|
||||
"size": 16.10,
|
||||
"extras": ""
|
||||
},
|
||||
"nVidia ChronoEdit sdnq-svd-uint4": {
|
||||
"path": "Disty0/ChronoEdit-14B-SDNQ-uint4-svd-r32",
|
||||
"preview": "Disty0--ChronoEdit-14B-SDNQ-uint4-svd-r32.jpg",
|
||||
"desc": "Quantization of nvidia/ChronoEdit-14B-Diffusers using SDNQ: sdnq-svd 4-bit uint with svd rank 32.",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"date": "2025 October",
|
||||
"size": 18.10,
|
||||
"extras": ""
|
||||
},
|
||||
"Tencent HunyuanImage 3.0 sdnq-svd-uint4": {
|
||||
"path": "Disty0/HunyuanImage3-SDNQ-uint4-svd-r32",
|
||||
"desc": "Quantization of tencent/HunyuanImage-3.0 using SDNQ: sdnq-svd 4-bit uint with svd rank 32.",
|
||||
"preview": "Disty0--HunyuanImage3-SDNQ-uint4-svd-r32.jpg",
|
||||
"extras": "",
|
||||
"skip": true,
|
||||
"tags": "quantized",
|
||||
"size": 57.06,
|
||||
"date": "2025 September"
|
||||
},
|
||||
"Tempest-by-Vlad XL sdnq-svd-uint4": {
|
||||
"path": "vladmandic/tempestByVlad_baseV01-SDNQ-uint4-svd",
|
||||
"preview": "vladmandic--tempestByVlad_baseV01-SDNQ-uint4-svd.jpg",
|
||||
"desc": "Quantization of vladmandic/tempestByVlad_baseV01 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"tags": "quantized",
|
||||
"size": 3.37,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI-XL v1.1 epsilon sdnq-svd-uint4": {
|
||||
"path": "Disty0/NoobAI-XL-v1.1-SDNQ-uint4-svd-r128",
|
||||
"preview": "Disty0--NoobAI-XL-v1.1-SDNQ-uint4-svd-r128.jpg",
|
||||
"desc": "Quantization of Laxhar/noobai-XL-1.1 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"tags": "quantized",
|
||||
"size": 3.37,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI-XL v1.0 v-pred sdnq-svd-uint4": {
|
||||
"path": "Disty0/NoobAI-XL-Vpred-v1.0-SDNQ-uint4-svd-r128",
|
||||
"preview": "Disty0--NoobAI-XL-Vpred-v1.0-SDNQ-uint4-svd-r128.jpg",
|
||||
"desc": "Quantization of Laxhar/noobai-XL-Vpred-1.0 using SDNQ: sdnq-svd 4-bit uint with svd rank 128",
|
||||
"tags": "quantized",
|
||||
"size": 3.37,
|
||||
"date": "2025 October",
|
||||
"extras": ""
|
||||
},
|
||||
|
||||
"Tempest-by-Vlad XL": {
|
||||
"path": "tempestByVlad_baseV01.safetensors@https://civitai.com/api/download/models/1301775",
|
||||
"preview": "tempestByVlad_baseV01.jpg",
|
||||
"desc": "Flexible SDXL model with custom encoder and finetuned for larger landscape resolutions with high details and high contrast.",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 January",
|
||||
"extras": ""
|
||||
},
|
||||
"Tempest-by-Vlad XL Hyper": {
|
||||
"path": "tempestByVlad_hyperV01.safetensors@https://civitai.com/api/download/models/1343512",
|
||||
"preview": "tempestByVlad_hyperV01.jpg",
|
||||
"desc": "Custom distilled variant with goal to get as-normal-as-possible model that works with low steps and guidance-free",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 January",
|
||||
"extras": ""
|
||||
},
|
||||
"Juggernaut XL XI": {
|
||||
"path": "juggernautXL_juggXIByRundiffusion.safetensors@https://civitai.com/api/download/models/782002",
|
||||
"preview": "juggernautXL_juggXIByRundiffusion.jpg",
|
||||
"desc": "Showcase finetuned model based on Stable diffusion XL",
|
||||
"date": "2024 August",
|
||||
"size": 6.94,
|
||||
"tags": "community",
|
||||
"extras": "sampler: DEIS, steps: 20, cfg_scale: 6.0"
|
||||
},
|
||||
"Juggernaut XL XI Lightning": {
|
||||
"path": "juggernautXL_juggXILightningByRD.safetensors@https://civitai.com/api/download/models/920957",
|
||||
"preview": "juggernautXL_juggXILightningByRD.jpg",
|
||||
"desc": "Showcase finetuned model based on Stable diffusion XL",
|
||||
"date": "2024 August",
|
||||
"size": 6.94,
|
||||
"tags": "community",
|
||||
"extras": "sampler: DPM SDE, steps: 6, cfg_scale: 2.0"
|
||||
},
|
||||
"Juggernaut SD Reborn": {
|
||||
"original": true,
|
||||
"path": "juggernaut_reborn.safetensors@https://civitai.com/api/download/models/274039",
|
||||
"preview": "juggernaut_reborn.jpg",
|
||||
"desc": "Showcase finetuned model based on Stable diffusion 1.5",
|
||||
"date": "2023 December",
|
||||
"size": 2.28,
|
||||
"tags": "community",
|
||||
"extras": "width: 512, height: 512, sampler: DEIS, steps: 20, cfg_scale: 6.0"
|
||||
},
|
||||
"WAI Illustrious XL v15": {
|
||||
"path": "waiIllustriousSDXL_v150.safetensors@https://civitai.com/api/download/models/2167369",
|
||||
"preview": "waiIllustriousSDXL_v150.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 August",
|
||||
"extras": ""
|
||||
},
|
||||
"Pony Realism XL v2.3": {
|
||||
"path": "ponyRealism_V23.safetensors@https://civitai.com/api/download/models/1763661",
|
||||
"preview": "ponyRealism_V23.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 May",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI XL 1.0 V-Pred": {
|
||||
"path": "noobaiXLNAIXL_vPred10Version.safetensors@https://huggingface.co/Laxhar/noobai-XL-Vpred-1.0/resolve/main/NoobAI-XL-Vpred-v1.0.safetensors",
|
||||
"preview": "noobaiXLNAIXL_vPred10Version.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2024 December",
|
||||
"extras": ""
|
||||
},
|
||||
"NoobAI XL 1.1 Epsilon": {
|
||||
"path": "noobaiXLNAIXL_epsilonPred11Version.safetensors@https://huggingface.co/Laxhar/noobai-XL-1.1/resolve/main/NoobAI-XL-v1.1.safetensors",
|
||||
"preview": "noobaiXLNAIXL_epsilonPred11Version.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2024 November",
|
||||
"extras": ""
|
||||
},
|
||||
"WAI-Ani-Pony XL v14": {
|
||||
"path": "waiANIPONYXL_v140.safetensors.safetensors@https://civitai.com/api/download/models/1767402",
|
||||
"preview": "waiANIPONYXL_v140.jpg",
|
||||
"desc": "",
|
||||
"tags": "community",
|
||||
"size": 6.94,
|
||||
"date": "2025 May",
|
||||
"extras": ""
|
||||
},
|
||||
"Tiwaz CenKreChro": {
|
||||
"path": "Tiwaz/CenKreChro",
|
||||
"preview": "Tiwaz--CenKreChro.jpg",
|
||||
"skip": true,
|
||||
"desc": "Based Centerfold Flux 5, trying to merge in Chroma and Krea.",
|
||||
"extras": "",
|
||||
"tags": "community",
|
||||
"date": "2025 September"
|
||||
},
|
||||
"purplesmartai Pony 7": {
|
||||
"path": "purplesmartai/pony-v7-base",
|
||||
"preview": "purplesmartai--pony-v7-base.jpg",
|
||||
"skip": true,
|
||||
"desc": "Pony V7 is a versatile character generation model based on AuraFlow architecture. It supports a wide range of styles and species types (humanoid, anthro, feral, and more) and handles character interactions through natural language prompts.",
|
||||
"extras": "",
|
||||
"tags": "community",
|
||||
"date": "October September"
|
||||
},
|
||||
"ShuttleAI Shuttle 3.0 Diffusion": {
|
||||
"path": "shuttleai/shuttle-3-diffusion",
|
||||
"desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition",
|
||||
"preview": "shuttleai--shuttle-3-diffusion.jpg",
|
||||
"tags": "community",
|
||||
"skip": true
|
||||
},
|
||||
"ShuttleAI Shuttle 3.1 Aesthetic": {
|
||||
"path": "shuttleai/shuttle-3.1-aesthetic",
|
||||
"desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition",
|
||||
"preview": "shuttleai--shuttle-3_1-aestetic.jpg",
|
||||
"tags": "community",
|
||||
"skip": true
|
||||
},
|
||||
"ShuttleAI Shuttle Jaguar": {
|
||||
"path": "shuttleai/shuttle-jaguar",
|
||||
"desc": "Shuttle uses Flux.1 Schnell as its base. It can produce images similar to Flux Dev or Pro in just 4 steps, and it is licensed under Apache 2. The model was partially de-distilled during training. When used beyond 10 steps, it enters refiner mode enhancing image details without altering the composition",
|
||||
"preview": "shuttleai--shuttle-jaguar.jpg",
|
||||
"tags": "community",
|
||||
"skip": true
|
||||
},
|
||||
|
||||
"Google Gemini 2.5 Flash Nano Banana": {
|
||||
"path": "gemini-2.5-flash-image",
|
||||
"desc": "Gemini can generate and process images conversationally. You can prompt Gemini with text, images, or a combination of both allowing you to create, edit, and iterate on visuals with unprecedented control.",
|
||||
"preview": "gemini-2.5-flash-image.jpg",
|
||||
"tags": "cloud",
|
||||
"skip": true
|
||||
},
|
||||
"Google Gemini 3.0 Pro Nano Banana": {
|
||||
"path": "gemini-3-pro-image-preview",
|
||||
"desc": "Built on Gemini 3. Create and edit images with studio-quality levels of precision and control",
|
||||
"preview": "gemini-3-pro-image-preview.jpg",
|
||||
"tags": "cloud",
|
||||
"skip": true
|
||||
"extras": "sampler: Default, cfg_scale: 1.5, steps: 50",
|
||||
"size": 15.3,
|
||||
"date": "2025 January"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -648,7 +648,7 @@ def check_diffusers():
|
||||
t_start = time.time()
|
||||
if args.skip_all:
|
||||
return
|
||||
sha = 'f6b6a7181eb44f0120b29cd897c129275f366c2a' # diffusers commit hash
|
||||
sha = 'd7a1c31f4f85bae5a9e01cdce49bd7346bd8ccd6' # diffusers commit hash
|
||||
# if args.use_rocm or args.use_zluda or args.use_directml:
|
||||
# sha = '043ab2520f6a19fce78e6e060a68dbc947edb9f9' # lock diffusers versions for now
|
||||
pkg = pkg_resources.working_set.by_key.get('diffusers', None)
|
||||
@@ -678,9 +678,12 @@ def check_transformers():
|
||||
if args.use_directml:
|
||||
target_transformers = '4.52.4'
|
||||
target_tokenizers = '0.21.4'
|
||||
elif args.new:
|
||||
target_transformers = '5.0.0rc2'
|
||||
target_tokenizers = '0.22.2'
|
||||
else:
|
||||
target_transformers = '4.57.3'
|
||||
target_tokenizers = '0.22.1'
|
||||
target_transformers = '4.57.5'
|
||||
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}')
|
||||
@@ -757,7 +760,7 @@ def install_rocm_zluda():
|
||||
|
||||
msg = f'ROCm: version={rocm.version}'
|
||||
if device is not None:
|
||||
msg += f', using agent {device.name}'
|
||||
msg += f', using agent {device}'
|
||||
log.info(msg)
|
||||
|
||||
if sys.platform == "win32":
|
||||
@@ -778,20 +781,20 @@ def install_rocm_zluda():
|
||||
zluda_installer.install()
|
||||
zluda_installer.set_default_agent(device)
|
||||
except Exception as e:
|
||||
log.warning(f'Failed to install ZLUDA: {e}')
|
||||
log.error(f'Install ZLUDA: {e}')
|
||||
|
||||
try:
|
||||
zluda_installer.load()
|
||||
except Exception as e:
|
||||
log.warning(f'Failed to load ZLUDA: {e}')
|
||||
log.error(f'Load ZLUDA: {e}')
|
||||
else: # TODO rocm: switch to pytorch source when it becomes available
|
||||
if device is None:
|
||||
log.warning('No ROCm agent was found. Please make sure that graphics driver is installed and up to date.')
|
||||
log.error('ROCm: no agent found - make sure that graphics driver is installed and up to date')
|
||||
if isinstance(rocm.environment, rocm.PythonPackageEnvironment):
|
||||
check_python(supported_minors=[11, 12, 13], reason='ROCm backend requires a Python version between 3.11 and 3.13')
|
||||
check_python(supported_minors=[11, 12, 13], reason='ROCm: python==3.11/3.12/3.13 required')
|
||||
torch_command = os.environ.get('TORCH_COMMAND', f'torch torchvision --index-url https://rocm.nightlies.amd.com/{device.therock}')
|
||||
else:
|
||||
check_python(supported_minors=[12], reason='ROCm Windows preview requires Python version 3.12')
|
||||
check_python(supported_minors=[12], reason='ROCm: Windows preview python==3.12 required')
|
||||
torch_command = os.environ.get('TORCH_COMMAND', '--no-cache-dir https://repo.radeon.com/rocm/windows/rocm-rel-6.4.4/torch-2.8.0a0%2Bgitfc14c65-cp312-cp312-win_amd64.whl https://repo.radeon.com/rocm/windows/rocm-rel-6.4.4/torchvision-0.24.0a0%2Bc85f008-cp312-cp312-win_amd64.whl')
|
||||
else:
|
||||
#check_python(supported_minors=[10, 11, 12, 13, 14], reason='ROCm backend requires a Python version between 3.10 and 3.13')
|
||||
@@ -818,12 +821,12 @@ def install_rocm_zluda():
|
||||
log.warning("ROCm: minimum supported version=6.0")
|
||||
|
||||
if device is None or os.environ.get("HSA_OVERRIDE_GFX_VERSION", None) is not None:
|
||||
log.info(f'ROCm: HSA_OVERRIDE_GFX_VERSION auto config skipped: device={device.name if device is not None else None} version={os.environ.get("HSA_OVERRIDE_GFX_VERSION", None)}')
|
||||
log.info(f'ROCm: HSA_OVERRIDE_GFX_VERSION auto config skipped: device={device} version={os.environ.get("HSA_OVERRIDE_GFX_VERSION", None)}')
|
||||
else:
|
||||
gfx_ver = device.get_gfx_version()
|
||||
if gfx_ver is not None and device.name.removeprefix("gfx") != gfx_ver.replace(".", ""):
|
||||
os.environ.setdefault('HSA_OVERRIDE_GFX_VERSION', gfx_ver)
|
||||
log.info(f'ROCm: HSA_OVERRIDE_GFX_VERSION config overridden: device={device.name} version={os.environ.get("HSA_OVERRIDE_GFX_VERSION", None)}')
|
||||
log.info(f'ROCm: HSA_OVERRIDE_GFX_VERSION config overridden: device={device} version={os.environ.get("HSA_OVERRIDE_GFX_VERSION", None)}')
|
||||
|
||||
ts('amd', t_start)
|
||||
return torch_command
|
||||
@@ -946,7 +949,7 @@ def check_torch():
|
||||
|
||||
if not is_cuda_available and not is_ipex_available and allow_rocm:
|
||||
from modules import rocm
|
||||
is_rocm_available = allow_rocm and (args.use_rocm or args.use_zluda or (len(rocm.agents) != 0 if sys.platform == "win32" else rocm.is_installed)) # late eval to avoid unnecessary import
|
||||
is_rocm_available = allow_rocm and (args.use_rocm or args.use_zluda or rocm.is_installed) # late eval to avoid unnecessary import
|
||||
|
||||
if is_cuda_available and args.use_cuda: # prioritize cuda
|
||||
torch_command = install_cuda()
|
||||
@@ -1397,6 +1400,7 @@ def set_environment():
|
||||
log.debug('Setting environment tuning')
|
||||
os.environ.setdefault('ACCELERATE', 'True')
|
||||
os.environ.setdefault('ATTN_PRECISION', 'fp16')
|
||||
os.environ.setdefault('ClDeviceGlobalMemSizeAvailablePercent', '100')
|
||||
os.environ.setdefault('CUDA_AUTO_BOOST', '1')
|
||||
os.environ.setdefault('CUDA_CACHE_DISABLE', '0')
|
||||
os.environ.setdefault('CUDA_DEVICE_DEFAULT_PERSISTING_L2_CACHE_PERCENTAGE_LIMIT', '0')
|
||||
@@ -1407,20 +1411,27 @@ def set_environment():
|
||||
os.environ.setdefault('GRADIO_ANALYTICS_ENABLED', 'False')
|
||||
os.environ.setdefault('K_DIFFUSION_USE_COMPILE', '0')
|
||||
os.environ.setdefault('KINETO_LOG_LEVEL', '3')
|
||||
os.environ.setdefault('NEOReadDebugKeys', '1')
|
||||
os.environ.setdefault('NUMEXPR_MAX_THREADS', '16')
|
||||
os.environ.setdefault('PYTHONHTTPSVERIFY', '0')
|
||||
os.environ.setdefault('PYTORCH_ENABLE_MPS_FALLBACK', '1')
|
||||
os.environ.setdefault('PYTORCH_ENABLE_XPU_FALLBACK', '1')
|
||||
os.environ.setdefault('RUNAI_STREAMER_CHUNK_BYTESIZE', '2097152')
|
||||
os.environ.setdefault('RUNAI_STREAMER_LOG_LEVEL', 'DEBUG' if os.environ.get('SD_LOAD_DEBUG') else 'WARNING')
|
||||
os.environ.setdefault('RUNAI_STREAMER_MEMORY_LIMIT', '-1')
|
||||
os.environ.setdefault('SAFETENSORS_FAST_GPU', '1')
|
||||
os.environ.setdefault('SYCL_CACHE_PERSISTENT', '1')
|
||||
os.environ.setdefault('TF_CPP_MIN_LOG_LEVEL', '2')
|
||||
os.environ.setdefault('TF_ENABLE_ONEDNN_OPTS', '0')
|
||||
os.environ.setdefault('TOKENIZERS_PARALLELISM', '0')
|
||||
os.environ.setdefault('TORCH_CUDNN_V8_API_ENABLED', '1')
|
||||
os.environ.setdefault('TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD', '1')
|
||||
os.environ.setdefault('TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL', '1')
|
||||
os.environ.setdefault('UR_L0_ENABLE_RELAXED_ALLOCATION_LIMITS', '1')
|
||||
os.environ.setdefault('USE_TORCH', '1')
|
||||
os.environ.setdefault('UV_INDEX_STRATEGY', 'unsafe-any-match')
|
||||
os.environ.setdefault('UV_NO_BUILD_ISOLATION', '1')
|
||||
os.environ.setdefault('UVICORN_TIMEOUT_KEEP_ALIVE', '60')
|
||||
os.environ.setdefault('RUNAI_STREAMER_CHUNK_BYTESIZE', '2097152')
|
||||
os.environ.setdefault('RUNAI_STREAMER_MEMORY_LIMIT', '-1')
|
||||
os.environ.setdefault('RUNAI_STREAMER_LOG_LEVEL', 'DEBUG' if os.environ.get('SD_LOAD_DEBUG') else 'WARNING')
|
||||
allocator = f'garbage_collection_threshold:{opts.get("torch_gc_threshold", 80)/100:0.2f},max_split_size_mb:512'
|
||||
if opts.get("torch_malloc", "native") == 'cudaMallocAsync':
|
||||
allocator += ',backend:cudaMallocAsync'
|
||||
@@ -1430,14 +1441,6 @@ def set_environment():
|
||||
os.environ.setdefault('PYTORCH_CUDA_ALLOC_CONF', allocator)
|
||||
os.environ.setdefault('PYTORCH_HIP_ALLOC_CONF', allocator)
|
||||
log.debug(f'Torch allocator: "{allocator}"')
|
||||
os.environ.setdefault('TORCH_ROCM_AOTRITON_ENABLE_EXPERIMENTAL', '1')
|
||||
os.environ.setdefault('NEOReadDebugKeys', '1')
|
||||
os.environ.setdefault('ClDeviceGlobalMemSizeAvailablePercent', '100')
|
||||
os.environ.setdefault('SYCL_CACHE_PERSISTENT', '1')
|
||||
os.environ.setdefault('UR_L0_ENABLE_RELAXED_ALLOCATION_LIMITS', '1')
|
||||
os.environ.setdefault('PYTORCH_ENABLE_XPU_FALLBACK', '1')
|
||||
os.environ.setdefault('PYTORCH_ENABLE_MPS_FALLBACK', '1')
|
||||
os.environ.setdefault('TOKENIZERS_PARALLELISM', '0')
|
||||
|
||||
|
||||
def check_extensions():
|
||||
@@ -1644,6 +1647,7 @@ def check_version(reset=True): # pylint: disable=unused-argument
|
||||
# git('git stash pop')
|
||||
ver = git('log -1 --pretty=format:"%h %ad"')
|
||||
log.info(f'Repository upgraded: {ver}')
|
||||
log.warning('Server restart is recommended to apply changes')
|
||||
if ver == latest: # double check
|
||||
restart()
|
||||
except Exception:
|
||||
|
||||
@@ -46,8 +46,8 @@ img { background-color: var(--background-color); }
|
||||
input[type=range] { height: var(--line-xs) !important; appearance: none !important; margin-top: 0 !important; min-width: max(4em, 100%) !important; width: 100% !important; background: transparent !important; }
|
||||
input[type=range]::-webkit-slider-runnable-track { width: 100% !important; height: var(--line-xs) !important; cursor: pointer !important; background: var(--input-background-fill) !important; border: 0px solid var(--primary-900) !important; }
|
||||
input[type=range]::-moz-range-track { width: 100% !important; height: var(--line-xs) !important; cursor: pointer !important; background: var(--input-background-fill) !important; border: 0px solid var(--primary-900) !important; }
|
||||
input[type=range]::-webkit-slider-thumb { border: 0px solid var(--primary-950)0 !important; height: var(--line-sm) !important; width: var(--line-sm) !important; background: var(--highlight-color) !important; cursor: pointer !important; appearance: none !important; margin-top: -4px; border-radius: 4px; }
|
||||
input[type=range]::-moz-range-thumb { border: 0px solid var(--primary-950)0 !important; height: var(--line-sm) !important; width: var(--line-sm) !important; background: var(--highlight-color) !important; cursor: pointer !important; appearance: none !important; margin-top: -4px; border-radius: 4px; }
|
||||
input[type=range]::-webkit-slider-thumb { border: 0px solid var(--primary-950) !important; height: var(--line-sm) !important; width: var(--line-sm) !important; background: var(--highlight-color) !important; cursor: pointer !important; appearance: none !important; margin-top: -4px; border-radius: 4px; }
|
||||
input[type=range]::-moz-range-thumb { border: 0px solid var(--primary-950) !important; height: var(--line-sm) !important; width: var(--line-sm) !important; background: var(--highlight-color) !important; cursor: pointer !important; appearance: none !important; margin-top: -4px; border-radius: 4px; }
|
||||
|
||||
::-webkit-scrollbar { width: 12px; height: 12px; }
|
||||
::-webkit-scrollbar-track { background: var(--primary-800); }
|
||||
|
||||
@@ -553,7 +553,7 @@ svg.feather.feather-image,
|
||||
}
|
||||
|
||||
.output-html {
|
||||
line-height: 1.2 rem;
|
||||
line-height: 1.2rem;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@@ -1016,7 +1016,7 @@ svg.feather.feather-image,
|
||||
|
||||
.loading {
|
||||
color: white;
|
||||
position: border-box;
|
||||
position: absolute;
|
||||
top: 85%;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
@@ -1028,7 +1028,7 @@ svg.feather.feather-image,
|
||||
border-radius: 50%;
|
||||
border-top: var(--spacing-md) solid var(--primary-600);
|
||||
animation: spin 2s linear infinite, pulse 1.5s ease-in-out infinite;
|
||||
position: border-box;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.loader::before,
|
||||
|
||||
@@ -43,12 +43,12 @@
|
||||
--button-secondary-background-fill-hover: var(--neutral-600);
|
||||
--block-title-text-color: var(--neutral-300);
|
||||
--radius-xxs: 0;
|
||||
--radius-xs: 1;
|
||||
--radius-xs: 1px;
|
||||
--radius-sm: 2px;
|
||||
--radius-md: 3;
|
||||
--radius-md: 3px;
|
||||
--radius-lg: 4px;
|
||||
--radius-xl: 5;
|
||||
--radius-xxl: 6;
|
||||
--radius-xl: 5px;
|
||||
--radius-xxl: 6px;
|
||||
--line-xs: 1.0em;
|
||||
--line-sm: 1.2em;
|
||||
--line-md: 1.4em;
|
||||
@@ -77,8 +77,10 @@ button { max-width: 400px; white-space: nowrap; }
|
||||
img { background-color: var(--background-color); }
|
||||
|
||||
input[type='range'] { display: block; margin: 0; padding: 0; height: 0.8em; background-color: transparent; overflow: hidden; cursor: pointer; box-shadow: 0 0 0 0 transparent; -webkit-appearance: none; appearance: none; }
|
||||
/* eslint-disable-next-line css/no-invalid-properties */
|
||||
input[type='range']::-webkit-slider-thumb { height: .9em; width: .9em; background-color: hsl(180, 54%, 61%); box-shadow: var(--range-shadow); border-radius: var(--radius-xs); }
|
||||
input[type='range']::-webkit-slider-runnable-track, input[type='range']::-webkit-slider-thumb { -webkit-appearance: none; }
|
||||
/* eslint-disable-next-line css/no-invalid-properties */
|
||||
input[type='range']::-moz-range-thumb { height: .9em; width: .9em; background-color: hsl(180, 54%, 61%); box-shadow: var(--range-shadow); }
|
||||
input[type='range']::-moz-range-track, input[type='range']::-webkit-slider-runnable-track { border: none; background: none; width: 100%; height: 100%; }
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ function controlInputMode(inputMode, ...args) {
|
||||
if (updateEl) updateEl.click();
|
||||
const tab = gradioApp().querySelector('#control-tab-input button.selected');
|
||||
if (!tab) return ['Image', ...args];
|
||||
// let inputTab = tab.innerText;
|
||||
const tabs = Array.from(gradioApp().querySelectorAll('#control-tab-input button'));
|
||||
const tabIdx = tabs.findIndex((btn) => btn.classList.contains('selected'));
|
||||
const tabNames = ['Image', 'Video', 'Batch', 'Folder'];
|
||||
@@ -21,7 +20,7 @@ async function setupControlUI() {
|
||||
const tabs = ['input', 'output', 'preview'];
|
||||
for (const tab of tabs) {
|
||||
const btn = gradioApp().getElementById(`control-${tab}-button`);
|
||||
if (!btn) continue; // eslint-disable-line no-continue
|
||||
if (!btn) continue;
|
||||
btn.style.cursor = 'pointer';
|
||||
btn.onclick = () => {
|
||||
const t = gradioApp().getElementById(`control-tab-${tab}`);
|
||||
|
||||
@@ -140,39 +140,55 @@ async function filterExtraNetworksForTab(searchTerm) {
|
||||
const cards = Array.from(pg.querySelectorAll('.card') || []);
|
||||
items += cards.length;
|
||||
if (searchTerm === '' || searchTerm === 'all/') {
|
||||
cards.forEach((elem) => elem.style.display = '');
|
||||
cards.forEach((elem) => { elem.style.display = ''; });
|
||||
} else if (searchTerm === 'reference/') {
|
||||
cards.forEach((elem) => elem.style.display = elem.dataset.name
|
||||
.toLowerCase()
|
||||
.includes('reference/') && elem.dataset.tags === '' ? '' : 'none');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = elem.dataset.name
|
||||
.toLowerCase()
|
||||
.includes('reference/') && elem.dataset.tags === '' ? '' : 'none';
|
||||
});
|
||||
} else if (searchTerm === 'distilled/') {
|
||||
cards.forEach((elem) => elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('distilled') ? '' : 'none');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('distilled') ? '' : 'none';
|
||||
});
|
||||
} else if (searchTerm === 'community/') {
|
||||
cards.forEach((elem) => elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('community') ? '' : 'none');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('community') ? '' : 'none';
|
||||
});
|
||||
} else if (searchTerm === 'cloud/') {
|
||||
cards.forEach((elem) => elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('cloud') ? '' : 'none');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('cloud') ? '' : 'none';
|
||||
});
|
||||
} else if (searchTerm === 'quantized/') {
|
||||
cards.forEach((elem) => elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('quantized') ? '' : 'none');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = elem.dataset.tags
|
||||
.toLowerCase()
|
||||
.includes('quantized') ? '' : 'none';
|
||||
});
|
||||
} else if (searchTerm === 'local/') {
|
||||
cards.forEach((elem) => elem.style.display = elem.dataset.name
|
||||
.toLowerCase()
|
||||
.includes('reference/') ? 'none' : '');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = elem.dataset.name
|
||||
.toLowerCase()
|
||||
.includes('reference/') ? 'none' : '';
|
||||
});
|
||||
} else if (searchTerm === 'diffusers/') {
|
||||
cards.forEach((elem) => elem.style.display = elem.dataset.name
|
||||
.toLowerCase().replace('models--', 'diffusers').replaceAll('\\', '/')
|
||||
.includes('diffusers/') ? '' : 'none');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = elem.dataset.name
|
||||
.toLowerCase().replace('models--', 'diffusers').replaceAll('\\', '/')
|
||||
.includes('diffusers/') ? '' : 'none';
|
||||
});
|
||||
} else if (searchTerm.startsWith('r#')) {
|
||||
searchTerm = searchTerm.substring(2);
|
||||
const re = new RegExp(searchTerm, 'i');
|
||||
cards.forEach((elem) => elem.style.display = re.test(`filename: ${elem.dataset.filename}|name: ${elem.dataset.name}|tags: ${elem.dataset.tags}`) ? '' : 'none');
|
||||
cards.forEach((elem) => {
|
||||
elem.style.display = re.test(`filename: ${elem.dataset.filename}|name: ${elem.dataset.name}|tags: ${elem.dataset.tags}`) ? '' : 'none';
|
||||
});
|
||||
} else {
|
||||
const searchList = searchTerm.split('|').filter((s) => s !== '' && !s.startsWith('-')).map((s) => s.trim());
|
||||
const excludeList = searchTerm.split('|').filter((s) => s !== '' && s.trim().startsWith('-')).map((s) => s.trim().substring(1).trim());
|
||||
@@ -198,8 +214,8 @@ async function filterExtraNetworksForTab(searchTerm) {
|
||||
}
|
||||
|
||||
function tryToRemoveExtraNetworkFromPrompt(textarea, text) {
|
||||
const re_extranet = /<([^:]+:[^:]+):[\d\.]+>/;
|
||||
const re_extranet_g = /\s+<([^:]+:[^:]+):[\d\.]+>/g;
|
||||
const re_extranet = /<([^:]+:[^:]+):[\d.]+>/;
|
||||
const re_extranet_g = /\s+<([^:]+:[^:]+):[\d.]+>/g;
|
||||
let m = text.match(re_extranet);
|
||||
let replaced = false;
|
||||
let newTextareaText;
|
||||
@@ -243,7 +259,7 @@ function sortExtraNetworks(fixed = 'no') {
|
||||
const cards = Array.from(pg.querySelectorAll('.card') || []);
|
||||
if (cards.length === 0) return 'sort: no cards';
|
||||
num += cards.length;
|
||||
cards.sort((a, b) => { // eslint-disable-line no-loop-func
|
||||
cards.sort((a, b) => {
|
||||
switch (sortVal) {
|
||||
case 0: return 0;
|
||||
case 1: return a.dataset.name ? a.dataset.name.localeCompare(b.dataset.name) : 0;
|
||||
@@ -310,21 +326,21 @@ function extraNetworksSearchButton(event) {
|
||||
|
||||
function extraNetworksFilterVersion(event) {
|
||||
const version = event.target.textContent.trim();
|
||||
const activeTab = getENActiveTab();
|
||||
const activePage = getENActivePage().toLowerCase();
|
||||
let cardContainer = gradioApp().querySelector(`#${activeTab}_${activePage}_cards`);
|
||||
if (!cardContainer) cardContainer = gradioApp().querySelector(`#txt2img_extra_networks_${activePage}_cards`);
|
||||
log('extraNetworksFilterVersion', { version, activeTab, activePage, cardContainer });
|
||||
if (!cardContainer) return;
|
||||
if (cardContainer.dataset.activeVersion === version) {
|
||||
cardContainer.dataset.activeVersion = '';
|
||||
cardContainer.querySelectorAll('.card').forEach((card) => card.style.display = '');
|
||||
} else {
|
||||
cardContainer.dataset.activeVersion = version;
|
||||
cardContainer.querySelectorAll('.card').forEach((card) => {
|
||||
if (card.dataset.version === version) card.style.display = '';
|
||||
else card.style.display = 'none';
|
||||
});
|
||||
const cardContainers = gradioApp().querySelectorAll('.extra-network-cards');
|
||||
log('extraNetworksFilterVersion', { activePage, version });
|
||||
for (const cardContainer of cardContainers) {
|
||||
if (!cardContainer.id.includes(activePage)) continue;
|
||||
if (cardContainer.dataset.activeVersion === version) {
|
||||
cardContainer.dataset.activeVersion = '';
|
||||
cardContainer.querySelectorAll('.card').forEach((card) => { card.style.display = ''; });
|
||||
} else {
|
||||
cardContainer.dataset.activeVersion = version;
|
||||
cardContainer.querySelectorAll('.card').forEach((card) => {
|
||||
if (card.dataset.version === version) card.style.display = '';
|
||||
else card.style.display = 'none';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
/* eslint lines-between-class-members: ["error", "always", { "exceptAfterSingleLine": true }] */
|
||||
let ws;
|
||||
let url;
|
||||
let currentImage;
|
||||
let currentImage = null;
|
||||
let pruneImagesTimer;
|
||||
let outstanding = 0;
|
||||
let lastSort = 0;
|
||||
let lastSortName = 'None';
|
||||
let gallerySelection = { files: [], index: -1 };
|
||||
const galleryHashes = new Set();
|
||||
let maintenanceController = new AbortController();
|
||||
const folderStylesheet = new CSSStyleSheet();
|
||||
@@ -24,6 +24,64 @@ const el = {
|
||||
|
||||
const SUPPORTED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'tiff', 'jp2', 'jxl', 'gif', 'mp4', 'mkv', 'avi', 'mjpeg', 'mpg', 'avr'];
|
||||
|
||||
function getVisibleGalleryFiles() {
|
||||
if (!el.files) return [];
|
||||
return Array.from(el.files.children).filter((node) => node.name && node.offsetParent);
|
||||
}
|
||||
|
||||
function updateGallerySelectionClasses(files = gallerySelection.files, index = gallerySelection.index) {
|
||||
files.forEach((file, i) => {
|
||||
file.classList.toggle('gallery-file-selected', i === index);
|
||||
});
|
||||
}
|
||||
|
||||
function refreshGallerySelection() {
|
||||
updateGallerySelectionClasses(gallerySelection.files, -1);
|
||||
const files = getVisibleGalleryFiles();
|
||||
const index = files.findIndex((file) => file.src === currentImage);
|
||||
gallerySelection = { files, index };
|
||||
updateGallerySelectionClasses(files, index);
|
||||
}
|
||||
|
||||
function resetGallerySelection() {
|
||||
updateGallerySelectionClasses(gallerySelection.files, -1);
|
||||
gallerySelection = { files: [], index: -1 };
|
||||
currentImage = null;
|
||||
}
|
||||
|
||||
function applyGallerySelection(index, { send = true } = {}) {
|
||||
if (!gallerySelection.files.length) refreshGallerySelection();
|
||||
const files = gallerySelection.files;
|
||||
if (!files.length) return;
|
||||
if (!Number.isInteger(index) || index < 0 || index >= files.length) {
|
||||
log('gallery selection index out of range', index, files.length);
|
||||
resetGallerySelection();
|
||||
return;
|
||||
}
|
||||
gallerySelection.index = index;
|
||||
currentImage = files[index].src;
|
||||
updateGallerySelectionClasses(files, index);
|
||||
if (send && el.btnSend) el.btnSend.click();
|
||||
}
|
||||
|
||||
function setGallerySelectionByElement(element, options) {
|
||||
if (!gallerySelection.files.length) refreshGallerySelection();
|
||||
let index = gallerySelection.files.findIndex((file) => file === element);
|
||||
if (index < 0) {
|
||||
refreshGallerySelection();
|
||||
index = gallerySelection.files.findIndex((file) => file === element);
|
||||
}
|
||||
if (index >= 0) applyGallerySelection(index, options);
|
||||
}
|
||||
|
||||
function buildGalleryFileUrl(path) {
|
||||
return new URL(`/file=${encodeURI(path)}`, window.location.origin).toString();
|
||||
}
|
||||
|
||||
window.getGallerySelection = () => ({ index: gallerySelection.index, files: gallerySelection.files });
|
||||
window.setGallerySelection = (index, options) => applyGallerySelection(index, options);
|
||||
window.getGallerySelectedUrl = () => (currentImage ? buildGalleryFileUrl(currentImage) : null);
|
||||
|
||||
/**
|
||||
* Wait for the `outstanding` variable to be below the specified value
|
||||
* @param {number} num - Threshold for `outstanding`
|
||||
@@ -103,11 +161,91 @@ function updateGalleryStyles() {
|
||||
.gallery-file:hover {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
:host(.gallery-file-selected) .gallery-file {
|
||||
box-shadow: 0 0 0 2px var(--sd-button-selected-color);
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
// Classes
|
||||
|
||||
class SimpleProgressBar {
|
||||
#container = document.createElement('div');
|
||||
#progress = document.createElement('div');
|
||||
#textDiv = document.createElement('div');
|
||||
#text = document.createElement('span');
|
||||
#visible = false;
|
||||
#hideTimeout = null;
|
||||
#interval = null;
|
||||
#max = 0;
|
||||
/** @type {Set} */
|
||||
#monitoredSet;
|
||||
|
||||
constructor(monitoredSet) {
|
||||
this.#monitoredSet = monitoredSet; // This is required because incrementing a variable with a class method turned out to not be an atomic operation
|
||||
this.#container.style.cssText = 'position:relative;overflow:hidden;border-radius:var(--sd-border-radius);width:100%;background-color:hsla(0,0%,36%,0.3);height:1.2rem;margin:0;padding:0;display:none;';
|
||||
this.#progress.style.cssText = 'position:absolute;left:0;height:100%;width:0;transition:width 200ms;';
|
||||
this.#progress.style.backgroundColor = 'hsla(110, 32%, 35%, 0.80)'; // alt: '#27911d'
|
||||
this.#textDiv.style.cssText = 'position:relative;margin:auto;width:max-content;height:100%;';
|
||||
this.#text.style.cssText = 'user-select:none;color:white;';
|
||||
|
||||
this.#textDiv.append(this.#text);
|
||||
this.#container.append(this.#progress, this.#textDiv);
|
||||
}
|
||||
|
||||
start(total) {
|
||||
this.clear();
|
||||
this.#max = total;
|
||||
this.#interval = setInterval(() => {
|
||||
this.#update(this.#monitoredSet.size, this.#max);
|
||||
}, 250);
|
||||
}
|
||||
|
||||
attachTo(element) {
|
||||
if (element.hasChildNodes) {
|
||||
element.innerHTML = '';
|
||||
}
|
||||
element.appendChild(this.#container);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.#stop();
|
||||
clearTimeout(this.#hideTimeout);
|
||||
this.#hideTimeout = null;
|
||||
this.#container.style.display = 'none';
|
||||
this.#visible = false;
|
||||
this.#progress.style.width = '0';
|
||||
this.#text.textContent = '';
|
||||
}
|
||||
|
||||
#update(loaded, max) {
|
||||
if (this.#hideTimeout) {
|
||||
this.#hideTimeout = null;
|
||||
}
|
||||
|
||||
this.#progress.style.width = `${Math.floor((loaded / max) * 100)}%`;
|
||||
this.#text.textContent = `${loaded}/${max}`;
|
||||
|
||||
if (!this.#visible) {
|
||||
this.#container.style.display = 'block';
|
||||
this.#visible = true;
|
||||
}
|
||||
if (loaded >= max) {
|
||||
this.#stop();
|
||||
this.#hideTimeout = setTimeout(() => {
|
||||
this.clear();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
#stop() {
|
||||
clearInterval(this.#interval);
|
||||
this.#interval = null;
|
||||
}
|
||||
}
|
||||
|
||||
const galleryProgressBar = new SimpleProgressBar(galleryHashes);
|
||||
|
||||
/* This isn't as robust as the Web Locks API, but it will at least work if accessing a remote machine without HTTPS */
|
||||
class SimpleFunctionQueue {
|
||||
#id;
|
||||
@@ -163,9 +301,16 @@ class SimpleFunctionQueue {
|
||||
// HTML Elements
|
||||
|
||||
class GalleryFolder extends HTMLElement {
|
||||
constructor(name) {
|
||||
constructor(folder) {
|
||||
super();
|
||||
this.name = decodeURI(name);
|
||||
// Support both old format (string) and new format (object with path and label)
|
||||
if (typeof folder === 'object' && folder !== null) {
|
||||
this.name = decodeURI(folder.path || '');
|
||||
this.label = decodeURI(folder.label || folder.path || '');
|
||||
} else {
|
||||
this.name = decodeURI(folder);
|
||||
this.label = this.name;
|
||||
}
|
||||
this.style.overflowX = 'hidden';
|
||||
this.shadow = this.attachShadow({ mode: 'open' });
|
||||
this.shadow.adoptedStyleSheets = [folderStylesheet];
|
||||
@@ -174,8 +319,8 @@ class GalleryFolder extends HTMLElement {
|
||||
connectedCallback() {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'gallery-folder';
|
||||
div.innerHTML = `<span class="gallery-folder-icon">\uf03e</span> ${this.name}`;
|
||||
div.title = this.name;
|
||||
div.innerHTML = `<span class="gallery-folder-icon">\uf03e</span> ${this.label}`;
|
||||
div.title = this.name; // Show full path on hover
|
||||
div.addEventListener('click', () => {
|
||||
for (const folder of el.folders.children) {
|
||||
if (folder.name === this.name) folder.shadow.firstElementChild.classList.add('gallery-folder-selected');
|
||||
@@ -220,7 +365,7 @@ async function handleSeparator(separator) {
|
||||
if (!f.name) continue; // Skip separators
|
||||
|
||||
// Check if file belongs to this exact directory
|
||||
const fileDir = f.name.match(/(.*)[\/\\]/);
|
||||
const fileDir = f.name.match(/(.*)[/\\]/);
|
||||
const fileDirPath = fileDir ? fileDir[1] : '';
|
||||
|
||||
if (separator.title.length > 0 && fileDirPath === separator.title) {
|
||||
@@ -232,14 +377,18 @@ async function handleSeparator(separator) {
|
||||
}
|
||||
|
||||
async function addSeparators() {
|
||||
document.querySelectorAll('.gallery-separator').forEach((node) => el.files.removeChild(node));
|
||||
document.querySelectorAll('.gallery-separator').forEach((node) => { el.files.removeChild(node); });
|
||||
const all = Array.from(el.files.children);
|
||||
let lastDir;
|
||||
let isFirstSeparator = true; // Flag to open the first separator by default
|
||||
|
||||
// Count root files (files without a directory path)
|
||||
const hasRootFiles = all.some((f) => f.name && !f.name.match(/[/\\]/));
|
||||
// Only auto-open first separator if there are no root files to display
|
||||
let isFirstSeparator = !hasRootFiles;
|
||||
|
||||
// First pass: create separators
|
||||
for (const f of all) {
|
||||
let dir = f.name?.match(/(.*)[\/\\]/);
|
||||
let dir = f.name?.match(/(.*)[/\\]/);
|
||||
if (!dir) dir = '';
|
||||
else dir = dir[1];
|
||||
if (dir !== lastDir) {
|
||||
@@ -249,7 +398,7 @@ async function addSeparators() {
|
||||
let fileCount = 0;
|
||||
for (const file of all) {
|
||||
if (!file.name) continue;
|
||||
const fileDir = file.name.match(/(.*)[\/\\]/);
|
||||
const fileDir = file.name.match(/(.*)[/\\]/);
|
||||
const fileDirPath = fileDir ? fileDir[1] : '';
|
||||
if (fileDirPath === dir) fileCount++;
|
||||
}
|
||||
@@ -299,7 +448,7 @@ async function addSeparators() {
|
||||
for (const f of all) {
|
||||
if (!f.name) continue; // Skip separators
|
||||
|
||||
const dir = f.name.match(/(.*)[\/\\]/);
|
||||
const dir = f.name.match(/(.*)[/\\]/);
|
||||
if (dir && dir[1]) {
|
||||
const dirPath = dir[1];
|
||||
const isOpen = separatorStates.get(dirPath);
|
||||
@@ -357,7 +506,7 @@ class GalleryFile extends HTMLElement {
|
||||
}
|
||||
|
||||
// Check separator state early to hide the element immediately
|
||||
const dir = this.name.match(/(.*)[\/\\]/);
|
||||
const dir = this.name.match(/(.*)[/\\]/);
|
||||
if (dir && dir[1]) {
|
||||
const dirPath = dir[1];
|
||||
const isOpen = separatorStates.get(dirPath);
|
||||
@@ -366,7 +515,9 @@ class GalleryFile extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
this.hash = await getHash(`${this.folder}/${this.name}/${this.size}/${this.mtime}`); // eslint-disable-line no-use-before-define
|
||||
// Normalize path to ensure consistent hash regardless of which folder view is used
|
||||
const normalizedPath = this.src.replace(/\/+/g, '/').replace(/\/$/, '');
|
||||
this.hash = await getHash(`${normalizedPath}/${this.size}/${this.mtime}`); // eslint-disable-line no-use-before-define
|
||||
const cachedData = (this.hash && opts.browser_cache) ? await idbGet(this.hash).catch(() => undefined) : undefined;
|
||||
const img = document.createElement('img');
|
||||
img.className = 'gallery-file';
|
||||
@@ -402,9 +553,11 @@ class GalleryFile extends HTMLElement {
|
||||
this.size = json.size;
|
||||
this.mtime = new Date(json.mtime);
|
||||
if (opts.browser_cache) {
|
||||
// Store file's actual parent directory (not browsed folder) for consistent cleanup
|
||||
const fileDir = this.src.replace(/\/+/g, '/').replace(/\/[^/]+$/, '');
|
||||
await idbAdd({
|
||||
hash: this.hash,
|
||||
folder: this.folder,
|
||||
folder: fileDir,
|
||||
file: this.name,
|
||||
size: this.size,
|
||||
mtime: this.mtime,
|
||||
@@ -430,8 +583,7 @@ class GalleryFile extends HTMLElement {
|
||||
return;
|
||||
} // ... to here unless modifications are also being made to maintenance functionality and the usage of AbortController/AbortSignal
|
||||
img.onclick = () => {
|
||||
currentImage = this.src;
|
||||
el.btnSend.click();
|
||||
setGallerySelectionByElement(this, { send: true });
|
||||
};
|
||||
img.title = `Folder: ${this.folder}\nFile: ${this.name}\nSize: ${this.size.toLocaleString()} bytes\nModified: ${this.mtime.toLocaleString()}`;
|
||||
if (this.shadow.children.length > 0) {
|
||||
@@ -538,7 +690,7 @@ async function wsConnect(socket, timeout = 5000) {
|
||||
|
||||
let loop = 0;
|
||||
while (socket.readyState === WebSocket.CONNECTING && loop < ttl) {
|
||||
await new Promise((resolve) => setTimeout(resolve, intrasleep)); // eslint-disable-line no-promise-executor-return
|
||||
await new Promise((resolve) => { setTimeout(resolve, intrasleep); });
|
||||
loop++;
|
||||
}
|
||||
return isOpened();
|
||||
@@ -569,7 +721,7 @@ async function gallerySearch() {
|
||||
});
|
||||
|
||||
allFiles.forEach((f) => {
|
||||
const dir = f.name.match(/(.*)[\/\\]/);
|
||||
const dir = f.name.match(/(.*)[/\\]/);
|
||||
const dirPath = (dir && dir[1]) ? dir[1] : '';
|
||||
const isOpen = separatorStates.get(dirPath);
|
||||
f.style.display = (!dirPath || isOpen) ? 'unset' : 'none';
|
||||
@@ -603,7 +755,7 @@ async function gallerySearch() {
|
||||
if (isMatch) {
|
||||
fileMatches.add(f);
|
||||
totalFound++;
|
||||
const dir = f.name.match(/(.*)[\/\\]/);
|
||||
const dir = f.name.match(/(.*)[/\\]/);
|
||||
const dirPath = (dir && dir[1]) ? dir[1] : '';
|
||||
directoryMatches.set(dirPath, (directoryMatches.get(dirPath) || 0) + 1);
|
||||
}
|
||||
@@ -634,6 +786,7 @@ async function gallerySearch() {
|
||||
|
||||
const t1 = performance.now();
|
||||
updateStatusWithSort('Filter', ['Images', `${totalFound.toLocaleString()} / ${allFiles.length.toLocaleString()}`], `${iconStopwatch} ${Math.floor(t1 - t0).toLocaleString()}ms`);
|
||||
refreshGallerySelection();
|
||||
}, 250);
|
||||
}
|
||||
|
||||
@@ -653,59 +806,84 @@ async function gallerySort(btn) {
|
||||
if (arr.length === 0) return; // no files to sort
|
||||
if (btn) lastSort = btn.charCodeAt(0);
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
// Helper to get directory path from a file node
|
||||
const getDirPath = (node) => {
|
||||
const match = node.name.match(/(.*)[/\\]/);
|
||||
return match ? match[1] : '';
|
||||
};
|
||||
|
||||
// Partition into root files and subfolder files - root files always stay at top
|
||||
const rootFiles = arr.filter((node) => !getDirPath(node));
|
||||
const subfolderFiles = arr.filter((node) => getDirPath(node));
|
||||
|
||||
// Group subfolder files by directory
|
||||
const folderGroups = new Map();
|
||||
for (const file of subfolderFiles) {
|
||||
const dir = getDirPath(file);
|
||||
if (!folderGroups.has(dir)) {
|
||||
folderGroups.set(dir, []);
|
||||
}
|
||||
folderGroups.get(dir).push(file);
|
||||
}
|
||||
|
||||
// Sort function based on current sort mode
|
||||
let sortFn;
|
||||
switch (lastSort) {
|
||||
case 61789: // name asc
|
||||
lastSortName = 'Name Ascending';
|
||||
arr
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => a.name.localeCompare(b.name);
|
||||
break;
|
||||
case 61790: // name dsc
|
||||
lastSortName = 'Name Descending';
|
||||
arr
|
||||
.sort((b, a) => a.name.localeCompare(b.name))
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => b.name.localeCompare(a.name);
|
||||
break;
|
||||
case 61792: // size asc
|
||||
lastSortName = 'Size Ascending';
|
||||
arr
|
||||
.sort((a, b) => a.size - b.size)
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => a.size - b.size;
|
||||
break;
|
||||
case 61793: // size dsc
|
||||
lastSortName = 'Size Descending';
|
||||
arr
|
||||
.sort((b, a) => a.size - b.size)
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => b.size - a.size;
|
||||
break;
|
||||
case 61794: // resolution asc
|
||||
lastSortName = 'Resolution Ascending';
|
||||
arr
|
||||
.sort((a, b) => a.width * a.height - b.width * b.height)
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => a.width * a.height - b.width * b.height;
|
||||
break;
|
||||
case 61795: // resolution dsc
|
||||
lastSortName = 'Resolution Descending';
|
||||
arr
|
||||
.sort((b, a) => a.width * a.height - b.width * b.height)
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => b.width * b.height - a.width * a.height;
|
||||
break;
|
||||
case 61662:
|
||||
lastSortName = 'Modified Ascending';
|
||||
arr
|
||||
.sort((a, b) => a.mtime - b.mtime)
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => a.mtime - b.mtime;
|
||||
break;
|
||||
case 61661:
|
||||
lastSortName = 'Modified Descending';
|
||||
arr
|
||||
.sort((b, a) => a.mtime - b.mtime)
|
||||
.forEach((node) => fragment.appendChild(node));
|
||||
sortFn = (a, b) => b.mtime - a.mtime;
|
||||
break;
|
||||
default:
|
||||
lastSortName = 'None';
|
||||
sortFn = null;
|
||||
break;
|
||||
}
|
||||
|
||||
// Sort root files
|
||||
if (sortFn) {
|
||||
rootFiles.sort(sortFn);
|
||||
}
|
||||
rootFiles.forEach((node) => fragment.appendChild(node));
|
||||
|
||||
// Sort folder names alphabetically, then sort files within each folder
|
||||
const sortedFolderNames = Array.from(folderGroups.keys()).sort((a, b) => a.localeCompare(b));
|
||||
for (const folderName of sortedFolderNames) {
|
||||
const files = folderGroups.get(folderName);
|
||||
if (sortFn) {
|
||||
files.sort(sortFn);
|
||||
}
|
||||
files.forEach((node) => fragment.appendChild(node));
|
||||
}
|
||||
|
||||
if (fragment.children.length === 0) return;
|
||||
el.files.innerHTML = '';
|
||||
el.files.appendChild(fragment);
|
||||
@@ -716,7 +894,7 @@ async function gallerySort(btn) {
|
||||
for (const f of all) {
|
||||
if (!f.name) continue; // Skip separators
|
||||
|
||||
const dir = f.name.match(/(.*)[\/\\]/);
|
||||
const dir = f.name.match(/(.*)[/\\]/);
|
||||
if (dir && dir[1]) {
|
||||
const dirPath = dir[1];
|
||||
const isOpen = separatorStates.get(dirPath);
|
||||
@@ -729,6 +907,7 @@ async function gallerySort(btn) {
|
||||
const t1 = performance.now();
|
||||
log(`gallerySort: char=${lastSort} len=${arr.length} time=${Math.floor(t1 - t0)} sort=${lastSortName}`);
|
||||
updateStatusWithSort(['Images', arr.length.toLocaleString()], `${iconStopwatch} ${Math.floor(t1 - t0).toLocaleString()}ms`);
|
||||
refreshGallerySelection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -856,12 +1035,15 @@ async function fetchFilesHT(evt, controller) {
|
||||
}
|
||||
}
|
||||
|
||||
if (controller.signal.aborted) return;
|
||||
el.files.appendChild(fragment);
|
||||
|
||||
const t1 = performance.now();
|
||||
log(`gallery: folder=${evt.target.name} num=${numFiles} time=${Math.floor(t1 - t0)}ms`);
|
||||
updateStatusWithSort(['Folder', evt.target.name], ['Images', numFiles.toLocaleString()], `${iconStopwatch} ${Math.floor(t1 - t0).toLocaleString()}ms`);
|
||||
galleryProgressBar.start(numFiles);
|
||||
addSeparators();
|
||||
refreshGallerySelection();
|
||||
thumbCacheCleanup(evt.target.name, numFiles, controller);
|
||||
}
|
||||
|
||||
@@ -871,6 +1053,8 @@ async function fetchFilesWS(evt) { // fetch file-by-file list over websockets
|
||||
maintenanceController.abort('Gallery update'); // Abort previous controller
|
||||
maintenanceController = controller; // Point to new controller for next time
|
||||
galleryHashes.clear(); // Must happen AFTER the AbortController steps
|
||||
galleryProgressBar.clear();
|
||||
resetGallerySelection();
|
||||
|
||||
el.files.innerHTML = '';
|
||||
updateGalleryStyles();
|
||||
@@ -915,11 +1099,14 @@ async function fetchFilesWS(evt) { // fetch file-by-file list over websockets
|
||||
}
|
||||
};
|
||||
ws.onclose = (event) => {
|
||||
if (controller.signal.aborted) return;
|
||||
el.files.appendChild(fragment);
|
||||
// gallerySort();
|
||||
log(`gallery: folder=${evt.target.name} num=${numFiles} time=${Math.floor(t1 - t0)}ms`);
|
||||
updateStatusWithSort(['Folder', evt.target.name], ['Images', numFiles.toLocaleString()], `${iconStopwatch} ${Math.floor(t1 - t0).toLocaleString()}ms`);
|
||||
galleryProgressBar.start(numFiles);
|
||||
addSeparators();
|
||||
refreshGallerySelection();
|
||||
thumbCacheCleanup(evt.target.name, numFiles, controller);
|
||||
};
|
||||
ws.onerror = (event) => {
|
||||
@@ -973,7 +1160,8 @@ async function monitorGalleries() {
|
||||
|
||||
async function setOverlayAnimation() {
|
||||
const busyAnimation = document.createElement('style');
|
||||
busyAnimation.textContent = '.idbBusyAnim{width:16px;height:16px;border-radius:50%;display:block;margin:40px;position:relative;background:#ff3d00;color:#fff;box-shadow:-24px 0,24px 0;box-sizing:border-box;animation:2s ease-in-out infinite overlayRotation}@keyframes overlayRotation{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}'; // eslint-disable-line max-len
|
||||
// eslint-disable-next-line @stylistic/max-len
|
||||
busyAnimation.textContent = '.idbBusyAnim{width:16px;height:16px;border-radius:50%;display:block;margin:40px;position:relative;background:#ff3d00;color:#fff;box-shadow:-24px 0,24px 0;box-sizing:border-box;animation:2s ease-in-out infinite overlayRotation}@keyframes overlayRotation{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}';
|
||||
document.head.append(busyAnimation);
|
||||
}
|
||||
|
||||
@@ -990,6 +1178,12 @@ async function initGallery() { // triggered on gradio change to monitor when ui
|
||||
updateGalleryStyles();
|
||||
injectGalleryStatusCSS();
|
||||
setOverlayAnimation();
|
||||
const progress = gradioApp().getElementById('tab-gallery-progress');
|
||||
if (progress) {
|
||||
galleryProgressBar.attachTo(progress);
|
||||
} else {
|
||||
log('initGallery', 'Failed to attach loading progress bar');
|
||||
}
|
||||
el.search.addEventListener('input', gallerySearch);
|
||||
el.btnSend = gradioApp().getElementById('tab-gallery-send-image');
|
||||
document.getElementById('tab-gallery-files').style.height = opts.logmonitor_show ? '75vh' : '85vh';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
let gpuInterval = null; // eslint-disable-line prefer-const
|
||||
let gpuInterval = null;
|
||||
const chartData = { mem: [], load: [] };
|
||||
|
||||
async function updateGPUChart(mem, load) {
|
||||
const maxLen = 120;
|
||||
const colorRangeMap = $.range_map({ // eslint-disable-line no-undef
|
||||
const colorRangeMap = $.range_map({
|
||||
'0:5': '#fffafa',
|
||||
'6:10': '#fff7ed',
|
||||
'11:20': '#fed7aa',
|
||||
@@ -22,8 +22,8 @@ async function updateGPUChart(mem, load) {
|
||||
chartData.load.push(load);
|
||||
if (chartData.mem.length > maxLen) chartData.mem.shift();
|
||||
chartData.mem.push(mem);
|
||||
$('#gpuChart').sparkline(chartData.load, sparklineConfigLOAD); // eslint-disable-line no-undef
|
||||
$('#gpuChart').sparkline(chartData.mem, sparklineConfigMEM); // eslint-disable-line no-undef
|
||||
$('#gpuChart').sparkline(chartData.load, sparklineConfigLOAD);
|
||||
$('#gpuChart').sparkline(chartData.mem, sparklineConfigMEM);
|
||||
}
|
||||
|
||||
async function updateGPU() {
|
||||
|
||||
@@ -32,6 +32,7 @@ function closeModal(evt, force = false) {
|
||||
}
|
||||
|
||||
function modalImageSwitch(offset) {
|
||||
const negmod = (n, m) => ((n % m) + m) % m;
|
||||
const galleryButtons = all_gallery_buttons();
|
||||
if (galleryButtons.length > 1) {
|
||||
const currentButton = selected_gallery_button();
|
||||
@@ -39,7 +40,6 @@ function modalImageSwitch(offset) {
|
||||
galleryButtons.forEach((v, i) => {
|
||||
if (v === currentButton) result = i;
|
||||
});
|
||||
const negmod = (n, m) => ((n % m) + m) % m;
|
||||
if (result !== -1) {
|
||||
const nextButton = galleryButtons[negmod((result + offset), galleryButtons.length)];
|
||||
nextButton.click();
|
||||
@@ -47,8 +47,24 @@ function modalImageSwitch(offset) {
|
||||
const modal = gradioApp().getElementById('lightboxModal');
|
||||
modalImage.src = nextButton.children[0].src;
|
||||
if (modalImage.style.display === 'none') modal.style.setProperty('background-image', `url(${modalImage.src})`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const galleryFilesContainer = gradioApp().getElementById('tab-gallery-files');
|
||||
if (!galleryFilesContainer || !galleryFilesContainer.offsetParent) return;
|
||||
const gallerySelection = window.getGallerySelection();
|
||||
if (!gallerySelection.files.length || gallerySelection.files.length <= 1) return;
|
||||
const baseIndex = gallerySelection.index >= 0 ? gallerySelection.index : 0;
|
||||
const nextIndex = negmod((baseIndex + offset), gallerySelection.files.length);
|
||||
window.setGallerySelection(nextIndex, { send: true });
|
||||
const modalImage = gradioApp().getElementById('modalImage');
|
||||
const modal = gradioApp().getElementById('lightboxModal');
|
||||
const directSrc = window.getGallerySelectedUrl();
|
||||
if (modalImage && modal && directSrc) {
|
||||
modalImage.src = directSrc;
|
||||
if (modalImage.style.display === 'none') modal.style.setProperty('background-image', `url(${directSrc})`);
|
||||
}
|
||||
}
|
||||
|
||||
function modalSaveImage(event) {
|
||||
|
||||
@@ -150,7 +150,10 @@ async function idbFolderCleanup(keepSet, folder, signal) {
|
||||
throw new Error('IndexedDB cleaning function must be told the current active folder');
|
||||
}
|
||||
|
||||
let removals = new Set(await idbGetAllKeys('folder', folder));
|
||||
// Use range query to match folder and all its subdirectories
|
||||
const folderNormalized = folder.replace(/\/+/g, '/').replace(/\/$/, '');
|
||||
const range = IDBKeyRange.bound(folderNormalized, `${folderNormalized}\uffff`, false, true);
|
||||
let removals = new Set(await idbGetAllKeys('folder', range));
|
||||
removals = removals.difference(keepSet); // Don't need to keep full set in memory
|
||||
const totalRemovals = removals.size;
|
||||
if (signal.aborted) {
|
||||
|
||||
@@ -56,7 +56,7 @@ async function logMonitor() {
|
||||
if (imgGallery) imgGallery.style.height = opts.logmonitor_show ? '50vh' : '55vh';
|
||||
|
||||
if (!opts.logmonitor_show) {
|
||||
Array.from(document.getElementsByClassName('log-monitor')).forEach((el) => el.style.display = 'none');
|
||||
Array.from(document.getElementsByClassName('log-monitor')).forEach((el) => { el.style.display = 'none'; });
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ const log = async (...msg) => {
|
||||
window.logger.innerHTML += window.logPrettyPrint(...msg);
|
||||
scrollBottom(window.logger);
|
||||
}
|
||||
console.log(ts, ...msg); // eslint-disable-line no-console
|
||||
console.log(ts, ...msg);
|
||||
};
|
||||
|
||||
const debug = async (...msg) => {
|
||||
@@ -20,7 +20,7 @@ const debug = async (...msg) => {
|
||||
window.logger.innerHTML += window.logPrettyPrint(...msg);
|
||||
scrollBottom(window.logger);
|
||||
}
|
||||
console.debug(ts, ...msg); // eslint-disable-line no-console
|
||||
console.debug(ts, ...msg);
|
||||
};
|
||||
|
||||
const error = async (...msg) => {
|
||||
@@ -30,7 +30,7 @@ const error = async (...msg) => {
|
||||
window.logger.innerHTML += window.logPrettyPrint(...msg);
|
||||
scrollBottom(window.logger);
|
||||
}
|
||||
console.error(ts, ...msg); // eslint-disable-line no-console
|
||||
console.error(ts, ...msg);
|
||||
// const txt = msg.join(' ');
|
||||
// if (!txt.includes('asctime') && !txt.includes('xhr.')) xhrPost('/sdapi/v1/log', { error: txt }); // eslint-disable-line no-use-before-define
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ function setRefreshInterval() {
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.hidden) refreshInterval = Math.max(2500, opts.live_preview_refresh_period || 1000);
|
||||
else refreshInterval = opts.live_preview_refresh_period || 1000;
|
||||
log('refreshInterval', document.visibilityState, refreshInterval);
|
||||
// log('refreshInterval', document.visibilityState, refreshInterval);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2031,42 +2031,43 @@ div:has(>#tab-gallery-folders) {
|
||||
|
||||
.loading {
|
||||
color: white;
|
||||
position: border-box;
|
||||
top: 85%;
|
||||
font-size: 1.5em;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.loader {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
animation: spin 4s linear infinite, hue 5s infinite alternate;
|
||||
border: var(--spacing-md) solid transparent;
|
||||
border-radius: 50%;
|
||||
border-top: var(--spacing-md) solid var(--primary-600);
|
||||
animation: spin 2s linear infinite, hue 5s infinite alternate;
|
||||
position: border-box;
|
||||
border-top: var(--spacing-md) solid var(--sd-main-accent-color);
|
||||
height: 300px;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.loader::before,
|
||||
.loader::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
bottom: 6px;
|
||||
left: 6px;
|
||||
right: 6px;
|
||||
border-radius: 50%;
|
||||
.loader::before, .loader::after {
|
||||
border: var(--spacing-md) solid transparent;
|
||||
animation: hue 5s infinite alternate;
|
||||
border-radius: 50%;
|
||||
bottom: 6px;
|
||||
content: "";
|
||||
left: 6px;
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 6px;
|
||||
}
|
||||
|
||||
.loader::before {
|
||||
border-top-color: var(--primary-900);
|
||||
animation: spin 3s linear infinite;
|
||||
animation: 3s spin linear infinite, hue 5s infinite alternate;
|
||||
border-top-color: var(--sd-main-accent-color);
|
||||
filter: brightness(50%);
|
||||
}
|
||||
|
||||
.loader::after {
|
||||
border-top-color: var(--primary-300);
|
||||
animation: spin 1.5s linear infinite;
|
||||
animation: spin 1.5s linear infinite, hue 5s infinite alternate;
|
||||
border-top-color: var(--sd-main-accent-color);
|
||||
filter: brightness(150%);
|
||||
}
|
||||
|
||||
.docs-search textarea {
|
||||
@@ -2126,11 +2127,11 @@ div:has(>#tab-gallery-folders) {
|
||||
|
||||
.docs-card-h1 {
|
||||
font-weight: bold;
|
||||
font-size: 1.0;
|
||||
font-size: 1.0em;
|
||||
}
|
||||
|
||||
.docs-card-h2 {
|
||||
font-size: 1.0;
|
||||
font-size: 1.0em;
|
||||
max-height: 4em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ async function initModels() {
|
||||
`;
|
||||
el.innerHTML = res.length > 0 ? ready() : warn();
|
||||
el.style.display = 'block';
|
||||
setTimeout(() => el.style.display = 'none', res.length === 0 ? 30000 : 1500);
|
||||
setTimeout(() => { el.style.display = 'none'; }, res.length === 0 ? 30000 : 1500);
|
||||
if (res.length === 0) {
|
||||
if (en.classList.contains('hide')) gradioApp().getElementById('txt2img_extra_networks_btn').click();
|
||||
const repeat = setInterval(() => {
|
||||
|
||||
@@ -6,7 +6,7 @@ async function waitForOpts() {
|
||||
// make sure all of the ui is ready and options are loaded
|
||||
const t0 = performance.now();
|
||||
let t1 = performance.now();
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
while (true) {
|
||||
if (t1 - t0 > 120000) {
|
||||
log('waitForOpts timeout');
|
||||
break;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
function startTrainMonitor() {
|
||||
gradioApp().querySelector('#train_error').innerHTML = '';
|
||||
const id = randomId();
|
||||
const onProgress = (progress) => gradioApp().getElementById('train_progress').innerHTML = progress.textinfo;
|
||||
const onProgress = (progress) => { gradioApp().getElementById('train_progress').innerHTML = progress.textinfo; };
|
||||
requestProgress(id, gradioApp().getElementById('train_gallery'), null, onProgress, false);
|
||||
const res = Array.from(arguments);
|
||||
res[0] = id;
|
||||
|
||||
@@ -33,9 +33,10 @@ function clip_gallery_urls(gallery) {
|
||||
}
|
||||
|
||||
function isVisible(el) {
|
||||
if (!el) return false;
|
||||
const rect = el.getBoundingClientRect();
|
||||
if (rect.width === 0 && rect.height === 0) return false;
|
||||
return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
|
||||
return (rect.top >= 0) && (rect.left >= 0) && (rect.bottom <= (window.innerHeight || document.documentElement.clientHeight)) && (rect.right <= (window.innerWidth || document.documentElement.clientWidth));
|
||||
}
|
||||
|
||||
function all_gallery_buttons() {
|
||||
@@ -63,18 +64,31 @@ function selected_gallery_index() {
|
||||
const button = selected_gallery_button();
|
||||
let result = -1;
|
||||
buttons.forEach((v, i) => { if (v === button) { result = i; } });
|
||||
if (result === -1 && gradioApp().getElementById('tab-gallery-search')?.checkVisibility()) {
|
||||
const gallerySelection = window.getGallerySelection();
|
||||
if (Number.isInteger(gallerySelection.index)) result = gallerySelection.index;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function selected_gallery_files() {
|
||||
function selected_gallery_files(tabname) {
|
||||
let allImages = [];
|
||||
let allThumbnails;
|
||||
if (tabname && tabname !== 'gallery') allThumbnails = gradioApp().querySelectorAll('div[id$=_gallery].gradio-gallery .thumbnail-item.thumbnail-small');
|
||||
else allThumbnails = gradioApp().querySelectorAll('.gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small');
|
||||
try {
|
||||
let allCurrentButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnail-item.thumbnail-small');
|
||||
if (allCurrentButtons.length === 0) allCurrentButtons = gradioApp().querySelectorAll('.gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small');
|
||||
allImages = Array.from(allCurrentButtons).map((v) => v.querySelector('img')?.src);
|
||||
allImages = allImages.filter((el) => isVisible(el));
|
||||
} catch { /**/ }
|
||||
const selectedIndex = selected_gallery_index();
|
||||
allImages = Array.from(allThumbnails).map((v) => v.querySelector('img'));
|
||||
if (tabname && tabname !== 'gallery') allImages = allImages.filter((img) => isVisible(img));
|
||||
allImages = allImages.map((img) => {
|
||||
let fn = img.src;
|
||||
if (fn.includes('file=')) fn = fn.split('file=')[1];
|
||||
return decodeURI(fn);
|
||||
});
|
||||
} catch (err) {
|
||||
error(`selected_gallery_files: ${err}`);
|
||||
}
|
||||
let selectedIndex = -1;
|
||||
if (tabname && tabname !== 'gallery') selectedIndex = selected_gallery_index();
|
||||
return [allImages, selectedIndex];
|
||||
}
|
||||
|
||||
@@ -86,6 +100,16 @@ function extract_image_from_gallery(gallery) {
|
||||
return [gallery[index]];
|
||||
}
|
||||
|
||||
function send_to_kanvas(gallery) {
|
||||
const [image] = extract_image_from_gallery(gallery);
|
||||
log('sendToKanvas', image);
|
||||
if (window.loadFromURL && image.data) window.loadFromURL(image.data);
|
||||
// const inputPanelEl = gradioApp().getElementById('control-template-column-input');
|
||||
// if (inputPanelEl) inputPanelEl.classList.remove('hidden');
|
||||
const inputPanelCb = gradioApp().getElementById('control_dynamic_input');
|
||||
if (inputPanelCb && !inputPanelCb.checked) inputPanelCb.click();
|
||||
}
|
||||
|
||||
async function setTheme(val, old) {
|
||||
if (!old || val === old) return;
|
||||
old = old.replace('modern/', '');
|
||||
@@ -99,7 +123,7 @@ async function setTheme(val, old) {
|
||||
const href = link.href.replace(old, val);
|
||||
const res = await fetch(href);
|
||||
if (res.ok) {
|
||||
log('setTheme:', old, val);
|
||||
log('setTheme', old, val);
|
||||
link.href = link.href.replace(old, val);
|
||||
} else {
|
||||
log('setTheme: CSS not found', val);
|
||||
@@ -254,7 +278,12 @@ function submit_control(...args) {
|
||||
const res = create_submit_args(args);
|
||||
res[0] = id;
|
||||
res[1] = window.submit_state;
|
||||
res[2] = gradioApp().querySelector('#control-tabs > .tab-nav > .selected')?.innerText.toLowerCase() || ''; // selected tab name
|
||||
|
||||
const tabs = Array.from(gradioApp().querySelectorAll('#control-tabs > .tab-nav > button'));
|
||||
const tabIdx = tabs.findIndex((btn) => btn.classList.contains('selected'));
|
||||
const tabNames = ['ControlNet', 'T2I Adapter', 'XS', 'Lite', 'Reference'];
|
||||
const selectedTab = tabNames[tabIdx] || 'ControlNet';
|
||||
res[2] = selectedTab.toLowerCase();
|
||||
window.submit_state = '';
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ async function getUIDefaults() {
|
||||
const btn = gradioApp().getElementById('ui_defaults_view');
|
||||
if (!btn) return;
|
||||
const intersectionObserver = new IntersectionObserver((entries) => {
|
||||
if (entries[0].intersectionRatio <= 0) { }
|
||||
if (entries[0].intersectionRatio <= 0) { /* Pass */ }
|
||||
if (entries[0].intersectionRatio > 0) btn.click();
|
||||
});
|
||||
intersectionObserver.observe(btn); // monitor visibility of tab
|
||||
|
||||
@@ -67,11 +67,8 @@ def get_custom_args():
|
||||
del env['PS1']
|
||||
installer.log.trace(f'Environment: {installer.print_dict(env)}')
|
||||
env = [f'{k}={v}' for k, v in os.environ.items() if k.startswith('SD_')]
|
||||
installer.log.debug(f'Env flags: {env}')
|
||||
ldpreload = os.environ.get('LD_PRELOAD', None)
|
||||
ldpath = os.environ.get('LD_LIBRARY_PATH', None)
|
||||
if ldpreload is not None or ldpath is not None:
|
||||
installer.log.debug(f'Linker flags: preload="{ldpreload}" path="{ldpath}"')
|
||||
ld = [f'{k}={v}' for k, v in os.environ.items() if k.startswith('LD_')]
|
||||
installer.log.debug(f'Flags: sd={env} ld={ld}')
|
||||
rec('args')
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 274 KiB |
@@ -1081,7 +1081,7 @@ class StableDiffusionXLPipelineAPG(
|
||||
latents,
|
||||
)
|
||||
|
||||
# 6. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline
|
||||
# 6. Prepare extra step kwargs.
|
||||
extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
|
||||
|
||||
# 7. Prepare added time ids & embeddings
|
||||
|
||||
@@ -965,7 +965,7 @@ class StableDiffusionPipelineAPG(
|
||||
latents,
|
||||
)
|
||||
|
||||
# 6. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline
|
||||
# 6. Prepare extra step kwargs.
|
||||
extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
|
||||
|
||||
# 6.1 Add image embeds for IP-Adapter
|
||||
|
||||
@@ -10,6 +10,7 @@ from starlette.websockets import WebSocket, WebSocketState
|
||||
from pydantic import BaseModel, Field # pylint: disable=no-name-in-module
|
||||
from PIL import Image
|
||||
from modules import shared, images, files_cache, modelstats
|
||||
from modules.paths import resolve_output_path
|
||||
|
||||
|
||||
debug = shared.log.debug if os.environ.get('SD_BROWSER_DEBUG', None) is not None else lambda *args, **kwargs: None
|
||||
@@ -128,20 +129,51 @@ def register_api(app: FastAPI): # register api
|
||||
|
||||
# @app.get('/sdapi/v1/browser/folders', response_model=List[str])
|
||||
def get_folders():
|
||||
def make_folder(path, label=None):
|
||||
"""Create folder entry with path and display label."""
|
||||
if label is None:
|
||||
label = os.path.basename(path) or path
|
||||
return {"path": path, "label": label}
|
||||
|
||||
reference_dir = os.path.join('models', 'Reference')
|
||||
folders = [shared.opts.data.get(f, '') for f in OPTS_FOLDERS]
|
||||
folders += list(shared.opts.browser_folders.split(','))
|
||||
folders += [reference_dir]
|
||||
folders = [f.strip() for f in folders if f != '']
|
||||
folders = list(dict.fromkeys(folders)) # filter duplicates
|
||||
folders = [f for f in folders if os.path.isdir(f)]
|
||||
if shared.demo is not None:
|
||||
for f in folders:
|
||||
if f not in shared.demo.allowed_paths:
|
||||
debug(f'Browser folders allow: {f}')
|
||||
shared.demo.allowed_paths.append(quote(f))
|
||||
debug(f'Browser folders: {folders}')
|
||||
return JSONResponse(content=folders)
|
||||
base_samples = shared.opts.outdir_samples
|
||||
base_grids = shared.opts.outdir_grids
|
||||
# Build list of resolved output paths with labels
|
||||
folders = []
|
||||
if base_samples:
|
||||
folders.append(make_folder(base_samples, os.path.basename(base_samples.rstrip('/\\'))))
|
||||
if base_grids and base_grids != base_samples:
|
||||
folders.append(make_folder(base_grids, os.path.basename(base_grids.rstrip('/\\'))))
|
||||
# Use the specific folder setting values as labels (e.g., "outputs/text" -> "outputs/text")
|
||||
folders.append(make_folder(resolve_output_path(base_samples, shared.opts.outdir_txt2img_samples), shared.opts.outdir_txt2img_samples))
|
||||
folders.append(make_folder(resolve_output_path(base_samples, shared.opts.outdir_img2img_samples), shared.opts.outdir_img2img_samples))
|
||||
folders.append(make_folder(resolve_output_path(base_samples, shared.opts.outdir_control_samples), shared.opts.outdir_control_samples))
|
||||
folders.append(make_folder(resolve_output_path(base_samples, shared.opts.outdir_extras_samples), shared.opts.outdir_extras_samples))
|
||||
folders.append(make_folder(resolve_output_path(base_samples, shared.opts.outdir_save), shared.opts.outdir_save))
|
||||
folders.append(make_folder(resolve_output_path(base_samples, shared.opts.outdir_video), shared.opts.outdir_video))
|
||||
folders.append(make_folder(resolve_output_path(base_samples, shared.opts.outdir_init_images), shared.opts.outdir_init_images))
|
||||
folders.append(make_folder(resolve_output_path(base_grids, shared.opts.outdir_txt2img_grids), shared.opts.outdir_txt2img_grids))
|
||||
folders.append(make_folder(resolve_output_path(base_grids, shared.opts.outdir_img2img_grids), shared.opts.outdir_img2img_grids))
|
||||
folders.append(make_folder(resolve_output_path(base_grids, shared.opts.outdir_control_grids), shared.opts.outdir_control_grids))
|
||||
# Custom browser folders and reference dir
|
||||
for f in shared.opts.browser_folders.split(','):
|
||||
f = f.strip()
|
||||
if f:
|
||||
folders.append(make_folder(f))
|
||||
folders.append(make_folder(reference_dir, 'Reference'))
|
||||
# Filter empty and duplicates (by path)
|
||||
seen_paths = set()
|
||||
unique_folders = []
|
||||
for f in folders:
|
||||
path = f["path"].strip()
|
||||
if path and path not in seen_paths and os.path.isdir(path):
|
||||
seen_paths.add(path)
|
||||
unique_folders.append(f)
|
||||
if shared.demo is not None and path not in shared.demo.allowed_paths:
|
||||
debug(f'Browser folders allow: {path}')
|
||||
shared.demo.allowed_paths.append(quote(path))
|
||||
debug(f'Browser folders: {unique_folders}')
|
||||
return JSONResponse(content=unique_folders)
|
||||
|
||||
# @app.get("/sdapi/v1/browser/thumb", response_model=dict)
|
||||
async def get_thumb(file: str):
|
||||
|
||||
@@ -3,6 +3,7 @@ from fastapi.responses import JSONResponse
|
||||
from modules import errors, shared, scripts_manager, ui
|
||||
from modules.api import models, script, helpers
|
||||
from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
|
||||
from modules.paths import resolve_output_path
|
||||
|
||||
|
||||
errors.install()
|
||||
@@ -105,8 +106,8 @@ class APIGenerate():
|
||||
p = StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)
|
||||
self.prepare_ip_adapter(txt2imgreq, p)
|
||||
p.scripts = script_runner
|
||||
p.outpath_grids = shared.opts.outdir_grids or shared.opts.outdir_txt2img_grids
|
||||
p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_txt2img_samples
|
||||
p.outpath_grids = resolve_output_path(shared.opts.outdir_grids, shared.opts.outdir_txt2img_grids)
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_txt2img_samples)
|
||||
for key, value in getattr(txt2imgreq, "extra", {}).items():
|
||||
setattr(p, key, value)
|
||||
jobid = shared.state.begin('API-TXT', api=True)
|
||||
@@ -157,8 +158,8 @@ class APIGenerate():
|
||||
self.prepare_ip_adapter(img2imgreq, p)
|
||||
p.init_images = [helpers.decode_base64_to_image(x) for x in init_images]
|
||||
p.scripts = script_runner
|
||||
p.outpath_grids = shared.opts.outdir_img2img_grids
|
||||
p.outpath_samples = shared.opts.outdir_img2img_samples
|
||||
p.outpath_grids = resolve_output_path(shared.opts.outdir_grids, shared.opts.outdir_img2img_grids)
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_img2img_samples)
|
||||
for key, value in getattr(img2imgreq, "extra", {}).items():
|
||||
setattr(p, key, value)
|
||||
jobid = shared.state.begin('API-IMG', api=True)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
import time
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
from fastapi import Request, Depends
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi.responses import FileResponse
|
||||
@@ -95,11 +95,11 @@ def get_config():
|
||||
del options['sd_lora']
|
||||
return options
|
||||
|
||||
def set_config(req: Dict[str, Any]):
|
||||
def set_config(req: dict[str, Any]):
|
||||
updated = []
|
||||
for k, v in req.items():
|
||||
updated.append({ k: shared.opts.set(k, v) })
|
||||
shared.opts.save(shared.config_filename)
|
||||
shared.opts.save()
|
||||
return { "updated": updated }
|
||||
|
||||
def get_cmd_flags():
|
||||
|
||||
@@ -89,7 +89,7 @@ def set_ck_flash_attention(backend: str, device: torch.device):
|
||||
if backend == "rocm":
|
||||
if not installed('flash-attn'):
|
||||
log.info('Torch attention: type="Flash attention" building...')
|
||||
agent = rocm.Agent(getattr(torch.cuda.get_device_properties(device), "gcnArchName", "gfx0000"))
|
||||
agent = rocm.Agent(device)
|
||||
install(rocm.get_flash_attention_command(agent), reinstall=True)
|
||||
else:
|
||||
install('flash-attn')
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
import os
|
||||
import sys
|
||||
import html
|
||||
import threading
|
||||
import time
|
||||
import cProfile
|
||||
from modules import shared, progress, errors, timer
|
||||
|
||||
|
||||
queue_lock = threading.Lock()
|
||||
debug = os.environ.get('SD_QUEUE_DEBUG', None) is not None
|
||||
|
||||
|
||||
def get_lock():
|
||||
if debug:
|
||||
fn = f'{sys._getframe(3).f_code.co_name}:{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access
|
||||
errors.log.debug(f'Queue: fn={fn} lock={queue_lock.locked()}')
|
||||
return queue_lock
|
||||
|
||||
|
||||
def wrap_queued_call(func):
|
||||
def f(*args, **kwargs):
|
||||
with queue_lock:
|
||||
with get_lock():
|
||||
res = func(*args, **kwargs)
|
||||
return res
|
||||
return f
|
||||
@@ -24,7 +35,7 @@ def wrap_gradio_gpu_call(func, extra_outputs=None, name=None):
|
||||
progress.add_task_to_queue(id_task)
|
||||
else:
|
||||
id_task = None
|
||||
with queue_lock:
|
||||
with get_lock():
|
||||
progress.start_task(id_task)
|
||||
res = [None, '', '', '']
|
||||
try:
|
||||
|
||||
@@ -7,8 +7,7 @@ from installer import install, log
|
||||
|
||||
full_dct = False
|
||||
full_html = False
|
||||
base_models = ['', 'ODOR', 'SD 1.4', 'SD 1.5', 'SD 1.5 LCM', 'SD 1.5 Hyper', 'SD 2.0', 'SD 2.0 768', 'SD 2.1', 'SD 2.1 768', 'SD 2.1 Unclip', 'SDXL 0.9', 'SDXL 1.0', 'SD 3', 'SD 3.5', 'SD 3.5 Medium', 'SD 3.5 Large', 'SD 3.5 Large Turbo', 'Pony', 'Flux.1 S', 'Flux.1 D', 'Flux.1 Kontext', 'AuraFlow', 'SDXL 1.0 LCM', 'SDXL Distilled', 'SDXL Turbo', 'SDXL Lightning', 'SDXL Hyper', 'Stable Cascade', 'SVD', 'SVD XT', 'Playground v2', 'PixArt a', 'PixArt E', 'Hunyuan 1', 'Hunyuan Video', 'Lumina', 'Kolors', 'Illustrious', 'Mochi', 'LTXV', 'CogVideoX', 'NoobAI', 'Wan Video', 'Wan Video 1.3B t2v', 'Wan Video 14B t2v', 'Wan Video 14B i2v 480p', 'Wan Video 14B i2v 720p', 'HiDream', 'OpenAI', 'Imagen4', 'Other']
|
||||
|
||||
base_models = ['', 'AuraFlow', 'Chroma', 'CogVideoX', 'Flux.1 S', 'Flux.1 D', 'Flux.1 Krea', 'Flux.1 Kontext', 'Flux.2 D', 'HiDream', 'Hunyuan 1', 'Hunyuan Video', 'Illustrious', 'Kolors', 'LTXV', 'Lumina', 'Mochi', 'NoobAI', 'PixArt a', 'PixArt E', 'Pony', 'Pony V7', 'Qwen', 'SD 1.4', 'SD 1.5', 'SD 1.5 LCM', 'SD 1.5 Hyper', 'SD 2.0', 'SD 2.1', 'SDXL 1.0', 'SDXL Lightning', 'SDXL Hyper', 'Wan Video 1.3B t2v', 'Wan Video 14B t2v', 'Wan Video 14B i2v 480p', 'Wan Video 14B i2v 720p', 'Wan Video 2.2 TI2V-5B', 'Wan Video 2.2 I2V-A14B', 'Wan Video 2.2 T2V-A14B', 'Wan Video 2.5 T2V', 'Wan Video 2.5 I2V', 'ZImageTurbo', 'Other']
|
||||
|
||||
@dataclass
|
||||
class ModelImage():
|
||||
|
||||
@@ -194,7 +194,6 @@ param_scheduler = [
|
||||
dict(
|
||||
# use quadratic formula to warm up 5 epochs
|
||||
# and lr is updated by iteration
|
||||
# TODO: fix default scope in get function
|
||||
type='mmdet.QuadraticWarmupLR',
|
||||
by_epoch=True,
|
||||
begin=0,
|
||||
|
||||
@@ -12,8 +12,6 @@ from torch.nn import functional as F
|
||||
def swish(x, inplace: bool = False):
|
||||
"""Swish - Described originally as SiLU (https://arxiv.org/abs/1702.03118v3)
|
||||
and also as Swish (https://arxiv.org/abs/1710.05941).
|
||||
|
||||
TODO Rename to SiLU with addition to PyTorch
|
||||
"""
|
||||
return x.mul_(x.sigmoid()) if inplace else x.mul(x.sigmoid())
|
||||
|
||||
|
||||
@@ -22,8 +22,6 @@ __all__ = ['swish_jit', 'SwishJit', 'mish_jit', 'MishJit',
|
||||
def swish_jit(x, inplace: bool = False):
|
||||
"""Swish - Described originally as SiLU (https://arxiv.org/abs/1702.03118v3)
|
||||
and also as Swish (https://arxiv.org/abs/1710.05941).
|
||||
|
||||
TODO Rename to SiLU with addition to PyTorch
|
||||
"""
|
||||
return x.mul(x.sigmoid())
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ class SwishJitAutoFn(torch.autograd.Function):
|
||||
|
||||
Swish - Described originally as SiLU (https://arxiv.org/abs/1702.03118v3)
|
||||
and also as Swish (https://arxiv.org/abs/1710.05941).
|
||||
|
||||
TODO Rename to SiLU with addition to PyTorch
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -483,7 +483,7 @@ def _decode_block_str(block_str):
|
||||
Returns:
|
||||
A list of block args (dicts)
|
||||
Raises:
|
||||
ValueError: if the string def not properly specified (TODO)
|
||||
ValueError: if the string def not properly specified
|
||||
"""
|
||||
assert isinstance(block_str, str)
|
||||
ops = block_str.split('_')
|
||||
|
||||
@@ -155,7 +155,7 @@ class LinearSplitter(nn.Module):
|
||||
|
||||
b_prev = b_prev / b_prev.sum(dim=1, keepdim=True) # renormalize for gurantees
|
||||
# print(b_prev.shape, S_normed.shape)
|
||||
# if is_for_query:(1).expand(-1, b_prev.size(0)//n, -1, -1, -1, -1).flatten(0,1) # TODO ? can replace all this with a single torch.repeat?
|
||||
# if is_for_query:(1).expand(-1, b_prev.size(0)//n, -1, -1, -1, -1).flatten(0,1)
|
||||
b = b_prev.unsqueeze(2) * S_normed
|
||||
b = b.flatten(1,2) # .shape n, prev_nbins * split_factor, h, w
|
||||
|
||||
|
||||
@@ -395,7 +395,7 @@ def get_config(model_name, mode='train', dataset=None, **overwrite_kwargs):
|
||||
overwrite_kwargs = split_combined_args(overwrite_kwargs)
|
||||
config = {**config, **overwrite_kwargs}
|
||||
|
||||
# Casting to bool # TODO: Not necessary. Remove and test
|
||||
# Casting to bool
|
||||
for key in KEYS_TYPE_BOOL:
|
||||
if key in config:
|
||||
config[key] = bool(config[key])
|
||||
|
||||
@@ -18,6 +18,7 @@ from modules.processing_class import StableDiffusionProcessingControl
|
||||
from modules.ui_common import infotext_to_html
|
||||
from modules.api import script
|
||||
from modules.generation_parameters_copypaste import create_override_settings_dict
|
||||
from modules.paths import resolve_output_path
|
||||
|
||||
|
||||
debug = os.environ.get('SD_CONTROL_DEBUG', None) is not None
|
||||
@@ -402,8 +403,8 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg
|
||||
hdr_mode=hdr_mode, hdr_brightness=hdr_brightness, hdr_color=hdr_color, hdr_sharpen=hdr_sharpen, hdr_clamp=hdr_clamp,
|
||||
hdr_boundary=hdr_boundary, hdr_threshold=hdr_threshold, hdr_maximize=hdr_maximize, hdr_max_center=hdr_max_center, hdr_max_boundary=hdr_max_boundary, hdr_color_picker=hdr_color_picker, hdr_tint_ratio=hdr_tint_ratio,
|
||||
# path
|
||||
outpath_samples=shared.opts.outdir_samples or shared.opts.outdir_control_samples,
|
||||
outpath_grids=shared.opts.outdir_grids or shared.opts.outdir_control_grids,
|
||||
outpath_samples=resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_control_samples),
|
||||
outpath_grids=resolve_output_path(shared.opts.outdir_grids, shared.opts.outdir_control_grids),
|
||||
# overrides
|
||||
override_settings=extra
|
||||
)
|
||||
@@ -572,13 +573,13 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg
|
||||
|
||||
# what are we doing?
|
||||
if 'control' in p.ops:
|
||||
p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_control_samples
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_control_samples)
|
||||
elif 'img2img' in p.ops:
|
||||
p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_img2img_samples
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_img2img_samples)
|
||||
elif 'txt2img' in p.ops:
|
||||
p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_txt2img_samples
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_txt2img_samples)
|
||||
else: # fallback to txt2img
|
||||
p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_txt2img_samples
|
||||
p.outpath_samples = resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_txt2img_samples)
|
||||
|
||||
# pipeline
|
||||
output = None
|
||||
|
||||
@@ -181,7 +181,7 @@ def api_list_models(model_type: str = None):
|
||||
model_list += list(predefined_qwen)
|
||||
if model_type == 'hunyuandit' or model_type == 'all':
|
||||
model_list += list(predefined_hunyuandit)
|
||||
if model_type == 'z_image':
|
||||
if model_type == 'zimage':
|
||||
model_list += list(predefined_zimage)
|
||||
model_list += sorted(find_models())
|
||||
return model_list
|
||||
@@ -207,7 +207,7 @@ def list_models(refresh=False):
|
||||
models = ['None'] + list(predefined_qwen) + sorted(find_models())
|
||||
elif modules.shared.sd_model_type == 'hunyuandit':
|
||||
models = ['None'] + list(predefined_hunyuandit) + sorted(find_models())
|
||||
elif modules.shared.sd_model_type == 'z_image':
|
||||
elif modules.shared.sd_model_type == 'zimage':
|
||||
models = ['None'] + list(predefined_zimage) + sorted(find_models())
|
||||
else:
|
||||
log.warning(f'Control {what} model list failed: unknown model type')
|
||||
@@ -273,7 +273,7 @@ class ControlNet():
|
||||
elif shared.sd_model_type == 'hunyuandit':
|
||||
from diffusers import HunyuanDiT2DControlNetModel as cls
|
||||
config = 'Tencent-Hunyuan/HunyuanDiT-v1.2-ControlNet-Diffusers-Canny'
|
||||
elif shared.sd_model_type == 'z_image':
|
||||
elif shared.sd_model_type == 'zimage':
|
||||
from diffusers import ZImageControlNetModel as cls
|
||||
if '2.0' in model_id:
|
||||
config = 'hlky/Z-Image-Turbo-Fun-Controlnet-Union-2.0'
|
||||
|
||||
@@ -67,6 +67,10 @@ def has_triton(early:bool=False) -> bool:
|
||||
return test_triton(early=early)
|
||||
|
||||
|
||||
def get_hip_agent() -> rocm.Agent:
|
||||
return rocm.Agent(device)
|
||||
|
||||
|
||||
def get_backend(shared_cmd_opts):
|
||||
global args # pylint: disable=global-statement
|
||||
args = shared_cmd_opts
|
||||
@@ -91,7 +95,6 @@ def get_backend(shared_cmd_opts):
|
||||
|
||||
def get_gpu_info():
|
||||
def get_driver():
|
||||
import subprocess
|
||||
if torch.xpu.is_available():
|
||||
try:
|
||||
return torch.xpu.get_device_properties(torch.xpu.current_device()).driver_version
|
||||
@@ -99,6 +102,7 @@ def get_gpu_info():
|
||||
return ''
|
||||
elif torch.cuda.is_available() and torch.version.cuda:
|
||||
try:
|
||||
import subprocess
|
||||
result = subprocess.run('nvidia-smi --query-gpu=driver_version --format=csv,noheader', shell=True, check=False, env=os.environ, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
version = result.stdout.decode(encoding="utf8", errors="ignore").strip()
|
||||
return version
|
||||
@@ -110,7 +114,7 @@ def get_gpu_info():
|
||||
def get_package_version(pkg: str):
|
||||
import pkg_resources
|
||||
spec = pkg_resources.working_set.by_key.get(pkg, None) # more reliable than importlib
|
||||
version = pkg_resources.get_distribution(pkg).version if spec is not None else ''
|
||||
version = pkg_resources.get_distribution(pkg).version if spec is not None else None
|
||||
return version
|
||||
|
||||
if not torch.cuda.is_available():
|
||||
@@ -324,9 +328,9 @@ def test_fp16():
|
||||
elif backend == 'rocm':
|
||||
# gfx1102 (RX 7600, 7500, 7650 and 7700S) causes segfaults with fp16
|
||||
# agent can be overriden to gfx1100 to get gfx1102 working with ROCm so check the gpu name as well
|
||||
agent = getattr(torch.cuda.get_device_properties(device), "gcnArchName", "gfx0000")
|
||||
agent = get_hip_agent()
|
||||
agent_name = getattr(torch.cuda.get_device_properties(device), "name", "AMD Radeon RX 0000")
|
||||
if agent == "gfx1102" or (agent == "gfx1100" and any(i in agent_name for i in ("7600", "7500", "7650", "7700S"))):
|
||||
if agent.gfx_version == 0x1102 or (agent.gfx_version == 0x1100 and any(i in agent_name for i in ("7600", "7500", "7650", "7700S"))):
|
||||
fp16_ok = False
|
||||
return fp16_ok
|
||||
try:
|
||||
@@ -355,7 +359,7 @@ def test_bf16():
|
||||
elif backend == 'rocm' or backend == 'zluda':
|
||||
agent = None
|
||||
if backend == 'rocm':
|
||||
agent = rocm.Agent(getattr(torch.cuda.get_device_properties(device), "gcnArchName", "gfx0000"))
|
||||
agent = get_hip_agent()
|
||||
else:
|
||||
from modules.zluda_installer import default_agent
|
||||
agent = default_agent
|
||||
@@ -396,7 +400,8 @@ def test_triton(early: bool = False):
|
||||
triton_ok = False
|
||||
except Exception as e:
|
||||
triton_ok = False
|
||||
log.warning(f"Triton test fail: {e}")
|
||||
line = str(e).splitlines()[0]
|
||||
log.warning(f"Triton test fail: {line}")
|
||||
if debug:
|
||||
from modules import errors
|
||||
errors.display(e, 'Triton')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
import os
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
import git
|
||||
from modules import shared, errors
|
||||
from modules.paths import extensions_dir, extensions_builtin_dir
|
||||
@@ -11,6 +11,34 @@ if not os.path.exists(extensions_dir):
|
||||
os.makedirs(extensions_dir)
|
||||
|
||||
|
||||
def parse_isotime(time_string: str) -> datetime:
|
||||
# If Python minimum version is 3.11+, this function can be replaced with datetime.fromisoformat()
|
||||
trimmed = time_string.rstrip("Z")
|
||||
if "." in trimmed:
|
||||
trimmed = trimmed.split(".")[0]
|
||||
match len(trimmed):
|
||||
case 16:
|
||||
return datetime.strptime(trimmed, "%Y-%m-%dT%H:%M").replace(tzinfo=timezone.utc)
|
||||
case 19:
|
||||
return datetime.strptime(trimmed, "%Y-%m-%dT%H:%M:%S").replace(tzinfo=timezone.utc)
|
||||
case _:
|
||||
raise ValueError(f"Unexpected time string format: '{time_string}'")
|
||||
|
||||
|
||||
def format_dt(d: datetime, seconds = False) -> str:
|
||||
if d.tzinfo is None:
|
||||
return d.strftime('%Y-%m-%d %H:%M')
|
||||
if seconds:
|
||||
return d.astimezone(timezone.utc).strftime('%Y-%m-%d %H:%M:%S')
|
||||
return d.astimezone(timezone.utc).strftime('%Y-%m-%d %H:%M')
|
||||
|
||||
|
||||
def ts2utc(timestamp: int) -> datetime:
|
||||
try:
|
||||
return datetime.fromtimestamp(timestamp, timezone.utc)
|
||||
except Exception:
|
||||
return "unknown"
|
||||
|
||||
def active():
|
||||
if shared.opts.disable_all_extensions == "all":
|
||||
return []
|
||||
@@ -106,8 +134,8 @@ class Extension:
|
||||
self.branch = None
|
||||
self.remote = None
|
||||
self.have_info_from_repo = False
|
||||
self.mtime = 0
|
||||
self.ctime = 0
|
||||
self.mtime = "2000-01-01T00:00Z"
|
||||
self.ctime = "2000-01-01T00:00Z"
|
||||
|
||||
def read_info(self, force=False):
|
||||
if self.have_info_from_repo and not force:
|
||||
@@ -142,7 +170,7 @@ class Extension:
|
||||
except Exception:
|
||||
self.branch = 'unknown'
|
||||
self.commit_hash = head.hexsha
|
||||
self.version = f"<p>{self.commit_hash[:8]}</p><p>{datetime.fromtimestamp(self.commit_date).strftime('%a %b%d %Y %H:%M')}</p>"
|
||||
self.version = f"<p>{self.commit_hash[:8]}</p><p>{format_dt(ts2utc(self.commit_date))}</p>"
|
||||
except Exception as ex:
|
||||
shared.log.error(f"Extension: failed reading data from git repo={self.name}: {ex}")
|
||||
self.remote = None
|
||||
|
||||
@@ -108,7 +108,6 @@ def activate(p, extra_network_data=None, step=0, include=[], exclude=[]):
|
||||
if args is not None:
|
||||
continue
|
||||
try:
|
||||
# extra_network.activate(p, [])
|
||||
signature = list(inspect.signature(extra_network.activate).parameters)
|
||||
if 'include' in signature and 'exclude' in signature:
|
||||
extra_network.activate(p, [], include=include, exclude=exclude)
|
||||
|
||||
@@ -882,7 +882,7 @@ class StableDiffusionXLInstantIDPipeline(StableDiffusionXLControlNetPipeline):
|
||||
guidance_scale_tensor, embedding_dim=self.unet.config.time_cond_proj_dim
|
||||
).to(device=device, dtype=latents.dtype)
|
||||
|
||||
# 7. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline
|
||||
# 7. Prepare extra step kwargs.
|
||||
extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
|
||||
|
||||
# 7.1 Create tensor stating which controlnets to keep
|
||||
|
||||
@@ -679,7 +679,7 @@ class PhotoMakerStableDiffusionXLPipeline(StableDiffusionXLPipeline):
|
||||
latents,
|
||||
)
|
||||
|
||||
# 9. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline
|
||||
# 9. Prepare extra step kwargs.
|
||||
extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
|
||||
|
||||
# 10. Prepare added time ids & embeddings
|
||||
|
||||
@@ -181,7 +181,6 @@ def match(threshold, truths, priors, variances, labels, landms, loc_t, conf_t, l
|
||||
best_prior_idx_filter.squeeze_(1)
|
||||
best_prior_overlap.squeeze_(1)
|
||||
best_truth_overlap.index_fill_(0, best_prior_idx_filter, 2) # ensure best prior
|
||||
# TODO refactor: index best_prior_idx with long tensor
|
||||
# ensure every gt matches with its prior of max overlap
|
||||
for j in range(best_prior_idx.size(0)): # 判别此anchor是预测哪一个boxes
|
||||
best_truth_idx[best_prior_idx[j]] = j
|
||||
|
||||
@@ -99,7 +99,7 @@ def align_crop_face_landmarks(img,
|
||||
# - np.flipud(eye_to_mouth) * [-1, 1]: rotate 90 clockwise
|
||||
# norm with the hypotenuse: get the direction
|
||||
x /= np.hypot(*x) # get the hypotenuse of a right triangle
|
||||
rect_scale = 1 # TODO: you can edit it to get larger rect
|
||||
rect_scale = 1
|
||||
x *= max(np.hypot(*eye_to_eye) * 2.0 * rect_scale, np.hypot(*eye_to_mouth) * 1.8 * rect_scale)
|
||||
# y: half height of the oriented crop rectangle
|
||||
y = np.flipud(x) * [-1, 1]
|
||||
@@ -116,7 +116,6 @@ def align_crop_face_landmarks(img,
|
||||
|
||||
quad_ori = np.copy(quad)
|
||||
# Shrink, for large face
|
||||
# TODO: do we really need shrink
|
||||
shrink = int(np.floor(qsize / output_size * 0.5))
|
||||
if shrink > 1:
|
||||
h, w = img.shape[0:2]
|
||||
|
||||
@@ -52,7 +52,6 @@ def _attn_fwd_inner(acc, l_i, m_i, q, k_ptrs, v_ptrs, bias_ptrs, stride_kn, stri
|
||||
qk = tl.zeros([BLOCK_M, BLOCK_N], dtype=ACCUMULATOR_TYPE)
|
||||
# We start from end of seqlen_k so only the first iteration would need
|
||||
# to be checked for padding if it is not a multiple of block_n
|
||||
# TODO: This can be optimized to only be true for the padded block.
|
||||
if MASK_STEPS:
|
||||
# If this is the last block / iteration, we want to
|
||||
# mask if the sequence length is not a multiple of block size
|
||||
@@ -105,7 +104,7 @@ def _attn_fwd_inner(acc, l_i, m_i, q, k_ptrs, v_ptrs, bias_ptrs, stride_kn, stri
|
||||
# CAVEAT: Must update l_ij before applying dropout
|
||||
l_ij = tl.sum(p, 1)
|
||||
if ENABLE_DROPOUT:
|
||||
rng_output = tl.rand(philox_seed, philox_ptrs) # TODO: use tl.randint for better performance
|
||||
rng_output = tl.rand(philox_seed, philox_ptrs)
|
||||
dropout_mask = rng_output > dropout_p
|
||||
|
||||
# return scores with negative values for dropped vals
|
||||
@@ -304,7 +303,6 @@ def attn_fwd(Q, K, V, bias, Cache_seqlens, Cache_batch_idx, # pylint: disable=un
|
||||
# softmax_lse = tl.where(lse_mask, 0.0, softmax_lse)
|
||||
l_ptrs_mask = offs_m < MAX_SEQLENS_Q
|
||||
tl.store(l_ptrs, l, mask=l_ptrs_mask)
|
||||
# TODO: Should dropout and return encoded softmax be handled here too?
|
||||
return
|
||||
|
||||
# If MQA / GQA, set the K and V head offsets appropriately.
|
||||
|
||||
@@ -116,7 +116,6 @@ class MetaData():
|
||||
assert self.cu_seqlens_q is not None
|
||||
assert self.cu_seqlens_k is not None
|
||||
assert len(self.cu_seqlens_q) == len(self.cu_seqlens_k)
|
||||
# TODO: Remove once bias is supported with varlen
|
||||
assert self.bias is None
|
||||
# assert not self.return_scores
|
||||
else:
|
||||
@@ -125,7 +124,6 @@ class MetaData():
|
||||
assert self.cu_seqlens_q is None and self.cu_seqlens_k is None
|
||||
assert k.shape == v.shape
|
||||
assert q.shape[-1] == k.shape[-1] and q.shape[-1] == v.shape[-1]
|
||||
# TODO: Change assert if we support qkl f8 and v f16
|
||||
assert q.dtype == k.dtype and q.dtype == v.dtype
|
||||
assert o.shape == q.shape
|
||||
assert (nheads_q % nheads_k) == 0
|
||||
@@ -243,7 +241,6 @@ def input_helper(
|
||||
equal_seqlens=False
|
||||
|
||||
# gen tensors
|
||||
# TODO: the gen functions should maybe have different gen modes like random, ones, increasing seqlen
|
||||
q, cu_seqlens_q, max_seqlen_q = generate_varlen_tensor(TOTAL_SEQLENS_Q, HQ, D_HEAD, batch_size=BATCH, dtype=dtype, device=device, equal_seqlens=equal_seqlens, DEBUG_INPUT=DEBUG_INPUT)
|
||||
k, cu_seqlens_k, max_seqlen_k = generate_varlen_tensor(TOTAL_SEQLENS_K, HK, D_HEAD, batch_size=BATCH, dtype=dtype, device=device, equal_seqlens=equal_seqlens, DEBUG_INPUT=DEBUG_INPUT)
|
||||
v, _, _ = generate_varlen_tensor(TOTAL_SEQLENS_K, HK, D_HEAD, batch_size=BATCH, dtype=dtype, device=device, equal_seqlens=equal_seqlens, DEBUG_INPUT=DEBUG_INPUT)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import os
|
||||
import re
|
||||
import random
|
||||
import threading
|
||||
import numpy as np
|
||||
import torch
|
||||
import gradio as gr
|
||||
from PIL import Image
|
||||
from modules import shared, processing, timer, paths, extra_networks, progress, ui_video_vlm
|
||||
from modules import shared, processing, timer, paths, extra_networks, progress, ui_video_vlm, call_queue
|
||||
from modules.video_models.video_utils import check_av
|
||||
from modules.framepack import framepack_install # pylint: disable=wrong-import-order
|
||||
from modules.framepack import framepack_load # pylint: disable=wrong-import-order
|
||||
@@ -18,7 +17,6 @@ tmp_dir = os.path.join(paths.data_path, 'tmp', 'framepack')
|
||||
git_dir = os.path.join(os.path.dirname(__file__), 'framepack')
|
||||
git_repo = 'https://github.com/lllyasviel/framepack'
|
||||
git_commit = 'c5d375661a2557383f0b8da9d11d14c23b0c4eaf'
|
||||
queue_lock = threading.Lock()
|
||||
loaded_variant = None
|
||||
|
||||
|
||||
@@ -131,7 +129,7 @@ def run_framepack(task_id, _ui_state, init_image, end_image, start_weight, end_w
|
||||
return
|
||||
|
||||
progress.add_task_to_queue(task_id)
|
||||
with queue_lock:
|
||||
with call_queue.get_lock():
|
||||
progress.start_task(task_id)
|
||||
|
||||
yield from load_model(variant, attention)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from __future__ import annotations
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
@@ -8,9 +9,9 @@ from modules.infotext import parse, mapping, quote, unquote # pylint: disable=un
|
||||
|
||||
|
||||
type_of_gr_update = type(gr.update())
|
||||
paste_fields = {}
|
||||
paste_fields: dict[str, dict] = {}
|
||||
field_names = {}
|
||||
registered_param_bindings = []
|
||||
registered_param_bindings: list[ParamBinding] = []
|
||||
debug = shared.log.trace if os.environ.get('SD_PASTE_DEBUG', None) is not None else lambda *args, **kwargs: None
|
||||
debug('Trace: PASTE')
|
||||
parse_generation_parameters = parse # compatibility
|
||||
@@ -18,7 +19,7 @@ infotext_to_setting_name_mapping = mapping # compatibility
|
||||
|
||||
|
||||
class ParamBinding:
|
||||
def __init__(self, paste_button, tabname, source_text_component=None, source_image_component=None, source_tabname=None, override_settings_component=None, paste_field_names=None):
|
||||
def __init__(self, paste_button, tabname: str, source_text_component=None, source_image_component=None, source_tabname=None, override_settings_component=None, paste_field_names=None):
|
||||
self.paste_button = paste_button
|
||||
self.tabname = tabname
|
||||
self.source_text_component = source_text_component
|
||||
@@ -60,7 +61,7 @@ def image_from_url_text(filedata):
|
||||
if len(filedata) == 0:
|
||||
return None
|
||||
filedata = filedata[0]
|
||||
if type(filedata) == dict:
|
||||
if not isinstance(filedata, str):
|
||||
shared.log.warning('Incorrect filedata received')
|
||||
return None
|
||||
if filedata.startswith("data:image/png;base64,"):
|
||||
@@ -71,13 +72,13 @@ def image_from_url_text(filedata):
|
||||
filedata = filedata[len("data:image/jpeg;base64,"):]
|
||||
if filedata.startswith("data:image/jxl;base64,"):
|
||||
filedata = filedata[len("data:image/jxl;base64,"):]
|
||||
filedata = base64.decodebytes(filedata.encode('utf-8'))
|
||||
image = Image.open(io.BytesIO(filedata))
|
||||
filebytes = base64.decodebytes(filedata.encode('utf-8'))
|
||||
image = Image.open(io.BytesIO(filebytes))
|
||||
images.read_info_from_image(image)
|
||||
return image
|
||||
|
||||
|
||||
def add_paste_fields(tabname, init_img, fields, override_settings_component=None):
|
||||
def add_paste_fields(tabname: str, init_img: gr.Image | gr.HTML | None, fields: list[tuple[gr.components.Component, str]] | None, override_settings_component=None):
|
||||
paste_fields[tabname] = {"init_img": init_img, "fields": fields, "override_settings_component": override_settings_component}
|
||||
try:
|
||||
field_names[tabname] = [f[1] for f in fields if f[1] is not None and not callable(f[1])] if fields is not None else [] # tuple (component, label)
|
||||
@@ -108,7 +109,7 @@ def get_all_fields():
|
||||
return all_fields
|
||||
|
||||
|
||||
def create_buttons(tabs_list):
|
||||
def create_buttons(tabs_list: list[str]) -> dict[str, gr.Button]:
|
||||
buttons = {}
|
||||
for tab in tabs_list:
|
||||
name = tab
|
||||
@@ -128,7 +129,7 @@ def create_buttons(tabs_list):
|
||||
return buttons
|
||||
|
||||
|
||||
def should_skip(param):
|
||||
def should_skip(param: str):
|
||||
skip_params = [p.strip().lower() for p in shared.opts.disable_apply_params.split(",")]
|
||||
if not shared.opts.clip_skip_enabled:
|
||||
skip_params += ['clip skip']
|
||||
@@ -149,18 +150,26 @@ def connect_paste_params_buttons():
|
||||
if binding.tabname not in paste_fields:
|
||||
debug(f"Not not registered: tab={binding.tabname}")
|
||||
continue
|
||||
fields = paste_fields[binding.tabname]["fields"]
|
||||
fields: list[tuple[gr.components.Component, str]] = paste_fields[binding.tabname]["fields"]
|
||||
|
||||
destination_image_component = paste_fields[binding.tabname]["init_img"]
|
||||
if binding.source_image_component and destination_image_component:
|
||||
binding.paste_button.click(
|
||||
_js="extract_image_from_gallery" if isinstance(binding.source_image_component, gr.Gallery) else None,
|
||||
fn=send_image,
|
||||
inputs=[binding.source_image_component],
|
||||
outputs=[destination_image_component],
|
||||
show_progress='hidden',
|
||||
)
|
||||
|
||||
if binding.source_image_component:
|
||||
if isinstance(destination_image_component, gr.Image):
|
||||
binding.paste_button.click(
|
||||
_js="extract_image_from_gallery" if isinstance(binding.source_image_component, gr.Gallery) else None,
|
||||
fn=send_image,
|
||||
inputs=[binding.source_image_component],
|
||||
outputs=[destination_image_component],
|
||||
show_progress='hidden',
|
||||
)
|
||||
elif isinstance(destination_image_component, gr.HTML): # kanvas
|
||||
binding.paste_button.click(
|
||||
_js="send_to_kanvas",
|
||||
fn=None,
|
||||
inputs=[binding.source_image_component],
|
||||
outputs=[],
|
||||
show_progress='hidden',
|
||||
)
|
||||
override_settings_component = binding.override_settings_component or paste_fields[binding.tabname]["override_settings_component"]
|
||||
if binding.source_text_component is not None and fields is not None:
|
||||
connect_paste(binding.paste_button, fields, binding.source_text_component, override_settings_component, binding.tabname)
|
||||
|
||||
@@ -19,19 +19,32 @@ def check_tmp_file(gradio, filename):
|
||||
ok = False
|
||||
if hasattr(gradio, 'temp_file_sets'):
|
||||
ok = ok or any(filename in fileset for fileset in gradio.temp_file_sets)
|
||||
if shared.opts.outdir_samples != '':
|
||||
ok = ok or Path(shared.opts.outdir_samples).resolve() in Path(filename).resolve().parents
|
||||
else:
|
||||
ok = ok or Path(shared.opts.outdir_txt2img_samples).resolve() in Path(filename).resolve().parents
|
||||
ok = ok or Path(shared.opts.outdir_img2img_samples).resolve() in Path(filename).resolve().parents
|
||||
ok = ok or Path(shared.opts.outdir_extras_samples).resolve() in Path(filename).resolve().parents
|
||||
if shared.opts.outdir_grids != '':
|
||||
ok = ok or Path(shared.opts.outdir_grids).resolve() in Path(filename).resolve().parents
|
||||
else:
|
||||
ok = ok or Path(shared.opts.outdir_txt2img_grids).resolve() in Path(filename).resolve().parents
|
||||
ok = ok or Path(shared.opts.outdir_img2img_grids).resolve() in Path(filename).resolve().parents
|
||||
ok = ok or Path(shared.opts.outdir_save).resolve() in Path(filename).resolve().parents
|
||||
ok = ok or Path(shared.opts.outdir_init_images).resolve() in Path(filename).resolve().parents
|
||||
# Check resolved output paths (base + specific)
|
||||
base_samples = shared.opts.outdir_samples
|
||||
base_grids = shared.opts.outdir_grids
|
||||
resolved_paths = [
|
||||
paths.resolve_output_path(base_samples, shared.opts.outdir_txt2img_samples),
|
||||
paths.resolve_output_path(base_samples, shared.opts.outdir_img2img_samples),
|
||||
paths.resolve_output_path(base_samples, shared.opts.outdir_extras_samples),
|
||||
paths.resolve_output_path(base_samples, shared.opts.outdir_control_samples),
|
||||
paths.resolve_output_path(base_samples, shared.opts.outdir_save),
|
||||
paths.resolve_output_path(base_samples, shared.opts.outdir_video),
|
||||
paths.resolve_output_path(base_samples, shared.opts.outdir_init_images),
|
||||
paths.resolve_output_path(base_grids, shared.opts.outdir_txt2img_grids),
|
||||
paths.resolve_output_path(base_grids, shared.opts.outdir_img2img_grids),
|
||||
paths.resolve_output_path(base_grids, shared.opts.outdir_control_grids),
|
||||
]
|
||||
# Also check base folders directly if set
|
||||
if base_samples:
|
||||
resolved_paths.append(base_samples)
|
||||
if base_grids:
|
||||
resolved_paths.append(base_grids)
|
||||
for path in resolved_paths:
|
||||
if path:
|
||||
try:
|
||||
ok = ok or Path(path).resolve() in Path(filename).resolve().parents
|
||||
except Exception:
|
||||
pass
|
||||
return ok
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import hashlib
|
||||
import os.path
|
||||
from rich import progress, errors
|
||||
from modules import shared
|
||||
from installer import log, console
|
||||
from modules.json_helpers import readfile, writefile
|
||||
from modules.paths import data_path
|
||||
|
||||
|
||||
cache_filename = os.path.join(data_path, "cache.json")
|
||||
cache_data = None
|
||||
progress_ok = True
|
||||
@@ -12,17 +14,17 @@ progress_ok = True
|
||||
def init_cache():
|
||||
global cache_data # pylint: disable=global-statement
|
||||
if cache_data is None:
|
||||
cache_data = {} if not os.path.isfile(cache_filename) else shared.readfile(cache_filename, lock=True, as_type="dict")
|
||||
cache_data = {} if not os.path.isfile(cache_filename) else readfile(cache_filename, lock=True, as_type="dict")
|
||||
|
||||
|
||||
def dump_cache():
|
||||
shared.writefile(cache_data, cache_filename)
|
||||
writefile(cache_data, cache_filename)
|
||||
|
||||
|
||||
def cache(subsection):
|
||||
global cache_data # pylint: disable=global-statement
|
||||
if cache_data is None:
|
||||
cache_data = {} if not os.path.isfile(cache_filename) else shared.readfile(cache_filename, lock=True, as_type="dict")
|
||||
cache_data = {} if not os.path.isfile(cache_filename) else readfile(cache_filename, lock=True, as_type="dict")
|
||||
s = cache_data.get(subsection, {})
|
||||
cache_data[subsection] = s
|
||||
return s
|
||||
@@ -35,11 +37,11 @@ def calculate_sha256(filename, quiet=False):
|
||||
if not quiet:
|
||||
if progress_ok:
|
||||
try:
|
||||
with progress.open(filename, 'rb', description=f'[cyan]Calculating hash: [yellow]{filename}', auto_refresh=True, console=shared.console) as f:
|
||||
with progress.open(filename, 'rb', description=f'[cyan]Calculating hash: [yellow]{filename}', auto_refresh=True, console=console) as f:
|
||||
for chunk in iter(lambda: f.read(blksize), b""):
|
||||
hash_sha256.update(chunk)
|
||||
except errors.LiveError:
|
||||
shared.log.warning('Hash: attempting to use function in a thread')
|
||||
log.warning('Hash: attempting to use function in a thread')
|
||||
progress_ok = False
|
||||
if not progress_ok:
|
||||
with open(filename, 'rb') as f:
|
||||
@@ -65,6 +67,7 @@ def sha256_from_cache(filename, title, use_addnet_hash=False):
|
||||
|
||||
|
||||
def sha256(filename, title, use_addnet_hash=False):
|
||||
from modules import shared
|
||||
global progress_ok # pylint: disable=global-statement
|
||||
hashes = cache("hashes-addnet") if use_addnet_hash else cache("hashes")
|
||||
sha256_value = sha256_from_cache(filename, title, use_addnet_hash)
|
||||
@@ -81,7 +84,7 @@ def sha256(filename, title, use_addnet_hash=False):
|
||||
with progress.open(filename, 'rb', description=f'[cyan]Calculating hash: [yellow]{filename}', auto_refresh=True, console=shared.console) as f:
|
||||
sha256_value = addnet_hash_safetensors(f)
|
||||
except errors.LiveError:
|
||||
shared.log.warning('Hash: attempting to use function in a thread')
|
||||
log.warning('Hash: attempting to use function in a thread')
|
||||
progress_ok = False
|
||||
if not progress_ok:
|
||||
with open(filename, 'rb') as f:
|
||||
|
||||
@@ -10,6 +10,7 @@ def apply(p, model_type):
|
||||
shared.log.warning(f'HiDiffusion: class={shared.sd_model.__class__.__name__} not supported')
|
||||
return
|
||||
unapply()
|
||||
pipe = shared.sd_model.pipe if hasattr(shared.sd_model, 'pipe') else shared.sd_model
|
||||
if getattr(p, 'hidiffusion', False) is True:
|
||||
t0 = time.time()
|
||||
hidiffusion.is_aggressive_raunet = shared.opts.hidiffusion_steps > 0
|
||||
@@ -30,11 +31,12 @@ def apply(p, model_type):
|
||||
hidiffusion.switching_threshold_ratio_dict['sdxl_4096']['T2_ratio'] = t2
|
||||
hidiffusion.switching_threshold_ratio_dict['sdxl_turbo_1024']['T2_ratio'] = t2
|
||||
p.extra_generation_params['HiDiffusion Ratios'] = f'{shared.opts.hidiffusion_t1}/{shared.opts.hidiffusion_t2}'
|
||||
pipe = shared.sd_model.pipe if hasattr(shared.sd_model, 'pipe') else shared.sd_model
|
||||
hidiffusion.apply_hidiffusion(pipe, apply_raunet=shared.opts.hidiffusion_raunet, apply_window_attn=shared.opts.hidiffusion_attn, model_type=model_type, steps=p.steps)
|
||||
p.extra_generation_params['HiDiffusion'] = f'{shared.opts.hidiffusion_raunet}/{shared.opts.hidiffusion_attn}/{shared.opts.hidiffusion_steps > 0}:{shared.opts.hidiffusion_steps}'
|
||||
t1 = time.time()
|
||||
shared.log.debug(f'Applying HiDiffusion: raunet={shared.opts.hidiffusion_raunet} attn={shared.opts.hidiffusion_attn} aggressive={shared.opts.hidiffusion_steps > 0}:{shared.opts.hidiffusion_steps} t1={shared.opts.hidiffusion_t1} t2={shared.opts.hidiffusion_t2} time={t1-t0:.2f} type={shared.sd_model_type} width={p.width} height={p.height}')
|
||||
elif hasattr(pipe, 'unet') and getattr(pipe.unet, 'hidiffusion', False):
|
||||
shared.log.warning('HiDiffusion: model reload recomended')
|
||||
|
||||
|
||||
def unapply():
|
||||
|
||||
@@ -2,7 +2,6 @@ from typing import Type, Dict, Any, Tuple, Optional
|
||||
import math
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
from diffusers.utils.torch_utils import is_torch_version
|
||||
from diffusers.pipelines import auto_pipeline
|
||||
|
||||
|
||||
@@ -85,7 +84,6 @@ def make_diffusers_transformer_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
class transformer_block(block_class):
|
||||
# Save for unpatching later
|
||||
_parent = block_class
|
||||
_forward = block_class.forward
|
||||
|
||||
def forward(
|
||||
self,
|
||||
@@ -98,7 +96,6 @@ def make_diffusers_transformer_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
class_labels: Optional[torch.LongTensor] = None,
|
||||
added_cond_kwargs: Optional[Dict[str, torch.Tensor]] = None,
|
||||
) -> torch.FloatTensor:
|
||||
|
||||
# reference: https://github.com/microsoft/Swin-Transformer
|
||||
def window_partition(x, window_size, shift_size, H, W):
|
||||
B, _N, C = x.shape
|
||||
@@ -158,7 +155,11 @@ def make_diffusers_transformer_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
# MSW-MSA
|
||||
rand_num = torch.rand(1)
|
||||
_B, N, _C = hidden_states.shape
|
||||
ori_H, ori_W = self.info['size']
|
||||
try:
|
||||
ori_H, ori_W = self.info['size']
|
||||
except Exception as e:
|
||||
raise RuntimeError(f'HiDiffusion: cls={self.__class__.__name__} info={hasattr(self, "info")} parent={hasattr(self, "_parent")} orphaned call') from e
|
||||
|
||||
downsample_ratio = round(((ori_H*ori_W) / N)**0.5)
|
||||
H, W = (math.ceil(ori_H/downsample_ratio), math.ceil(ori_W/downsample_ratio))
|
||||
widow_size = (math.ceil(H/2), math.ceil(W/2))
|
||||
@@ -249,7 +250,6 @@ def make_diffusers_transformer_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
hidden_states = hidden_states.squeeze(1)
|
||||
return hidden_states
|
||||
|
||||
_patched_forward = forward
|
||||
return transformer_block
|
||||
|
||||
|
||||
@@ -257,7 +257,6 @@ def make_diffusers_cross_attn_down_block(block_class: Type[torch.nn.Module]) ->
|
||||
# replace conventional downsampler with resolution-aware downsampler
|
||||
class cross_attn_down_block(block_class):
|
||||
_parent = block_class # Save for unpatching later
|
||||
_forward = block_class.forward
|
||||
timestep = 0
|
||||
aggressive_raunet = False
|
||||
T1_ratio = 0
|
||||
@@ -280,7 +279,10 @@ def make_diffusers_cross_attn_down_block(block_class: Type[torch.nn.Module]) ->
|
||||
self.info['pipeline']._num_timesteps = self.max_timestep # pylint: disable=protected-access
|
||||
self.max_timestep = self.info['pipeline']._num_timesteps # pylint: disable=protected-access
|
||||
# self.max_timestep = len(self.info['scheduler'].timesteps)
|
||||
ori_H, ori_W = self.info['size']
|
||||
try:
|
||||
ori_H, ori_W = self.info['size']
|
||||
except Exception as e:
|
||||
raise RuntimeError(f'HiDiffusion: cls={self.__class__.__name__} info={hasattr(self, "info")} parent={hasattr(self, "_parent")} orphaned call') from e
|
||||
if self.model == 'sd15':
|
||||
if ori_H < 256 or ori_W < 256:
|
||||
self.T1_ratio = switching_threshold_ratio_dict['sd15_1024'][self.switching_threshold_ratio]
|
||||
@@ -294,8 +296,6 @@ def make_diffusers_cross_attn_down_block(block_class: Type[torch.nn.Module]) ->
|
||||
self.T1_ratio = switching_threshold_ratio_dict['sdxl_2048'][self.switching_threshold_ratio]
|
||||
if self.info['is_inpainting_task']:
|
||||
self.aggressive_raunet = inpainting_is_aggressive_raunet
|
||||
elif self.info['is_playground']:
|
||||
self.aggressive_raunet = playground_is_aggressive_raunet
|
||||
else:
|
||||
self.aggressive_raunet = is_aggressive_raunet
|
||||
else:
|
||||
@@ -329,7 +329,7 @@ def make_diffusers_cross_attn_down_block(block_class: Type[torch.nn.Module]) ->
|
||||
|
||||
return custom_forward
|
||||
|
||||
ckpt_kwargs: Dict[str, Any] = {"use_reentrant": False} if is_torch_version(">=", "1.11.0") else {}
|
||||
ckpt_kwargs: Dict[str, Any] = {"use_reentrant": False}
|
||||
hidden_states = torch.utils.checkpoint.checkpoint(
|
||||
create_custom_forward(resnet),
|
||||
hidden_states,
|
||||
@@ -382,7 +382,6 @@ def make_diffusers_cross_attn_down_block(block_class: Type[torch.nn.Module]) ->
|
||||
|
||||
return hidden_states, output_states
|
||||
|
||||
_patched_forward = forward
|
||||
return cross_attn_down_block
|
||||
|
||||
|
||||
@@ -391,7 +390,6 @@ def make_diffusers_cross_attn_up_block(block_class: Type[torch.nn.Module]) -> Ty
|
||||
class cross_attn_up_block(block_class):
|
||||
# Save for unpatching later
|
||||
_parent = block_class
|
||||
_forward = block_class.forward
|
||||
timestep = 0
|
||||
aggressive_raunet = False
|
||||
T1_ratio = 0
|
||||
@@ -411,7 +409,6 @@ def make_diffusers_cross_attn_up_block(block_class: Type[torch.nn.Module]) -> Ty
|
||||
attention_mask: Optional[torch.FloatTensor] = None,
|
||||
encoder_attention_mask: Optional[torch.FloatTensor] = None,
|
||||
) -> torch.FloatTensor:
|
||||
|
||||
def fix_scale(first, second):
|
||||
if (first.shape[-1] != second.shape[-1] or first.shape[-2] != second.shape[-2]):
|
||||
rescale = min(second.shape[-2] / first.shape[-2], second.shape[-1] / first.shape[-1])
|
||||
@@ -420,7 +417,10 @@ def make_diffusers_cross_attn_up_block(block_class: Type[torch.nn.Module]) -> Ty
|
||||
return first
|
||||
|
||||
self.max_timestep = self.info['pipeline']._num_timesteps # pylint: disable=protected-access
|
||||
ori_H, ori_W = self.info['size']
|
||||
try:
|
||||
ori_H, ori_W = self.info['size']
|
||||
except Exception as e:
|
||||
raise RuntimeError(f'HiDiffusion: cls={self.__class__.__name__} info={hasattr(self, "info")} parent={hasattr(self, "_parent")} orphaned call') from e
|
||||
if self.model == 'sd15':
|
||||
if ori_H < 256 or ori_W < 256:
|
||||
self.T1_ratio = switching_threshold_ratio_dict['sd15_1024'][self.switching_threshold_ratio]
|
||||
@@ -435,8 +435,6 @@ def make_diffusers_cross_attn_up_block(block_class: Type[torch.nn.Module]) -> Ty
|
||||
|
||||
if self.info['is_inpainting_task']:
|
||||
self.aggressive_raunet = inpainting_is_aggressive_raunet
|
||||
elif self.info['is_playground']:
|
||||
self.aggressive_raunet = playground_is_aggressive_raunet
|
||||
else:
|
||||
self.aggressive_raunet = is_aggressive_raunet
|
||||
|
||||
@@ -483,7 +481,6 @@ def make_diffusers_cross_attn_up_block(block_class: Type[torch.nn.Module]) -> Ty
|
||||
self.timestep = 0
|
||||
return hidden_states
|
||||
|
||||
_patched_forward = forward
|
||||
return cross_attn_up_block
|
||||
|
||||
|
||||
@@ -492,7 +489,6 @@ def make_diffusers_downsampler_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
class downsampler_block(block_class):
|
||||
# Save for unpatching later
|
||||
_parent = block_class
|
||||
_forward = block_class.forward
|
||||
T1_ratio = 0
|
||||
T1 = 0
|
||||
timestep = 0
|
||||
@@ -502,7 +498,10 @@ def make_diffusers_downsampler_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
def forward(self, hidden_states: torch.Tensor, scale = 1.0) -> torch.Tensor: # pylint: disable=unused-argument
|
||||
self.max_timestep = self.info['pipeline']._num_timesteps # pylint: disable=protected-access
|
||||
# self.max_timestep = len(self.info['scheduler'].timesteps)
|
||||
ori_H, ori_W = self.info['size']
|
||||
try:
|
||||
ori_H, ori_W = self.info['size']
|
||||
except Exception as e:
|
||||
raise RuntimeError(f'HiDiffusion: cls={self.__class__.__name__} info={hasattr(self, "info")} parent={hasattr(self, "_parent")} orphaned call') from e
|
||||
if self.model == 'sd15':
|
||||
if ori_H < 256 or ori_W < 256:
|
||||
self.T1_ratio = switching_threshold_ratio_dict['sd15_1024'][self.switching_threshold_ratio]
|
||||
@@ -516,8 +515,6 @@ def make_diffusers_downsampler_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
self.T1_ratio = switching_threshold_ratio_dict['sdxl_2048'][self.switching_threshold_ratio]
|
||||
if self.info['is_inpainting_task']:
|
||||
self.aggressive_raunet = inpainting_is_aggressive_raunet
|
||||
elif self.info['is_playground']:
|
||||
self.aggressive_raunet = playground_is_aggressive_raunet
|
||||
else:
|
||||
self.aggressive_raunet = is_aggressive_raunet
|
||||
else:
|
||||
@@ -551,7 +548,6 @@ def make_diffusers_downsampler_block(block_class: Type[torch.nn.Module]) -> Type
|
||||
self.timestep = 0
|
||||
return hidden_states
|
||||
|
||||
_patched_forward = forward
|
||||
return downsampler_block
|
||||
|
||||
|
||||
@@ -560,7 +556,6 @@ def make_diffusers_upsampler_block(block_class: Type[torch.nn.Module]) -> Type[t
|
||||
class upsampler_block(block_class):
|
||||
# Save for unpatching later
|
||||
_parent = block_class
|
||||
_forward = block_class.forward
|
||||
T1_ratio = 0
|
||||
T1 = 0
|
||||
timestep = 0
|
||||
@@ -570,7 +565,10 @@ def make_diffusers_upsampler_block(block_class: Type[torch.nn.Module]) -> Type[t
|
||||
def forward(self, hidden_states: torch.Tensor, scale = 1.0) -> torch.Tensor: # pylint: disable=unused-argument
|
||||
self.max_timestep = self.info['pipeline']._num_timesteps # pylint: disable=protected-access
|
||||
# self.max_timestep = len(self.info['scheduler'].timesteps)
|
||||
ori_H, ori_W = self.info['size']
|
||||
try:
|
||||
ori_H, ori_W = self.info['size']
|
||||
except Exception as e:
|
||||
raise RuntimeError(f'HiDiffusion: cls={self.__class__.__name__} info={hasattr(self, "info")} parent={hasattr(self, "_parent")} orphaned call') from e
|
||||
if self.model == 'sd15':
|
||||
if ori_H < 256 or ori_W < 256:
|
||||
self.T1_ratio = switching_threshold_ratio_dict['sd15_1024'][self.switching_threshold_ratio]
|
||||
@@ -585,8 +583,6 @@ def make_diffusers_upsampler_block(block_class: Type[torch.nn.Module]) -> Type[t
|
||||
|
||||
if self.info['is_inpainting_task']:
|
||||
self.aggressive_raunet = inpainting_is_aggressive_raunet
|
||||
elif self.info['is_playground']:
|
||||
self.aggressive_raunet = playground_is_aggressive_raunet
|
||||
else:
|
||||
self.aggressive_raunet = is_aggressive_raunet
|
||||
else:
|
||||
@@ -606,7 +602,6 @@ def make_diffusers_upsampler_block(block_class: Type[torch.nn.Module]) -> Type[t
|
||||
|
||||
return F.conv2d(hidden_states, self.weight, self.bias, self.stride, self.padding, self.dilation, self.groups)
|
||||
|
||||
_patched_forward = forward
|
||||
return upsampler_block
|
||||
|
||||
|
||||
@@ -632,12 +627,13 @@ def apply_hidiffusion(
|
||||
"""
|
||||
global current_steps # pylint: disable=global-statement
|
||||
current_steps = steps
|
||||
if hasattr(model, 'controlnet'):
|
||||
if hasattr(model, 'controlnet') and (model_type == 'sd' or model_type == 'sdxl'):
|
||||
from .hidiffusion_controlnet import make_diffusers_sdxl_contrtolnet_ppl, make_diffusers_unet_2d_condition
|
||||
make_ppl_fn = make_diffusers_sdxl_contrtolnet_ppl
|
||||
model.__class__ = make_ppl_fn(model.__class__)
|
||||
make_block_fn = make_diffusers_unet_2d_condition
|
||||
model.unet.__class__ = make_block_fn(model.unet.__class__)
|
||||
|
||||
diffusion_model = model.unet if hasattr(model, "unet") else model
|
||||
diffusion_model.num_upsamplers += 12
|
||||
diffusion_model.info = {
|
||||
@@ -646,14 +642,13 @@ def apply_hidiffusion(
|
||||
'hooks': [],
|
||||
'text_to_img_controlnet': hasattr(model, 'controlnet'),
|
||||
'is_inpainting_task': model.__class__ in auto_pipeline.AUTO_INPAINT_PIPELINES_MAPPING.values(),
|
||||
'is_playground': False,
|
||||
'pipeline': model}
|
||||
model.info = diffusion_model.info
|
||||
hook_diffusion_model(diffusion_model)
|
||||
|
||||
if model_type == 'sd':
|
||||
modified_key = sd15_hidiffusion_key()
|
||||
for key, module in diffusion_model.named_modules():
|
||||
if hasattr(module, "_parent"):
|
||||
raise RuntimeError(f'HiDiffusion: key={key} module={module.__class__} already patched')
|
||||
if apply_raunet and key in modified_key['down_module_key']:
|
||||
module.__class__ = make_diffusers_downsampler_block(module.__class__)
|
||||
module.switching_threshold_ratio = 'T1_ratio'
|
||||
@@ -668,15 +663,15 @@ def apply_hidiffusion(
|
||||
module.switching_threshold_ratio = 'T2_ratio'
|
||||
if apply_window_attn and key in modified_key['windown_attn_module_key']:
|
||||
module.__class__ = make_diffusers_transformer_block(module.__class__)
|
||||
if hasattr(module, "_patched_forward"):
|
||||
module.forward = module._patched_forward # pylint: disable=protected-access
|
||||
module.model = 'sd15'
|
||||
module.info = diffusion_model.info
|
||||
|
||||
if hasattr(module, "_parent"):
|
||||
module.model = 'sd15'
|
||||
module.info = diffusion_model.info
|
||||
|
||||
elif model_type == 'sdxl':
|
||||
modified_key = sdxl_hidiffusion_key()
|
||||
for key, module in diffusion_model.named_modules():
|
||||
if hasattr(module, "_parent"):
|
||||
raise RuntimeError(f'HiDiffusion: key={key} module={module.__class__} already patched')
|
||||
if apply_raunet and key in modified_key['down_module_key']:
|
||||
module.__class__ = make_diffusers_cross_attn_down_block(module.__class__)
|
||||
module.switching_threshold_ratio = 'T1_ratio'
|
||||
@@ -691,25 +686,26 @@ def apply_hidiffusion(
|
||||
module.switching_threshold_ratio = 'T2_ratio'
|
||||
if apply_window_attn and key in modified_key['windown_attn_module_key']:
|
||||
module.__class__ = make_diffusers_transformer_block(module.__class__)
|
||||
if hasattr(module, "_patched_forward"):
|
||||
module.forward = module._patched_forward # pylint: disable=protected-access
|
||||
module.model = 'sdxl'
|
||||
module.info = diffusion_model.info
|
||||
if hasattr(module, "_parent"):
|
||||
module.model = 'sdxl'
|
||||
module.info = diffusion_model.info
|
||||
else:
|
||||
raise RuntimeError('HiDiffusion: unsupported model type')
|
||||
return model
|
||||
|
||||
model.info = diffusion_model.info
|
||||
model.hidiffusion = True
|
||||
hook_diffusion_model(diffusion_model)
|
||||
|
||||
|
||||
def remove_hidiffusion(model: torch.nn.Module):
|
||||
""" Removes hidiffusion from a Diffusion module if it was already patched. """
|
||||
for _, module in model.unet.named_modules():
|
||||
model = model.unet if hasattr(model, "unet") else model
|
||||
for _, module in model.named_modules():
|
||||
while hasattr(module, "_parent"):
|
||||
model.hidiffusion = True
|
||||
module.__class__ = module._parent # pylint: disable=protected-access
|
||||
if hasattr(module, "info"):
|
||||
for hook in module.info["hooks"]:
|
||||
for hook in module.info.get("hooks", []):
|
||||
hook.remove()
|
||||
module.info["hooks"].clear()
|
||||
del module.info
|
||||
if hasattr(module, "_forward"):
|
||||
module.forward = module._forward # pylint: disable=protected-access
|
||||
if hasattr(module, "_parent"):
|
||||
module.__class__ = module._parent # pylint: disable=protected-access
|
||||
return model
|
||||
|
||||
@@ -15,6 +15,7 @@ def make_diffusers_unet_2d_condition(block_class):
|
||||
class unet_2d_condition(block_class):
|
||||
# Save for unpatching later
|
||||
_parent = block_class
|
||||
|
||||
def forward(
|
||||
self,
|
||||
sample: torch.FloatTensor,
|
||||
@@ -549,7 +550,7 @@ def make_diffusers_sdxl_contrtolnet_ppl(block_class):
|
||||
# # scale the initial noise by the standard deviation required by the scheduler
|
||||
# latents = latents * self.scheduler.init_noise_sigma
|
||||
|
||||
# 7. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline
|
||||
# 7. Prepare extra step kwargs.
|
||||
extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
|
||||
|
||||
# 7.1 Create tensor stating which controlnets to keep
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
"""
|
||||
TODO:
|
||||
- apply metadata
|
||||
- preview
|
||||
- load/save
|
||||
TODO: apply metadata, preview, load/save
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
@@ -164,7 +164,7 @@ def save_image(image,
|
||||
if not check_grid_size([image]):
|
||||
return None, None, None
|
||||
if path is None or path == '': # set default path to avoid errors when functions are triggered manually or via api and param is not set
|
||||
path = shared.opts.outdir_save
|
||||
path = paths.resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_save)
|
||||
namegen = FilenameGenerator(p, seed, prompt, image, grid=grid)
|
||||
suffix = suffix if suffix is not None else ''
|
||||
basename = '' if basename is None else basename
|
||||
@@ -311,7 +311,7 @@ def parse_novelai_metadata(data: dict):
|
||||
return geninfo
|
||||
|
||||
|
||||
def read_info_from_image(image: Image, watermark: bool = False):
|
||||
def read_info_from_image(image: Image.Image, watermark: bool = False):
|
||||
if image is None:
|
||||
return '', {}
|
||||
if isinstance(image, str):
|
||||
@@ -419,7 +419,7 @@ def draw_overlay(im, text: str = '', y_offset: int = 0):
|
||||
return im
|
||||
|
||||
|
||||
def set_watermark(image, wm_text: str = None, wm_image: Image.Image = None):
|
||||
def set_watermark(image, wm_text: str | None = None, wm_image: Image.Image | None = None):
|
||||
if shared.opts.image_watermark_position != 'none' and wm_image is not None: # visible watermark
|
||||
if isinstance(wm_image, str):
|
||||
try:
|
||||
|
||||
@@ -7,6 +7,7 @@ from modules import scripts_manager, shared, processing, images, errors
|
||||
from modules.generation_parameters_copypaste import create_override_settings_dict
|
||||
from modules.ui_common import plaintext_to_html
|
||||
from modules.memstats import memory_stats
|
||||
from modules.paths import resolve_output_path
|
||||
|
||||
|
||||
debug = shared.log.trace if os.environ.get('SD_PROCESS_DEBUG', None) is not None else lambda *args, **kwargs: None
|
||||
@@ -239,8 +240,8 @@ def img2img(id_task: str, state: str, mode: int,
|
||||
|
||||
p = processing.StableDiffusionProcessingImg2Img(
|
||||
sd_model=shared.sd_model,
|
||||
outpath_samples=shared.opts.outdir_samples or shared.opts.outdir_img2img_samples,
|
||||
outpath_grids=shared.opts.outdir_grids or shared.opts.outdir_img2img_grids,
|
||||
outpath_samples=resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_img2img_samples),
|
||||
outpath_grids=resolve_output_path(shared.opts.outdir_grids, shared.opts.outdir_img2img_grids),
|
||||
prompt=prompt,
|
||||
negative_prompt=negative_prompt,
|
||||
styles=prompt_styles,
|
||||
|
||||
@@ -143,12 +143,11 @@ def torch_tensor(data, *args, dtype=None, device=None, **kwargs):
|
||||
global device_supports_fp64
|
||||
if check_cuda(device):
|
||||
device = return_xpu(device)
|
||||
if not device_supports_fp64:
|
||||
if check_device_type(device, "xpu"):
|
||||
if dtype == torch.float64:
|
||||
dtype = torch.float32
|
||||
elif dtype is None and (hasattr(data, "dtype") and (data.dtype == torch.float64 or data.dtype == float)):
|
||||
dtype = torch.float32
|
||||
if not device_supports_fp64 and check_device_type(device, "xpu"):
|
||||
if dtype == torch.float64:
|
||||
dtype = torch.float32
|
||||
elif dtype is None and (hasattr(data, "dtype") and (data.dtype == torch.float64 or data.dtype == float)):
|
||||
dtype = torch.float32
|
||||
return original_torch_tensor(data, *args, dtype=dtype, device=device, **kwargs)
|
||||
|
||||
|
||||
@@ -223,8 +222,6 @@ def torch_empty(*args, device=None, **kwargs):
|
||||
original_torch_randn = torch.randn
|
||||
@wraps(torch.randn)
|
||||
def torch_randn(*args, device=None, dtype=None, **kwargs):
|
||||
if dtype is bytes:
|
||||
dtype = None
|
||||
if check_cuda(device):
|
||||
return original_torch_randn(*args, device=return_xpu(device), dtype=dtype, **kwargs)
|
||||
else:
|
||||
@@ -258,13 +255,32 @@ def torch_full(*args, device=None, **kwargs):
|
||||
return original_torch_full(*args, device=device, **kwargs)
|
||||
|
||||
|
||||
original_torch_arange = torch.arange
|
||||
@wraps(torch.arange)
|
||||
def torch_arange(*args, device=None, dtype=None, **kwargs):
|
||||
global device_supports_fp64
|
||||
if check_cuda(device):
|
||||
if not device_supports_fp64 and dtype == torch.float64:
|
||||
dtype = torch.float32
|
||||
return original_torch_arange(*args, device=return_xpu(device), dtype=dtype, **kwargs)
|
||||
else:
|
||||
if not device_supports_fp64 and check_device_type(device, "xpu") and dtype == torch.float64:
|
||||
dtype = torch.float32
|
||||
return original_torch_arange(*args, device=device, dtype=dtype, **kwargs)
|
||||
|
||||
|
||||
original_torch_linspace = torch.linspace
|
||||
@wraps(torch.linspace)
|
||||
def torch_linspace(*args, device=None, **kwargs):
|
||||
def torch_linspace(*args, device=None, dtype=None, **kwargs):
|
||||
global device_supports_fp64
|
||||
if check_cuda(device):
|
||||
return original_torch_linspace(*args, device=return_xpu(device), **kwargs)
|
||||
if not device_supports_fp64 and dtype == torch.float64:
|
||||
dtype = torch.float32
|
||||
return original_torch_linspace(*args, device=return_xpu(device), dtype=dtype, **kwargs)
|
||||
else:
|
||||
return original_torch_linspace(*args, device=device, **kwargs)
|
||||
if not device_supports_fp64 and check_device_type(device, "xpu") and dtype == torch.float64:
|
||||
dtype = torch.float32
|
||||
return original_torch_linspace(*args, device=device, dtype=dtype, **kwargs)
|
||||
|
||||
|
||||
original_torch_eye = torch.eye
|
||||
@@ -358,6 +374,7 @@ def ipex_hijacks():
|
||||
torch.ones = torch_ones
|
||||
torch.zeros = torch_zeros
|
||||
torch.full = torch_full
|
||||
torch.arange = torch_arange
|
||||
torch.linspace = torch_linspace
|
||||
torch.eye = torch_eye
|
||||
torch.load = torch_load
|
||||
|
||||