invokeai/backend/model_manager/README.md
This document describes Invoke's model management system and common tasks for extending model support.
The model management system handles the full lifecycle of models: identification, loading, and running. The system is extensible and supports multiple model architectures, formats, and quantization schemes.
configs/): Determines model type, architecture, format, and metadata when users install models.load/): Loads models from disk into memory for inference.model_manager/. The inference code is run in nodes in the graph execution system.The taxonomy.py module defines the type system for models:
ModelType: The kind of model (e.g., Main, LoRA, ControlNet, VAE).ModelFormat: Storage format - may imply a quantization or some other quality (e.g., Diffusers, Checkpoint, LyCORIS, BnbQuantizednf4b).BaseModelType: Associated pipeline architecture (e.g., StableDiffusion1, StableDiffusionXL, Flux). Models without an associated base use Any (e.g., CLIPVision is its own thing).ModelVariantType, FluxVariantType, ClipVariantType: Architecture-specific variants.These enums form a discriminated union that uniquely identifies each model configuration class.
Model configs are Pydantic models that describe a model on disk. They include the model taxonomy, path, and any metadata needed for loading or running the model.
Model configs are stored in the database.
When a user installs a model, the system attempts to identify it by trying each registered config class until one matches.
Config Classes (configs/):
Config_Base, either directly or indirectly via some intermediary class (e.g., Diffusers_Config_Base, Checkpoint_Config_Base, or something narrower).type, format, base, and optional variant.from_model_on_disk(cls, mod: ModelOnDisk, override_fields: dict) -> Self. This method inspects the model on disk and raises NotAMatchError if the model doesn't match the config class, or returns an instance of the config class if it does.
ModelOnDisk is a helper class that abstracts the model weights. It should be the entrypoint for inspecting the model (e.g., loading state dicts).Identification Process:
ModelConfigFactory.from_model_on_disk() is called with a path to the model.from_model_on_disk() on each.Unknown_Config is returned as a fallback.Utilities (identification_utils.py):
NotAMatchError: Exception raised when a model doesn't match a config class.get_config_dict_or_raise(): Load JSON config files from diffusers/transformers models.raise_for_class_name(): Validate class names in config files.raise_for_override_fields(): Validate user-provided override fields against the config schema.state_dict_has_any_keys_*(): Helpers for inspecting state dict keys.Model loaders handle instantiating models from disk into memory.
Loader Classes (load/model_loaders/):
@ModelLoaderRegistry.register(base=..., type=..., format=...). The type, format and base indicate which configs classes the loader can handle._load_model(self, config: AnyModelConfig, submodel_type: Optional[SubModelType]) -> AnyModel.Model Cache (load/model_cache/):
This system typically does not require changes to support new model types, but it is important to understand how it works.
Loading Process:
base, type, and format attributes._load_model() method is called with the model config.ModelCache.put().ModelCache.get() and ModelCache.lock().Model running is architecture-specific and typically implemented in folders adjacent to model_manager/.
Inference code doesn't necessarily follow any specific pattern, and doesn't interact directly with the model management system except to receive model configs and loaded models.
At a high level, when a node needs to run a model, it will:
key).InvocationContext API to load the model. The request is dispatched to the model manager which will load the model and return the a model loader with a context manager that yields the in-memory model, mediating VRAM/RAM management as needed.When identification fails or produces incorrect results for a model that should be supported, you may need to refine the identification logic.
Steps:
tests/model_identification/README.md.configs/ (e.g., configs/lora.py for LoRA models).from_model_on_disk() method for some existing models to understand the patterns for identification logic.state_dict[key].shape).identification_utils.py.pytest tests/model_identification/test_identification.py.
uv pip install -e ".[dev,test]").Key Files:
configs/<model_type>.pyconfigs/identification_utils.pytaxonomy.pytests/model_identification/README.mdAdding a new model type requires implementing identification and loading logic. Inference and new nodes ("invocations") may be required if the model type doesn't fit into existing architectures or nodes.
Steps:
ModelType enum value in taxonomy.py if needed.BaseModelType (or use Any if not architecture-specific).ModelFormat if the model uses a unique storage format.You may need to add other attributes, depending on the model.
configs/ (e.g., configs/new_model.py).Config_Base and appropriate format base class:
Diffusers_Config_Base for diffusers-style models.Checkpoint_Config_Base for single-file checkpoint models.type, format, and base as Literal fields with defaults. Remember, these must uniquely identify the config class.from_model_on_disk():
NotAMatchError if the model doesn't match.configs/factory.py:
AnyModelConfig union.Annotated[YourConfig, YourConfig.get_tag()] entry.load/model_loaders/ (e.g., load/model_loaders/new_model.py).ModelLoader.@ModelLoaderRegistry.register(base=..., type=..., format=...)._load_model():
config.path.submodel_type if the model has submodels (e.g., text encoders, VAE).Follow the instructions in tests/model_identification/README.md.
BaseInvocation for many examples.Typically, you will not need to do anything for the model to work in the Workflow Editor. When you define the node's model field, you can provide constraints for what type of models are selectable. The UI will automatically filter the list of models based on the model taxonomy.
For example, this field definition in a node will allow users to select only "main" (pipeline) Stable Diffusion 1.x or 2.x models:
model: ModelIdentifierField = InputField(
ui_model_base=[BaseModelType.StableDiffusion1, BaseModelType.StableDiffusion2],
ui_model_type=ModelType.Main,
)
This same pattern works for any combination of type, base, format, and variant.
The Canvas and Generate tabs use graphs internally, but they don't expose the full graph editor UI. Instead, they provide a simplified interface for common tasks.
They use "graph builder" functions, which take the user's selected settings and build a graph behind the scenes. We have one graph builder for each model architecture.
Updating or adding a graph builder can be a bit complex, and you'd likely need to update other UI components and state management to support the new model type.
The SDXL graph builder is a good example: invokeai/frontend/web/src/features/nodes/util/graph/generation/buildSDXLGraph.ts