compel 2.3.1 (latest, Nov 2025) declares transformers~=4.25 in its
metadata, i.e. >=4.25,<5.0. After transformers 5.0 (2026-01-26) and
huggingface-hub 1.0 (2025-10-27) shipped, the weekly DEPS_REFRESH
cache rotation in CI started seeing the new majors and pip's resolver
went into multi-hour backtracking storms walking every transformers
4.x candidate against every accelerate/hf-hub/tokenizers combination
to find a set compel would accept. The 2026-04-29 backend-build for
the diffusers backend (darwin-mps + l4t + cublas13-turboquant matrix
cells) hit the GitHub Actions 6h job timeout still inside pip
install — the build itself never started.
compel is the only hard upper bound on transformers in this stack
(diffusers, accelerate, peft, optimum-quanto are all flexible), and
upstream support for transformers 5 is still in flight: damian0815/
compel#129 ("Modernize Compel for Transformers 5") and #128 ("Bump
transformers version to >5.0") are both open as of today.
backend.py only constructs Compel() when COMPEL=1 is set in the env
(default off), so make compel a true optional extra:
- Wrap the top-level `from compel import ...` in try/except
ImportError, mirroring the existing sd_embed pattern.
- Auto-disable COMPEL with a warning when the module isn't
installed, instead of crashing on module load.
- Drop compel from all eight requirements-*.txt variants so the
resolver no longer has to satisfy its transformers cap.
- Leave a TODO in backend.py and in each requirements file
pointing at the upstream PR/issue, so the dependency can be
reinstated once compel supports transformers >= 5.
Users who rely on weighted-prompt embeddings can opt in with a
manual `pip install compel` alongside COMPEL=1; the warning emitted
on startup tells them how.
Assisted-by: Claude:claude-opus-4-7 [Bash Read Edit WebFetch]
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
LocalAI Diffusers Backend
This backend provides gRPC access to Hugging Face diffusers pipelines with dynamic pipeline loading.
Creating a separate environment for the diffusers project
make diffusers
Dynamic Pipeline Loader
The diffusers backend includes a dynamic pipeline loader (diffusers_dynamic_loader.py) that automatically discovers and loads diffusers pipelines at runtime. This eliminates the need for per-pipeline conditional statements - new pipelines added to diffusers become available automatically without code changes.
How It Works
-
Pipeline Discovery: On first use, the loader scans the
diffuserspackage to find all classes that inherit fromDiffusionPipeline. -
Registry Caching: Discovery results are cached for the lifetime of the process to avoid repeated scanning.
-
Task Aliases: The loader automatically derives task aliases from class names (e.g., "text-to-image", "image-to-image", "inpainting") without hardcoding.
-
Multiple Resolution Methods: Pipelines can be resolved by:
- Exact class name (e.g.,
StableDiffusionPipeline) - Task alias (e.g.,
text-to-image,img2img) - Model ID (uses HuggingFace Hub to infer pipeline type)
- Exact class name (e.g.,
Usage Examples
from diffusers_dynamic_loader import (
load_diffusers_pipeline,
get_available_pipelines,
get_available_tasks,
resolve_pipeline_class,
discover_diffusers_classes,
get_available_classes,
)
# List all available pipelines
pipelines = get_available_pipelines()
print(f"Available pipelines: {pipelines[:10]}...")
# List all task aliases
tasks = get_available_tasks()
print(f"Available tasks: {tasks}")
# Resolve a pipeline class by name
cls = resolve_pipeline_class(class_name="StableDiffusionPipeline")
# Resolve by task alias
cls = resolve_pipeline_class(task="stable-diffusion")
# Load and instantiate a pipeline
pipe = load_diffusers_pipeline(
class_name="StableDiffusionPipeline",
model_id="runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16
)
# Load from single file
pipe = load_diffusers_pipeline(
class_name="StableDiffusionPipeline",
model_id="/path/to/model.safetensors",
from_single_file=True,
torch_dtype=torch.float16
)
# Discover other diffusers classes (schedulers, models, etc.)
schedulers = discover_diffusers_classes("SchedulerMixin")
print(f"Available schedulers: {list(schedulers.keys())[:5]}...")
# Get list of available scheduler classes
scheduler_list = get_available_classes("SchedulerMixin")
Generic Class Discovery
The dynamic loader can discover not just pipelines but any class type from diffusers:
# Discover all scheduler classes
schedulers = discover_diffusers_classes("SchedulerMixin")
# Discover all model classes
models = discover_diffusers_classes("ModelMixin")
# Get a sorted list of available classes
scheduler_names = get_available_classes("SchedulerMixin")
Special Pipeline Handling
Most pipelines are loaded dynamically through load_diffusers_pipeline(). Only pipelines requiring truly custom initialization logic are handled explicitly:
FluxTransformer2DModel: Requires quantization and custom transformer loading (cannot use dynamic loader)WanPipeline/WanImageToVideoPipeline: Uses dynamic loader with special VAE (float32 dtype)SanaPipeline: Uses dynamic loader with post-load dtype conversion for VAE/text encoderStableVideoDiffusionPipeline: Uses dynamic loader with CPU offload handlingVideoDiffusionPipeline: Alias for DiffusionPipeline with video flags
All other pipelines (StableDiffusionPipeline, StableDiffusionXLPipeline, FluxPipeline, etc.) are loaded purely through the dynamic loader.
Error Handling
When a pipeline cannot be resolved, the loader provides helpful error messages listing available pipelines and tasks:
ValueError: Unknown pipeline class 'NonExistentPipeline'.
Available pipelines: AnimateDiffPipeline, AnimateDiffVideoToVideoPipeline, ...
Environment Variables
| Variable | Default | Description |
|---|---|---|
COMPEL |
0 |
Enable Compel for prompt weighting |
SD_EMBED |
0 |
Enable sd_embed for prompt weighting |
XPU |
0 |
Enable Intel XPU support |
CLIPSKIP |
1 |
Enable CLIP skip support |
SAFETENSORS |
1 |
Use safetensors format |
CHUNK_SIZE |
8 |
Decode chunk size for video |
FPS |
7 |
Video frames per second |
DISABLE_CPU_OFFLOAD |
0 |
Disable CPU offload |
FRAMES |
64 |
Number of video frames |
BFL_REPO |
ChuckMcSneed/FLUX.1-dev |
Flux base repo |
PYTHON_GRPC_MAX_WORKERS |
1 |
Max gRPC workers |
Running Tests
./test.sh
The test suite includes:
- Unit tests for the dynamic loader (
test_dynamic_loader.py) - Integration tests for the gRPC backend (
test.py)