Compel re-weights parts of a prompt before the text encoder sees it
A prompting enhancement library for transformers-type text embedding systems
At a glance
- What is it?
- Compel is a Python library that lets you attach weights to parts of a prompt string and have the same weighting applied to the embedding tensor the text encoder produces, with dedicated classes for Stable Diffusion, SDXL, Flux, Lumina2 and Sana pipelines. It comes from the InvokeAI prompting code and installs with pip, but it pins transformers tightly and it ignores one of the prompting features it was built from.
- Who is it for?
- Compel is a good fit if you build images with Hugging Face diffusers and want prompt weighting without hand-editing attention or embedding tensors, especially if you work across more than one model family and want one syntax for all of them. It is the wrong choice if your workflow depends on cross-attention swapping, which Compel ignores, or if you cannot accept a dependency set that requires transformers 5.x and Python 3.10 or newer.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A weighting syntax that survives the text encoder
Compel is described as a text prompt weighting and blending library for transformers-type text embedding systems. The mechanism is the interesting part. With a flexible and intuitive syntax, you can re-weight different parts of a prompt string and thus re-weight the different parts of the embedding tensor produced from the string.
That distinction matters. Attaching a weight to a token in the text does nothing by itself, because the text encoder has already folded the prompt into a single tensor by the time you see it. Compel parses the prompt into weighted pieces and produces embeddings in which the weighted pieces carry their weight, so the emphasis you write survives the encoding step rather than being flattened away.
The syntax is compact. A double plus marks an upweight, as in the string a cat playing with a ball++ in the forest, and the Flux example in the README shows a double minus for the other direction, with a prompt that mixes both, Astronaut---- in a jungle++++, cold color palette, muted colors, detailed, 8k.
The library is aimed at people building images with diffusers pipelines. It is tested and developed against Hugging Face's StableDiffusionPipeline, and the README says it should work with any diffusers-based system that uses a Tokenizer and a Text Encoder of some kind. The code was adapted from the InvokeAI prompting code, by the same author.
Installing the package and producing a first embedding
Installation is a single pip command, pip install compel, with no build step and no extra tooling.
The quickstart assumes Hugging Face diffusers 0.12 or newer, and the flow is the same in every example. Build the pipeline, wrap it in the Compel class for that model, call the object with your prompt to get a conditioning object, and then hand the embeds from that object to the pipeline:
from diffusers import StableDiffusionPipeline
from compel import CompelForSD
pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
compel = CompelForSD(pipeline)
# upweight "ball"
prompt = "a cat playing with a ball++ in the forest"
conditioning = compel(prompt)
# generate image
images = pipeline(prompt_embeds=conditioning.embeds, num_inference_steps=20).images
images[0].save("image.jpg")The thing to notice is that the pipeline call is otherwise ordinary. You are not passing a prompt string to the pipeline, you are passing prompt_embeds, and the rest of the arguments, num_inference_steps here, are the ones you would have used anyway.
The dependency floor is stated for the current main branch: Python 3.10 or newer and transformers 5.x but below 6. The pyproject file lists the same bounds alongside diffusers 0.11 or newer, pyparsing 3.0 and torch, and the classifiers cover Python 3.10 through 3.13.
Negative prompts and batches share one conditioning call
A negative prompt is passed to the same call, and the conditioning object carries a separate tensor for it:
from diffusers import StableDiffusionPipeline
from compel import CompelForSD
pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
compel = CompelForSD(pipeline)
# upweight "ball"
prompt = "a cat playing with a ball++ in the forest"
negative_prompt = "blurry, low quality, deformed"
conditioning = compel(prompt, negative_prompt=negative_prompt)
# generate image
images = pipeline(prompt_embeds=conditioning.embeds, negative_prompt_embeds=conditioning.negative_embeds, num_inference_steps=20).images
images[0].save("image.jpg")Batching works the same way, with lists for both arguments and the option of a single string for the negative prompt, which is then shared across all generated images:
prompt = ["a cat playing with a ball++ in the forest", "a dog wearing a hat++"]
negative_prompt = ["blurry, low quality, deformed", "painting"]
# or: negative_prompt = "blurry, low quality, deformed" # shared across all generated images
conditioning = compel(prompt, negative_prompt=negative_prompt)The documentation also covers a style prompt, which the README says works with SDXL or Flux, and a demo notebook, compel-demo.ipynb, that is also available as a Colab notebook.
One piece of the original functionality is deliberately left out. Cross-attention control with .swap() is currently ignored by Compel, and the README explains the workaround: you can use it by calling build_conditioning_tensor_for_prompt_object() yourself and implementing cross-attention control in your diffusion loop. In other words, the feature exists in the underlying prompting design but Compel does not wire it into the normal path.
One Compel class per model family, and the ones that need masks
Because different text encoders expect different conditioning inputs, Compel ships a class per model family and the call sites differ accordingly.
For SDXL you use CompelForSDXL, and the pipeline receives both the prompt embeds and the pooled embeds, along with their negative counterparts:
from diffusers import DiffusionPipeline
from compel import CompelForSDXL
import torch
device = 'cuda'
pipeline = DiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", variant="fp16",
use_safetensors=True, torch_dtype=torch.float16).to(device)
prompt = "a cat playing with a ball++ in the forest"
negative_prompt = "low quality, blurry"
compel = CompelForSDXL(pipeline)
conditioning = compel(prompt, negative_prompt=negative_prompt)Flux has its own class, CompelForFlux, and the same pooled embeds pattern appears in its pipeline call.
The newer models require more plumbing. CompelForLumina2 handles the system prompt and returns both the prompt embeddings and the required attention masks, so the pipeline call has to pass prompt_attention_mask and negative_prompt_attention_mask alongside the embeds. CompelForSana behaves the same way for Sana pipelines, minus the system prompt, and like the pipeline itself it lowercases prompts before encoding.
That last detail is the kind of thing that silently changes results. A prompt you wrote with capitals does not reach the encoder with them.
The version constraints are the real cost of using it
Compel is a small library, but it sits in the most volatile part of the Python ecosystem, and the version requirements are tight rather than loose.
The current main-branch support targets transformers 5.x with a ceiling below 6. That is a narrow window, and it is the kind of constraint that turns into work when the ecosystem moves. If your project is on transformers 4.x today, adopting Compel means moving your whole diffusers stack, not just adding a dependency.
The release history shows the same tension from the other side. The tagged releases are v2.4.0 on 2026-05-30, v2.3.1 on 2025-11-02 and v2.3.0 on 2025-10-05, while the version in pyproject.toml is already 2.5.1. So the source tree is ahead of the last published tag, and the last push was on 2026-10-10. The repository is not archived, so development continues, but the main branch and the installed package are not the same thing, and the README describes the main-branch support targets, which is a deliberate signal that the newest code is where the bleeding edge is.
For a team that wants stability, pinning to the latest tag is the safer choice. For a team that needs a model family the tag does not yet handle, the main branch is the only option, and then you are testing the library yourself.
Compel as a library against InvokeAI's own prompting code
The alternative to using Compel is to work with the prompting implementation it was adapted from, the InvokeAI prompting code, and there is a meaningful difference in approach between the two.
InvokeAI's code lives inside its own application, so its prompting behaviour is tied to that application's pipeline and configuration. Compel takes that design and turns it into a standalone package with a small public surface: a class per model family, a call that returns a conditioning object, and a documented syntax for weighting. The consequence is that Compel can be dropped into any diffusers-based system, including a plain script or a notebook, whereas the original travels with the application it came from.
The second alternative is doing it by hand. You can tokenize a prompt yourself, run the text encoder, and scale the parts of the resulting tensor you care about, then pass those tensors to the pipeline. That is entirely possible and it is what Compel automates, but it means every model family needs its own implementation of where the tokens landed in the tensor, and the SDXL pooled embeds and the attention masks used by Lumina2 and Sana have to be handled separately. Compel exists so that this mapping is written once per model family and reused.
The trade is the dependency set. Compel requires diffusers, pyparsing, torch and a specific transformers range, and it will not be a good fit in a project that has deliberately kept itself to a minimal, stable dependency set.
Editorial conclusion
Compel is a good fit if you build images with Hugging Face diffusers and want prompt weighting without hand-editing attention or embedding tensors, especially if you work across more than one model family and want one syntax for all of them. It is the wrong choice if your workflow depends on cross-attention swapping, which Compel ignores, or if you cannot accept a dependency set that requires transformers 5.x and Python 3.10 or newer. Verify first that the model class you need exists, since each pipeline family has its own Compel class, and check the installed version against your transformers pin before you build a prompt library around it.
Frequently asked questions
How do I install Compel and upweight a word in a prompt?
Install it with pip install compel, wrap your diffusers pipeline in the matching Compel class such as CompelForSD, and mark the word with a double plus as in a cat playing with a ball++ in the forest. The returned conditioning object carries embeds you pass to the pipeline as prompt_embeds.
Which Python and transformers versions does Compel support?
The current main-branch support targets Python 3.10 or newer and transformers 5.x with a ceiling below 6. The pyproject.toml lists diffusers 0.11 or newer, pyparsing 3.0 and torch as the rest of the dependencies.
Does Compel support cross-attention control with swap?
No. The README states that cross-attention control with .swap() is currently ignored by Compel. You can still use it by calling build_conditioning_tensor_for_prompt_object() yourself and implementing cross-attention control in your diffusion loop.
Does Compel work with Flux, Lumina2 and Sana pipelines?
Yes, each has its own class: CompelForFlux, CompelForLumina2 and CompelForSana. CompelForLumina2 handles the system prompt and returns the required attention masks, and CompelForSana does the same minus the system prompt and lowercases prompts before encoding.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/damian0815-compel)Was this useful?