Merge pull request #3936 from vladmandic/dev

merge dev
This commit is contained in:
Vladimir Mandic
2025-05-15 12:10:53 -04:00
committed by GitHub
60 changed files with 365 additions and 308 deletions
+21 -6
View File
@@ -1,16 +1,31 @@
# Change Log for SD.Next
## Update for 2025-05-12
## Update for 2025-05-15
Curious how your system is performing?
*Curious how your system is performing?*
Run a built-in benchmark and compare to over 15k unique results world-wide: (Benchmark data)[https://vladmandic.github.io/sd-extension-system-info/pages/benchmark.html]!
From slowest 0.02 it/s running on 6th gen CPU without acceleration up to 275 it/s running on tuned GH100 system!
From slowest 0.02 it/s running on 6th gen CPU without acceleration up to 275+ it/s running on tuned GH100 system!
Also, since quantization is becoming a necessity for almost all new models, see comparison of different quantization methods available in SD.Next: [Quantization](https://vladmandic.github.io/sdnext-docs/Quantization/)
*Hint*: Even if you may not need quantization for your current model, it may be worth trying it out as it can significantly improve performance!
For ZLUDA users, this update adds [compatibility](https://github.com/vladmandic/sdnext/issues/3918) with with latest AMD Adrenaline drivers
Btw, last few releases have been smaller, but more regular so do check posts about previous releases as features do quickly add up!
- **Wiki**
- Updates for: *WSL, ZLUDA, ROCm*
- Updates for: *Quantization, NNCF, WSL, ZLUDA, ROCm*
- **Compute**
- ZLUDA: update to `zluda==3.9.5` with `torch==2.7.0`
*Note*: delete `.zluda` folder so that newest zluda will be installed if you are using the latest AMD Adrenaline driver
- NNCF: added experimental support for direct INT8 MatMul
- **Feature**
- Prompt Enhance: option to allow/disallow NSFW content
- **Fixes**
- OpenVINO: force cpu device
- Gradio: major cleanup and fixing defaults and ranges
- Pydantic: update to api types
- UI defaults: match correct prompt components
## Update for 2025-05-12
@@ -973,7 +988,7 @@ Commit hash: `master: #dcfc9f3` `dev: #935cac6`
- optimizations: full offload, quantization and tiling support
- [TeaCache](https://github.com/ali-vilab/TeaCache/blob/main/TeaCache4LTX-Video/README.md) integration
- **VAE**:
- tiling granular options in *settings -> variable auto encoder*
- tiling granular options in *settings -> Variational Auto Encoder*
- **UI**:
- live preview optimizations and error handling
- live preview high quality output, thanks @Disty0
+22 -12
View File
@@ -4,20 +4,31 @@ Main ToDo list can be found at [GitHub projects](https://github.com/users/vladma
## Current
- [Diffusers guiders](https://github.com/huggingface/diffusers/pull/11311)
- [Nunchaku PulID](https://github.com/mit-han-lab/nunchaku/pull/274)
- Video: API support
### Issues/Limitations
N/A
- Control: API enhance scripts compatibility
- Video: API support
## Future Candidates
- Control: API enhance scripts compatibility
- IPAdapter: negative guidance: <https://github.com/huggingface/diffusers/discussions/7167>
- Video: STG: <https://github.com/huggingface/diffusers/blob/main/examples/community/README.md#spatiotemporal-skip-guidance>
- Video: SmoothCache: https://github.com/huggingface/diffusers/issues/11135
- [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)
- [LBM](https://github.com/gojasper/LBM)
- [SmoothCache](https://github.com/huggingface/diffusers/issues/11135)
- [Magi](https://github.com/SandAI-org/MAGI-1)
- [SkyReels-v2](https://github.com/huggingface/diffusers/pull/11518)
- [WanAI-2.1 VACE](https://huggingface.co/Wan-AI/Wan2.1-VACE-14B)
- [LTXVideo-0.9.7](https://github.com/huggingface/diffusers/pull/11516)
- [VisualClose](https://github.com/huggingface/diffusers/pull/11377)
- [SEVA](https://github.com/huggingface/diffusers/pull/11440)
- [CausVid-Plus](https://github.com/goatWu/CausVid-Plus/)
- [Index-AniSora](https://github.com/bilibili/Index-anisora)
- [HiDream GGUF](https://github.com/huggingface/diffusers/pull/11550)
- [JoyCaption-Beta-One](https://huggingface.co/fancyfeast/llama-joycaption-beta-one-hf-llava)
- [Diffusers guiders](https://github.com/huggingface/diffusers/pull/11311)
- [Nunchaku PulID](https://github.com/mit-han-lab/nunchaku/pull/274)
- [Dream0](https://huggingface.co/ByteDance/DreamO)
- [Pydantic changes](https://github.com/Cschlaefli/automatic)
## Code TODO
@@ -31,14 +42,13 @@ N/A
- loader: load receipe
- loader: save receipe
- lora: add other quantization types
- lora: add t5 key support for sd35/f1
- lora: maybe force imediate quantization
- lora: add t5 key support for sd35/f16
- lora: support pre-quantized flux
- model load: force-reloading entire model as loading transformers only leads to massive memory usage
- model loader: implement model in-memory caching
- modernui: monkey-patch for missing tabs.select event
- modules/lora/lora_extract.py:185:9: W0511: TODO: lora: support pre-quantized flux
- nunchaku: batch support
- nunchaku: cache-dir for transformer and t5 loader
- processing: remove duplicate mask params
- resize image: enable full VAE mode for resize-latent
+2
View File
@@ -53,6 +53,7 @@ def enhance(args): # pylint: disable=redefined-outer-name
'prompt': str(args.prompt),
'seed': int(args.seed),
'type': str(args.type),
'nsfw': bool(args.nsfw),
}
if args.model:
options['model'] = str(args.model)
@@ -69,6 +70,7 @@ if __name__ == "__main__":
parser.add_argument('--type', type=str, default='text', choices=['text', 'image', 'video'], required=False, help='enhance type')
parser.add_argument('--model', type=str, default=None, required=False, help='model name')
parser.add_argument('--image', type=str, default=None, required=False, help='optional input image')
parser.add_argument('--nsfw', type=bool, action=argparse.BooleanOptionalAction, required=False, help='nsfw allowed')
args = parser.parse_args()
log.info(f'api-upscale: {args}')
result = enhance(args)
+1 -1
View File
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "Variabler Auto-Encoder",
"hint": "Einstellungen bezüglich variablem Auto-Encoder und Bilddekodierungsprozess während der Generierung"
},
+2 -2
View File
@@ -59,7 +59,7 @@
{"id":"","label":"Hypernetwork","localized":"","hint":"Small trained neural network that modifies behavior of the loaded model"},
{"id":"","label":"VLM Caption","localized":"","hint":"Analyze image using vision langugage model"},
{"id":"","label":"CLiP Interrogate","localized":"","hint":"Analyze image using CLiP model"},
{"id":"","label":"VAE","localized":"","hint":"Variable Auto Encoder: model used to run image decode at the end of generate"},
{"id":"","label":"VAE","localized":"","hint":"Variational Auto Encoder: model used to run image decode at the end of generate"},
{"id":"","label":"History","localized":"","hint":"List of previous generations that can be further reprocessed"},
{"id":"","label":"UI disable variable aspect ratio","localized":"","hint":"When disabled, all thumbnails appear as squared images"},
{"id":"","label":"Build info on first access","localized":"","hint":"Prevents server from building EN page on server startup and instead build it when requested"},
@@ -247,7 +247,7 @@
{"id":"","label":"Unload model","localized":"","hint":"Unload currently loaded model"},
{"id":"","label":"Reload model","localized":"","hint":"Reload currently selected model"},
{"id":"","label":"Models & Loading","localized":"","hint":"Settings related to base models, primary backend and model load behavior"},
{"id":"","label":"Variable Auto Encoder","localized":"","hint":"Settings related to variable auto encoder and image decoding process during generate"},
{"id":"","label":"Variational Auto Encoder","localized":"","hint":"Settings related to Variational Auto Encoder and image decoding process during generate"},
{"id":"","label":"Text encoder","localized":"","hint":"Settings related to text encoder and prompt encoding processing during generate"},
{"id":"","label":"Compute Settings","localized":"","hint":"Settings related to compute precision, cross attention, and optimizations for computing platforms"},
{"id":"","label":"Backend Settings","localized":"","hint":"Settings related to compute backends: torch, onnx and olive"},
+2 -2
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder: modelo usado para ejecutar la decodificación de la imagen al final de la generación"
"hint": "Variational Auto Encoder: modelo usado para ejecutar la decodificación de la imagen al final de la generación"
},
{
"id": "",
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "Autoencoder Variable",
"hint": "Configuración relacionada con el autoencoder variable y el proceso de decodificación de imágenes durante la generación"
},
+2 -2
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder : modèle utilisé pour exécuter le décodage d'image à la fin de la génération"
"hint": "Variational Auto Encoder : modèle utilisé pour exécuter le décodage d'image à la fin de la génération"
},
{
"id": "",
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "Encodeur automatique variable",
"hint": "Paramètres liés à l'encodeur automatique variable et au processus de décodage d'image pendant la génération"
},
+2 -2
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder: model koji se koristi za pokretanje dekodiranja slike na kraju generiranja"
"hint": "Variational Auto Encoder: model koji se koristi za pokretanje dekodiranja slike na kraju generiranja"
},
{
"id": "",
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "Varijabilni Auto Encoder",
"hint": "Postavke vezane uz varijabilni auto encoder i proces dekodiranja slike tijekom generiranja"
},
+4 -4
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder: modello utilizzato per eseguire la decodifica dell'immagine alla fine della generazione"
"hint": "Variational Auto Encoder: modello utilizzato per eseguire la decodifica dell'immagine alla fine della generazione"
},
{
"id": "",
@@ -1402,9 +1402,9 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"localized": "Variable Auto Encoder",
"hint": "Impostazioni relative al variable auto encoder e al processo di decodifica delle immagini durante la generazione"
"label": "Variational Auto Encoder",
"localized": "Variational Auto Encoder",
"hint": "Impostazioni relative al Variational Auto Encoder e al processo di decodifica delle immagini durante la generazione"
},
{
"id": "",
+2 -2
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder:生成の最後にイメージデコードを実行するために使用されるモデル"
"hint": "Variational Auto Encoder:生成の最後にイメージデコードを実行するために使用されるモデル"
},
{
"id": "",
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "可変オートエンコーダー",
"hint": "生成時の可変オートエンコーダーと画像デコードプロセスに関する設定。"
},
+3 -3
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder: 생성 종료 시 이미지 디코드를 실행하는 데 사용되는 모델"
"hint": "Variational Auto Encoder: 생성 종료 시 이미지 디코드를 실행하는 데 사용되는 모델"
},
{
"id": "",
@@ -1402,8 +1402,8 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"localized": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "Variational Auto Encoder",
"hint": "가변 자동 인코더 및 생성 중 이미지 디코딩 프로세스와 관련된 설정입니다."
},
{
+2 -2
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder: modelo usado para executar a decodificação da imagem no final da geração"
"hint": "Variational Auto Encoder: modelo usado para executar a decodificação da imagem no final da geração"
},
{
"id": "",
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "Auto Encoder Variável",
"hint": "Configurações relacionadas ao auto encoder variável e ao processo de decodificação de imagem durante a geração"
},
+2 -2
View File
@@ -324,7 +324,7 @@
"id": "",
"label": "VAE",
"localized": "VAE",
"hint": "Variable Auto Encoder: модель, используемая для запуска декодирования изображения в конце генерации"
"hint": "Variational Auto Encoder: модель, используемая для запуска декодирования изображения в конце генерации"
},
{
"id": "",
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "Вариативный автоэнкодер",
"hint": "Настройки, связанные с вариативным автоэнкодером и процессом декодирования изображений во время генерации"
},
+1 -1
View File
@@ -1402,7 +1402,7 @@
},
{
"id": "",
"label": "Variable Auto Encoder",
"label": "Variational Auto Encoder",
"localized": "可变自动编码器",
"hint": "与可变自动编码器和生成过程中图像解码过程相关的设置"
},
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -546,7 +546,7 @@ def check_diffusers():
t_start = time.time()
if args.skip_all or args.skip_git or args.experimental:
return
sha = '0ba1f76d4dde6d25b33dbdca73b6aa21bb682c56' # diffusers commit hash
sha = '20379d9d1395b8e95977faf80facff43065ba75f' # diffusers commit hash
pkg = pkg_resources.working_set.by_key.get('diffusers', None)
minor = int(pkg.version.split('.')[1] if pkg is not None else 0)
cur = opts.get('diffusers_version', '') if minor > 0 else ''
@@ -655,7 +655,7 @@ def install_rocm_zluda():
if error is None:
try:
zluda_installer.load()
torch_command = os.environ.get('TORCH_COMMAND', 'torch==2.6.0 torchvision --index-url https://download.pytorch.org/whl/cu118')
torch_command = os.environ.get('TORCH_COMMAND', 'torch==2.7.0 torchvision --index-url https://download.pytorch.org/whl/cu118')
except Exception as e:
error = e
log.warning(f'Failed to load ZLUDA: {e}')
+1 -1
View File
@@ -23,7 +23,7 @@ ReqControl = models.create_model_from_signature(
model_name = "StableDiffusionProcessingControl",
additional_fields = [
{"key": "sampler_name", "type": str, "default": "UniPC"},
{"key": "script_name", "type": str, "default": None},
{"key": "script_name", "type": Optional[str], "default": None},
{"key": "script_args", "type": list, "default": []},
{"key": "send_images", "type": bool, "default": True},
{"key": "save_images", "type": bool, "default": False},
+24 -19
View File
@@ -67,8 +67,11 @@ class PydanticModelGenerator:
def generate_model(self):
model_fields = { d.field: (d.field_type, Field(default=d.field_value, alias=d.field_alias, exclude=d.field_exclude)) for d in self._model_def }
DynamicModel = create_model(self._model_name, **model_fields)
DynamicModel.__config__.allow_population_by_field_name = True
DynamicModel.__config__.allow_mutation = True
try:
DynamicModel.__config__.allow_population_by_field_name = True
DynamicModel.__config__.allow_mutation = True
except Exception:
pass
return DynamicModel
### item classes
@@ -182,7 +185,7 @@ class ItemScript(BaseModel):
class ItemExtension(BaseModel):
name: str = Field(title="Name", description="Extension name")
remote: str = Field(title="Remote", description="Extension Repository URL")
branch: str = Field(title="Branch", description="Extension Repository Branch")
branch: str = Field(default="uknnown", title="Branch", description="Extension Repository Branch")
commit_hash: str = Field(title="Commit Hash", description="Extension Repository Commit Hash")
version: str = Field(title="Version", description="Extension Version")
commit_date: str = Field(title="Commit Date", description="Extension Repository Commit Date")
@@ -197,7 +200,7 @@ ReqTxt2Img = PydanticModelGenerator(
{"key": "sampler_index", "type": Union[int, str], "default": 0},
{"key": "sampler_name", "type": str, "default": "UniPC"},
{"key": "hr_sampler_name", "type": str, "default": "Same as primary"},
{"key": "script_name", "type": str, "default": "none"},
{"key": "script_name", "type": Optional[str], "default": "none"},
{"key": "script_args", "type": list, "default": []},
{"key": "send_images", "type": bool, "default": True},
{"key": "save_images", "type": bool, "default": False},
@@ -221,13 +224,11 @@ ReqImg2Img = PydanticModelGenerator(
{"key": "sampler_index", "type": Union[int, str], "default": 0},
{"key": "sampler_name", "type": str, "default": "UniPC"},
{"key": "hr_sampler_name", "type": str, "default": "Same as primary"},
{"key": "script_name", "type": str, "default": "none"},
{"key": "script_args", "type": list, "default": []},
{"key": "init_images", "type": list, "default": None},
{"key": "denoising_strength", "type": float, "default": 0.5},
{"key": "mask", "type": str, "default": None},
{"key": "mask", "type": Optional[str], "default": None},
{"key": "include_init_images", "type": bool, "default": False, "exclude": True},
{"key": "script_name", "type": str, "default": None},
{"key": "script_name", "type": Optional[str], "default": "none"},
{"key": "script_args", "type": list, "default": []},
{"key": "send_images", "type": bool, "default": True},
{"key": "save_images", "type": bool, "default": False},
@@ -274,6 +275,7 @@ class ReqPromptEnhance(BaseModel):
system_prompt: Optional[str] = Field(title="System prompt", default=None, description="Model system prompt")
image: Optional[str] = Field(title="Image", default=None, description="Image to work on, must be a Base64 string containing the image's data.")
seed: int = Field(title="Seed", default=-1, description="Seed used to generate the prompt")
nsfw: bool = Field(title="NSFW", default=True, description="Should NSFW content be allowed?")
class ResPromptEnhance(BaseModel):
prompt: str = Field(title="Prompt", description="Enhanced prompt")
@@ -305,9 +307,9 @@ class ReqGetLog(BaseModel):
class ReqPostLog(BaseModel):
message: Optional[str] = Field(title="Message", description="The info message to log")
debug: Optional[str] = Field(title="Debug message", description="The debug message to log")
error: Optional[str] = Field(title="Error message", description="The error message to log")
message: Optional[str] = Field(default=None, title="Message", description="The info message to log")
debug: Optional[str] = Field(default=None, title="Debug message", description="The debug message to log")
error: Optional[str] = Field(default=None, title="Error message", description="The error message to log")
class ReqHistory(BaseModel):
id: str = Field(default=None, title="Task ID", description="Task ID")
@@ -320,8 +322,8 @@ class ResProgress(BaseModel):
progress: float = Field(title="Progress", description="The progress with a range of 0 to 1")
eta_relative: float = Field(title="ETA in secs")
state: dict = Field(title="State", description="The current state snapshot")
current_image: str = Field(default=None, title="Current image", description="The current image in base64 format. opts.show_progress_every_n_steps is required for this to work.")
textinfo: str = Field(default=None, title="Info text", description="Info text used by WebUI.")
current_image: Optional[str] = Field(default=None, title="Current image", description="The current image in base64 format. opts.show_progress_every_n_steps is required for this to work.")
textinfo: Optional[str] = Field(default=None, title="Info text", description="Info text used by WebUI.")
class ResHistory(BaseModel):
id: str = Field(title="ID", description="Task ID")
@@ -344,9 +346,9 @@ class ResStatus(BaseModel):
steps: int = Field(title="Steps", description="Total steps")
queued: int = Field(title="Queued", description="Number of queued tasks")
uptime: int = Field(title="Uptime", description="Uptime of the server")
elapsed: Optional[float] = Field(title="Elapsed time")
eta: Optional[float] = Field(title="ETA in secs")
progress: Optional[float] = Field(title="Progress", description="The progress with a range of 0 to 1")
elapsed: Optional[float] = Field(default=None, title="Elapsed time")
eta: Optional[float] = Field(default=None, title="ETA in secs")
progress: Optional[float] = Field(default=None, title="Progress", description="The progress with a range of 0 to 1")
class ReqInterrogate(BaseModel):
@@ -403,7 +405,7 @@ _options = vars(shared.parser)['_option_string_actions']
for key in _options:
if _options[key].dest != 'help':
flag = _options[key]
_type = str
_type = Optional[str]
if _options[key].default is not None:
_type = type(_options[key].default)
flags.update({flag.dest: (_type, Field(default=flag.default, description=flag.help))})
@@ -481,6 +483,9 @@ def create_model_from_signature(func: Callable, model_name: str, base_model: Typ
__base__=base_model,
__config__=config,
)
model.__config__.allow_population_by_field_name = True
model.__config__.allow_mutation = True
try:
model.__config__.allow_population_by_field_name = True
model.__config__.allow_mutation = True
except Exception:
pass
return model
+3
View File
@@ -146,6 +146,7 @@ class APIProcess():
prompt=req.prompt,
system=req.system_prompt,
seed=seed,
nsfw=req.nsfw,
)
elif req.type == 'image':
from modules.scripts import scripts_txt2img
@@ -157,6 +158,7 @@ class APIProcess():
system=req.system_prompt,
image=decode_base64_to_image(req.image),
seed=seed,
nsfw=req.nsfw,
)
elif req.type == 'video':
from modules.ui_video_vlm import enhance_prompt
@@ -167,6 +169,7 @@ class APIProcess():
prompt=req.prompt,
model=model,
system_prompt=req.system_prompt,
nsfw=req.nsfw,
)
else:
raise HTTPException(status_code=400, detail="prompt enhancement: invalid type")
+1 -1
View File
@@ -69,7 +69,7 @@ class Extension:
if repo.active_branch:
self.branch = repo.active_branch.name
except Exception:
pass
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>"
except Exception as ex:
+2 -2
View File
@@ -92,12 +92,12 @@ class Script(scripts.Script):
gr.HTML('<a href="https://photo-maker.github.io/" target="_blank">&nbsp Tenecent ARC Lab PhotoMaker</a><br>')
with gr.Row():
pm_model = gr.Dropdown(label='PhotoMaker Model', choices=['PhotoMaker v1', 'PhotoMaker v2'], value='PhotoMaker v2')
pm_trigger = gr.Text(label='Trigger word', placeholder="enter one word in prompt")
pm_trigger = gr.Textbox(label='Trigger word', placeholder="enter one word in prompt")
with gr.Row():
pm_strength = gr.Slider(label='Strength', minimum=0.0, maximum=2.0, step=0.01, value=1.0)
pm_start = gr.Slider(label='Start', minimum=0.0, maximum=1.0, step=0.01, value=0.5)
with gr.Row():
files = gr.File(label='Input images', file_count='multiple', file_types=['image'], type='file', interactive=True, height=100)
files = gr.File(label='Input images', file_count='multiple', file_types=['image'], interactive=True, height=100)
with gr.Row():
gallery = gr.Gallery(show_label=False, value=[])
files.change(fn=self.load_images, inputs=[files], outputs=[gallery])
+34 -2
View File
@@ -84,14 +84,46 @@ def Blocks_get_config_file(self, *args, **kwargs):
return config
def patch_gradio():
def wrap_gradio_js(fn):
def wrapper(*args, js=None, _js=None, **kwargs):
if _js is not None:
js = _js
return fn(*args, js=js, **kwargs)
return wrapper
gradio.components.Button.click = wrap_gradio_js(gradio.components.Button.click)
gradio.components.Textbox.submit = wrap_gradio_js(gradio.components.Textbox.submit)
gradio.components.Image.clear = wrap_gradio_js(gradio.components.Image.clear)
gradio.components.Image.change = wrap_gradio_js(gradio.components.Image.change)
gradio.components.Image.upload = wrap_gradio_js(gradio.components.Image.upload)
gradio.components.Video.change = wrap_gradio_js(gradio.components.Video.change)
gradio.components.Video.clear = wrap_gradio_js(gradio.components.Video.clear)
gradio.components.Slider.change = wrap_gradio_js(gradio.components.Slider.change)
gradio.components.Dropdown.change = wrap_gradio_js(gradio.components.Dropdown.change)
gradio.components.File.change = wrap_gradio_js(gradio.components.File.change)
gradio.components.File.clear = wrap_gradio_js(gradio.components.File.clear)
gradio.components.Number.change = wrap_gradio_js(gradio.components.Number.change)
gradio.components.Textbox.change = wrap_gradio_js(gradio.components.Textbox.change)
gradio.components.Radio.change = wrap_gradio_js(gradio.components.Radio.change)
gradio.components.Checkbox.change = wrap_gradio_js(gradio.components.Checkbox.change)
gradio.components.CheckboxGroup.change = wrap_gradio_js(gradio.components.CheckboxGroup.change)
gradio.components.ColorPicker.change = wrap_gradio_js(gradio.components.ColorPicker.change)
gradio.layouts.Tab.select = wrap_gradio_js(gradio.layouts.Tab.select)
gradio.components.Image.edit = lambda *args, **kwargs: None
# gradio.components.image.Image.__init__ missing tool, brush_radius, mask_opacity, edit()
def init():
global hijacked, original_IOComponent_init, original_Block_get_config, original_BlockContext_init, original_Blocks_get_config_file # pylint: disable=global-statement
if hijacked:
return
gr.components.Image.preprocess = gr_image_preprocess
gr.components.IOComponent.pil_to_temp_file = gr_tempdir.pil_to_temp_file
original_IOComponent_init = patches.patch(__name__, obj=gr.components.IOComponent, field="__init__", replacement=IOComponent_init)
if hasattr(gr.components, 'IOComponent'):
gr.components.IOComponent.pil_to_temp_file = gr_tempdir.pil_to_temp_file
original_IOComponent_init = patches.patch(__name__, obj=gr.components.IOComponent, field="__init__", replacement=IOComponent_init)
original_Block_get_config = patches.patch(__name__, obj=gr.blocks.Block, field="get_config", replacement=Block_get_config)
original_BlockContext_init = patches.patch(__name__, obj=gr.blocks.BlockContext, field="__init__", replacement=BlockContext_init)
original_Blocks_get_config_file = patches.patch(__name__, obj=gr.blocks.Blocks, field="get_config_file", replacement=Blocks_get_config_file)
if not gr.__version__.startswith('3.43'):
patch_gradio()
hijacked = True
+1 -1
View File
@@ -151,7 +151,7 @@ def network_add_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn.G
new_weight = dequant_weight.to(devices.device, dtype=torch.float32) + lora_weights.to(devices.device, dtype=torch.float32)
self.weight = torch.nn.Parameter(new_weight, requires_grad=False)
self.pre_ops.pop("0")
self._custom_forward_fn = None
self._custom_forward_fn = None # pylint: disable=protected-access
self = nncf_compress_layer(self, num_bits, is_asym_mode, torch_dtype=devices.dtype, quant_conv=shared.opts.nncf_quantize_conv_layers, group_size=shared.opts.nncf_compress_weights_group_size, use_int8_matmul=shared.opts.nncf_decompress_int8_matmul)
self = self.to(device)
del dequant_weight
+4 -4
View File
@@ -111,7 +111,6 @@ def create_nncf_config(kwargs = None, allow_nncf: bool = True, module: str = 'Mo
load_nncf(silent=True)
if intel_nncf is None:
return kwargs
from modules.model_quant_nncf import NNCFQuantizer, NNCFConfig
diffusers.quantizers.auto.AUTO_QUANTIZER_MAPPING["nncf"] = NNCFQuantizer
transformers.quantizers.auto.AUTO_QUANTIZER_MAPPING["nncf"] = NNCFQuantizer
@@ -269,12 +268,12 @@ def load_nncf(msg='', silent=False):
log.warning('Quantization: nncf installed please restart')
install('jstyleson', quiet=True)
install('texttable', quiet=True)
install('tabulate', quiet=True)
try:
import nncf
intel_nncf = nncf
try:
# silence the pytorch version warning
nncf.common.logging.logger.warn_bkc_version_mismatch = lambda *args, **kwargs: None
nncf.common.logging.logger.warn_bkc_version_mismatch = lambda *args, **kwargs: None # silence the pytorch version warning
except Exception:
pass
fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access
@@ -328,7 +327,8 @@ def apply_layerwise(sd_model, quiet:bool=False):
m.quantization_method = quantization_config.QuantizationMethod.LAYERWISE # pylint: disable=no-member
log.quiet(quiet, f'Quantization: type=layerwise module={module} cls={cls} storage={storage_dtype} compute={devices.dtype} blocking={not non_blocking}')
except Exception as e:
log.error(f'Quantization: type=layerwise {e}')
if 'Hook with name' not in str(e):
log.error(f'Quantization: type=layerwise {e}')
def nncf_compress_model(model, op=None, sd_model=None, do_gc=True):
+50 -81
View File
@@ -1,28 +1,25 @@
# pylint: disable=redefined-builtin,no-member
from typing import Any, Dict, List, Tuple, Optional, Union
from dataclasses import dataclass
from enum import Enum
import os
import torch
from diffusers.quantizers.base import DiffusersQuantizer
from diffusers.quantizers.quantization_config import QuantizationConfigMixin
from diffusers.utils import get_module_from_name
from accelerate import init_empty_weights
from accelerate.utils import CustomDtype
from modules import devices, shared
debug = os.environ.get('SD_QUANT_DEBUG', None) is not None
torch_dtype_dict = {
"int8": torch.int8,
"uint8": torch.uint8,
"int4": CustomDtype.INT4,
"uint4": CustomDtype.INT4,
}
weights_dtype_dict = {
"int8_asym": "uint8",
"int8_sym": "int8",
@@ -31,21 +28,20 @@ weights_dtype_dict = {
"int8": "uint8",
"int4": "uint4",
}
linear_types = ["NNCFLinear", "Linear"]
conv_types = ["NNCFConv1d", "NNCFConv2d", "NNCFConv3d", "Conv1d", "Conv2d", "Conv3d"]
conv_transpose_types = ["NNCFConvTranspose1d", "NNCFConvTranspose2d", "NNCFConvTranspose3d", "ConvTranspose1d", "ConvTranspose2d", "ConvTranspose3d"]
allowed_types = []
allowed_types.extend(linear_types)
allowed_types.extend(conv_types)
allowed_types.extend(conv_transpose_types)
class QuantizationMethod(str, Enum):
NNCF = "nncf"
def nncf_compress_layer(layer, num_bits, is_asym_mode, torch_dtype=None, quant_conv=False, group_size=0, use_int8_matmul=False, param_name=None):
def nncf_compress_layer(layer, num_bits, is_asym_mode, torch_dtype=None, quant_conv=False, group_size=0, use_int8_matmul=False, param_name=None): # pylint: disable=unused-argument
if layer.__class__.__name__ in allowed_types:
if torch_dtype is None:
torch_dtype = devices.dtype
@@ -64,7 +60,7 @@ def nncf_compress_layer(layer, num_bits, is_asym_mode, torch_dtype=None, quant_c
else:
reduction_axes = -1
channel_size = layer.weight.shape[-1]
use_int8_matmul = use_int8_matmul and not is_asym_mode and channel_size >= 1024 and layer.weight.shape[0] >= 1024
use_int8_matmul = use_int8_matmul and not is_asym_mode and channel_size >= 32 and layer.weight.shape[0] >= 32
if not use_int8_matmul and (group_size > 0 or (num_bits == 4 and group_size != -1)):
if group_size == 0:
@@ -110,12 +106,12 @@ def nncf_compress_layer(layer, num_bits, is_asym_mode, torch_dtype=None, quant_c
zero_point = zero_point.to(torch_dtype)
if use_int8_matmul:
layer._custom_forward_fn = linear_forward_int8_matmul
layer._custom_forward_fn = linear_forward_int8_matmul # pylint: disable=protected-access
scale = scale.squeeze(-1)
if num_bits == 8:
compressed_weight = compressed_weight.transpose(0,1)
else:
layer._custom_forward_fn = None
layer._custom_forward_fn = None # pylint: disable=protected-access
if num_bits == 4:
if is_asym_mode:
@@ -125,7 +121,6 @@ def nncf_compress_layer(layer, num_bits, is_asym_mode, torch_dtype=None, quant_c
compressed_weight_shape=compressed_weight.shape,
result_dtype=torch_dtype,
result_shape=result_shape,
use_int8_matmul=use_int8_matmul,
)
else:
decompressor = INT4SymmetricWeightsDecompressor(
@@ -142,7 +137,6 @@ def nncf_compress_layer(layer, num_bits, is_asym_mode, torch_dtype=None, quant_c
zero_point=zero_point.data,
result_dtype=torch_dtype,
result_shape=result_shape,
use_int8_matmul=use_int8_matmul,
)
else:
decompressor = INT8SymmetricWeightsDecompressor(
@@ -152,12 +146,9 @@ def nncf_compress_layer(layer, num_bits, is_asym_mode, torch_dtype=None, quant_c
use_int8_matmul=use_int8_matmul,
)
compressed_weight = decompressor.pack_weight(compressed_weight)
compressed_weight = compressed_weight.to(return_device)
compressed_weight = decompressor.pack_weight(compressed_weight).to(return_device)
decompressor = decompressor.to(return_device)
layer.register_pre_forward_operation(decompressor)
layer.weight.requires_grad = False
layer.weight.data = compressed_weight
return layer
@@ -201,8 +192,9 @@ class NNCFQuantizer(DiffusersQuantizer):
use_keep_in_fp32_modules = True
requires_calibration = False
required_packages = ["nncf"]
torch_dtype = None
def __init__(self, quantization_config, **kwargs):
def __init__(self, quantization_config, **kwargs): # pylint: disable=useless-parent-delegation
super().__init__(quantization_config, **kwargs)
def check_if_quantized_param(
@@ -213,7 +205,7 @@ class NNCFQuantizer(DiffusersQuantizer):
state_dict: Dict[str, Any],
**kwargs,
):
module, tensor_name = get_module_from_name(model, param_name)
module, _ = get_module_from_name(model, param_name)
return module.__class__.__name__.startswith("NNCF") and param_name.endswith(".weight")
def check_quantized_param(self, *args, **kwargs) -> bool:
@@ -222,19 +214,19 @@ class NNCFQuantizer(DiffusersQuantizer):
"""
return self.check_if_quantized_param(*args, **kwargs)
def create_quantized_param(
def create_quantized_param( # pylint: disable=arguments-differ
self,
model,
param_value: "torch.Tensor",
param_name: str,
target_device: "torch.device",
state_dict: Dict[str, Any],
unexpected_keys: List[str],
state_dict: Dict[str, Any], # pylint: disable=unused-argument
unexpected_keys: List[str], # pylint: disable=unused-argument
**kwargs,
):
# load the model params to target_device first
layer, tensor_name = get_module_from_name(model, param_name)
layer._parameters[tensor_name] = torch.nn.Parameter(param_value).to(device=target_device)
layer._parameters[tensor_name] = torch.nn.Parameter(param_value).to(device=target_device) # pylint: disable=protected-access
split_param_name = param_name.split(".")
if param_name not in self.modules_to_not_convert and not any(param in split_param_name for param in self.modules_to_not_convert):
@@ -252,7 +244,7 @@ class NNCFQuantizer(DiffusersQuantizer):
max_memory = {key: val * 0.70 for key, val in max_memory.items()}
return max_memory
def adjust_target_dtype(self, target_dtype: "torch.dtype") -> "torch.dtype":
def adjust_target_dtype(self, target_dtype: "torch.dtype") -> "torch.dtype": # pylint: disable=unused-argument,arguments-renamed
return torch_dtype_dict[self.quantization_config.weights_dtype]
def update_torch_dtype(self, torch_dtype: "torch.dtype" = None) -> "torch.dtype":
@@ -261,10 +253,10 @@ class NNCFQuantizer(DiffusersQuantizer):
self.torch_dtype = torch_dtype
return torch_dtype
def _process_model_before_weight_loading(
def _process_model_before_weight_loading( # pylint: disable=arguments-differ
self,
model,
device_map,
device_map, # pylint: disable=unused-argument
keep_in_fp32_modules: List[str] = [],
**kwargs,
):
@@ -289,19 +281,19 @@ class NNCFQuantizer(DiffusersQuantizer):
"""
return config
def update_unexpected_keys(self, model, unexpected_keys: List[str], prefix: str) -> List[str]:
def update_unexpected_keys(self, model, unexpected_keys: List[str], prefix: str) -> List[str]: # pylint: disable=unused-argument
"""
needed for transformers compatibilty, no-op function
"""
return unexpected_keys
def update_missing_keys_after_loading(self, model, missing_keys: List[str], prefix: str) -> List[str]:
def update_missing_keys_after_loading(self, model, missing_keys: List[str], prefix: str) -> List[str]: # pylint: disable=unused-argument
"""
needed for transformers compatibilty, no-op function
"""
return missing_keys
def update_expected_keys(self, model, expected_keys: List[str], loaded_keys: List[str]) -> List[str]:
def update_expected_keys(self, model, expected_keys: List[str], loaded_keys: List[str]) -> List[str]: # pylint: disable=unused-argument
"""
needed for transformers compatibilty, no-op function
"""
@@ -330,16 +322,18 @@ class NNCFConfig(QuantizationConfigMixin):
modules left in their original precision (e.g. Whisper encoder, Llava encoder, Mixtral gate layers).
"""
def __init__(
def __init__( # pylint: disable=super-init-not-called
self,
weights_dtype: str = "int8_sym",
group_size: int = 0,
use_int8_matmul: bool = False,
modules_to_not_convert: Optional[List[str]] = None,
**kwargs,
**kwargs, # pylint: disable=unused-argument
):
self.quant_method = QuantizationMethod.NNCF
self.weights_dtype = weights_dtype_dict[weights_dtype.lower()]
self.group_size = group_size
self.use_int8_matmul = use_int8_matmul
self.modules_to_not_convert = modules_to_not_convert
self.post_init()
@@ -347,8 +341,6 @@ class NNCFConfig(QuantizationConfigMixin):
self.num_bits = 8 if self.weights_dtype in {"int8", "uint8"} else 4
self.is_asym_mode = self.weights_dtype in {"uint8", "uint4"}
self.is_integer = True
self.group_size = group_size
self.use_int8_matmul = use_int8_matmul
def post_init(self):
r"""
@@ -380,16 +372,11 @@ class NNCF_T5DenseGatedActDense(torch.nn.Module): # forward can't find what self
def get_int_scale_asymmetric(weight: torch.FloatTensor, reduction_axes: List[int], num_bits: int) -> Tuple[torch.FloatTensor, torch.FloatTensor]:
level_low = 0
level_high = 2**num_bits
min_values = torch.amin(weight, dim=reduction_axes, keepdims=True)
zero_point = torch.amin(weight, dim=reduction_axes, keepdims=True)
max_values = torch.amax(weight, dim=reduction_axes, keepdims=True)
scale = ((max_values - min_values) / (level_high - 1))
scale = (max_values - zero_point) / (2**num_bits - 1)
eps = torch.finfo(scale.dtype).eps # prevent divison by 0
scale = torch.where(torch.abs(scale) < eps, eps, scale)
zero_point = (level_low - (min_values / scale))
return scale, zero_point
@@ -397,7 +384,6 @@ def get_int_scale_symmetric(weight: torch.FloatTensor, reduction_axes: List[int]
w_abs_min = torch.abs(torch.amin(weight, dim=reduction_axes, keepdims=True))
w_max = torch.amax(weight, dim=reduction_axes, keepdims=True)
scale = torch.where(w_abs_min >= w_max, w_abs_min, -w_max) / (2 ** (num_bits - 1))
eps = torch.finfo(scale.dtype).eps # prevent divison by 0
scale = torch.where(torch.abs(scale) < eps, eps, scale)
return scale
@@ -407,26 +393,25 @@ def quantize_int(weight: torch.FloatTensor, scale: torch.FloatTensor, zero_point
dtype = torch.uint8 if is_asym_mode else torch.int8
level_low = 0 if is_asym_mode else -(2 ** (num_bits - 1))
level_high = 2**num_bits - 1 if is_asym_mode else 2 ** (num_bits - 1) - 1
compressed_weight = weight / scale
if zero_point is not None:
compressed_weight += zero_point
compressed_weight = torch.round(compressed_weight).clamp_(level_low, level_high).to(dtype)
compressed_weight = torch.sub(weight, zero_point).div_(scale)
else:
compressed_weight = torch.div(weight, scale)
compressed_weight = compressed_weight.round_().clamp_(level_low, level_high).to(dtype)
if flatten:
compressed_weight = compressed_weight.flatten(0,-2)
return compressed_weight
def decompress_asymmetric(input: torch.Tensor, scale: torch.Tensor, zero_point: torch.Tensor, dtype: torch.dtype, result_shape: torch.Size) -> torch.Tensor:
result = torch.mul(torch.sub(input.to(dtype=scale.dtype), zero_point), scale).to(dtype=dtype)
result = torch.addcmul(zero_point, input.to(dtype=scale.dtype), scale).to(dtype=dtype)
if result_shape is not None:
result = result.reshape(result_shape)
return result
def decompress_symmetric(input: torch.Tensor, scale: torch.Tensor, dtype: torch.dtype, result_shape: torch.Size) -> torch.Tensor:
result = torch.mul(input.to(dtype=scale.dtype), scale).to(dtype=dtype)
result = input.to(dtype=scale.dtype).mul_(scale).to(dtype=dtype)
if result_shape is not None:
result = result.reshape(result_shape)
return result
@@ -463,7 +448,7 @@ def unpack_uint4(packed_tensor: torch.Tensor, shape: torch.Size, transpose: Opti
def unpack_int4(packed_tensor: torch.Tensor, shape: torch.Size, dtype: Optional[torch.dtype] = torch.int8, transpose: Optional[bool] = False) -> torch.Tensor:
result = unpack_uint4(packed_tensor, shape).to(dtype=dtype) - 8
result = unpack_uint4(packed_tensor, shape).to(dtype=dtype).sub_(8)
if transpose:
result = result.transpose(0,1)
return result
@@ -472,9 +457,7 @@ def unpack_int4(packed_tensor: torch.Tensor, shape: torch.Size, dtype: Optional[
def quantize_int8_matmul_input(input: torch.FloatTensor, scale: torch.FloatTensor) -> Tuple[torch.ByteTensor, torch.FloatTensor]:
input_scale = torch.div(input.abs().max(), 127)
input = torch.div(input, input_scale).round_().clamp_(-128, 127).to(torch.int8).flatten(0,-2)
scale_dtype = torch.float32 if input.dtype == torch.float16 else torch.bfloat16
scale = torch.mul(input_scale.to(dtype=scale_dtype), scale.to(dtype=scale_dtype))
scale = torch.mul(input_scale, scale)
return input, scale
@@ -483,31 +466,23 @@ def int8_matmul(
weight: torch.Tensor,
scale: torch.Tensor,
compressed_weight_shape: torch.Size,
num_bits: int,
):
if num_bits == 4:
if compressed_weight_shape is not None:
weight = unpack_int4_compiled(weight, compressed_weight_shape, transpose=True)
return_dtype = input.dtype
output_shape = list(input.shape)
output_shape[-1] = weight.shape[-1]
input, scale = quantize_int8_matmul_input_compiled(input, scale)
return decompress_symmetric_compiled(torch._int_mm(input, weight), scale, return_dtype, output_shape)
return decompress_symmetric_compiled(torch._int_mm(input, weight), scale, return_dtype, output_shape) # pylint: disable=protected-access
class linear_forward_int8_matmul():
def __func__(self, input) -> torch.FloatTensor:
if self.pre_ops["0"].skip_int8_matmul:
return torch.nn.Linear.forward(self, input)
num_bits = self.pre_ops["0"].num_bits
scale = self.pre_ops["0"].scale
compressed_weight_shape = self.pre_ops["0"].compressed_weight_shape if num_bits == 4 else None
result = int8_matmul(input, self.weight, scale, compressed_weight_shape, num_bits)
result = int8_matmul(input, self.weight, self.pre_ops["0"].scale, getattr(self.pre_ops["0"], "compressed_weight_shape", None))
if self.bias is not None:
result = result + self.bias
result.add_(self.bias)
return result
@@ -518,12 +493,10 @@ class INT8AsymmetricWeightsDecompressor(torch.nn.Module):
zero_point: torch.Tensor,
result_dtype: torch.dtype,
result_shape: torch.Size,
use_int8_matmul: bool,
):
super().__init__()
self.num_bits = 8
self.quantization_mode = "asymmetric"
self.scale = scale
self.zero_point = zero_point
self.result_dtype = result_dtype
@@ -535,7 +508,7 @@ class INT8AsymmetricWeightsDecompressor(torch.nn.Module):
raise ValueError("Weight values are not in [0, 255].")
return weight.to(dtype=torch.uint8)
def forward(self, x, input=None, *args, return_decompressed_only=False):
def forward(self, x, input=None, *args, return_decompressed_only=False): # pylint: disable=keyword-arg-before-vararg,unused-argument
result = decompress_asymmetric_compiled(x.weight, self.scale, self.zero_point, self.result_dtype, self.result_shape)
if return_decompressed_only:
return result
@@ -554,11 +527,9 @@ class INT8SymmetricWeightsDecompressor(torch.nn.Module):
super().__init__()
self.num_bits = 8
self.quantization_mode = "symmetric"
self.scale = scale
self.result_dtype = result_dtype
self.result_shape = result_shape
self.use_int8_matmul = use_int8_matmul
self.skip_int8_matmul = False
self.input_scale = None
@@ -569,7 +540,7 @@ class INT8SymmetricWeightsDecompressor(torch.nn.Module):
raise ValueError("Weight values are not in [-128, 127].")
return weight.to(dtype=torch.int8)
def forward(self, x, input=None, *args, return_decompressed_only=False):
def forward(self, x, input=None, *args, return_decompressed_only=False): # pylint: disable=unused-argument,keyword-arg-before-vararg
if self.use_int8_matmul:
if input is not None:
if torch.numel(input[0]) / input[0].shape[-1] < 32:
@@ -594,12 +565,10 @@ class INT4AsymmetricWeightsDecompressor(torch.nn.Module):
compressed_weight_shape: torch.Size,
result_dtype: torch.dtype,
result_shape: torch.Size,
use_int8_matmul: bool,
):
super().__init__()
self.num_bits = 4
self.quantization_mode = "asymmetric"
self.scale = scale
self.zero_point = zero_point
self.compressed_weight_shape = compressed_weight_shape
@@ -612,7 +581,7 @@ class INT4AsymmetricWeightsDecompressor(torch.nn.Module):
raise ValueError("Weight values are not in [0, 15].")
return pack_uint4(weight.to(dtype=torch.uint8))
def forward(self, x, input=None, *args, return_decompressed_only=False):
def forward(self, x, input=None, *args, return_decompressed_only=False): # pylint: disable=unused-argument,keyword-arg-before-vararg
result = decompress_int4_asymmetric_compiled(x.weight, self.scale, self.zero_point, self.compressed_weight_shape, self.result_dtype, self.result_shape)
if return_decompressed_only:
return result
@@ -632,12 +601,10 @@ class INT4SymmetricWeightsDecompressor(torch.nn.Module):
super().__init__()
self.num_bits = 4
self.quantization_mode = "symmetric"
self.scale = scale
self.compressed_weight_shape = compressed_weight_shape
self.result_dtype = result_dtype
self.result_shape = result_shape
self.use_int8_matmul = use_int8_matmul
self.skip_int8_matmul = False
self.input_scale = None
@@ -648,7 +615,7 @@ class INT4SymmetricWeightsDecompressor(torch.nn.Module):
raise ValueError("Tensor values are not in [-8, 7].")
return pack_int4(weight.to(dtype=torch.int8))
def forward(self, x, input=None, *arg, return_decompressed_only=False):
def forward(self, x, input=None, *arg, return_decompressed_only=False): # pylint: disable=keyword-arg-before-vararg,unused-argument
if self.use_int8_matmul:
if input is not None:
if torch.numel(input[0]) / input[0].shape[-1] < 32:
@@ -672,16 +639,19 @@ if shared.opts.nncf_decompress_compile:
decompress_symmetric_compiled = torch.compile(decompress_symmetric, fullgraph=True)
decompress_int4_asymmetric_compiled = torch.compile(decompress_int4_asymmetric, fullgraph=True)
decompress_int4_symmetric_compiled = torch.compile(decompress_int4_symmetric, fullgraph=True)
quantize_int8_matmul_input_compiled = torch.compile(quantize_int8_matmul_input, fullgraph=True)
unpack_int4_compiled = torch.compile(unpack_int4, fullgraph=True)
if devices.backend != "ipex": # pytorch uses the cpu device in torch._int_mm op with ipex + torch.compile
quantize_int8_matmul_input_compiled = quantize_int8_matmul_input
unpack_int4_compiled = unpack_int4
int8_matmul = torch.compile(int8_matmul, fullgraph=True)
else:
quantize_int8_matmul_input_compiled = torch.compile(quantize_int8_matmul_input, fullgraph=True)
unpack_int4_compiled = torch.compile(unpack_int4, fullgraph=True)
except Exception as e:
shared.log.warning(f"Quantization: type=nncf Decompress using torch.compile is not available: {e}")
decompress_asymmetric_compiled = decompress_asymmetric
decompress_symmetric_compiled = decompress_symmetric
decompress_int4_asymmetric_compiled = decompress_int4_asymmetric
decompress_int4_symmetric_compiled = decompress_int4_symmetric
quantize_int8_matmul_input_compiled = quantize_int8_matmul_input
unpack_int4_compiled = unpack_int4
else:
@@ -689,6 +659,5 @@ else:
decompress_symmetric_compiled = decompress_symmetric
decompress_int4_asymmetric_compiled = decompress_int4_asymmetric
decompress_int4_symmetric_compiled = decompress_int4_symmetric
quantize_int8_matmul_input_compiled = quantize_int8_matmul_input
unpack_int4_compiled = unpack_int4
+1 -1
View File
@@ -68,7 +68,7 @@ def create_ui():
with gr.Row():
cache_list_optimized_headers = ["height", "width"]
cache_list_optimized_types = ["str", "str"]
cache_list_optimized = gr.Dataframe(None, label="Optimized caches", show_label=True, overflow_row_behaviour='paginate', interactive=False, max_rows=10, headers=cache_list_optimized_headers, datatype=cache_list_optimized_types, type="array")
cache_list_optimized = gr.Dataframe(None, label="Optimized caches", show_label=True, interactive=False, headers=cache_list_optimized_headers, datatype=cache_list_optimized_types, type="array")
cache_list_optimized.select(fn=select_cache_optimized, inputs=[cache_list_optimized,], outputs=[cache_optimized_selected,])
cache_remove_optimized = gr.Button(value="Remove selected cache", visible=False)
cache_remove_optimized.click(fn=remove_cache_optimized, inputs=[cache_state_dirname, cache_optimized_selected,])
+2 -2
View File
@@ -367,10 +367,10 @@ class YoloRestorer(Detailer):
with gr.Row():
negative = gr.Textbox(label="Detailer negative prompt", value='', placeholder='Detailer negative prompt', lines=2, elem_id=f"{tab}_detailer_negative")
with gr.Row():
steps = gr.Slider(label="Detailer steps", elem_id=f"{tab}_detailer_steps", value=10, min=0, max=99, step=1)
steps = gr.Slider(label="Detailer steps", elem_id=f"{tab}_detailer_steps", value=10, minimum=0, maximum=99, step=1)
strength = gr.Slider(label="Detailer strength", elem_id=f"{tab}_detailer_strength", value=0.3, minimum=0, maximum=1, step=0.01)
with gr.Row():
max_detected = gr.Slider(label="Max detected", elem_id=f"{tab}_detailer_max", value=shared.opts.detailer_max, min=1, maximum=10, step=1)
max_detected = gr.Slider(label="Max detected", elem_id=f"{tab}_detailer_max", value=shared.opts.detailer_max, minimum=1, maximum=10, step=1)
with gr.Row():
padding = gr.Slider(label="Edge padding", elem_id=f"{tab}_detailer_padding", value=shared.opts.detailer_padding, minimum=0, maximum=100, step=1)
blur = gr.Slider(label="Edge blur", elem_id=f"{tab}_detailer_blur", value=shared.opts.detailer_blur, minimum=0, maximum=100, step=1)
+8 -3
View File
@@ -412,9 +412,14 @@ class ScriptRunner:
api_args = []
for control in controls:
debug(f'Script control: parent={script.parent} script="{script.name}" label="{control.label}" type={control} id={control.elem_id}')
if not isinstance(control, gr.components.IOComponent):
errors.log.error(f'Invalid script control: "{script.filename}" control={control}')
continue
if hasattr(gr.components, 'IOComponent'):
if not isinstance(control, gr.components.IOComponent):
errors.log.error(f'Invalid script control: "{script.filename}" control={control}')
continue
else:
if not isinstance(control, gr.components.Component):
errors.log.error(f'Invalid script control: "{script.filename}" control={control}')
continue
control.custom_script_source = os.path.basename(script.filename)
arg_info = api_models.ScriptArg(label=control.label or "")
for field in ("value", "minimum", "maximum", "step", "choices"):
+15 -15
View File
@@ -423,7 +423,7 @@ options_templates.update(options_section(('model_options', "Models Options"), {
"model_h1_llama_repo": OptionInfo("Default", "HiDream: LLama repo", gr.Textbox),
}))
options_templates.update(options_section(('vae_encoder', "Variable Auto Encoder"), {
options_templates.update(options_section(('vae_encoder', "Variational Auto Encoder"), {
"sd_vae": OptionInfo("Automatic", "VAE model", gr.Dropdown, lambda: {"choices": shared_items.sd_vae_items()}, refresh=shared_items.refresh_vae_list),
"diffusers_vae_upcast": OptionInfo("default", "VAE upcasting", gr.Radio, {"choices": ['default', 'true', 'false']}),
"no_half_vae": OptionInfo(False if not cmd_opts.use_openvino else True, "Full precision (--no-half-vae)"),
@@ -525,6 +525,20 @@ options_templates.update(options_section(('quantization', "Quantization Settings
"bnb_quantization_type": OptionInfo("nf4", "Quantization type", gr.Dropdown, {"choices": ['nf4', 'fp8', 'fp4'], "visible": native}),
"bnb_quantization_storage": OptionInfo("uint8", "Backend storage", gr.Dropdown, {"choices": ["float16", "float32", "int8", "uint8", "float64", "bfloat16"], "visible": native}),
"nncf_compress_sep": OptionInfo("<h2>NNCF: Neural Network Compression Framework</h2>", "", gr.HTML),
"nncf_compress_weights": OptionInfo([], "Quantization enabled", gr.CheckboxGroup, {"choices": ["Model", "Transformer", "VAE", "TE", "Video", "LLM", "ControlNet"], "visible": native}),
"nncf_compress_mode": OptionInfo("post", "Quantization mode", gr.Dropdown, {"choices": ['pre', 'post'], "visible": native and not cmd_opts.use_openvino}),
"nncf_compress_weights_mode": OptionInfo("INT8_SYM", "Quantization type", gr.Dropdown, {"choices": ['INT8', 'INT8_SYM', 'INT4_ASYM', 'INT4_SYM', 'NF4'] if cmd_opts.use_openvino else ['INT8', 'INT8_SYM', 'INT4', 'INT4_SYM']}),
"nncf_compress_weights_raito": OptionInfo(0, "Compress ratio", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.01, "visible": cmd_opts.use_openvino}),
"nncf_compress_weights_group_size": OptionInfo(0, "Group size", gr.Slider, {"minimum": -1, "maximum": 4096, "step": 1, "visible": native}),
"nncf_quantize": OptionInfo([], "OpenVINO enabled", gr.CheckboxGroup, {"choices": ["Model", "VAE", "TE"], "visible": cmd_opts.use_openvino}),
"nncf_quantize_mode": OptionInfo("INT8", "OpenVINO activations mode", gr.Dropdown, {"choices": ['INT8', 'FP8_E4M3', 'FP8_E5M2'], "visible": cmd_opts.use_openvino}),
"nncf_quantize_conv_layers": OptionInfo(False, "Quantize the convolutional layers", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_decompress_fp32": OptionInfo(False, "Decompress using full precision", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_decompress_compile": OptionInfo(devices.has_triton(), "Decompress using torch.compile", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_decompress_int8_matmul": OptionInfo(False, "Use direct INT8 MatMul", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_quantize_shuffle_weights": OptionInfo(False, "Shuffle weights in post mode", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"quanto_quantization_sep": OptionInfo("<h2>Optimum Quanto</h2>", "", gr.HTML),
"quanto_quantization": OptionInfo([], "Quantization enabled", gr.CheckboxGroup, {"choices": ["Model", "Transformer", "VAE", "TE", "Video", "LLM", "ControlNet"], "visible": native}),
"quanto_quantization_type": OptionInfo("int8", "Quantization weights type", gr.Dropdown, {"choices": ["float8", "int8", "int4", "int2"], "visible": native}),
@@ -540,20 +554,6 @@ options_templates.update(options_section(('quantization', "Quantization Settings
"torchao_quantization_mode": OptionInfo("pre", "Quantization mode", gr.Dropdown, {"choices": ['pre', 'post'], "visible": native}),
"torchao_quantization_type": OptionInfo("int8_weight_only", "Quantization type", gr.Dropdown, {"choices": ['int4_weight_only', 'int8_dynamic_activation_int4_weight', 'int8_weight_only', 'int8_dynamic_activation_int8_weight', 'float8_weight_only', 'float8_dynamic_activation_float8_weight', 'float8_static_activation_float8_weight'], "visible": native}),
"nncf_compress_sep": OptionInfo("<h2>NNCF: Neural Network Compression Framework</h2>", "", gr.HTML),
"nncf_compress_weights": OptionInfo([], "Quantization enabled", gr.CheckboxGroup, {"choices": ["Model", "Transformer", "VAE", "TE", "Video", "LLM", "ControlNet"], "visible": native}),
"nncf_compress_mode": OptionInfo("post", "Quantization mode", gr.Dropdown, {"choices": ['pre', 'post'], "visible": native and not cmd_opts.use_openvino}),
"nncf_compress_weights_mode": OptionInfo("INT8_SYM", "Quantization type", gr.Dropdown, {"choices": ['INT8', 'INT8_SYM', 'INT4_ASYM', 'INT4_SYM', 'NF4'] if cmd_opts.use_openvino else ['INT8', 'INT8_SYM', 'INT4', 'INT4_SYM']}),
"nncf_compress_weights_raito": OptionInfo(0, "Compress ratio", gr.Slider, {"minimum": 0, "maximum": 1, "step": 0.01, "visible": cmd_opts.use_openvino}),
"nncf_compress_weights_group_size": OptionInfo(0, "Group size", gr.Slider, {"minimum": -1, "maximum": 4096, "step": 1, "visible": native}),
"nncf_quantize": OptionInfo([], "OpenVINO enabled", gr.CheckboxGroup, {"choices": ["Model", "VAE", "TE"], "visible": cmd_opts.use_openvino}),
"nncf_quantize_mode": OptionInfo("INT8", "OpenVINO activations mode", gr.Dropdown, {"choices": ['INT8', 'FP8_E4M3', 'FP8_E5M2'], "visible": cmd_opts.use_openvino}),
"nncf_quantize_conv_layers": OptionInfo(False, "Quantize the convolutional layers", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_decompress_fp32": OptionInfo(False, "Decompress using full precision", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_decompress_compile": OptionInfo(devices.has_triton(), "Decompress using torch.compile", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_decompress_int8_matmul": OptionInfo(False, "Use direct INT8 MatMul", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"nncf_quantize_shuffle_weights": OptionInfo(False, "Shuffle weights in post mode", gr.Checkbox, {"visible": native and not cmd_opts.use_openvino}),
"layerwise_quantization_sep": OptionInfo("<h2>Layerwise Casting</h2>", "", gr.HTML),
"layerwise_quantization": OptionInfo([], "Layerwise casting enabled", gr.CheckboxGroup, {"choices": ["Model", "Transformer", "TE"], "visible": native}),
"layerwise_quantization_storage": OptionInfo("float8_e4m3fn", "Layerwise casting storage", gr.Dropdown, {"choices": ["float8_e4m3fn", "float8_e5m2"], "visible": native}),
+6 -6
View File
@@ -61,11 +61,11 @@ def create_ui():
vlm_top_p.change(fn=update_vlm_params, inputs=[vlm_max_tokens, vlm_num_beams, vlm_temperature, vlm_do_sample, vlm_top_k, vlm_top_p], outputs=[])
with gr.Accordion(label='Batch caption', open=False, visible=True):
with gr.Row():
vlm_batch_files = gr.File(label="Files", show_label=True, file_count='multiple', file_types=['image'], type='file', interactive=True, height=100, elem_id='vlm_batch_files')
vlm_batch_files = gr.File(label="Files", show_label=True, file_count='multiple', file_types=['image'], interactive=True, height=100, elem_id='vlm_batch_files')
with gr.Row():
vlm_batch_folder = gr.File(label="Folder", show_label=True, file_count='directory', file_types=['image'], type='file', interactive=True, height=100, elem_id='vlm_batch_folder')
vlm_batch_folder = gr.File(label="Folder", show_label=True, file_count='directory', file_types=['image'], interactive=True, height=100, elem_id='vlm_batch_folder')
with gr.Row():
vlm_batch_str = gr.Text(label="Folder", value="", interactive=True, elem_id='vlm_batch_str')
vlm_batch_str = gr.Textbox(label="Folder", value="", interactive=True, elem_id='vlm_batch_str')
with gr.Row():
vlm_save_output = gr.Checkbox(label='Save caption files', value=True, elem_id="vlm_save_output")
vlm_save_append = gr.Checkbox(label='Append caption files', value=False, elem_id="vlm_save_append")
@@ -100,11 +100,11 @@ def create_ui():
clip_num_beams.change(fn=update_clip_params, inputs=[clip_min_length, clip_max_length, clip_chunk_size, clip_min_flavors, clip_max_flavors, clip_flavor_count, clip_num_beams], outputs=[])
with gr.Accordion(label='Batch interogate', open=False, visible=True):
with gr.Row():
clip_batch_files = gr.File(label="Files", show_label=True, file_count='multiple', file_types=['image'], type='file', interactive=True, height=100, elem_id='clip_batch_files')
clip_batch_files = gr.File(label="Files", show_label=True, file_count='multiple', file_types=['image'], interactive=True, height=100, elem_id='clip_batch_files')
with gr.Row():
clip_batch_folder = gr.File(label="Folder", show_label=True, file_count='directory', file_types=['image'], type='file', interactive=True, height=100, elem_id='clip_batch_folder')
clip_batch_folder = gr.File(label="Folder", show_label=True, file_count='directory', file_types=['image'], interactive=True, height=100, elem_id='clip_batch_folder')
with gr.Row():
clip_batch_str = gr.Text(label="Folder", value="", interactive=True, elem_id='clip_batch_str')
clip_batch_str = gr.Textbox(label="Folder", value="", interactive=True, elem_id='clip_batch_str')
with gr.Row():
clip_save_output = gr.Checkbox(label='Save caption files', value=True, elem_id="clip_save_output")
clip_save_append = gr.Checkbox(label='Append caption files', value=False, elem_id="clip_save_append")
+15 -15
View File
@@ -129,7 +129,7 @@ def create_ui(_blocks: gr.Blocks=None):
txt_prompt_img = gr.File(label="", elem_id="control_prompt_image", file_count="single", type="binary", visible=False)
txt_prompt_img.change(fn=images.image_data, inputs=[txt_prompt_img], outputs=[prompt, txt_prompt_img])
with gr.Group(elem_id="control_interface", equal_height=False):
with gr.Group(elem_id="control_interface"):
with gr.Row(elem_id='control_status'):
result_txt = gr.HTML(elem_classes=['control-result'], elem_id='control-result')
@@ -193,29 +193,29 @@ def create_ui(_blocks: gr.Blocks=None):
with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-input'):
with gr.Tab('Image', id='in-image') as tab_image:
input_mode = gr.Label(value='select', visible=False)
input_image = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=True, tool="editor", height=gr_height, visible=True, image_mode='RGB', elem_id='control_input_select', elem_classes=['control-image'])
input_resize = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=True, tool="select", height=gr_height, visible=False, image_mode='RGB', elem_id='control_input_resize', elem_classes=['control-image'])
input_inpaint = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=True, tool="sketch", height=gr_height, visible=False, image_mode='RGB', elem_id='control_input_inpaint', brush_radius=32, mask_opacity=0.6, elem_classes=['control-image'])
input_image = gr.Image(label="Input", show_label=False, type="pil", interactive=True, tool="editor", height=gr_height, visible=True, image_mode='RGB', elem_id='control_input_select', elem_classes=['control-image'])
input_resize = gr.Image(label="Input", show_label=False, type="pil", interactive=True, tool="select", height=gr_height, visible=False, image_mode='RGB', elem_id='control_input_resize', elem_classes=['control-image'])
input_inpaint = gr.Image(label="Input", show_label=False, type="pil", interactive=True, tool="sketch", height=gr_height, visible=False, image_mode='RGB', elem_id='control_input_inpaint', brush_radius=32, mask_opacity=0.6, elem_classes=['control-image'])
btn_interrogate = ui_sections.create_interrogate_button('control')
with gr.Row():
input_buttons = [gr.Button('Select', visible=True, interactive=False), gr.Button('Inpaint', visible=True, interactive=True), gr.Button('Outpaint', visible=True, interactive=True)]
with gr.Tab('Video', id='in-video') as tab_video:
input_video = gr.Video(label="Input", show_label=False, interactive=True, height=gr_height, elem_classes=['control-image'])
with gr.Tab('Batch', id='in-batch') as tab_batch:
input_batch = gr.File(label="Input", show_label=False, file_count='multiple', file_types=['image'], type='file', interactive=True, height=gr_height)
input_batch = gr.File(label="Input", show_label=False, file_count='multiple', file_types=['image'], interactive=True, height=gr_height)
with gr.Tab('Folder', id='in-folder') as tab_folder:
input_folder = gr.File(label="Input", show_label=False, file_count='directory', file_types=['image'], type='file', interactive=True, height=gr_height)
input_folder = gr.File(label="Input", show_label=False, file_count='directory', file_types=['image'], interactive=True, height=gr_height)
with gr.Column(scale=9, elem_id='control-init-column', visible=False) as column_init:
gr.HTML('<span id="control-init-button">Init input</p>')
with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-init'):
with gr.Tab('Image', id='init-image') as tab_image_init:
init_image = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=True, tool="editor", height=gr_height, elem_classes=['control-image'])
init_image = gr.Image(label="Input", show_label=False, type="pil", interactive=True, tool="editor", height=gr_height, elem_classes=['control-image'])
with gr.Tab('Video', id='init-video') as tab_video_init:
init_video = gr.Video(label="Input", show_label=False, interactive=True, height=gr_height, elem_classes=['control-image'])
with gr.Tab('Batch', id='init-batch') as tab_batch_init:
init_batch = gr.File(label="Input", show_label=False, file_count='multiple', file_types=['image'], type='file', interactive=True, height=gr_height, elem_classes=['control-image'])
init_batch = gr.File(label="Input", show_label=False, file_count='multiple', file_types=['image'], interactive=True, height=gr_height, elem_classes=['control-image'])
with gr.Tab('Folder', id='init-folder') as tab_folder_init:
init_folder = gr.File(label="Input", show_label=False, file_count='directory', file_types=['image'], type='file', interactive=True, height=gr_height, elem_classes=['control-image'])
init_folder = gr.File(label="Input", show_label=False, file_count='directory', file_types=['image'], interactive=True, height=gr_height, elem_classes=['control-image'])
with gr.Column(scale=9, elem_id='control-output-column', visible=True) as _column_output:
gr.HTML('<span id="control-output-button">Output</p>')
with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-output') as output_tabs:
@@ -229,7 +229,7 @@ def create_ui(_blocks: gr.Blocks=None):
gr.HTML('<span id="control-preview-button">Preview</p>')
with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-preview'):
with gr.Tab('Preview', id='preview-image') as _tab_preview:
preview_process = gr.Image(label="Preview", show_label=False, type="pil", source="upload", interactive=False, height=gr_height, visible=True, elem_id='control_preview', elem_classes=['control-image'])
preview_process = gr.Image(label="Preview", show_label=False, type="pil", interactive=False, height=gr_height, visible=True, elem_id='control_preview', elem_classes=['control-image'])
with gr.Accordion('Control elements', open=False, elem_id="control_elements"):
with gr.Tabs(elem_id='control-tabs') as _tabs_control_type:
@@ -259,7 +259,7 @@ def create_ui(_blocks: gr.Blocks=None):
image_upload = gr.UploadButton(label=ui_symbols.upload, file_types=['image'], elem_classes=['form', 'gradio-button', 'tool'])
image_reuse= ui_components.ToolButton(value=ui_symbols.reuse)
process_btn= ui_components.ToolButton(value=ui_symbols.preview)
image_preview = gr.Image(label="Input", type="pil", source="upload", height=128, width=128, visible=False, interactive=True, show_label=False, show_download_button=False, container=False, elem_id=f'control_unit-{i}-override')
image_preview = gr.Image(label="Input", type="pil", height=128, width=128, visible=False, interactive=True, show_label=False, show_download_button=False, container=False, elem_id=f'control_unit-{i}-override')
controlnet_ui_units.append(unit_ui)
units.append(unit.Unit(
unit_type = 'controlnet',
@@ -308,7 +308,7 @@ def create_ui(_blocks: gr.Blocks=None):
image_upload = gr.UploadButton(label=ui_symbols.upload, file_types=['image'], elem_classes=['form', 'gradio-button', 'tool'])
image_reuse= ui_components.ToolButton(value=ui_symbols.reuse)
process_btn= ui_components.ToolButton(value=ui_symbols.preview)
image_preview = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
image_preview = gr.Image(label="Input", show_label=False, type="pil", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
adapter_ui_units.append(unit_ui)
units.append(unit.Unit(
unit_type = 't2i adapter',
@@ -355,7 +355,7 @@ def create_ui(_blocks: gr.Blocks=None):
image_upload = gr.UploadButton(label=ui_symbols.upload, file_types=['image'], elem_classes=['form', 'gradio-button', 'tool'])
image_reuse= ui_components.ToolButton(value=ui_symbols.reuse)
process_btn= ui_components.ToolButton(value=ui_symbols.preview)
image_preview = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
image_preview = gr.Image(label="Input", show_label=False, type="pil", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
controlnetxs_ui_units.append(unit_ui)
units.append(unit.Unit(
unit_type = 'xs',
@@ -400,7 +400,7 @@ def create_ui(_blocks: gr.Blocks=None):
reset_btn = ui_components.ToolButton(value=ui_symbols.reset)
image_upload = gr.UploadButton(label=ui_symbols.upload, file_types=['image'], elem_classes=['form', 'gradio-button', 'tool'])
image_reuse= ui_components.ToolButton(value=ui_symbols.reuse)
image_preview = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
image_preview = gr.Image(label="Input", show_label=False, type="pil", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
process_btn= ui_components.ToolButton(value=ui_symbols.preview)
lite_ui_units.append(unit_ui)
units.append(unit.Unit(
@@ -444,7 +444,7 @@ def create_ui(_blocks: gr.Blocks=None):
reset_btn = ui_components.ToolButton(value=ui_symbols.reset)
image_upload = gr.UploadButton(label=ui_symbols.upload, file_types=['image'], elem_classes=['form', 'gradio-button', 'tool'])
image_reuse= ui_components.ToolButton(value=ui_symbols.reuse)
image_preview = gr.Image(label="Input", show_label=False, type="pil", source="upload", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
image_preview = gr.Image(label="Input", show_label=False, type="pil", interactive=False, height=128, width=128, visible=False, elem_id=f'control_unit-{i}-override')
process_btn= ui_components.ToolButton(value=ui_symbols.preview)
units.append(unit.Unit(
unit_type = 'reference',
+1 -1
View File
@@ -59,7 +59,7 @@ def create_ui_wiki():
gr.HTML('<a href="https://github.com/vladmandic/sdnext/wiki" style="color: #AAA" target="_blank">&nbsp Open GitHub Wiki</a>')
with gr.Row():
wiki_search = gr.Textbox(label="Search Wiki Pages", elem_id="wiki_search")
wiki_search_btn = ui_components.ToolButton(value=ui_symbols.search, label="Search", elem_id="wiki_search_btn")
wiki_search_btn = ui_components.ToolButton(value=ui_symbols.search, elem_id="wiki_search_btn")
with gr.Row():
wiki_result = gr.HTML(elem_id="wiki_result", value='')
wiki_search.submit(_js="wikiSearch", fn=search_github, inputs=[wiki_search], outputs=[wiki_result])
+7 -7
View File
@@ -438,17 +438,17 @@ def create_html(search_text, sort_column):
def create_ui():
extensions_disable_all = gr.Radio(label="Disable all extensions", choices=["none", "user", "all"], value=shared.opts.disable_all_extensions, elem_id="extensions_disable_all", visible=False)
extensions_disabled_list = gr.Text(elem_id="extensions_disabled_list", visible=False, container=False)
extensions_update_list = gr.Text(elem_id="extensions_update_list", visible=False, container=False)
extensions_disabled_list = gr.Textbox(elem_id="extensions_disabled_list", visible=False, container=False)
extensions_update_list = gr.Textbox(elem_id="extensions_update_list", visible=False, container=False)
with gr.Tabs(elem_id="tabs_extensions"):
with gr.TabItem("Manage extensions", id="manage"):
with gr.Row(elem_id="extensions_installed_top"):
extension_to_install = gr.Text(elem_id="extension_to_install", visible=False)
extension_to_install = gr.Textbox(elem_id="extension_to_install", visible=False)
install_extension_button = gr.Button(elem_id="install_extension_button", visible=False)
uninstall_extension_button = gr.Button(elem_id="uninstall_extension_button", visible=False)
update_extension_button = gr.Button(elem_id="update_extension_button", visible=False)
with gr.Column(scale=4):
search_text = gr.Text(label="Search")
search_text = gr.Textbox(label="Search")
with gr.Column(scale=1):
sort_column = gr.Dropdown(value="default", label="Sort by", choices=list(sort_ordering.keys()), multiselect=False)
with gr.Column(scale=1):
@@ -508,9 +508,9 @@ def create_ui():
outputs=[extensions_table, info],
)
with gr.TabItem("Manual install", id="install_from_url"):
install_url = gr.Text(label="Extension GIT repository URL")
install_branch = gr.Text(label="Specific branch name", placeholder="Leave empty for default main branch")
install_dirname = gr.Text(label="Local directory name", placeholder="Leave empty for auto")
install_url = gr.Textbox(label="Extension GIT repository URL")
install_branch = gr.Textbox(label="Specific branch name", placeholder="Leave empty for default main branch")
install_dirname = gr.Textbox(label="Local directory name", placeholder="Leave empty for auto")
install_button = gr.Button(value="Install", variant="primary")
info = gr.HTML(elem_id="extension_info")
install_button.click(
+1 -1
View File
@@ -603,7 +603,7 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
text = gr.HTML('<div>title</div>')
ui.details_components.append(text)
with gr.Column(scale=1):
img = gr.Image(value=None, show_label=False, interactive=False, container=False, show_download_button=False, show_info=False, elem_id=f"{tabname}_extra_details_img", elem_classes=['extra-details-img'])
img = gr.Image(value=None, show_label=False, interactive=False, container=False, show_download_button=False, elem_id=f"{tabname}_extra_details_img", elem_classes=['extra-details-img'])
ui.details_components.append(img)
with gr.Row():
btn_save_img = gr.Button('Replace', elem_classes=['small-button'])
+8 -8
View File
@@ -43,14 +43,14 @@ def create_ui():
with gr.Blocks() as tab:
with gr.Row(elem_id='tab-gallery-sort-buttons'):
sort_buttons = []
sort_buttons.append(ToolButton(value=ui_symbols.sort_alpha_asc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_alpha_dsc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_size_asc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_size_dsc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_num_asc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_num_dsc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_time_asc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_time_dsc, show_label=False, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_alpha_asc, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_alpha_dsc, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_size_asc, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_size_dsc, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_num_asc, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_num_dsc, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_time_asc, elem_classes=['gallery-sort']))
sort_buttons.append(ToolButton(value=ui_symbols.sort_time_dsc, elem_classes=['gallery-sort']))
gr.Textbox(show_label=False, placeholder='Search', elem_id='tab-gallery-search')
gr.HTML('', elem_id='tab-gallery-status')
for btn in sort_buttons:
-2
View File
@@ -47,8 +47,6 @@ def create_ui():
show_label=True,
interactive=False,
wrap=True,
overflow_row_behaviour='paginate',
max_rows=50,
elem_id='history_table',
)
with gr.Row():
+6 -6
View File
@@ -68,20 +68,20 @@ def create_ui():
img2img_selected_tab = gr.State(0) # pylint: disable=abstract-class-instantiated
state = gr.Textbox(value='', visible=False)
with gr.TabItem('Image', id='img2img_image', elem_id="img2img_image_tab") as tab_img2img:
img_init = gr.Image(label="", elem_id="img2img_image", show_label=False, source="upload", interactive=True, type="pil", tool="editor", image_mode="RGBA", height=512)
img_init = gr.Image(label="", elem_id="img2img_image", show_label=False, interactive=True, type="pil", tool="editor", image_mode="RGBA", height=512)
interrogate_btn = ui_sections.create_interrogate_button(tab='img2img')
add_copy_image_controls('img2img', img_init)
with gr.TabItem('Inpaint', id='img2img_inpaint', elem_id="img2img_inpaint_tab") as tab_inpaint:
img_inpaint = gr.Image(label="", elem_id="img2img_inpaint", show_label=False, source="upload", interactive=True, type="pil", tool="sketch", image_mode="RGBA", height=512)
img_inpaint = gr.Image(label="", elem_id="img2img_inpaint", show_label=False, interactive=True, type="pil", tool="sketch", image_mode="RGBA", height=512)
add_copy_image_controls('inpaint', img_inpaint)
with gr.TabItem('Sketch', id='img2img_sketch', elem_id="img2img_sketch_tab") as tab_sketch:
img_sketch = gr.Image(label="", elem_id="img2img_sketch", show_label=False, source="upload", interactive=True, type="pil", tool="color-sketch", image_mode="RGBA", height=512)
img_sketch = gr.Image(label="", elem_id="img2img_sketch", show_label=False, interactive=True, type="pil", tool="color-sketch", image_mode="RGBA", height=512)
add_copy_image_controls('sketch', img_sketch)
with gr.TabItem('Composite', id='img2img_composite', elem_id="img2img_composite_tab") as tab_inpaint_color:
img_composite = gr.Image(label="", show_label=False, elem_id="img2img_composite", source="upload", interactive=True, type="pil", tool="color-sketch", image_mode="RGBA", height=512)
img_composite = gr.Image(label="", show_label=False, elem_id="img2img_composite", interactive=True, type="pil", tool="color-sketch", image_mode="RGBA", height=512)
img_composite_orig = gr.State(None) # pylint: disable=abstract-class-instantiated
img_composite_orig_update = False
@@ -99,8 +99,8 @@ def create_ui():
add_copy_image_controls('composite', img_composite)
with gr.TabItem('Upload', id='inpaint_upload', elem_id="img2img_inpaint_upload_tab") as tab_inpaint_upload:
init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", elem_id="img_inpaint_base")
init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", elem_id="img_inpaint_mask")
init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, interactive=True, type="pil", elem_id="img_inpaint_base")
init_mask_inpaint = gr.Image(label="Mask", interactive=True, type="pil", elem_id="img_inpaint_mask")
with gr.TabItem('Batch', id='batch', elem_id="img2img_batch_tab") as tab_batch:
gr.HTML("<p style='padding-bottom: 1em;' class=\"text-gray-500\">Run image processing on upload images or files in a folder<br>If masks are provided will run inpaint</p>")
+6 -2
View File
@@ -26,7 +26,9 @@ class UiLoadsave:
def apply_field(obj, field, condition=None, init_field=None):
key = f"{path}/{field}"
if getattr(obj, 'custom_script_source', None) is not None:
if hasattr(obj, 'use_original'):
pass
elif getattr(obj, 'custom_script_source', None) is not None:
key = f"customscript/{obj.custom_script_source}/{key}"
if getattr(obj, 'do_not_save_to_config', False):
return
@@ -45,7 +47,9 @@ class UiLoadsave:
init_field(saved_value)
if debug_ui and key in self.component_mapping and not key.startswith('customscript'):
errors.log.warning(f'UI duplicate: key="{key}" id={getattr(obj, "elem_id", None)} class={getattr(obj, "elem_classes", None)}')
if field == 'value' and key not in self.component_mapping:
if hasattr(obj, 'skip'):
print('HERE', key)
if (field == 'value') and (key not in self.component_mapping):
self.component_mapping[key] = x
if field == 'open' and key not in self.component_mapping:
self.component_open[key] = x
+12 -24
View File
@@ -23,11 +23,11 @@ def create_ui():
dummy_component = gr.Label(visible=False)
with gr.Row(elem_id="models_tab"):
with gr.Column(elem_id='models_output_container', scale=1):
# models_output = gr.Text(elem_id="models_output", value="", show_label=False)
# models_output = gr.Textbox(elem_id="models_output", value="", show_label=False)
gr.HTML(elem_id="models_progress", value="")
models_image = gr.Image(elem_id="models_image", show_label=False, interactive=False, type='pil')
models_outcome = gr.HTML(elem_id="models_error", value="")
models_file = gr.File(label='', type='file', help='', visible=False)
models_file = gr.File(label='', visible=False)
with gr.Column(elem_id='models_input_container', scale=3):
@@ -327,7 +327,7 @@ def create_ui():
with gr.Row():
precision = gr.Dropdown(label="Model precision", choices=["fp32", "fp16", "bf16"], value="fp16")
comp_scheduler = gr.Dropdown(label="Sampler", choices=[s.name for s in sd_samplers.samplers if s.constructor is not None])
comp_prediction = gr.Dropdown(Label="Prediction type", choices=["epsilon", "v"], value="epsilon")
comp_prediction = gr.Dropdown(label="Prediction type", choices=["epsilon", "v"], value="epsilon")
with gr.Row():
with gr.Column(scale=3):
gr.HTML('Merge LoRA<br>')
@@ -349,7 +349,7 @@ def create_ui():
meta_desc = gr.Textbox(placeholder="Model description", lines=3, show_label=False)
meta_hint = gr.Textbox(placeholder="Model hint", lines=3, show_label=False)
with gr.Column(scale=3):
meta_thumbnail = gr.Image(label="Thumbnail", type='pil', source='upload')
meta_thumbnail = gr.Image(label="Thumbnail", type='pil')
with gr.Row():
gr.HTML('Note: Save is optional as you can merge in-memory and use newly created model immediately')
with gr.Row():
@@ -357,7 +357,7 @@ def create_ui():
create_safetensors = gr.Checkbox(label="Save safetensors", value=True)
debug = gr.Checkbox(label="Debug info", value=False)
model_modules_btn = gr.Button(label="Modules", variant='primary')
model_modules_btn = gr.Button(value="Modules", variant='primary')
model_modules_btn.click(
fn=extras.run_model_modules,
inputs=[
@@ -389,8 +389,6 @@ def create_ui():
show_label=True,
interactive=False,
wrap=True,
overflow_row_behaviour='paginate',
max_rows=50,
)
def list_models():
@@ -452,7 +450,7 @@ def create_ui():
gr.HTML('<h2>&nbspDownload model from huggingface<br></h2>')
with gr.Row():
hf_search_text = gr.Textbox('', label='Search models', placeholder='search huggingface models')
hf_search_btn = ToolButton(value=ui_symbols.search, label="Search")
hf_search_btn = ToolButton(value=ui_symbols.search)
with gr.Row():
with gr.Column(scale=2):
with gr.Row():
@@ -472,7 +470,7 @@ def create_ui():
with gr.Row():
hf_headers = ['Name', 'Pipeline', 'Tags', 'Downloads', 'Updated', 'URL']
hf_types = ['str', 'str', 'str', 'number', 'date', 'markdown']
hf_results = gr.DataFrame(None, label='Search results', show_label=True, interactive=False, wrap=True, overflow_row_behaviour='paginate', max_rows=10, headers=hf_headers, datatype=hf_types, type='array')
hf_results = gr.DataFrame(None, label='Search results', show_label=True, interactive=False, wrap=True, headers=hf_headers, datatype=hf_types, type='array')
hf_search_text.submit(fn=hf_search, inputs=[hf_search_text], outputs=[hf_results])
hf_search_btn.click(fn=hf_search, inputs=[hf_search_text], outputs=[hf_results])
@@ -684,7 +682,7 @@ def create_ui():
with gr.Row():
civit_search_text = gr.Textbox('', label='Search models', placeholder='keyword')
civit_search_tag = gr.Textbox('', label='', placeholder='tags')
civit_search_btn = ToolButton(value=ui_symbols.search, label="Search", interactive=True)
civit_search_btn = ToolButton(value=ui_symbols.search, interactive=True)
with gr.Row():
civit_search_res = gr.HTML('')
with gr.Row():
@@ -704,25 +702,16 @@ def create_ui():
with gr.Row():
civit_headers1 = ['ID', 'Name', 'Tags', 'Downloads', 'Rating']
civit_types1 = ['number', 'str', 'str', 'number', 'number']
civit_results1 = gr.DataFrame(value=None, label=None, show_label=False, interactive=False,
wrap=True, overflow_row_behaviour='paginate', max_rows=10,
headers=civit_headers1, datatype=civit_types1, type='array',
visible=False)
civit_results1 = gr.DataFrame(value=None, label=None, show_label=False, interactive=False, wrap=True, headers=civit_headers1, datatype=civit_types1, type='array', visible=False)
with gr.Row():
with gr.Column():
civit_headers2 = ['ID', 'ModelID', 'Name', 'Base', 'Created', 'Preview']
civit_types2 = ['number', 'number', 'str', 'str', 'date', 'str']
civit_results2 = gr.DataFrame(value=None, label='Model versions', show_label=True,
interactive=False, wrap=True, overflow_row_behaviour='paginate',
max_rows=10, headers=civit_headers2, datatype=civit_types2,
type='array', visible=False)
civit_results2 = gr.DataFrame(value=None, label='Model versions', show_label=True, interactive=False, wrap=True, headers=civit_headers2, datatype=civit_types2, type='array', visible=False)
with gr.Column():
civit_headers3 = ['Name', 'Size', 'Metadata', 'URL']
civit_types3 = ['str', 'number', 'str', 'str']
civit_results3 = gr.DataFrame(value=None, label='Model variants', show_label=True,
interactive=False, wrap=True, overflow_row_behaviour='paginate',
max_rows=10, headers=civit_headers3, datatype=civit_types3,
type='array', visible=False)
civit_results3 = gr.DataFrame(value=None, label='Model variants', show_label=True, interactive=False, wrap=True, headers=civit_headers3, datatype=civit_types3, type='array', visible=False)
def is_visible(component):
visible = len(component) > 0 if component is not None else False
@@ -751,8 +740,7 @@ def create_ui():
civit_headers4 = ['ID', 'File', 'Name', 'Versions', 'Current', 'Latest', 'Update']
civit_types4 = ['number', 'str', 'str', 'number', 'str', 'str', 'str']
civit_widths4 = ['10%', '25%', '25%', '5%', '10%', '10%', '15%']
civit_results4 = gr.DataFrame(value=None, label=None, show_label=False, interactive=False, wrap=True, overflow_row_behaviour='paginate',
row_count=20, max_rows=100, headers=civit_headers4, datatype=civit_types4, type='array', column_widths=civit_widths4)
civit_results4 = gr.DataFrame(value=None, label=None, show_label=False, interactive=False, wrap=True, row_count=20, headers=civit_headers4, datatype=civit_types4, type='array', column_widths=civit_widths4)
with gr.Row():
gr.HTML('<h3>Select model from the list and download update if available</h3>')
with gr.Row():
+1 -3
View File
@@ -284,7 +284,7 @@ def create_ui(gr_status, gr_file):
cls = gr.Textbox(label="Model class", placeholder="Class name", interactive=False)
with gr.Row():
repo = gr.Textbox(label="Model repo", placeholder="Repo name", interactive=True)
link = gr.HTML(value="", interactive=False)
link = gr.HTML(value="")
with gr.Row():
headers = ['ID', 'Name', 'Loadable', 'Default', 'Class', 'Local', 'Remote', 'Dtype', 'Quant']
datatype = ['number', 'str', 'bool', 'str', 'str', 'str', 'str', 'str', 'bool']
@@ -296,8 +296,6 @@ def create_ui(gr_status, gr_file):
wrap=True,
headers=headers,
datatype=datatype,
max_rows=None,
max_cols=None,
type='array',
elem_id="model_loader_df",
)
+2 -2
View File
@@ -22,7 +22,7 @@ def create_ui():
with gr.Tabs(elem_id="mode_extras"):
with gr.Tab('Process Image', id="single_image", elem_id="extras_single_tab") as tab_single:
with gr.Row():
extras_image = gr.Image(label="Source", source="upload", interactive=True, type="pil", elem_id="extras_image")
extras_image = gr.Image(label="Source", interactive=True, type="pil", elem_id="extras_image")
with gr.Tab('Process Batch', id="batch_process", elem_id="extras_batch_process_tab") as tab_batch:
image_batch = gr.Files(label="Batch process", interactive=True, elem_id="extras_image_batch")
with gr.Tab('Process Folder', id="batch_from_directory", elem_id="extras_batch_directory_tab") as tab_batch_dir:
@@ -44,7 +44,7 @@ def create_ui():
result_images, generation_info, html_info, html_info_formatted, html_log = ui_common.create_output_panel("extras")
gr.HTML('File metadata')
exif_info = gr.HTML(elem_id="pnginfo_html_info")
gen_info = gr.Text(elem_id="pnginfo_gen_info", visible=False)
gen_info = gr.Textbox(elem_id="pnginfo_gen_info", visible=False)
with gr.Row(elem_id='copy_buttons_process'):
copy_process_buttons = generation_parameters_copypaste.create_buttons(["txt2img", "img2img", "control", "caption"])
+3 -3
View File
@@ -87,7 +87,7 @@ def create_resolution_inputs(tab, default_width=1024, default_height=1024):
ar_dropdown = gr.Dropdown(show_label=False, interactive=True, choices=ar_list, value=ar_list[0], elem_id=f"{tab}_ar", elem_classes=["ar-dropdown"])
for c in [ar_dropdown, width, height]:
c.change(fn=ar_change, inputs=[ar_dropdown, width, height], outputs=[width, height], show_progress=False)
res_switch_btn = ToolButton(value=ui_symbols.switch, elem_id=f"{tab}_res_switch_btn", label="Switch dims")
res_switch_btn = ToolButton(value=ui_symbols.switch, elem_id=f"{tab}_res_switch_btn")
res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress=False)
return width, height
@@ -125,8 +125,8 @@ def create_seed_inputs(tab, reuse_visible=True, accordion=True, subseed_visible=
with gr.Accordion(open=False, label="Seed", elem_id=f"{tab}_seed_group", elem_classes=["small-accordion"]) if accordion else gr.Group():
with gr.Row(elem_id=f"{tab}_seed_row", variant="compact"):
seed = gr.Number(label='Initial seed', value=-1, elem_id=f"{tab}_seed", container=True)
random_seed = ToolButton(ui_symbols.random, elem_id=f"{tab}_random_seed", label='Random seed')
reuse_seed = ToolButton(ui_symbols.reuse, elem_id=f"{tab}_reuse_seed", label='Reuse seed', visible=reuse_visible)
random_seed = ToolButton(ui_symbols.random, elem_id=f"{tab}_random_seed")
reuse_seed = ToolButton(ui_symbols.reuse, elem_id=f"{tab}_reuse_seed", visible=reuse_visible)
with gr.Row(elem_id=f"{tab}_subseed_row", variant="compact", visible=subseed_visible):
subseed = gr.Number(label='Variation', value=-1, elem_id=f"{tab}_subseed", container=True)
random_subseed = ToolButton(ui_symbols.random, elem_id=f"{tab}_random_subseed")
+5 -2
View File
@@ -97,7 +97,10 @@ def create_setting_component(key, is_quicksettings=False):
res = None
if res is not None and not is_quicksettings:
res.change(fn=None, inputs=res, _js=f'(val) => markIfModified("{key}", val)')
try:
res.change(fn=None, inputs=res, _js=f'(val) => markIfModified("{key}", val)')
except Exception as e:
shared.log.error(f'Quicksetting: component={res} {e}')
if dirty_indicator is not None:
dirty_indicator.click(fn=lambda: shared.opts.get_default(key), outputs=[res], show_progress=False)
dirtyable_setting.__exit__()
@@ -186,7 +189,7 @@ def create_ui():
preview_theme = gr.Button(value="Preview theme", variant='primary', elem_id="settings_preview_theme")
defaults_submit = gr.Button(value="Restore defaults", variant='primary', elem_id="defaults_submit")
with gr.Row():
_settings_search = gr.Text(label="Search", elem_id="settings_search")
_settings_search = gr.Textbox(label="Search", elem_id="settings_search")
result = gr.HTML(elem_id="settings_result")
script_callbacks.ui_settings_callback() # let extensions create settings
+3 -3
View File
@@ -92,7 +92,7 @@ def create_ui():
with gr.Row():
engine = gr.Dropdown(label='Engine', choices=list(models_def.models), value='None', elem_id="video_engine")
model = gr.Dropdown(label='Model', choices=[''], value=None, elem_id="video_model")
btn_load = ToolButton(ui_symbols.loading, elem_id="video_model_load", label='Load model')
btn_load = ToolButton(ui_symbols.loading, elem_id="video_model_load")
with gr.Row():
url = gr.HTML(label='Model URL', elem_id='video_model_url', value='<br><br>')
with gr.Accordion(open=True, label="Size", elem_id='video_size_accordion'):
@@ -101,8 +101,8 @@ def create_ui():
with gr.Row():
frames = gr.Slider(label='Frames', minimum=1, maximum=1024, step=1, value=15, elem_id="video_frames")
seed = gr.Number(label='Initial seed', value=-1, elem_id="video_seed", container=True)
random_seed = ToolButton(ui_symbols.random, elem_id="video_random_seed", label='Random seed')
reuse_seed = ToolButton(ui_symbols.reuse, elem_id="video_reuse_seed", label='Reuse seed')
random_seed = ToolButton(ui_symbols.random, elem_id="video_random_seed")
reuse_seed = ToolButton(ui_symbols.reuse, elem_id="video_reuse_seed")
with gr.Accordion(open=True, label="Parameters", elem_id='video_parameters_accordion'):
steps, sampler_index = ui_sections.create_sampler_and_steps_selection(None, "video")
with gr.Row():
+10 -5
View File
@@ -9,7 +9,9 @@ models = [
system_prompts = {
'prefix': 'You are a video director.',
'desc': 'You will provide a prompt that can be used to create short, creative and dynamic video. Describe the subject of the video, add movement that fits the overall tone of the video, add camera movement.',
'suffix': 'NSFW content and nudity are allowed and must be fully described if present. Movement should be dynamic and creative. Do not specify duration and assume video is short. Avoid slow-motion and prefer faster movements. Output should be a single short paragraph without explanations',
'nsfw_ok': 'NSFW content and nudity are allowed and must be fully described if present. ',
'nsfw_no': 'NSFW content and nudity are not allowed. ',
'suffix': 'Movement should be dynamic and creative. Do not specify duration and assume video is short. Avoid slow-motion and prefer faster movements. Output should be a single short paragraph without explanations',
'example': 'Example: "Short video of beautiful blonde woman in her 20ies wearing a long flowing red dress. She is briskly walking on the beach during sunset and performing a pirouette ending with her hand pointing at the camera as she smiles. Camera is moving around her and zooming to her face. Sun is setting in the background causing changes in colors and shadows to move dynamically."',
't2v-prompt': 'You are a given short prompt with basic instructions.',
@@ -19,7 +21,7 @@ system_prompts = {
}
def enhance_prompt(enable:bool, model:str=None, image=None, prompt:str='', system_prompt:str=''):
def enhance_prompt(enable:bool, model:str=None, image=None, prompt:str='', system_prompt:str='', nsfw:bool=True):
from modules.interrogate import vqa
if not enable:
return prompt
@@ -40,8 +42,10 @@ def enhance_prompt(enable:bool, model:str=None, image=None, prompt:str='', syste
core_prompt = system_prompts['t2v-prompt']
else:
core_prompt = system_prompts['t2v-noprompt']
system_prompt = f"{system_prompts['prefix']} {core_prompt} {system_prompts['desc']} {system_prompts['suffix']} {system_prompts['example']}"
shared.log.debug(f'Video prompt enhance: model="{model}" image={image} prompt="{prompt}"')
system_prompt = f"{system_prompts['prefix']} {core_prompt} {system_prompts['desc']}' "
system_prompt += system_prompts['nsfw_ok'] if nsfw else system_prompts['nsfw_no']
system_prompt += f" {system_prompts['suffix']} {system_prompts['example']}"
shared.log.debug(f'Video prompt enhance: model="{model}" image={image} nsfw={nsfw} prompt="{prompt}"')
# shared.log.trace(f'Video prompt enhance: system="{system_prompt}"')
answer = vqa.interrogate(question='', prompt=prompt, system_prompt=system_prompt, image=image, model_name=model, quiet=False)
shared.log.debug(f'Video prompt enhance: answer="{answer}"')
@@ -52,6 +56,7 @@ def create_ui(prompt_element:gr.Textbox, image_element:gr.Image):
with gr.Accordion('Prompt enhance', open=False):
with gr.Row():
enable = gr.Checkbox(label='Enable', value=False)
nsfw = gr.Checkbox(label='NSFW allowed', value=True)
btn_enhance = gr.Button(value='Enhance now', elem_id='btn_enhance')
with gr.Row():
model = gr.Dropdown(label='Model', choices=models, value=models[0])
@@ -59,7 +64,7 @@ def create_ui(prompt_element:gr.Textbox, image_element:gr.Image):
system_prompt = gr.Textbox(label='System prompt', placeholder='override system prompt with user-provided prompt', lines=3)
btn_enhance.click(
fn=enhance_prompt,
inputs=[enable, model, image_element, prompt_element, system_prompt],
inputs=[enable, model, image_element, prompt_element, system_prompt, nsfw],
outputs=prompt_element,
show_progress=True,
)
+1 -1
View File
@@ -78,7 +78,7 @@ def install():
return
platform = "windows"
commit = os.environ.get("ZLUDA_HASH", "8d2128caf460b853b165cab0b4d8826b6b734ae7")
commit = os.environ.get("ZLUDA_HASH", "5e717459179dc272b7d7d23391f0fad66c7459cf")
if os.environ.get("ZLUDA_NIGHTLY", "0") == "1":
log.warning("Environment variable 'ZLUDA_NIGHTLY' will be removed. Please use command-line argument '--use-nightly' instead.")
args.use_nightly = True
+1 -1
View File
@@ -45,7 +45,7 @@ accelerate==1.6.0
opencv-contrib-python-headless==4.9.0.80
einops==0.4.1
gradio==3.43.2
huggingface_hub==0.31.1
huggingface_hub==0.31.2
numexpr==2.10.2
numpy==1.26.4
numba==0.61.2
+2 -2
View File
@@ -42,8 +42,8 @@ class Script(scripts.Script):
override = gr.Checkbox(label='Override resolution', value=True)
with gr.Accordion('Optional init image or video', open=False):
with gr.Row():
image = gr.Image(value=None, label='Image', type='pil', source='upload', width=256, height=256)
video = gr.Video(value=None, label='Video', source='upload', width=256, height=256)
image = gr.Image(value=None, label='Image', type='pil', width=256, height=256)
video = gr.Video(value=None, label='Video', width=256, height=256)
with gr.Row():
from modules.ui_sections import create_video_inputs
video_type, duration, loop, pad, interpolate = create_video_inputs(tab='img2img' if is_img2img else 'txt2img')
+4 -4
View File
@@ -17,20 +17,20 @@ class Script(scripts.Script):
gr.HTML('<a href="https://github.com/genforce/ctrl-x">&nbsp Ctrl-X: Controlling Structure and Appearance</a><br>')
with gr.Accordion(label='Structure', open=True):
with gr.Row():
struct_prompt = gr.Textbox(label='Prompt', value='', rows=1)
struct_prompt = gr.Textbox(label='Prompt', value='')
with gr.Row():
struct_strength = gr.Slider(label='Strength', value=0.5, minimum=0.0, maximum=1.0, step=0.05)
struct_guidance = gr.Slider(label='Guidance', value=5.0, minimum=0.0, maximum=14.0, step=0.05)
with gr.Row():
struct_image = gr.Image(label='Image', source='upload', type='pil')
struct_image = gr.Image(label='Image', type='pil')
with gr.Accordion(label='Appearance', open=True):
with gr.Row():
appear_prompt = gr.Textbox(label='Prompt', value='', rows=1)
appear_prompt = gr.Textbox(label='Prompt', value='')
with gr.Row():
appear_strength = gr.Slider(label='Strength', value=0.5, minimum=0.0, maximum=1.0, step=0.05)
appear_guidance = gr.Slider(label='Guidance', value=5.0, minimum=0.0, maximum=14.0, step=0.05)
with gr.Row():
appear_image = gr.Image(label='Image', source='upload', type='pil')
appear_image = gr.Image(label='Image', type='pil')
return struct_prompt, struct_strength, struct_guidance, struct_image, appear_prompt, appear_strength, appear_guidance, appear_image
def restore(self):
+1 -1
View File
@@ -1872,7 +1872,7 @@ class Script(scripts.Script):
strength = gr.Slider(minimum=0.0, maximum=2.0, value=1.0, label='Mask strength')
model = gr.Dropdown(label='Model', choices=['None', 'DPT Tiny', 'DPT Hybrid', 'DPT Large'], value='None')
with gr.Row():
image = gr.Image(label="Image map", show_label=False, type="pil", source="upload", interactive=True, tool="editor", visible=True, image_mode='RGB')
image = gr.Image(label="Image map", show_label=False, type="pil", interactive=True, tool="editor", visible=True, image_mode='RGB')
return enabled, strength, invert, model, image
def depthmap(self, image_init: Image.Image, image_map: Image.Image, model: str, strength: float, invert: bool):
+3 -2
View File
@@ -73,13 +73,13 @@ class Script(scripts.Script):
def ui(self, _is_img2img):
with gr.Row():
self.button = gr.Button(value='Enhance prompt')
self.auto_apply = gr.Checkbox(label='Auto apply', default=False)
self.auto_apply = gr.Checkbox(label='Auto apply', value=False)
with gr.Row():
self.max_length = gr.Slider(label='Length', minimum=64, maximum=512, step=1, value=128)
self.temperature = gr.Slider(label='Temperature', minimum=0.1, maximum=2.0, step=0.05, value=0.7)
self.repetition_penalty = gr.Slider(label='Penalty', minimum=0.1, maximum=2.0, step=0.05, value=1.2)
with gr.Row():
self.table = gr.DataFrame(self.prompts, label='', show_label=False, interactive=False, wrap=True, datatype="str", col_count=1, max_rows=num_return_sequences, headers=['Prompts'])
self.table = gr.DataFrame(self.prompts, label='', show_label=False, interactive=False, wrap=True, datatype="str", col_count=1, headers=['Prompts'])
if self.prompt is not None:
self.button.click(fn=self.enhance, inputs=[self.prompt, self.auto_apply, self.temperature, self.repetition_penalty, self.max_length], outputs=[self.table])
@@ -100,3 +100,4 @@ class Script(scripts.Script):
def after_component(self, component, **kwargs): # searching for actual ui prompt components
if getattr(component, 'elem_id', '') in ['txt2img_prompt', 'img2img_prompt', 'control_prompt', 'video_prompt']:
self.prompt = component
self.prompt.use_original = True
+5 -5
View File
@@ -66,25 +66,25 @@ class Script(scripts.Script):
ui_common.create_refresh_button(adapter, ipadapter.get_adapters)
with gr.Row():
scales.append(gr.Slider(label='Strength', minimum=0.0, maximum=1.0, step=0.01, value=0.5))
crops.append(gr.Checkbox(label='Crop to portrait', default=False, interactive=True))
crops.append(gr.Checkbox(label='Crop to portrait', value=False, interactive=True))
with gr.Row():
starts.append(gr.Slider(label='Start', minimum=0.0, maximum=1.0, step=0.1, value=0))
ends.append(gr.Slider(label='End', minimum=0.0, maximum=1.0, step=0.1, value=1))
with gr.Row():
files.append(gr.File(label='Input images', file_count='multiple', file_types=['image'], type='file', interactive=True, height=100))
files.append(gr.File(label='Input images', file_count='multiple', file_types=['image'], interactive=True, height=100))
with gr.Row():
image_galleries.append(gr.Gallery(show_label=False, value=[], visible=False, container=False, rows=1))
with gr.Row():
masks.append(gr.File(label='Input masks', file_count='multiple', file_types=['image'], type='file', interactive=True, height=100))
masks.append(gr.File(label='Input masks', file_count='multiple', file_types=['image'], interactive=True, height=100))
with gr.Row():
mask_galleries.append(gr.Gallery(show_label=False, value=[], visible=False))
files[i].change(fn=self.load_images, inputs=[files[i]], outputs=[image_galleries[i]])
masks[i].change(fn=self.load_images, inputs=[masks[i]], outputs=[mask_galleries[i]])
units.append(unit)
num_adapters.change(fn=self.display_units, inputs=[num_adapters], outputs=units)
layers_active = gr.Checkbox(label='Layer options', default=False, interactive=True)
layers_active = gr.Checkbox(label='Layer options', value=False, interactive=True)
layers_label = gr.HTML('<a href="https://huggingface.co/docs/diffusers/main/en/using-diffusers/ip_adapter#style--layout-control" target="_blank">InstantStyle: advanced layer activation</a>', visible=False)
layers = gr.Text(label='Layer scales', placeholder='{\n"down": {"block_2": [0.0, 1.0]},\n"up": {"block_0": [0.0, 1.0, 0.0]}\n}', rows=1, type='text', interactive=True, lines=5, visible=False, show_label=False)
layers = gr.Textbox(label='Layer scales', placeholder='{\n"down": {"block_2": [0.0, 1.0]},\n"up": {"block_0": [0.0, 1.0, 0.0]}\n}', type='text', interactive=True, lines=5, visible=False, show_label=False)
layers_active.change(fn=self.display_advanced, inputs=[layers_active], outputs=[layers_label, layers])
return [num_adapters] + [unload_adapter] + adapters + scales + files + crops + starts + ends + masks + [layers_active] + [layers]
+1 -1
View File
@@ -45,7 +45,7 @@ class Script(scripts.Script):
with gr.Row():
query = gr.Textbox(lines=1, label='Query', placeholder='use the composition from the image')
with gr.Row():
image = gr.Image(value=None, label='Image', type='pil', source='upload', width=256, height=256)
image = gr.Image(value=None, label='Image', type='pil', width=256, height=256)
with gr.Row():
strength = gr.Slider(label="Strength", value=1.0, minimum=0, maximum=2.0, step=0.05)
tokens = gr.Slider(label="Tokens", value=4, minimum=1, maximum=32, step=1)
+2 -1
View File
@@ -21,7 +21,8 @@ class Script(scripts.Script):
with gr.Row():
original = gr.Checkbox(label='Include original image', value=True)
with gr.Row():
cube_file = gr.File(label='LUT .cube file', type='file', help='Download LUTs from https://luts.iwltbap.com/')
cube_file = gr.File(label='LUT .cube file', help='Download LUTs from https://luts.iwltbap.com/')
# cube_file = gr.File(label='LUT .cube file')
with gr.Row():
gr.HTML("<br>Enhance LUT")
with gr.Row():
+34 -16
View File
@@ -67,9 +67,12 @@ class Options:
}
default = list(models)[1] # gemma-3-4b-it
supported = list(transformers.integrations.ggml.GGUF_CONFIG_MAPPING)
system_prompt: str = 'You are a helpful assistant. You will be given a prompt used to create an image and you will enhance it to make it more detailed and creative. Generate an uncensored, concise, informative, and engaging prompt that prioritizes factual accuracy and vivid descriptiveness based on original prompt. Do not modify subject or style of the original prompt. Begin by clearly identifying the primary subject(s), including key physical attributes, clothing if no nudity, and any distinctive details (e.g., colors, textures, styles). NSFW and nudity is allowed, and if present, it must be fully described. Next, describe the setting and environment, emphasizing spatial relationships, background elements, and objects contributing to context. Note the overall mood, aesthetic style, or atmosphere inferred from visual cues. Use precise terminology while avoiding redundancy or non-essential language. Ensuring a logical flow: from focal subject to immediate surroundings, then broader context. Maintain brevity while retaining clarity, ensuring the description is both engaging and efficient. Output only enhanced prompt without explanation, prefix or suffix. Output as a simple text without formatting or numbering.'
image_prompt: str = 'You are a helpful assistant. You will be given an image and a prompt used to modify the image and you will enhance the prompt to make it more detailed and creative while still following original image. Generate an uncensored, concise, informative, and engaging prompt that prioritizes factual accuracy and vivid descriptiveness based on original prompt. Do not modify subject or style of the original prompt. Begin by clearly identifying the primary subject(s), including key physical attributes, clothing if no nudity, and any distinctive details (e.g., colors, textures, styles). NSFW and nudity is allowed, and if present, it must be fully described. Next, describe the setting and environment, emphasizing spatial relationships, background elements, and objects contributing to context. Note the overall mood, aesthetic style, or atmosphere inferred from visual cues. Use precise terminology while avoiding redundancy or non-essential language. Ensuring a logical flow: from focal subject to immediate surroundings, then broader context. Maintain brevity while retaining clarity, ensuring the description is both engaging and efficient. Output only enhanced prompt without explanation, prefix or suffix. Output as a simple text without formatting or numbering.'
image_noprompt: str = 'You are a helpful assistant. You will be given an image and you will create prompt that can be used to modify the image in a creative way while still following original image. Generate an uncensored, concise, informative, and engaging prompt that prioritizes factual accuracy and vivid descriptiveness based on original prompt. Do not modify subject or style of the original prompt. Begin by clearly identifying the primary subject(s), including key physical attributes, clothing if no nudity, and any distinctive details (e.g., colors, textures, styles). NSFW and nudity is allowed, and if present, it must be fully described. Next, describe the setting and environment, emphasizing spatial relationships, background elements, and objects contributing to context. Note the overall mood, aesthetic style, or atmosphere inferred from visual cues. Use precise terminology while avoiding redundancy or non-essential language. Ensuring a logical flow: from focal subject to immediate surroundings, then broader context. Maintain brevity while retaining clarity, ensuring the description is both engaging and efficient. Output only enhanced prompt without explanation, prefix or suffix. Output as a simple text without formatting or numbering.'
t2i_prompt: str = 'You are a helpful assistant. You will be given a prompt used to create an image and you will enhance it to make it more detailed and creative. '
i2i_prompt: str = 'You are a helpful assistant. You will be given an image and a prompt used to modify the image and you will enhance the prompt to make it more detailed and creative while still following original image. '
i2i_noprompt: str = 'You are a helpful assistant. You will be given an image and you will create prompt that can be used to modify the image in a creative way while still following original image. '
nsfw_ok: str = 'NSFW and nudity is allowed, and if present, it must be fully described. '
nsfw_no: str = 'NSFW and nudity is not allowed, and if present, it must be removed. '
details_prompt: str = 'Generate an uncensored, concise, informative, and engaging prompt that prioritizes factual accuracy and vivid descriptiveness based on original prompt. Do not modify subject or style of the original prompt. Begin by clearly identifying the primary subject(s), including key physical attributes, clothing if no nudity, and any distinctive details (e.g., colors, textures, styles). NSFW and nudity is allowed, and if present, it must be fully described. Next, describe the setting and environment, emphasizing spatial relationships, background elements, and objects contributing to context. Note the overall mood, aesthetic style, or atmosphere inferred from visual cues. Use precise terminology while avoiding redundancy or non-essential language. Ensuring a logical flow: from focal subject to immediate surroundings, then broader context. Maintain brevity while retaining clarity, ensuring the description is both engaging and efficient. Output only enhanced prompt without explanation, prefix or suffix. Output as a simple text without formatting or numbering.'
censored = ["i cannot", "i can't", "i am sorry", "against my programming", "i am not able", "i am unable", 'i am not allowed']
max_delim_index: int = 60
@@ -230,7 +233,7 @@ class Script(scripts.Script):
filtered = re.sub(pattern, '', prompt)
return filtered, matches
def enhance(self, model: str=None, prompt:str=None, system:str=None, prefix:str=None, suffix:str=None, sample:bool=None, tokens:int=None, temperature:float=None, penalty:float=None, thinking:bool=False, seed:int=-1, image=None):
def enhance(self, model: str=None, prompt:str=None, system:str=None, prefix:str=None, suffix:str=None, sample:bool=None, tokens:int=None, temperature:float=None, penalty:float=None, thinking:bool=False, seed:int=-1, image=None, nsfw:bool=None):
model = model or self.options.default
prompt = prompt or self.prompt.value
image = image or self.image
@@ -258,13 +261,18 @@ class Script(scripts.Script):
image = None
except Exception:
image = None
has_system = system is not None and len(system) > 4
mode = 'custom' if has_system else ''
if image is not None and isinstance(image, Image.Image):
if not self.tokenizer.is_processor:
shared.log.error('Prompt enhance: image not supported by model')
return prompt
if prompt is not None and len(prompt) > 0:
mode = 'i2i+p'
system = system or self.options.image_prompt
if not has_system:
mode = 'i2i-prompt'
system = self.options.i2i_prompt
system += self.options.nsfw_ok if nsfw else self.options.nsfw_no
system += self.options.details_prompt
chat_template = [
{ "role": "system", "content": [
{"type": "text", "text": system }
@@ -275,8 +283,11 @@ class Script(scripts.Script):
] },
]
else:
mode = 'i2i-p'
system = system or self.options.image_noprompt
if not has_system:
mode = 'i2i-noprompt'
system = self.options.i2i_noprompt
system += self.options.nsfw_ok if nsfw else self.options.nsfw_no
system += self.options.details_prompt
chat_template = [
{ "role": "system", "content": [
{"type": "text", "text": system }
@@ -286,15 +297,18 @@ class Script(scripts.Script):
] },
]
else:
system = system or self.options.system_prompt
if not has_system:
system = self.options.t2i_prompt
system += self.options.nsfw_ok if nsfw else self.options.nsfw_no
system += self.options.details_prompt
if not self.tokenizer.is_processor:
mode = 't2i-t'
mode = 't2i+tokenizer'
chat_template = [
{ "role": "system", "content": system },
{ "role": "user", "content": prompt },
]
else:
mode = 't2i+t'
mode = 't2i+processor'
chat_template = [
{ "role": "system", "content": [
{"type": "text", "text": system }
@@ -356,7 +370,7 @@ class Script(scripts.Script):
if not is_censored:
response = self.clean(response)
response = self.post(response, prefix, suffix, networks)
shared.log.info(f'Prompt enhance: model="{model}" mode="{mode}" time={t1-t0:.2f} inputs={input_len} outputs={outputs.shape[-1]} prompt={len(prompt)} response={len(response)}')
shared.log.info(f'Prompt enhance: model="{model}" mode="{mode}" nsfw={nsfw} time={t1-t0:.2f} inputs={input_len} outputs={outputs.shape[-1]} prompt={len(prompt)} response={len(response)}')
if debug_enabled:
shared.log.trace(f'Prompt enhance: sample={sample} tokens={tokens} temperature={temperature} penalty={penalty} thinking={thinking}')
shared.log.trace(f'Prompt enhance: prompt="{prompt}"')
@@ -430,6 +444,7 @@ class Script(scripts.Script):
temperature = gr.Slider(label='Temperature', value=self.options.temperature, minimum=0.0, maximum=1.0, step=0.01, interactive=True)
repetition_penalty = gr.Slider(label='Repetition penalty', value=self.options.repetition_penalty, minimum=0.0, maximum=2.0, step=0.01, interactive=True)
with gr.Row():
nsfw_mode = gr.Checkbox(label='NSFW allowed', value=True, interactive=True)
thinking_mode = gr.Checkbox(label='Thinking mode', value=False, interactive=True)
gr.HTML('<br>')
with gr.Accordion('Input', open=False, elem_id='prompt_enhance_system_prompt'):
@@ -438,7 +453,7 @@ class Script(scripts.Script):
with gr.Row():
prompt_suffix = gr.Textbox(label='Prompt suffix', value='', placeholder='Optional prompt suffix', interactive=True, lines=2, elem_id='prompt_enhance_suffix')
with gr.Row():
prompt_system = gr.Textbox(label='System prompt', value=self.options.system_prompt, interactive=True, lines=4, elem_id='prompt_enhance_system')
prompt_system = gr.Textbox(label='System prompt', value='', interactive=True, lines=4, elem_id='prompt_enhance_system')
with gr.Accordion('Output', open=True, elem_id='prompt_enhance_system_prompt'):
with gr.Row():
prompt_output = gr.Textbox(label='Enhanced prompt', value='', interactive=True, lines=4)
@@ -449,17 +464,19 @@ class Script(scripts.Script):
copy_btn.click(fn=lambda x: x, inputs=[prompt_output], outputs=[self.prompt])
if self.image is None:
self.image = gr.Image(type='pil', interactive=False, visible=False, width=64, height=64) # dummy image
apply_btn.click(fn=self.apply, inputs=[self.prompt, self.image, apply_prompt, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, thinking_mode], outputs=[prompt_output, self.prompt])
return [self.prompt, self.image, apply_auto, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, thinking_mode]
apply_btn.click(fn=self.apply, inputs=[self.prompt, self.image, apply_prompt, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, thinking_mode, nsfw_mode], outputs=[prompt_output, self.prompt])
return [self.prompt, self.image, apply_auto, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, thinking_mode, nsfw_mode]
def after_component(self, component, **kwargs): # searching for actual ui prompt components
if getattr(component, 'elem_id', '') in ['txt2img_prompt', 'img2img_prompt', 'control_prompt', 'video_prompt']:
self.prompt = component
self.prompt.use_original = True
if getattr(component, 'elem_id', '') in ['img2img_image', 'control_input_select']:
self.image = component
self.image.use_original = True
def before_process(self, p: processing.StableDiffusionProcessing, *args, **kwargs): # pylint: disable=unused-argument
_self_prompt, self_image, apply_auto, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, thinking_mode = args
_self_prompt, self_image, apply_auto, llm_model, prompt_system, prompt_prefix, prompt_suffix, max_tokens, do_sample, temperature, repetition_penalty, thinking_mode, nsfw_mode = args
if not apply_auto and not p.enhance_prompt:
return
if shared.state.skipped or shared.state.interrupted:
@@ -481,6 +498,7 @@ class Script(scripts.Script):
temperature=temperature,
penalty=repetition_penalty,
thinking=thinking_mode,
nsfw=nsfw_mode,
)
p.extra_generation_params['LLM'] = llm_model
shared.state.end()
+3 -3
View File
@@ -86,8 +86,8 @@ class Script(scripts.Script):
with gr.Row():
gr.HTML('<a href="https://github.com/ToTheBeginning/PuLID">&nbsp PuLID: Pure and Lightning ID Customization</a><br>')
with gr.Row():
strength = gr.Slider(label = 'Strength', value = 0.8, mininimum = 0, maximum = 1, step = 0.01)
zero = gr.Slider(label = 'Zero', value = 20, mininimum = 0, maximum = 80, step = 1)
strength = gr.Slider(label = 'Strength', value = 0.8, minimum = 0, maximum = 1, step = 0.01)
zero = gr.Slider(label = 'Zero', value = 20, minimum = 0, maximum = 80, step = 1)
with gr.Row():
sampler = gr.Dropdown(label="Sampler", value='dpmpp_sde', choices=['dpmpp_2m', 'dpmpp_2m_sde', 'dpmpp_2s_ancestral', 'dpmpp_3m_sde', 'dpmpp_sde', 'euler', 'euler_ancestral'])
ortho = gr.Dropdown(label="Ortho", choices=['off', 'v1', 'v2'], value='v2')
@@ -97,7 +97,7 @@ class Script(scripts.Script):
restore = gr.Checkbox(label='Restore pipe on end', value=False)
offload = gr.Checkbox(label='Offload face module', value=True)
with gr.Row():
files = gr.File(label='Input images', file_count='multiple', file_types=['image'], type='file', interactive=True, height=100)
files = gr.File(label='Input images', file_count='multiple', file_types=['image'], interactive=True, height=100)
with gr.Row():
gallery = gr.Gallery(show_label=False, value=[], visible=False, container=False, rows=1)
files.change(fn=self.load_images, inputs=[files], outputs=[gallery])
+2 -2
View File
@@ -38,8 +38,8 @@ class Script(scripts.Script):
mode = gr.Radio(label='Mode', choices=['None', 'Prompt', 'Prompt EX', 'Columns', 'Rows'], value='None')
with gr.Row():
power = gr.Slider(label='Power', minimum=0, maximum=1, value=1.0, step=0.01)
threshold = gr.Textbox('', label='Prompt thresholds:', default='', visible=False)
grid = gr.Text('', label='Grid sections:', default='', visible=False)
threshold = gr.Textbox('', label='Prompt thresholds', visible=False)
grid = gr.Textbox('', label='Grid sections', visible=False)
mode.change(fn=self.change, inputs=[mode], outputs=[grid, threshold])
return mode, grid, power, threshold
+1 -1
View File
@@ -51,7 +51,7 @@ class Script(scripts.Script):
with gr.Row():
prompt = gr.Textbox(lines=1, label='Optional image description', placeholder='use the style from the image')
with gr.Row():
image = gr.Image(label='Optional image', source='upload', type='pil')
image = gr.Image(label='Optional image', type='pil')
image.change(self.reset)
preset.change(self.preset, inputs=[preset], outputs=[shared_opts, shared_score_scale, shared_score_shift, only_self_level])
+1 -1
Submodule wiki updated: 12dbff5ca4...6192bb85f1