stable-diffusion-webui icon indicating copy to clipboard operation
stable-diffusion-webui copied to clipboard

[Feature Request]: Load additional prompt/tags when adding lora/embedding/hn

Open WesleyNery opened this issue 2 years ago • 12 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues and checked the recent builds/commits

What would your feature do ?

Like with the previews, have a tag associated to a additional network in which adds it's value to the prompt, the same way it adds the network name and strength where applicable. Specially with lora's trained on more than one concept or that have activator tags, we gotta keep notes on how to use it, generally. That adds up kinda fast. so, having a structure like: lora1.safetensors lora1.preview.png lora1.additional.txt

Proposed workflow

  1. CLick on Extra Networks
  2. Select whatever you need from the previews
  3. It adds the tags you put on a file automatically to the prompt, like "lora:name:1, activation tag1, activation tag N..."

Additional information

No response

WesleyNery avatar Feb 01 '23 12:02 WesleyNery

my work around this is to name the model after the trigger word, but obviously with ones with many triggers i have the same issue, so this would be a nice feature

gitaiuser20 avatar Feb 01 '23 20:02 gitaiuser20

my work around this is to name the model after the trigger word, but obviously with ones with many triggers i have the same issue, so this would be a nice feature

I do this as well. I've even added a -additional.txt and made a script that auto-add the tags from the file to a wildcard file that I can use. but that works with dynamic prompts only.

WesleyNery avatar Feb 01 '23 20:02 WesleyNery

Alright, so I did a thing:

            additional_file=path  + '-additional.txt'
            additional_vars = {}
            if os.path.isfile(additional_file):
                with open(additional_file) as myfile:
                    for line in myfile:
                        key, value = line.partition("=")[::2]
                        additional_vars[key.strip()] = str(value.strip())
            if "multiplier" in additional_vars:
                multiplier=additional_vars["multiplier"]
            else:
                multiplier=1
            if "tags" in additional_vars:
                tags=additional_vars["tags"]
            else:
                tags=""
            prompt =  "<lora:"+name+":" + str(multiplier) +">,"+tags

I put this on ui_extra_networks_lora.py, def list_items. It works. Problems:

  • I have almost no python knowledge, so this is badly written
  • Misplaced. I couldn't make it work on the Yield (see item 1) and could not make opts.extra_networks_default_multiplier work
  • I know almost nothing about gitHub and how things work, so cant make a pull request (would probably be a very bad one)
  • When you 'unclick' the lora, the tags added will be left behind But hey, it works. If anyone can make this better or add it, would be appreciated.

WesleyNery avatar Feb 09 '23 15:02 WesleyNery

hi, WesleyNery Can you paste all ui_extra_networks_lora.py It seems no work for me, how to define "-additional.txt" it:

1 Is it same directory as lora?

2 what is additional name? lora1.safetensors lora1.preview.png "lora1.additional.txt" or "lora1-additional.txt" or "-additional.txt"

3 the additionl.txt put activator tags like wildcard, like this? Trigger Words1 Trigger Words2 Trigger Words3

xueqing0622 avatar Feb 26 '23 23:02 xueqing0622

you can go to my issue page to see my idea about lora get Trigger Words automatic, I think this is another efficient way https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/8152 Hope you can get the way to do it

xueqing0622 avatar Feb 27 '23 00:02 xueqing0622

for sure, here it is. StableDiffusion.zip The file name can be anything you would like, I chose '*-additional.txt', like on your example: lora1.safetensors lora1.preview.png lora1-additional.txt But again, that's what I chose. you can change the file sulfix to whatever, just change it on the code. On the file I look for 'tags=' and 'multiplier=', for example:

character_kanzaki aoi_demon slayer-additional.txt: tags=kanzaki aoi (kimetsu no yaiba),butterfly_hair_ornament,demon_slayer_uniform,bangs, blue eyes, parted bangs,bright pupils, forehead multiplier=0.7 So when I click the lora it sets the strentgh to 0.7 and puts all the tags.

WesleyNery avatar Feb 27 '23 00:02 WesleyNery

I add *-additional.txt with lora and embeddings same directory. and replace the .py file ".\extensions-builtin\Lora\ui_extra_networks_lora.py" ".\modules\ui_extra_networks_textual_inversion.py" and in CLick on Extra Networks, embeddings and lora seems no work, I check the zip file, the ui_extra_networks_lora.py still the same as original one. And I add the script you write, but still no work, I check a lot of times, but no find the wrong place.

import json import os import lora

from modules import shared, ui_extra_networks

class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage): def init(self): super().init('Lora')

def refresh(self):
    lora.list_available_loras()

def list_items(self):
    for name, lora_on_disk in lora.available_loras.items():
        path, ext = os.path.splitext(lora_on_disk.filename)
        previews = [path + ".png", path + ".preview.png"]

        preview = None
        for file in previews:
            if os.path.isfile(file):
                preview = self.link_preview(file)
                break
                
  
        additional_file=path  + '-additional.txt'
        additional_vars = {}
        if os.path.isfile(additional_file):
            with open(additional_file) as myfile:
                for line in myfile:
                    key, value = line.partition("=")[::2]
                    additional_vars[key.strip()] = str(value.strip())
        if "multiplier" in additional_vars:
            multiplier=additional_vars["multiplier"]
        else:
            multiplier=1
        if "tags" in additional_vars:
            tags=additional_vars["tags"]
        else:
            tags=""
        prompt =  "<lora:"+name+":" + str(multiplier) +">,"+tags


        yield {
            "name": name,
            "filename": path,
            "preview": preview,
            "search_term": self.search_terms_from_path(lora_on_disk.filename),
            "prompt": json.dumps(f"<lora:{name}:") + " + opts.extra_networks_default_multiplier + " + json.dumps(">"),
            "local_preview": path + ".png",
        }

def allowed_directories_for_previews(self):
    return [shared.cmd_opts.lora_dir]
   

xueqing0622 avatar Feb 27 '23 05:02 xueqing0622

I recheck again, and done: this should change to: "prompt": json.dumps(prompt),

Thanks,WesleyNery, very useful tools, No need to find the trigger words. Have a nice day

xueqing0622 avatar Feb 27 '23 05:02 xueqing0622

Hi,WesleyNery Can you change the "ui_extra_networks_checkpoints.py" as lora and embeddings, Because checkpoint also have Trigger Words to get better effect. I change it like your "ui_extra_networks_textual_inversion.py" But it not work, can you check or write it again, many thanks:

import html import json import os import urllib.parse

from modules import shared, ui_extra_networks, sd_models

class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage): def init(self): super().init('Checkpoints') self.allow_negative_prompt = True

def refresh(self):
    shared.refresh_checkpoints()

def list_items(self):
    checkpoint: sd_models.CheckpointInfo
    for name, checkpoint in sd_models.checkpoints_list.items():
        path, ext = os.path.splitext(checkpoint.filename)
        previews = [path + ".png", path + ".preview.png"]

        preview = None
        for file in previews:
            if os.path.isfile(file):
                preview = self.link_preview(file)
                break
                     ##########            
        additional_file=path  + '-additional.txt'
        additional_vars = {}
        if os.path.isfile(additional_file):
            with open(additional_file) as myfile:
                for line in myfile:
                    key, value = line.partition("=")[::2]
                    additional_vars[key.strip()] = str(value.strip())
                
        if "multiplier" in additional_vars:
            multiplier=additional_vars["multiplier"]
        else:
            multiplier=1
        if "tags" in additional_vars:
            tags=additional_vars["tags"]
        else:
            tags=""
        prompt = tags


        yield {
            "name": checkpoint.name_for_extra,
            "filename": path,
            "preview": preview,
            "search_term": self.search_terms_from_path(checkpoint.filename) + " " + (checkpoint.sha256 or ""),
            "onclick": '"' + html.escape(f"""return selectCheckpoint({json.dumps(name)})""") + '"',
            "prompt": json.dumps(prompt),
            "local_preview": path + ".png",
        }

def allowed_directories_for_previews(self):
    return [v for v in [shared.cmd_opts.ckpt_dir, sd_models.model_path] if v is not None]

xueqing0622 avatar Feb 27 '23 15:02 xueqing0622

Here is an idea for an extension:

  • A tab that displays all 'embeddings' and when you click on one it will check if you have 'tags templates' in a 'file-additional.txt' file (or something similar).
  • If you do, then a mini-window will pop up showing the titles of each template you have for that embedding and if you click on it it will edit the prompt and negative_prompt in accordance to your template.
  • It should only add the tags that do not yet exist on the prompt/negative_prompt to prevent duplicates (and override existing ones if the weights do not match) plus you should be able to also specify tags to be excluded for each template as well as the weight of the embedding.
  • Once that's done it should highlight the embedding 'box' with a color to alert the user that embedding is being used - might also be a cool idea to be able to specify the highlight color per template.
  • Clicking back on a embedding already in use will remove all existing tags (from the prompt and negative_prompt) of the selected template and de-highlight it.

Here is an example of how a 'file-additional.txt' could look like:

# Title:SFW,Color:green
weight:0.7
prompt:character_name, clothes, (dress:1.2)
negative_prompt:nsfw, (nude)
exclude_from_prompt:nsfw,nude,partially undressed,topless
exclude_from_negative_prompt:clothes, clothing, dress

# Title:NSFW,Color:red
weight:0.6
prompt:character_name, (nude:1.2), nsfw
negative_prompt:clothes, clothing, dress
exclude_from_prompt:clothes, dress
exclude_from_negative_prompt:nsfw,nude

Example workflow: current prompt: 1girl, solo, (partially undressed:1.3), [clothes], nsfw current negative_prompt: easynegative, (nude:1.2), dress

EXT TAB > click character lora -> (template window shows up with SFW/NSFW buttons) click SFW -> embedding box gets highlighted in green AND prompt/negative_prompt becomes:

prompt: 1girl, solo, <filename:07>, character_name, clothes, (dress:1.2) negative_prompt: easynegative, nsfw, (nude)

This is a simplification but you get the idea. I'm sure lots of people could really use something like this since LoRas are becoming so popular nowadays.

GreenLandisaLie avatar Mar 02 '23 21:03 GreenLandisaLie

What I would love to see is an extension that creates a metadata file next to each model.

That we could store the:

  • Title
  • Description
  • Recommended Weight
  • Trigger Phrase - prompt to go with the model
  • URL
  • Example Prompt
  • And display Model Info

Then when you mouse over the model you would see a description. Clicking on the model would put not only the model tag, but also the recommended weight value and the trigger phrase.


For example, if I clicked on a Mazda Miata LoRA, rather than just adding <lora:Mazda Miata:1> to the prompt,

it would put <lora:Mazda Miata:0.6>, MazdaMiata, 1car Using my preset weight and tags with the model.


The only needed Icons on the card would be an edit icon and an insert without the trigger phrase icon.

2023-03-12 13_10_02-Stable Diffusion — Mozilla Firefox copy

  • Clicking the model would add the model with the set weight and trigger phrase. Example: <lora:GI Landscape 2:0.8>, Render of a {prompt} in Mondstat, CG, Unreal Render

  • Clicking the no-tag icon would add the model without the trigger phrase Example: <lora:GI Landscape 2:0.8>

  • Clicking the gear would open the edit box.

Here is a mockup edit box.

2023-03-12 13_10_37-Stable Diffusion — Mozilla Firefox copy


The metadata files should be universal, such as JSON or XML. Easy to edit manually. But there should also be an edit icon in the UI on the model to edit the fields.

Additionally, it would be nice to have it scrape starting metadata from sites like Civitai to pull the initial values, which could then be modified.

I find the default weight of 1 and recommended trigger words are almost never enough on their own to get a good result. I have been manually adding every single LoRA, TI, and Hyper to my Styles CSV list to have it fill in the best weight, and trigger phrase combo. This works but is annoying as it requires me to double my efforts. It would be great to be able to specify the values that I want for each model.

Here is a fork of the civitai extension that is trying to add some of this functionality.

https://github.com/butaixianran/Stable-Diffusion-Webui-Civitai-Helper/issues/36#issuecomment-1465201501

MrKuenning avatar Mar 13 '23 18:03 MrKuenning

A great suggestion. At risk of making the dialog box longer, a filterable, multi-select checklist filled with currently loaded models that the user can use to link LORA<->Model might be snazzy. Enables a future option on the parent page of the lora selection window to "filter compatible/favored loras against current model selection".

cbreden avatar Mar 14 '23 06:03 cbreden

Pushed an update to dev that adds an edit dialog for loras partially according to the mockup above:

firefox_0W5lKrdllB

AUTOMATIC1111 avatar Jul 15 '23 22:07 AUTOMATIC1111

That looks awesome, I love the addition of Tags.

MrKuenning avatar Jul 17 '23 17:07 MrKuenning