wip diffusers

This commit is contained in:
Vladimir Mandic
2023-07-02 21:07:26 -04:00
parent a2caafe4df
commit cc685a8729
7 changed files with 81 additions and 47 deletions
+13 -9
View File
@@ -23,27 +23,31 @@ to update repo, do not use `--upgrade` flag, use manual `git pull` instead
### Diffusers
- sd 1.5 and sd 2.1 model
models can be downloaded from huggingface hub
but focus on default model for now and i'll add downloader soon
- lora, textual inversion
only loras/textual-inversions downloaded from huggingface hub are supported for now
i'll add standard safetensors soon
- model downloader: tabs -> models -> hf hub
- txt2img, img2img, inpaint, outpaint, process
- hires fix, restore faces, etc?
### Experimental
### Experimental - don't test yet
- cuda model compile using `reduce overhead` model with and without `fullgraph`
- cuda model compile using `reduce overhead` model with or without `fullgraph`
- kandinsky model
## Todo
- enable loading of safetensors models
- lora
- embedding
- safetensors models
- cleanup logging
- search&download models from hfhub
- controlnet extension
- multidiffusion extension
- sdxl model
## Limitations
- extra networks
- controlnet
- multi-diffusion
## Issues
- TBD
+3 -4
View File
@@ -11,9 +11,8 @@ if __name__ == "__main__":
model_filter = hf.ModelFilter(
model_name=keyword,
task='text-to-image',
tags='stable-diffusion',
library=['diffusers', 'stable-diffusion'],
library=['diffusers'],
)
res = hf_api.list_models(filter=model_filter, full=True, limit=50, sort="downloads", direction=-1)
models = [{ 'name': m.modelId, 'downloads': m.downloads, 'mtime': m.lastModified, 'url': f'https://huggingface.co/{m.modelId}' } for m in res]
print('Online', models)
models = [{ 'name': m.modelId, 'downloads': m.downloads, 'mtime': m.lastModified, 'url': f'https://huggingface.co/{m.modelId}', 'pipeline': m.pipeline_tag, 'tags': m.tags } for m in res]
print(models)
+2
View File
@@ -90,6 +90,8 @@ def compatibility_args(opts, args):
group.add_argument("--sub-quad-chunk-threshold", help=argparse.SUPPRESS, default=opts.sub_quad_chunk_threshold)
group.add_argument("--lora-dir", help=argparse.SUPPRESS, default=opts.lora_dir)
group.add_argument("--lyco-dir", help=argparse.SUPPRESS, default=opts.lyco_dir)
group.add_argument("--embeddings-dir", help=argparse.SUPPRESS, default=opts.embeddings_dir)
group.add_argument("--hypernetwork-dir", help=argparse.SUPPRESS, default=opts.hypernetwork_dir)
group.add_argument("--lyco-patch-lora", help=argparse.SUPPRESS, default=opts.lyco_patch_lora)
group.add_argument("--lyco-debug", help=argparse.SUPPRESS, action='store_true', default=False)
group.add_argument("--enable-console-prompts", help=argparse.SUPPRESS, action='store_true', default=False)
+4 -3
View File
@@ -11,6 +11,7 @@ from modules.paths import script_path, models_path
diffuser_repos = []
def download_diffusers_model(hub_id: str, cache_dir: str = None, download_config: Dict[str, str] = None):
from diffusers import DiffusionPipeline
import huggingface_hub as hf
@@ -41,6 +42,7 @@ def download_diffusers_model(hub_id: str, cache_dir: str = None, download_config
return pipeline_dir
def load_diffusers_models(model_path: str, command_path: str = None):
import huggingface_hub as hf
places = []
@@ -74,10 +76,9 @@ def find_diffuser(name: str):
filt = hf.ModelFilter(
model_name=name,
task='text-to-image',
tags='stable-diffusion',
library=['diffusers', 'stable-diffusion'],
library=['diffusers'],
)
models = list(api.list_models(filter=filt, full=True, limit=50, sort="downloads", direction=-1))
models = list(api.list_models(filter=filt, full=True, limit=5, sort="downloads", direction=-1))
shared.log.debug(f'Searching diffusers models: {name} {len(models) > 0}')
if len(models) > 0:
return models[0].modelId
+1 -1
View File
@@ -14,9 +14,9 @@ import safetensors.torch
from omegaconf import OmegaConf
import tomesd
from transformers import logging as transformers_logging
import diffusers
import ldm.modules.midas as midas
from ldm.util import instantiate_from_config
import diffusers
from modules import paths, shared, modelloader, devices, script_callbacks, sd_vae, sd_disable_initialization, errors, hashes, sd_models_config
from modules.sd_hijack_inpainting import do_inpainting_hijack
from modules.timer import Timer
+2 -22
View File
@@ -234,31 +234,15 @@ def list_checkpoint_tiles():
default_checkpoint = list_checkpoint_tiles()[0] if len(list_checkpoint_tiles()) > 0 else "model.ckpt"
def load_diffusers_ckpt(model_repo: str):
cached_dir = modelloader.download_diffusers_model(model_repo)
print(f"Downloaded {cached_dir}")
return ""
def load_diffusers_lora(lora_repo: str):
pipe = sys.modules[__name__].sd_model
if lora_repo == "":
pipe._remove_text_encoder_monkey_patch() # pylint: disable=W0212
proc_cls_name = next(iter(pipe.unet.attn_processors.values())).__class__.__name__
non_lora_proc_cls = getattr(diffusers.models.attention_processor, proc_cls_name[len("LORA"):])
pipe.unet.set_attn_processor(non_lora_proc_cls())
print("Removed LoRA.")
return ""
elif is_url(lora_repo):
with tempfile.TemporaryDirectory() as temp_dir:
os.system(f"wget -P {temp_dir} {lora_repo}")
temp_file_path = os.path.join(temp_dir, lora_repo.split('/')[-1])
pipe.load_lora_weights(temp_file_path)
lora_repo = '/'.join(lora_repo.split('/')[-2:])
print(f"Loaded Civit.ai LoRA: {lora_repo}")
return f"{lora_repo} is loaded. Pass empty text field to remove LoRA or pass new LoRA id."
elif len(lora_repo.split('/')) == 2:
lora_dir = os.path.dirname(opts.data["diffusers_dir"])
cache_dir = os.path.join(lora_dir, "Diffusers_LoRA")
@@ -269,34 +253,30 @@ def load_diffusers_lora(lora_repo: str):
print(f"{lora_repo} is not a valid LoRA identifier.")
return ""
def load_diffusers_text_inv(text_inv_repo: str):
pipe = sys.modules[__name__].sd_model
if text_inv_repo == "":
pipe.tokenizer = pipe.tokenizer.__class__.from_pretrained(pipe.tokenizer.name_or_path)
pipe.text_encoder.resize_token_embeddings(len(pipe.tokenizer))
print("Removed all textual inversions.")
return ""
elif is_url(text_inv_repo):
with tempfile.TemporaryDirectory() as temp_dir:
os.system(f"wget -P {temp_dir} {text_inv_repo}")
temp_file_path = os.path.join(temp_dir, text_inv_repo.split('/')[-1])
pipe.load_textual_inversion(temp_file_path)
text_inv_repo = '/'.join(text_inv_repo.split('/')[-2:])
print(f"Loaded Civit.ai Textual Inv: {text_inv_repo}")
elif len(text_inv_repo.split('/')) == 2:
text_inv_dir = os.path.dirname(opts.data["diffusers_dir"])
cache_dir = os.path.join(text_inv_dir, "Diffusers_Text_Inv")
pipe.load_textual_inversion(text_inv_repo, cache_dir=cache_dir)
print(f"Loaded {text_inv_repo}")
text_inv_tokens = pipe.tokenizer.added_tokens_encoder.keys()
text_inv_tokens = [t for t in text_inv_tokens if not (len(t.split("_")) > 1 and t.split("_")[-1].isdigit())]
return f"{', '.join(text_inv_tokens)} loaded. Pass empty text field to remove all or add new textual inversion id."
def refresh_checkpoints():
import modules.sd_models # pylint: disable=W0621
return modules.sd_models.list_models()
+56 -8
View File
@@ -162,14 +162,62 @@ def create_ui():
model_list_btn.click(fn=list_models, inputs=[], outputs=[model_table, models_outcome])
with gr.Tab(label="HF Hub"):
""""
options_templates.update(options_section(('diffusers', "Diffusers"), {
"diffusers_ckpt_download": OptionInfo("", "HFHub Checkpoint download", gr.Textbox, {"placeholder": "e.g. runwayml/stable-diffusion-v1-5"}, submit=load_diffusers_ckpt),
"diffusers_lora_download": OptionInfo("", "HFHub LoRA download", gr.Textbox, {"placeholder": "e.g. pcuenq/pokemon-lora"}, submit=load_diffusers_lora),
"diffusers_text_inv_download": OptionInfo("", "HFHub Textual Inversion download", gr.Textbox, {"placeholder": "e.g. sd-concepts-library/midjourney-style"}, submit=load_diffusers_text_inv),
}))
"""
with gr.Tab(label="Huggingface"):
data = []
os.environ.setdefault('HF_HUB_DISABLE_EXPERIMENTAL_WARNING', '1')
os.environ.setdefault('HF_HUB_DISABLE_SYMLINKS_WARNING', '1')
os.environ.setdefault('HF_HUB_DISABLE_IMPLICIT_TOKEN', '1')
os.environ.setdefault('HUGGINGFACE_HUB_VERBOSITY', 'warning')
def hf_search(keyword):
import huggingface_hub as hf
hf_api = hf.HfApi()
model_filter = hf.ModelFilter(
model_name=keyword,
task='text-to-image',
library=['diffusers'],
)
models = hf_api.list_models(filter=model_filter, full=True, limit=50, sort="downloads", direction=-1)
data.clear()
for model in models:
tags = [t for t in model.tags if not t.startswith('diffusers') and not t.startswith('license') and not t.startswith('arxiv') and len(t) > 2]
data.append([model.modelId, model.pipeline_tag, tags, model.downloads, model.lastModified, f'https://huggingface.co/{model.modelId}'])
return data
def hf_select(evt: gr.SelectData):
return data[evt.index[0]][0]
def hf_download_model(hub_id: str):
from modules.shared import log, opts
from modules.modelloader import download_diffusers_model
try:
download_diffusers_model(hub_id, cache_dir=opts.diffusers_dir)
except Exception as e:
log.error(f"Diffuser model downloaded error: model={hub_id} {e}")
return f"Diffuser model downloaded error: model={hub_id} {e}"
from modules.sd_models import list_models # pylint: disable=W0621
list_models()
log.info(f"Diffuser model downloaded: model={hub_id}")
return f'Diffuser model downloaded: model={hub_id}'
with gr.Row():
hf_search_text = gr.Textbox('', label = 'Seach models', placeholder='search huggingface models')
with gr.Row():
hf_selected = gr.Textbox('', label = 'Select model', placeholder='select model from search results or enter model name manually')
with gr.Row():
hf_download_model_btn = gr.Button(value="Download model", variant='primary')
with gr.Row():
hf_headers = ['Name', 'Pipeline', 'Tags', 'Downloads', 'Updated', 'URL']
hf_results = gr.DataFrame([], label = 'Search results', show_label = True, interactive = False, wrap = True, overflow_row_behaviour = 'paginate', max_rows = 10, headers = hf_headers, type='array')
hf_search_text.submit(fn=hf_search, inputs=[hf_search_text], outputs=[hf_results])
hf_results.select(hf_select, inputs=None, outputs=[hf_selected])
hf_download_model_btn.click(fn=hf_download_model, inputs=[hf_selected], outputs=[models_outcome])
# TODO load_diffusers_lora
# TODO load_diffusers_text_inv
with gr.Tab(label="CivitAI"):
pass