Compel
Compel is an active Python library, currently at version 2.3.1, designed to enhance prompting for transformers-type text embedding systems. It provides a flexible and intuitive syntax for sophisticated prompt weighting, blending, and concatenation, commonly used with Hugging Face `diffusers` pipelines. The library aims to give users granular control over how text encoders interpret complex prompt strings, and it maintains a regular release cadence with ongoing development.
Common errors
-
RuntimeError: Sizes of tensors must match except in dimension 1. Expected size 77 but got size 154 for tensor number X in the list.
cause This error often occurs with SDXL when its two tokenizers (`tokenizer` and `tokenizer_2`) produce conditioning tensors of different sequence lengths, typically due to differing padding tokens or specific prompt characters (like `!`) causing disparate tokenization lengths across the two text encoders.fixFor SDXL, ensure `CompelForSDXL` is correctly initialized with both tokenizers and text encoders (`compel = CompelForSDXL(pipeline)`). If the issue persists with special characters like '!', a workaround is to initialize `Compel` with a duplicated tokenizer for both: `compel = Compel(tokenizer=[pipeline.tokenizer, pipeline.tokenizer], text_encoder=[pipeline.text_encoder, pipeline.text_encoder_2], ...)` as a temporary fix, along with `truncate_long_prompts=False` and `pad_conditioning_tensors_to_same_length()`. -
Token indices sequence length is longer than the specified maximum sequence length for this model (XXX > 77). Running this sequence through the model will result in indexing errors.
cause This warning (or sometimes an error if not handled) indicates that an input prompt exceeds the maximum token length (typically 77 tokens for many Stable Diffusion models). It appears when `truncate_long_prompts=False` is set during `Compel` initialization, allowing longer prompts that are then chunked.fixIf you intend to use long prompts, ensure `truncate_long_prompts=False` is set in `Compel` initialization and always use `compel.pad_conditioning_tensors_to_same_length()` for all conditioning tensors. If truncation is desired, ensure `truncate_long_prompts=True` (which is the default behavior in `Compel`).
Warnings
- breaking With Compel v2.0.0, the API for controlling returned embeddings changed for SDXL support. The boolean argument `use_penultimate_clip_layer` was replaced by the `returned_embeddings_type` enum (e.g., `ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NORMALIZED`).
- breaking In v1.0.0, the downweighting algorithm was changed to mask tokens (default) instead of literally removing them. This new behavior preserves positional embeddings, but the old behavior can be re-enabled if necessary.
- gotcha When using `pipeline.enable_sequential_cpu_offloading()` with SDXL models, `compel` may require explicit device assignment to prevent issues. This was addressed in v2.0.2.
- gotcha For long prompts (when `truncate_long_prompts=False`) or prompts using the `.and()` operator, conditioning tensors for positive and negative prompts may have different lengths, leading to errors in the diffusion pipeline.
- gotcha To avoid VRAM leaks and manage memory efficiently, especially in iterative generation loops, ensure `compel` operations are performed within a `with torch.no_grad():` block.
Install
-
pip install compel
Imports
- Compel
from compel.compel import Compel
from compel import Compel
- CompelForSD
from compel import CompelForSD
- CompelForSDXL
from compel import CompelForSDXL
- ReturnedEmbeddingsType
from compel import ReturnedEmbeddingsType
- DownweightMode
from compel import DownweightMode
Quickstart
import torch
from diffusers import DiffusionPipeline
from compel import CompelForSDXL
# Ensure you have a Hugging Face token if the model is private or gated
# os.environ['HF_TOKEN'] = os.environ.get('HF_TOKEN', '')
# Load an SDXL pipeline
pipeline = DiffusionPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
variant="fp16",
use_safetensors=True,
torch_dtype=torch.float16
).to("cuda") # Or 'cpu' if no GPU
# Initialize CompelForSDXL with the pipeline
compel = CompelForSDXL(pipeline)
# Define prompts with weighting syntax
positive_prompt = "A cat playing with a ball++ in the forest, (high quality, photorealistic)1.2"
negative_prompt = "deformed, ugly, blurry, out of focus, worst quality, low quality-"
# Generate conditioning tensors
conditioning = compel(positive_prompt)
negative_conditioning = compel(negative_prompt)
# For SDXL, prompt_embeds and pooled_prompt_embeds are used
image = pipeline(
prompt_embeds=conditioning.embeds,
pooled_prompt_embeds=conditioning.pooled_embeds,
negative_prompt_embeds=negative_conditioning.embeds,
negative_pooled_prompt_embeds=negative_conditioning.pooled_embeds,
num_inference_steps=30,
width=1024,
height=1024
).images[0]
# Save the generated image
# image.save("compel_example_image.png")
print("Image generated successfully.")