@@ -128,6 +128,15 @@ def to_dict(self) -> Dict[str, Any]:
128128 """
129129 return {** self .__dict__ }
130130
131+ def __getattr__ (self , name ):
132+ """
133+ Allow attribute access to intermediate values. If an attribute is not found in the object, look for it in the
134+ intermediates dict.
135+ """
136+ if name in self .intermediates :
137+ return self .intermediates [name ]
138+ raise AttributeError (f"'{ self .__class__ .__name__ } ' object has no attribute '{ name } '" )
139+
131140 def __repr__ (self ):
132141 def format_value (v ):
133142 if hasattr (v , "shape" ) and hasattr (v , "dtype" ):
@@ -638,7 +647,7 @@ def __call__(self, pipeline, state: PipelineState) -> PipelineState:
638647 break
639648
640649 if block is None :
641- logger .warning (f"skipping auto block: { self .__class__ .__name__ } " )
650+ logger .info (f"skipping auto block: { self .__class__ .__name__ } " )
642651 return pipeline , state
643652
644653 try :
@@ -1450,9 +1459,10 @@ def __init__(
14501459 Args:
14511460 blocks: `ModularPipelineBlocks` instance. If None, will attempt to load
14521461 default blocks based on the pipeline class name.
1453- pretrained_model_name_or_path: Path to a pretrained pipeline configuration. If provided,
1454- will load component specs (only for from_pretrained components) and config values from the saved
1455- modular_model_index.json file.
1462+ pretrained_model_name_or_path: Path to a pretrained pipeline configuration. Can be None if the pipeline
1463+ does not require any additional loading config. If provided, will first try to load component specs
1464+ (only for from_pretrained components) and config values from `modular_model_index.json`, then
1465+ fallback to `model_index.json` for compatibility with standard non-modular repositories.
14561466 components_manager:
14571467 Optional ComponentsManager for managing multiple component cross different pipelines and apply
14581468 offloading strategies.
@@ -1501,18 +1511,70 @@ def __init__(
15011511
15021512 # update component_specs and config_specs from modular_repo
15031513 if pretrained_model_name_or_path is not None :
1504- config_dict = self .load_config (pretrained_model_name_or_path , ** kwargs )
1505-
1506- for name , value in config_dict .items ():
1507- # all the components in modular_model_index.json are from_pretrained components
1508- if name in self ._component_specs and isinstance (value , (tuple , list )) and len (value ) == 3 :
1509- library , class_name , component_spec_dict = value
1510- component_spec = self ._dict_to_component_spec (name , component_spec_dict )
1511- component_spec .default_creation_method = "from_pretrained"
1512- self ._component_specs [name ] = component_spec
1514+ cache_dir = kwargs .pop ("cache_dir" , None )
1515+ force_download = kwargs .pop ("force_download" , False )
1516+ proxies = kwargs .pop ("proxies" , None )
1517+ token = kwargs .pop ("token" , None )
1518+ local_files_only = kwargs .pop ("local_files_only" , False )
1519+ revision = kwargs .pop ("revision" , None )
1520+
1521+ load_config_kwargs = {
1522+ "cache_dir" : cache_dir ,
1523+ "force_download" : force_download ,
1524+ "proxies" : proxies ,
1525+ "token" : token ,
1526+ "local_files_only" : local_files_only ,
1527+ "revision" : revision ,
1528+ }
1529+ # try to load modular_model_index.json
1530+ try :
1531+ config_dict = self .load_config (pretrained_model_name_or_path , ** load_config_kwargs )
1532+ except EnvironmentError as e :
1533+ logger .debug (f"modular_model_index.json not found: { e } " )
1534+ config_dict = None
1535+
1536+ # update component_specs and config_specs based on modular_model_index.json
1537+ if config_dict is not None :
1538+ for name , value in config_dict .items ():
1539+ # all the components in modular_model_index.json are from_pretrained components
1540+ if name in self ._component_specs and isinstance (value , (tuple , list )) and len (value ) == 3 :
1541+ library , class_name , component_spec_dict = value
1542+ component_spec = self ._dict_to_component_spec (name , component_spec_dict )
1543+ component_spec .default_creation_method = "from_pretrained"
1544+ self ._component_specs [name ] = component_spec
1545+
1546+ elif name in self ._config_specs :
1547+ self ._config_specs [name ].default = value
1548+
1549+ # if modular_model_index.json is not found, try to load model_index.json
1550+ else :
1551+ logger .debug (" loading config from model_index.json" )
1552+ try :
1553+ from diffusers import DiffusionPipeline
1554+
1555+ config_dict = DiffusionPipeline .load_config (pretrained_model_name_or_path , ** load_config_kwargs )
1556+ except EnvironmentError as e :
1557+ logger .debug (f" model_index.json not found in the repo: { e } " )
1558+ config_dict = None
1559+
1560+ # update component_specs and config_specs based on model_index.json
1561+ if config_dict is not None :
1562+ for name , value in config_dict .items ():
1563+ if name in self ._component_specs and isinstance (value , (tuple , list )) and len (value ) == 2 :
1564+ library , class_name = value
1565+ component_spec_dict = {
1566+ "repo" : pretrained_model_name_or_path ,
1567+ "subfolder" : name ,
1568+ "type_hint" : (library , class_name ),
1569+ }
1570+ component_spec = self ._dict_to_component_spec (name , component_spec_dict )
1571+ component_spec .default_creation_method = "from_pretrained"
1572+ self ._component_specs [name ] = component_spec
1573+ elif name in self ._config_specs :
1574+ self ._config_specs [name ].default = value
15131575
1514- elif name in self . _config_specs :
1515- self . _config_specs [ name ]. default = value
1576+ if len ( kwargs ) > 0 :
1577+ logger . warning ( f"Unexpected input ' { kwargs . keys () } ' provided. This input will be ignored." )
15161578
15171579 register_components_dict = {}
15181580 for name , component_spec in self ._component_specs .items ():
@@ -1570,8 +1632,10 @@ def from_pretrained(
15701632
15711633 Args:
15721634 pretrained_model_name_or_path (`str` or `os.PathLike`, optional):
1573- Path to a pretrained pipeline configuration. If provided, will load component specs (only for
1574- from_pretrained components) and config values from the modular_model_index.json file.
1635+ Path to a pretrained pipeline configuration. It will first try to load config from
1636+ `modular_model_index.json`, then fallback to `model_index.json` for compatibility with standard
1637+ non-modular repositories. If the repo does not contain any pipeline config, it will be set to None
1638+ during initialization.
15751639 trust_remote_code (`bool`, optional):
15761640 Whether to trust remote code when loading the pipeline, need to be set to True if you want to create
15771641 pipeline blocks based on the custom code in `pretrained_model_name_or_path`
@@ -1607,11 +1671,35 @@ def from_pretrained(
16071671 }
16081672
16091673 try :
1674+ # try to load modular_model_index.json
16101675 config_dict = cls .load_config (pretrained_model_name_or_path , ** load_config_kwargs )
1676+ except EnvironmentError as e :
1677+ logger .debug (f" modular_model_index.json not found in the repo: { e } " )
1678+ config_dict = None
1679+
1680+ if config_dict is not None :
16111681 pipeline_class = _get_pipeline_class (cls , config = config_dict )
1612- except EnvironmentError :
1613- pipeline_class = cls
1614- pretrained_model_name_or_path = None
1682+ else :
1683+ try :
1684+ logger .debug (" try to load model_index.json" )
1685+ from diffusers import DiffusionPipeline
1686+ from diffusers .pipelines .auto_pipeline import _get_model
1687+
1688+ config_dict = DiffusionPipeline .load_config (pretrained_model_name_or_path , ** load_config_kwargs )
1689+ except EnvironmentError as e :
1690+ logger .debug (f" model_index.json not found in the repo: { e } " )
1691+
1692+ if config_dict is not None :
1693+ logger .debug (" try to determine the modular pipeline class from model_index.json" )
1694+ standard_pipeline_class = _get_pipeline_class (cls , config = config_dict )
1695+ model_name = _get_model (standard_pipeline_class .__name__ )
1696+ pipeline_class_name = MODULAR_PIPELINE_MAPPING .get (model_name , ModularPipeline .__name__ )
1697+ diffusers_module = importlib .import_module ("diffusers" )
1698+ pipeline_class = getattr (diffusers_module , pipeline_class_name )
1699+ else :
1700+ # there is no config for modular pipeline, assuming that the pipeline block does not need any from_pretrained components
1701+ pipeline_class = cls
1702+ pretrained_model_name_or_path = None
16151703
16161704 pipeline = pipeline_class (
16171705 blocks = blocks ,
@@ -1949,17 +2037,31 @@ def update_components(self, **kwargs):
19492037 for name , component in passed_components .items ():
19502038 current_component_spec = self ._component_specs [name ]
19512039
1952- # warn if type changed
2040+ # log if type changed
19532041 if current_component_spec .type_hint is not None and not isinstance (
19542042 component , current_component_spec .type_hint
19552043 ):
1956- logger .warning (
2044+ logger .info (
19572045 f"ModularPipeline.update_components: adding { name } with new type: { component .__class__ .__name__ } , previous type: { current_component_spec .type_hint .__name__ } "
19582046 )
19592047 # update _component_specs based on the new component
1960- new_component_spec = ComponentSpec .from_component (name , component )
1961- if new_component_spec .default_creation_method != current_component_spec .default_creation_method :
2048+ if component is None :
2049+ new_component_spec = current_component_spec
2050+ if hasattr (self , name ) and getattr (self , name ) is not None :
2051+ logger .warning (f"ModularPipeline.update_components: setting { name } to None (spec unchanged)" )
2052+ elif current_component_spec .default_creation_method == "from_pretrained" and not (
2053+ hasattr (component , "_diffusers_load_id" ) and component ._diffusers_load_id is not None
2054+ ):
19622055 logger .warning (
2056+ f"ModularPipeline.update_components: { name } has no valid _diffusers_load_id. "
2057+ f"This will result in empty loading spec, use ComponentSpec.load() for proper specs"
2058+ )
2059+ new_component_spec = ComponentSpec (name = name , type_hint = type (component ))
2060+ else :
2061+ new_component_spec = ComponentSpec .from_component (name , component )
2062+
2063+ if new_component_spec .default_creation_method != current_component_spec .default_creation_method :
2064+ logger .info (
19632065 f"ModularPipeline.update_components: changing the default_creation_method of { name } from { current_component_spec .default_creation_method } to { new_component_spec .default_creation_method } ."
19642066 )
19652067
@@ -1980,7 +2082,7 @@ def update_components(self, **kwargs):
19802082 if current_component_spec .type_hint is not None and not isinstance (
19812083 created_components [name ], current_component_spec .type_hint
19822084 ):
1983- logger .warning (
2085+ logger .info (
19842086 f"ModularPipeline.update_components: adding { name } with new type: { created_components [name ].__class__ .__name__ } , previous type: { current_component_spec .type_hint .__name__ } "
19852087 )
19862088 # update _component_specs based on the user passed component_spec
0 commit comments