damian0815 / compel

A prompting enhancement library for transformers-type text embedding systems
MIT License
519 stars 47 forks source link

TypeError: unsupported operand type(s) for +: 'NoneType' and 'int' in get_embeddings_for_weighted_prompt_fragments #105

Open Clement-Lelievre opened 2 days ago

Clement-Lelievre commented 2 days ago

Hi @damian0815 ,

I found a case that makes compel crash, here is a MRE (I did not attempt to find the shortest possible prompt that makes it crash):

using compel==2.0.3

pipe = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0"
) 

prompts = [
    "\u20281. Style - (((Character entering the game))), - (((In-game, so a bit casual and simple style))), - Looking to the Right, - Full body must be visible, - (((3 heads tall))) \u20282. Concept \u2028- (((Hero in the zombie apocalypse)))\u2028 - The top is a white T-shirt \u2028- - (((He has a backpack on his back)))\u2028"
]
kwargs = {}
kwargs["tokenizer"] = [
    pipe.tokenizer,
    pipe.tokenizer_2,
]
kwargs["text_encoder"] = [
    pipe.text_encoder, 
    pipe.text_encoder_2,
]

compel = Compel(**kwargs)
compel(prompts)

The reason seemingly comes from SDXL's tokenizer: look at EmbeddingsProvider.get_token_ids, you'll see that here some lists are empty (after trimming bos and eos), I did not investigate whether this is expected behavior from the tokenizer. This in turn triggers the creation of the None in your code, specifically in _get_token_ranges_for_fragments here. Btw the typing of _get_token_ranges_for_fragments is incorrect in those cases where the return can contain None, so not only ints

Let me know,