compel5 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- compel5-0.1.0/LICENSE +7 -0
- compel5-0.1.0/PKG-INFO +414 -0
- compel5-0.1.0/README.md +375 -0
- compel5-0.1.0/pyproject.toml +76 -0
- compel5-0.1.0/setup.cfg +4 -0
- compel5-0.1.0/src/compel/__init__.py +6 -0
- compel5-0.1.0/src/compel/compel.py +438 -0
- compel5-0.1.0/src/compel/conditioning_scheduler.py +43 -0
- compel5-0.1.0/src/compel/convenience_wrappers.py +215 -0
- compel5-0.1.0/src/compel/cross_attention_control.py +30 -0
- compel5-0.1.0/src/compel/diffusers_textual_inversion_manager.py +19 -0
- compel5-0.1.0/src/compel/embeddings_provider.py +698 -0
- compel5-0.1.0/src/compel/prompt_parser.py +698 -0
- compel5-0.1.0/src/compel5.egg-info/PKG-INFO +414 -0
- compel5-0.1.0/src/compel5.egg-info/SOURCES.txt +21 -0
- compel5-0.1.0/src/compel5.egg-info/dependency_links.txt +1 -0
- compel5-0.1.0/src/compel5.egg-info/requires.txt +13 -0
- compel5-0.1.0/src/compel5.egg-info/top_level.txt +1 -0
- compel5-0.1.0/test/test_compel.py +592 -0
- compel5-0.1.0/test/test_diffusers_smoke.py +186 -0
- compel5-0.1.0/test/test_embeddings_provider.py +523 -0
- compel5-0.1.0/test/test_prompt_parser.py +627 -0
- compel5-0.1.0/test/test_smoke.py +94 -0
compel5-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2023 by Damian Stewart
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
compel5-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: compel5
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A maintained fork of Compel for modern Diffusers and Transformers versions.
|
|
5
|
+
Author: Damian Stewart
|
|
6
|
+
Maintainer: Christian Tannahill
|
|
7
|
+
Project-URL: Homepage, https://github.com/Cstannahill/compel5
|
|
8
|
+
Project-URL: Repository, https://github.com/Cstannahill/compel5.git
|
|
9
|
+
Project-URL: Issues, https://github.com/Cstannahill/compel5/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Cstannahill/compel5/releases
|
|
11
|
+
Keywords: diffusers,transformers,stable-diffusion,sdxl,prompt-weighting,text-embeddings
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: torch
|
|
28
|
+
Requires-Dist: transformers<6,>=5
|
|
29
|
+
Requires-Dist: diffusers>=0.35
|
|
30
|
+
Requires-Dist: pyparsing<4,>=3
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: build; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff; extra == "dev"
|
|
35
|
+
Requires-Dist: twine; extra == "dev"
|
|
36
|
+
Provides-Extra: examples
|
|
37
|
+
Requires-Dist: notebook>=6.5.7; extra == "examples"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# Compel
|
|
41
|
+
A text prompt weighting and blending library for transformers-type text embedding systems, by [@damian0815](https://github.com/damian0815).
|
|
42
|
+
|
|
43
|
+
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.
|
|
44
|
+
|
|
45
|
+
Tested and developed against Hugging Face's `StableDiffusionPipeline` but it should work with any diffusers-based system that uses an `Tokenizer` and a `Text Encoder` of some kind.
|
|
46
|
+
|
|
47
|
+
Adapted from the [InvokeAI](https://github.com/invoke-ai) prompting code (also by [@damian0815](https://github.com/damian0815)).
|
|
48
|
+
|
|
49
|
+
Note that cross-attention control `.swap()` is currently ignored by Compel, but you can use it by calling `build_conditioning_tensor_for_prompt_object()` yourself, and implementing cross-attention control in your diffusion loop.
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
`pip install compel`
|
|
54
|
+
|
|
55
|
+
Current main-branch support targets:
|
|
56
|
+
|
|
57
|
+
- Python `>=3.10`
|
|
58
|
+
- `transformers >=5,<6`
|
|
59
|
+
|
|
60
|
+
## Documentation
|
|
61
|
+
|
|
62
|
+
Documentation is [here](doc/).
|
|
63
|
+
|
|
64
|
+
## Demo
|
|
65
|
+
|
|
66
|
+
See [compel-demo.ipynb](compel-demo.ipynb)
|
|
67
|
+
|
|
68
|
+
<a target="_blank" href="https://colab.research.google.com/github/damian0815/compel/blob/main/compel-demo.ipynb">
|
|
69
|
+
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
|
|
70
|
+
</a>
|
|
71
|
+
|
|
72
|
+
## Quickstart
|
|
73
|
+
|
|
74
|
+
With Hugging Face diffusers >=0.12:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from diffusers import StableDiffusionPipeline
|
|
78
|
+
from compel import CompelForSD
|
|
79
|
+
|
|
80
|
+
pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
|
|
81
|
+
compel = CompelForSD(pipeline)
|
|
82
|
+
|
|
83
|
+
# upweight "ball"
|
|
84
|
+
prompt = "a cat playing with a ball++ in the forest"
|
|
85
|
+
conditioning = compel(prompt)
|
|
86
|
+
|
|
87
|
+
# generate image
|
|
88
|
+
images = pipeline(prompt_embeds=conditioning.embeds, num_inference_steps=20).images
|
|
89
|
+
images[0].save("image.jpg")
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### With negative prompt:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from diffusers import StableDiffusionPipeline
|
|
96
|
+
from compel import CompelForSD
|
|
97
|
+
|
|
98
|
+
pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
|
|
99
|
+
compel = CompelForSD(pipeline)
|
|
100
|
+
|
|
101
|
+
# upweight "ball"
|
|
102
|
+
prompt = "a cat playing with a ball++ in the forest"
|
|
103
|
+
negative_prompt = "blurry, low quality, deformed"
|
|
104
|
+
conditioning = compel(prompt, negative_prompt=negative_prompt)
|
|
105
|
+
|
|
106
|
+
# generate image
|
|
107
|
+
images = pipeline(prompt_embeds=conditioning.embeds, negative_prompt_embeds=conditioning.negative_embeds, num_inference_steps=20).images
|
|
108
|
+
images[0].save("image.jpg")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Batched:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from diffusers import StableDiffusionPipeline
|
|
115
|
+
from compel import CompelForSD
|
|
116
|
+
|
|
117
|
+
pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
|
|
118
|
+
compel = CompelForSD(pipeline)
|
|
119
|
+
|
|
120
|
+
prompt = ["a cat playing with a ball++ in the forest", "a dog wearing a hat++"]
|
|
121
|
+
negative_prompt = ["blurry, low quality, deformed", "painting"]
|
|
122
|
+
# or: negative_prompt = "blurry, low quality, deformed" # shared across all generated images
|
|
123
|
+
conditioning = compel(prompt, negative_prompt=negative_prompt)
|
|
124
|
+
|
|
125
|
+
# generate image
|
|
126
|
+
images = pipeline(prompt_embeds=conditioning.embeds, negative_prompt_embeds=conditioning.negative_embeds, num_inference_steps=20).images
|
|
127
|
+
images[0].save("image.jpg")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### SDXL:
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from diffusers import DiffusionPipeline
|
|
134
|
+
from compel import CompelForSDXL
|
|
135
|
+
import torch
|
|
136
|
+
|
|
137
|
+
device = 'cuda'
|
|
138
|
+
pipeline = DiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", variant="fp16",
|
|
139
|
+
use_safetensors=True, torch_dtype=torch.float16).to(device)
|
|
140
|
+
|
|
141
|
+
prompt = "a cat playing with a ball++ in the forest"
|
|
142
|
+
negative_prompt = "low quality, blurry"
|
|
143
|
+
compel = CompelForSDXL(pipeline)
|
|
144
|
+
conditioning = compel(prompt, negative_prompt=negative_prompt)
|
|
145
|
+
|
|
146
|
+
generator = torch.Generator().manual_seed(42)
|
|
147
|
+
image = pipeline(prompt_embeds=conditioning.embeds,
|
|
148
|
+
pooled_prompt_embeds=conditioning.pooled_embeds,
|
|
149
|
+
negative_prompt_embeds=conditioning.negative_embeds,
|
|
150
|
+
negative_pooled_prompt_embeds=conditioning.negative_pooled_embeds,
|
|
151
|
+
num_inference_steps=25, width=1024, height=1024, generator=generator).images[0]
|
|
152
|
+
image.save('sdxl_image.jpg')
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Flux
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
from diffusers import FluxPipeline
|
|
159
|
+
from compel import CompelForFlux
|
|
160
|
+
import torch
|
|
161
|
+
|
|
162
|
+
device = "mps"
|
|
163
|
+
pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", torch_dtype=torch.float32).to(device) # bfloat16 causes NaN on MPS
|
|
164
|
+
compel = CompelForFlux(pipe)
|
|
165
|
+
|
|
166
|
+
prompt = "Astronaut---- in a jungle++++, cold color palette, muted colors, detailed, 8k"
|
|
167
|
+
|
|
168
|
+
conditioning = compel(prompt)
|
|
169
|
+
generator = torch.Generator().manual_seed(42)
|
|
170
|
+
images = pipe(prompt_embeds=conditioning.embeds, pooled_prompt_embeds=conditioning.pooled_embeds,
|
|
171
|
+
num_inference_steps=4, width=512, height=512, generator=generator)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Style prompt
|
|
175
|
+
|
|
176
|
+
Works with SDXL or Flux:
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from diffusers import DiffusionPipeline
|
|
180
|
+
from compel import CompelForSDXL
|
|
181
|
+
import torch
|
|
182
|
+
|
|
183
|
+
device = 'cuda'
|
|
184
|
+
pipeline = DiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", variant="fp16",
|
|
185
|
+
use_safetensors=True, torch_dtype=torch.float16).to(device)
|
|
186
|
+
|
|
187
|
+
prompt = "a cat playing with a ball++ in the forest"
|
|
188
|
+
style_prompt = "painting by van gogh, impasto, thick brush strokes"
|
|
189
|
+
negative_prompt = "low quality, blurry"
|
|
190
|
+
negative_style_prompt = "photography"
|
|
191
|
+
compel = CompelForSDXL(pipeline) # or CompelForFlux
|
|
192
|
+
conditioning = compel(prompt=prompt, negative_prompt=negative_prompt,
|
|
193
|
+
style_prompt=style_prompt, negative_style_prompt=negative_style_prompt)
|
|
194
|
+
|
|
195
|
+
generator = torch.Generator().manual_seed(42)
|
|
196
|
+
image = pipeline(prompt_embeds=conditioning.embeds,
|
|
197
|
+
pooled_prompt_embeds=conditioning.pooled_embeds,
|
|
198
|
+
negative_prompt_embeds=conditioning.negative_embeds,
|
|
199
|
+
negative_pooled_prompt_embeds=conditioning.negative_pooled_embeds,
|
|
200
|
+
num_inference_steps=25, width=1024, height=1024, generator=generator).images[0]
|
|
201
|
+
image.save('sdxl_image.jpg')
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Textual Inversion support
|
|
205
|
+
|
|
206
|
+
If you want to have access to 🤗diffusers textual inversions, instantiate a `DiffusersTextualInversionManager` and pass it on Compel init:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from diffusers import StableDiffusionPipeline
|
|
210
|
+
from compel import CompelForSD, DiffusersTextualInversionManager
|
|
211
|
+
pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5")
|
|
212
|
+
textual_inversion_manager = DiffusersTextualInversionManager(pipeline)
|
|
213
|
+
compel = CompelForSD(pipe=pipeline, textual_inversion_manager=textual_inversion_manager)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Memory usage/VRAM leaks
|
|
217
|
+
|
|
218
|
+
If you run into memory issues, please make sure you're running compel inside `with torch.no_grad():` blocks.
|
|
219
|
+
|
|
220
|
+
If this doesn't help, you could try this advice offered by @kshieh1:
|
|
221
|
+
> After image generation, you should explictly de-reference the tensor object (i.e., prompt_embeds = None) and call gc.collect()
|
|
222
|
+
|
|
223
|
+
See https://github.com/damian0815/compel/issues/24 for more details. Thanks @kshieh1 !
|
|
224
|
+
|
|
225
|
+
## Local Checkpoint Smoke Tests
|
|
226
|
+
|
|
227
|
+
The default test suite uses tiny local diffusers components so it stays fast and CI-friendly.
|
|
228
|
+
|
|
229
|
+
If you want to validate real local SDXL `.safetensors` checkpoints with `StableDiffusionXLPipeline.from_single_file(...)`,
|
|
230
|
+
run:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
COMPEL_RUN_LOCAL_CHECKPOINT_TESTS=1 python -m unittest test.test_diffusers_smoke -v
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
This opt-in path only uses local files and does not pull remote model weights.
|
|
237
|
+
|
|
238
|
+
## Changelog
|
|
239
|
+
|
|
240
|
+
#### 2.3.1 - Fix for 78 tokens / 77 tokens issue with SDXL; add `device` arg to `CompelFor*` constructors (thanks @dx2-66)
|
|
241
|
+
|
|
242
|
+
Current main-branch validation also includes opt-in local SDXL `.safetensors` single-file smoke tests for
|
|
243
|
+
`StableDiffusionXLPipeline.from_single_file(...)`; see `COMPEL_RUN_LOCAL_CHECKPOINT_TESTS=1` above.
|
|
244
|
+
|
|
245
|
+
### 2.3.0 - Tokenization info, SplitLongTextMode CLS token handling, negative/style bugfixes
|
|
246
|
+
|
|
247
|
+
* `CompelFor*` objects now return tokenization info via `conditioning.tokenization_info` dict, which contains keys for `main_positive` and (where appropriate) `main_negative`, `style_positive` and `style_negative`.
|
|
248
|
+
* `SplitLongTextMode` enum has additional options for handling the CLS (EOS) token - either the CLS token can be copied from the first chunk to subsequent chunks, or all CLS tokens can be merged and the merge duplicated on all chunks. See `SplitLongTextMode` enum for details.
|
|
249
|
+
* Misc edge case fixes for handling different combinations of style prompts and negative prompts with SDXL/Flux
|
|
250
|
+
|
|
251
|
+
#### 2.2.1 - fix for #116
|
|
252
|
+
|
|
253
|
+
### 2.2.0 - Flux support, usability improvement
|
|
254
|
+
|
|
255
|
+
* Flux is now supported
|
|
256
|
+
* Added `CompelForSD`, `CompelForFlux` and `CompelForSDXL` to simplify and streamline embeds vs pooled_embeds, negative prompts, and style prompts handling. See compel-demo-*.py/.ipynb for usage examples.
|
|
257
|
+
* Performance improvements when working with non-weighted prompts. If a prompt is passed with no weighting, the weighting logic is completely bypassed. **This may slightly change the outputs when no weighting is applied** - revert to the old slower behaviour by calling `compel.disable_no_weights_bypass()`.
|
|
258
|
+
* When working with `CompelForSD` and `CompelForSDXL` classes, non-truncation is now the default.
|
|
259
|
+
|
|
260
|
+
#### 2.1.1 - expose `split_long_text_mode` to top-level Compel, default to `SENTENCES`, fix bug where splitting would fail sometimes.
|
|
261
|
+
|
|
262
|
+
### 2.1.0 - add `split_long_text_mode` arg to control word splitting for long prompts when `truncate_long_prompts` is False. See `SplitLongTextMode`. Defaults to `WORDS`.
|
|
263
|
+
|
|
264
|
+
#### 2.0.3 - include contributed fixes #64, #80 and fix license in pyproject.toml/pypi
|
|
265
|
+
|
|
266
|
+
#### 2.0.2 - fix for `pipeline.enable_sequential_cpu_offloading()` with SDXL models (you need to pass `device='cuda'` on compel init)
|
|
267
|
+
|
|
268
|
+
#### 2.0.1 - fix for [#45](https://github.com/damian0815/compel/issues/45) padding issue with SDXL non-truncated prompts and `.and()`
|
|
269
|
+
|
|
270
|
+
### 2.0.0 - SDXL Support
|
|
271
|
+
|
|
272
|
+
With big thanks to Patrick von Platen from Hugging Face for [the pull request](https://github.com/damian0815/compel/pull/41), Compel now supports SDXL. Use it like this:
|
|
273
|
+
|
|
274
|
+
```py
|
|
275
|
+
from compel import Compel, ReturnedEmbeddingsType
|
|
276
|
+
from diffusers import DiffusionPipeline
|
|
277
|
+
import torch
|
|
278
|
+
|
|
279
|
+
pipeline = DiffusionPipeline.from_pretrained("stabilityai/stable-diffusion-xl-base-1.0", variant="fp16", use_safetensors=True, torch_dtype=torch.float16).to("cuda")
|
|
280
|
+
compel = Compel(tokenizer=[pipeline.tokenizer, pipeline.tokenizer_2] , text_encoder=[pipeline.text_encoder, pipeline.text_encoder_2], returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED, requires_pooled=[False, True])
|
|
281
|
+
# upweight "ball"
|
|
282
|
+
prompt = "a cat playing with a ball++ in the forest"
|
|
283
|
+
conditioning, pooled = compel(prompt)
|
|
284
|
+
# generate image
|
|
285
|
+
image = pipeline(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, num_inference_steps=30).images[0]
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Please note that this is a **breaking change** if you've been using clip skip: the old boolean arg `use_penultimate_clip_layer` has been replaced with an enum `ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NORMALIZED`.
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
#### 1.2.1 - actually apply `.and()` weights
|
|
292
|
+
|
|
293
|
+
### 1.2.0 - Concatenate embeddings using `.and()`
|
|
294
|
+
|
|
295
|
+
For Stable Diffusion 2.1 I've been experimenting with a new feature: concatenated embeddings. What I noticed, for example, is that for more complex prompts image generation quality becomes wildly better when the prompt is broken into multiple parts and fed to OpenCLIP separately.
|
|
296
|
+
|
|
297
|
+
TL;DR: you can now experiment with breaking up your prompts into segments, which for SD2.1 appears to improve the generated image. The syntax is `("prompt part 1", "prompt part 2").and()`. You can have more than one part, and you can also weight them, eg `("a man eating an apple", "sitting on the roof of a car", "high quality, trending on artstation, 8K UHD").and(1, 0.5, 0.5)` which will assign weight `1` to `man eating an apple` and `0.5` to `sitting on the roof of a car` and `high quality, trending on artstation, 8K UHD`.
|
|
298
|
+
|
|
299
|
+
Here's a nonsense example from the InvokeAI discord #garbage-bin channel, created by gogurt enjoyer's incredible [nightmare prompt generator](https://huggingface.co/cactusfriend/nightmare-invokeai-prompts):
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
a moist sloppy pindlesackboy sloppy hamblin' bogomadong, Clem Fandango is pissed-off, Wario's Woods in background, making a noise like ga-woink-a
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Plugging this straight into SD2.1 we get this, which is really not a good image:
|
|
306
|
+

|
|
307
|
+
|
|
308
|
+
However, if the prompt is broken up into chunks and fed into OpenCLIP separately as four separate prompts, and then concatenated:
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
a moist sloppy pindlesackboy sloppy hamblin' bogomadong
|
|
312
|
+
|
|
313
|
+
Clem Fandango is pissed-off
|
|
314
|
+
|
|
315
|
+
Wario's Woods in background
|
|
316
|
+
|
|
317
|
+
making a noise like ga-woink-a
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
then output image with the same seed is *so much* better:
|
|
321
|
+

|
|
322
|
+
|
|
323
|
+
In the new `.and()` syntax you would prompt this as follows:
|
|
324
|
+
```
|
|
325
|
+
("a moist sloppy pindlesackboy sloppy hamblin' bogomadong", "Clem Fandango is pissed-off", "Wario's Woods in background", "making a noise like ga-woink-a").and()
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
The effect can be more or less subtle. Here for example is
|
|
329
|
+
```
|
|
330
|
+
A dream of a distant galaxy, by Caspar David Friedrich, matte painting, trending on artstation, HQ
|
|
331
|
+
```
|
|
332
|
+

|
|
333
|
+
|
|
334
|
+
And the same split into two parts:
|
|
335
|
+
```
|
|
336
|
+
A dream of a distant galaxy, by Caspar David Friedrich, matte painting
|
|
337
|
+
|
|
338
|
+
trending on artstation, HQ
|
|
339
|
+
```
|
|
340
|
+

|
|
341
|
+
|
|
342
|
+
The Compel prompt for this is:
|
|
343
|
+
```
|
|
344
|
+
("A dream of a distant galaxy, by Caspar David Friedrich, matte painting", "trending on artstation, HQ").and()
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
#### 1.1.6 - misc small fixes
|
|
351
|
+
- add `DiffusersTextualInversionManager` (thanks @pdoane)
|
|
352
|
+
- fix batch embedding generation with truncated/non-truncated prompt lengths (#18, thanks @abassino)
|
|
353
|
+
- add note about memory leakage (ref #24, thanks @kshieh1)
|
|
354
|
+
- fix incorrect parsing when commas are not followed by whitespace (#34, thanks @moono)
|
|
355
|
+
|
|
356
|
+
#### 1.1.5 - fix for compel turning numbers into floats for text inside parentheses
|
|
357
|
+
|
|
358
|
+
#### 1.1.4 - fixes for #23 (sequential offload) and InvokeAI issue #3442 (allow hyphens in LoRA names)
|
|
359
|
+
|
|
360
|
+
#### 1.1.3 - enable fetching the penultimate CLIP hidden layer (aka "clip skip")
|
|
361
|
+
|
|
362
|
+
To use, pass `use_penultimate_clip_layer=True` when initializing your `Compel` instance. Note that there's no need to pass this flag for SD2.0/SD2.1 because diffusers already throws away the last hidden layer when loading the SD2.0+ text encoder.
|
|
363
|
+
|
|
364
|
+
#### 1.1.2 - fix for #21 (crash when parsing long prompts with truncation enabled if there is weighted fragments beyond the truncation boundary)
|
|
365
|
+
|
|
366
|
+
#### 1.1.1 - fix for #22 (issues parsing `.` characters inside parentheses)
|
|
367
|
+
|
|
368
|
+
#### 1.1.0 - support for parsing `withLora`/`useLora` on `parse_prompt_string()`.
|
|
369
|
+
|
|
370
|
+
* `Compel.parse_prompt_string()` now returns a `Conjunction`
|
|
371
|
+
* any appearances of `withLora(name[, weight])` or `useLora(name[, weight])` anywhere in the prompt string will be parsed to `LoraWeight` instances, and returned on the outermost `Conjunction` returned by `parse_prompt_string()`.
|
|
372
|
+
|
|
373
|
+
#### 1.0.5 - fix incorrect parsing when passing invalid (auto1111) syntax that has a float
|
|
374
|
+
|
|
375
|
+
also fix test case for default swap parameters
|
|
376
|
+
|
|
377
|
+
#### 1.0.4 - fix embeddings for empty swap target (eg `cat.swap("")`) when truncation is disabled
|
|
378
|
+
|
|
379
|
+
#### 1.0.3 - better defaults for .swap (https://github.com/damian0815/compel/issues/8)
|
|
380
|
+
|
|
381
|
+
#### 1.0.2 - fix padding for non-truncated batched embeddings (https://github.com/damian0815/compel/issues/9)
|
|
382
|
+
|
|
383
|
+
#### 1.0.1 - fix for InvokeAI's `--free_gpu_mem` option
|
|
384
|
+
|
|
385
|
+
### 1.0.0 - new downweighting algorithm
|
|
386
|
+
|
|
387
|
+
Downweighting now works by applying an attention mask to remove the downweighted tokens, rather than literally removing them from the sequence. This behaviour is the default, but the old behaviour can be re-enabled by passing `downweight_mode=DownweightMode.REMOVE` on init of the `Compel` instance.
|
|
388
|
+
|
|
389
|
+
Formerly, downweighting a token worked by both multiplying the weighting of the token's embedding, and doing an inverse-weighted blend with a copy of the token sequence that had the downweighted tokens removed. The intuition is that as weight approaches zero, the tokens being downweighted should be actually removed from the sequence. However, removing the tokens resulted in the positioning of all downstream tokens becoming messed up. The blend ended up blending a lot more than just the tokens in question.
|
|
390
|
+
|
|
391
|
+
As of v1.0.0, taking advice from @keturn and @bonlime (https://github.com/damian0815/compel/issues/7) the procedure is by default different. Downweighting still involves a blend but what is blended is a version of the token sequence with the downweighted tokens masked out, rather than removed. This correctly preserves positioning embeddings of the other tokens.
|
|
392
|
+
|
|
393
|
+
Also a bugfix: fix black images on weight 0 (https://github.com/invoke-ai/InvokeAI/issues/2832)
|
|
394
|
+
|
|
395
|
+
### 0.1.10 - add support for prompts longer than the model's max token length.
|
|
396
|
+
|
|
397
|
+
To enable, initialize `Compel` with `truncate_long_prompts=False` (default is True). Prompts that are longer than the model's `max_token_length` will be chunked and padded out to an integer multiple of `max_token_length`.
|
|
398
|
+
|
|
399
|
+
Note that even if you don't use a negative prompt, you'll need to build a conditioning tensor for a negative prompt of at least `""`, and use `compel.pad_conditioning_tensors_to_same_length()`, otherwise the you'll get an error about mismatched conditioning tensor lengths:
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
compel = Compel(..., truncate_long_prompts=False)
|
|
403
|
+
prompt = "a cat playing with a ball++ in the forest, amazing, exquisite, stunning, masterpiece, skilled, powerful, incredible, amazing, trending on gregstation, greg, greggy, greggs greggson, greggy mcgregface, ..." # very long prompt
|
|
404
|
+
conditioning = compel.build_conditioning_tensor(prompt)
|
|
405
|
+
negative_prompt = "" # it's necessary to create an empty prompt - it can also be very long, if you want
|
|
406
|
+
negative_conditioning = compel.build_conditioning_tensor(negative_prompt)
|
|
407
|
+
[conditioning, negative_conditioning] = compel.pad_conditioning_tensors_to_same_length([conditioning, negative_conditioning])
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
#### 0.1.9 - broken
|
|
411
|
+
|
|
412
|
+
#### 0.1.8 - downgrade Python min version to 3.7
|
|
413
|
+
|
|
414
|
+
#### 0.1.7 - InvokeAI compatibility
|