* feat(config): add model artifact source contract Assisted-by: Codex:GPT-5 [Codex] * feat(downloader): add authenticated raw-byte progress Assisted-by: Codex:GPT-5 [Codex] * feat(huggingface): resolve immutable snapshot manifests Assisted-by: Codex:GPT-5 [Codex] * feat(models): add artifact storage primitives Assisted-by: Codex:GPT-5 [Codex] * feat(models): materialize pinned Hugging Face snapshots Assisted-by: Codex:GPT-5 [Codex] * feat(models): bind managed snapshots at runtime Assisted-by: Codex:GPT-5 [Codex] * feat(gallery): materialize model artifacts during install Assisted-by: Codex:GPT-5 [Codex] * feat(gallery): declare managed Hugging Face artifacts Assisted-by: Codex:GPT-5 [Codex] * feat(models): preload managed model artifacts Assisted-by: Codex:GPT-5 [Codex] * fix(gallery): retain shared artifact caches on delete Assisted-by: Codex:GPT-5 [Codex] * feat(models): report artifact acquisition progress Assisted-by: Codex:GPT-5 [Codex] * refactor(backends): load managed models from ModelFile Assisted-by: Codex:GPT-5 [Codex] * refactor(backends): load staged speech model snapshots Assisted-by: Codex:GPT-5 [Codex] * refactor(backends): use staged snapshots in engine backends Assisted-by: Codex:GPT-5 [Codex] * test(distributed): cover staged artifact snapshots Assisted-by: Codex:GPT-5 [Codex] * docs: explain managed model artifacts Assisted-by: Codex:GPT-5 [Codex] * docs: add product design context Assisted-by: Codex:GPT-5 [Codex] * feat(ui): show model artifact download progress Assisted-by: Codex:GPT-5 [Codex] * Eagerly materialize Hugging Face artifacts Materialize HF-backed model references as managed GGUF artifacts during load, with lazy download retained only as fallback. Assisted-by: Codex:GPT-5 [shell] * Refactor HF downloads through a shared executor Assisted-by: Codex:GPT-5 [shell] * drop Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-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)