o
    ۷i                    @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlm	Z	 d dl
mZmZ d dlmZ d dlZd dlmZ d dlmZ d dlmZ d d	lmZ d
dlmZmZ d
dlmZmZmZmZ d
dl m!Z!m"Z"m#Z# d
dl$m%Z%m&Z& d
dl'm(Z(m)Z) d
dl*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z< e" rd dl=Z=e#>e?Z@deAfddZBdBddZCdBddZDdBddZEedeBdfdeDfd eEfd!eBd"fd#eBd$fd%eBd&fd'eCfd(eBd)fd*eBd+fd,eBd-fd.eBd/fd0eBd1fgZFeG d2d3 d3ZGeG d4d5 d5ZHG d6d7 d7ee!ZIG d8d9 d9eIZJG d:d; d;eJZKG d<d= d=eIZLG d>d? d?eIZMG d@dA dAee!ZNdS )C    N)OrderedDict)deepcopy)	dataclassfield)Any)create_repo)validate_hf_hub_args)tqdm)Self   )ConfigMixin
FrozenDict)LOADABLE_CLASSES_fetch_class_library_tuple_unwrap_modelsimple_get_class_obj)PushToHubMixinis_accelerate_availablelogging)get_class_from_dynamic_moduleresolve_trust_remote_code)load_or_create_model_cardpopulate_model_card)is_compiled_module   )ComponentsManager)MODULAR_MODEL_CARD_TEMPLATEComponentSpec
ConfigSpec
InputParamInsertableDictOutputParam_validate_requirementscombine_inputscombine_outputsformat_componentsformat_configsformat_workflow#generate_modular_model_card_contentmake_doc_stringpipeline_class_namec                    s   d fdd	}|S )zFCreate a mapping function that always returns the same pipeline class.Nc                    s    S N config_dictr*   r,   b/home/ubuntu/vllm_env/lib/python3.10/site-packages/diffusers/modular_pipelines/modular_pipeline.py_map_fnI   s   z'_create_default_map_fn.<locals>._map_fnr+   r,   )r*   r1   r,   r/   r0   _create_default_map_fnF   s   r2   c                 C   s$   | d u rdS d| v r| d rdS dS )NFlux2KleinModularPipelineis_distilledFlux2KleinBaseModularPipeliner,   r-   r,   r,   r0   _flux2_klein_map_fnO   s
   r6   c                 C   (   | d u rdS d| v r| d d urdS dS )NWanModularPipelineboundary_ratioWan22ModularPipeliner,   r-   r,   r,   r0   _wan_map_fnY   
   r;   c                 C   r7   )NWanImage2VideoModularPipeliner9   Wan22Image2VideoModularPipeliner,   r-   r,   r,   r0   _wan_i2v_map_fnc   r<   r?   zstable-diffusion-xl StableDiffusionXLModularPipelinewanzwan-i2vfluxFluxModularPipelinezflux-kontextFluxKontextModularPipelineflux2Flux2ModularPipelinezflux2-klein	qwenimageQwenImageModularPipelinezqwenimage-editQwenImageEditModularPipelinezqwenimage-edit-plus QwenImageEditPlusModularPipelinezqwenimage-layeredQwenImageLayeredModularPipelinezz-imageZImageModularPipelinec                
   @   s   e Zd ZU dZeedZeeef e	d< eedZ
eeee f e	d< ddededefd	d
Zddeee B dedeeeef B fddZdedeeef fddZdeeef fddZdd Zdd ZdS )PipelineStatezl
    [`PipelineState`] stores the state of a pipeline. It is used to pass data between pipeline blocks.
    )default_factoryvalueskwargs_mappingNkeyvaluekwargs_typec                 C   sD   || j |< |dur || jvr|g| j|< dS | j| | dS dS )z
        Add a value to the pipeline state.

        Args:
            key (str): The key for the value
            value (Any): The value to store
            kwargs_type (str): The kwargs_type with which the value is associated
        N)rO   rP   append)selfrQ   rR   rS   r,   r,   r0   set   s   
	
zPipelineState.setkeysdefaultreturnc                    s,   t |trj| S  fdd|D S )aU  
        Get one or multiple values from the pipeline state.

        Args:
            keys (str | list[str]): Key or list of keys for the values
            default (Any): The default value to return if not found

        Returns:
            Any | dict[str, Any]: Single value if keys is str, dictionary of values if keys is list
        c                    s   i | ]
}|j | qS r,   )rO   get).0rQ   rX   rU   r,   r0   
<dictcomp>       z%PipelineState.get.<locals>.<dictcomp>)
isinstancestrrO   rZ   )rU   rW   rX   r,   r\   r0   rZ      s   
zPipelineState.getc                 C   s   | j |g }| |S )z
        Get all values with matching kwargs_type.

        Args:
            kwargs_type (str): The kwargs_type to filter by

        Returns:
            dict[str, Any]: Dictionary of values with matching kwargs_type
        )rP   rZ   )rU   rS   value_namesr,   r,   r0   get_by_kwargs   s   

zPipelineState.get_by_kwargsc                 C   s
   i | j S )z8
        Convert PipelineState to a dictionary.
        )__dict__rU   r,   r,   r0   to_dict   s   
zPipelineState.to_dictc              	   C   sd   zt | d}W n ty   td| jj d| dw ||v r%|| S td| jj d| d)z
        Allow attribute access to intermediate values. If an attribute is not found in the object, look for it in the
        intermediates dict.
        rO   'z' object has no attribute ')object__getattribute__AttributeError	__class____name__)rU   namerO   r,   r,   r0   __getattr__   s   zPipelineState.__getattr__c                    sR   dd  d  fdd| j D }d dd | j D }d| d| d	S )
Nc                 S   s   t | drt | drd| j d| j dS t| tr=t| dkr=t | d dr=t | d dr=d| d j d| d j dS t| S )	NshapedtypeTensor(dtype=, shape=)r   z[Tensor(dtype=z), ...])hasattrro   rn   r_   listlenrepr)vr,   r,   r0   format_value   s
   2z,PipelineState.__repr__.<locals>.format_value
c                 3   (    | ]\}}d | d | V  qdS z    z: Nr,   r[   krw   rx   r,   r0   	<genexpr>      & z)PipelineState.__repr__.<locals>.<genexpr>c                 s   s$    | ]\}}d | d| V  qdS r{   r,   r|   r,   r,   r0   r      s   " zPipelineState(
  values={
z
  },
  kwargs_mapping={
z
  }
))joinrO   itemsrP   )rU   
values_strkwargs_mapping_strr,   r~   r0   __repr__   s   zPipelineState.__repr__r+   )rk   
__module____qualname____doc__r   dictrO   r`   r   __annotations__rP   rt   rV   rZ   rb   re   rm   r   r,   r,   r,   r0   rM      s   
 ,rM   c                   @   sH   e Zd ZdZdd ZdefddZdedefdd	Zd
d Z	dd Z
dS )
BlockStatez\
    Container for block state data with attribute access and formatted representation.
    c                 K   s"   |  D ]
\}}t| || qd S r+   )r   setattr)rU   kwargsrQ   rR   r,   r,   r0   __init__   s   zBlockState.__init__rQ   c                 C   s   t | |d S r+   getattr)rU   rQ   r,   r,   r0   __getitem__   s   zBlockState.__getitem__rR   c                 C   s   t | || d S r+   )r   )rU   rQ   rR   r,   r,   r0   __setitem__      zBlockState.__setitem__c                 C      t | j S )z
        Convert BlockState to a dictionary.

        Returns:
            dict[str, Any]: Dictionary containing all attributes of the BlockState
        )r   rc   r   rd   r,   r,   r0   as_dict   s   zBlockState.as_dictc                    s2   dd  d  fdd| j D }d| dS )Nc                 S   s  t | drt | drd| j d| j dS t| trCt| dkr?t | d dr?t | d dr?dd | D }d	t|  d
| S t| S t| trqt| dkrmt | d drmt | d drmdd | D }dt|  d
| S t| S t| tri }| 	 D ]O\}}t |drt |drd|j d|j d||< q|t|trt|dkrt |d drt |d drdd |D }d	t| d
| ||< q|t|||< q||S t| S )Nrn   ro   rp   rq   rr   r   c                 S      g | ]}|j qS r,   rn   r[   tr,   r,   r0   
<listcomp>       z=BlockState.__repr__.<locals>.format_value.<locals>.<listcomp>zlist[z] of Tensors with shapes c                 S   r   r,   r   r   r,   r,   r0   r     r   ztuple[zTensor(shape=z, dtype=c                 S   r   r,   r   r   r,   r,   r0   r     r   )
rs   ro   rn   r_   rt   ru   rv   tupler   r   )rw   shapesformatted_dictr}   valr,   r,   r0   rx      s:   
(
(
z)BlockState.__repr__.<locals>.format_valuery   c                 3   rz   r{   r,   r|   r~   r,   r0   r     r   z&BlockState.__repr__.<locals>.<genexpr>zBlockState(
z
))r   rc   r   )rU   
attributesr,   r~   r0   r      s   (zBlockState.__repr__N)rk   r   r   r   r   r`   r   r   r   r   r   r,   r,   r,   r0   r      s    	r   c                	   @   s  e Zd ZU dZdZdZdZeeef dB e	d< dZ
edd Zdd Zed	efd
dZed	ee fddZed	ee fddZed	ee fddZdd Zed	ee fddZed	ee fddZdd Zed	ee fddZdd Zedd Zd efd!d"Ze	#d?d$ed%e fd&d'Z!d?d(d)Z"			d@d$ee#j$B dB d*e%dB d+edB d	d,fd-d.Z&d/e'd	efd0d1Z(d/e'd2e)fd3d4Z*ed	ee fd5d6Z+ed	ee fd7d8Z,ed	ee fd9d:Z-ed	ee fd;d<Z.ed=d> Z/dS )AModularPipelineBlocksaU  
    Base class for all Pipeline Blocks: ConditionalPipelineBlocks, AutoPipelineBlocks, SequentialPipelineBlocks,
    LoopSequentialPipelineBlocks

    [`ModularPipelineBlocks`] provides method to load and save the definition of pipeline blocks.

    > [!WARNING] > This is an experimental feature and is likely to change in the future.
    zmodular_config.jsonN_requirementsc                 C   sP   t |jj}dd | D }tdd | D }t| dh }||fS )Nc                 S   s"   i | ]\}}|j tjkr||qS r,   rX   inspect_emptyr|   r,   r,   r0   r]   3     " z=ModularPipelineBlocks._get_signature_keys.<locals>.<dictcomp>c                 S   s    h | ]\}}|j tjkr|qS r,   r   r|   r,   r,   r0   	<setcomp>4       z<ModularPipelineBlocks._get_signature_keys.<locals>.<setcomp>rU   )r   	signaturer   
parametersr   rV   rW   )clsobjr   required_parametersoptional_parametersexpected_modulesr,   r,   r0   _get_signature_keys0  s
   z)ModularPipelineBlocks._get_signature_keysc                 C   s   t  | _d S r+   )r    
sub_blocksrd   r,   r,   r0   r   9  s   zModularPipelineBlocks.__init__rY   c                 C      dS )<Description of the block. Must be implemented by subclasses. r,   rd   r,   r,   r0   description<     z!ModularPipelineBlocks.descriptionc                 C      g S r+   r,   rd   r,   r,   r0   expected_componentsA     z)ModularPipelineBlocks.expected_componentsc                 C   r   r+   r,   rd   r,   r,   r0   expected_configsE  r   z&ModularPipelineBlocks.expected_configsc                 C   r   z<list of input parameters. Must be implemented by subclasses.r,   rd   r,   r,   r0   inputsI  r   zModularPipelineBlocks.inputsc                 C   &   g }| j D ]}|jr||j q|S r+   )r   requiredrT   rl   rU   input_namesinput_paramr,   r,   r0   _get_required_inputsN  s   
z*ModularPipelineBlocks._get_required_inputsc                 C      |   S r+   )r   rd   r,   r,   r0   required_inputsV     z%ModularPipelineBlocks.required_inputsc                 C   r   zJlist of intermediate output parameters. Must be implemented by subclasses.r,   rd   r,   r,   r0   intermediate_outputsZ  r   z*ModularPipelineBlocks.intermediate_outputsc                 C      | j S r+   r   rd   r,   r,   r0   _get_outputs_  s   z"ModularPipelineBlocks._get_outputsc                 C   r   r+   )r   rd   r,   r,   r0   outputsb  r   zModularPipelineBlocks.outputsc                 K      t d| jj )a  
        Get the block(s) that would execute given the inputs. Must be implemented by subclasses that support
        conditional block selection.

        Args:
            **kwargs: Input names and values. Only trigger inputs affect block selection.
        z.`get_execution_blocks` is not implemented for NotImplementedErrorrj   rk   rU   r   r,   r,   r0   get_execution_blocksg     z*ModularPipelineBlocks.get_execution_blocksc                 C   r   )z|
        Returns a list of available workflow names. Must be implemented by subclasses that define `_workflow_map`.
        z-`available_workflows` is not implemented for r   rd   r,   r,   r0   available_workflowsr  s   z)ModularPipelineBlocks.available_workflowsworkflow_namec                 C   r   )z
        Get the execution blocks for a specific workflow. Must be implemented by subclasses that define
        `_workflow_map`.

        Args:
            workflow_name: Name of the workflow to retrieve.
        z&`get_workflow` is not implemented for r   )rU   r   r,   r,   r0   get_workflowy  r   z"ModularPipelineBlocks.get_workflowFpretrained_model_name_or_pathtrust_remote_codec                    s   g d}fdd|D }| j |fi |}d|v o | j|d v }t|||}|s/|r/tdd|v r?|d d ur?t|d }|d | j }	|	d\}
}|
d }
t|f|
|d	|}||\  fd
dD }|di |S )N)	cache_dirforce_downloadlocal_files_only	local_dirproxiesrevision	subfoldertokenc                        i | ]}| v r|  |qS r,   popr[   rl   r   r,   r0   r]     r   z9ModularPipelineBlocks.from_pretrained.<locals>.<dictcomp>auto_mapzoSelected model repository does not happear to have any custom code or does not have a valid `config.json` file.requirements.z.py)module_file
class_namec                    s(   i | ]}| v s|v r| |qS r,   rZ   r   expected_kwargsr   optional_kwargsr,   r0   r]     s    "r,   )load_configrk   r   
ValueErrorr"   splitr   r   )r   r   r   r   hub_kwargs_names
hub_kwargsconfighas_remote_code_	class_refr   r   	block_clsblock_kwargsr,   r   r0   from_pretrained  s:   
z%ModularPipelineBlocks.from_pretrainedc                 K   s   | j j}t| j}|ddd dd}| jjj	ddd }| | d| i}| j
|d tt| dd }	|	r@| j
|	d	 | jd||d
| t| j}
t|
| _d S )Nr   r   __dynamic__r   r   )r   r   )r   )save_directorypush_to_hubr,   )rj   rk   typer   rsplitreplacesave_pretrained__func__r   r   register_to_configr"   r   save_configr   r   r   _internal_dict)rU   r   r   r   cls_namefull_modmoduleparent_moduler   r   r   r,   r,   r0   r     s   

z%ModularPipelineBlocks.save_pretrainedcomponents_manager
collectionModularPipelinec           	      C   sD   t | jtd}| }td}t||}|t| |||d}|S )zm
        create a ModularPipeline, optionally accept pretrained_model_name_or_path to load from hub.
        r  	diffusers)blocksr   r	  r
  )MODULAR_PIPELINE_MAPPINGrZ   
model_namer2   	importlibimport_moduler   r   )	rU   r   r	  r
  map_fnr*   diffusers_modulepipeline_classmodular_pipeliner,   r,   r0   init_pipeline  s   	

z#ModularPipelineBlocks.init_pipelinestatec           	      C   s   i }| j }|D ][}|jr5||j}|jr"|du r"td|j d|dus/|du r4|j|vr4|||j< q|jrb|j|vrBi ||j< ||j}|rb| D ]\}}|dura|||< |||j |< qNqtdi |S )z2Get all inputs and intermediates in one dictionaryNzRequired input 'z' is missingr,   )	r   rl   rZ   r   r   rS   rb   r   r   )	rU   r  datastate_inputsr   rR   inputs_kwargsr}   rw   r,   r,   r0   get_block_state  s*   


z%ModularPipelineBlocks.get_block_stateblock_statec           	      C   s   | j D ] }t||jstd|j dt||j}||j||j q| jD ]S}|jrLt||jrLt||j}||j}||urK||j||j q'|jrz|	|j}|
 D ] \}}|d u rbqYt||shqYt||}||ury||||j qYq'd S )NzIntermediate output 'z' is missing in block state)r   rs   rl   r   r   rV   rS   r   rZ   rb   r   )	rU   r  r  output_paramparamr   current_valueintermediate_kwargs
param_namer,   r,   r0   set_block_state  s0   



z%ModularPipelineBlocks.set_block_statec                 C      dd | j D S )Nc                 S      g | ]
}|j d ur|j qS r+   rl   )r[   r   r,   r,   r0   r     r^   z5ModularPipelineBlocks.input_names.<locals>.<listcomp>r   rd   r,   r,   r0   r     r   z!ModularPipelineBlocks.input_namesc                 C   r#  )Nc                 S   r$  r+   r%  r[   r  r,   r,   r0   r     r^   zCModularPipelineBlocks.intermediate_output_names.<locals>.<listcomp>r   rd   r,   r,   r0   intermediate_output_names  r   z/ModularPipelineBlocks.intermediate_output_namesc                 C   r#  )Nc                 S   r$  r+   r%  r'  r,   r,   r0   r     r^   z6ModularPipelineBlocks.output_names.<locals>.<listcomp>r   rd   r,   r,   r0   output_names  r   z"ModularPipelineBlocks.output_namesc                 C   r#  )Nc                 S   r   r,   r%  r[   	componentr,   r,   r0   r   #  r   z9ModularPipelineBlocks.component_names.<locals>.<listcomp>)r   rd   r,   r,   r0   component_names!  r   z%ModularPipelineBlocks.component_namesc                 C   "   t | j| j| j| jj| j| jdS N)r   r   r   r)   r   r   r   rj   rk   r   r   rd   r,   r,   r0   doc%     zModularPipelineBlocks.doc)FNNN)0rk   r   r   r   config_namer  r   r   r`   r   _workflow_mapclassmethodr   r   propertyr   rt   r   r   r   r   r   r   r   r   r!   r   r   r   r   r   r   boolr   r   osPathLiker   r  rM   r  r   r"  r   r(  r*  r-  r1  r,   r,   r,   r0   r   !  sz   
 	



/
r   c                   @   s2  e Zd ZdZg Zg Zg ZdZdd Ze	dd Z
e	dd Ze	d	d
 Ze	dd Ze	dee fddZe	deeeef  fddZe	dee fddZe	dee fddZe	deeef fddZdefddZdedB fddZe dedefddZdedB fdd Z d!d" Z!e	d#d$ Z"dS )%ConditionalPipelineBlocksa  
    A Pipeline Blocks that conditionally selects a block to run based on the inputs. Subclasses must implement the
    `select_block` method to define the logic for selecting the block. Currently, we only support selection logic based
    on the presence or absence of inputs (i.e., whether they are `None` or not)

    This class inherits from [`ModularPipelineBlocks`]. Check the superclass documentation for the generic methods the
    library implements for all the pipeline blocks (such as loading or saving etc.)

    > [!WARNING] > This is an experimental feature and is likely to change in the future.

    Attributes:
        block_classes: List of block classes to be used. Must have the same length as `block_names`.
        block_names: List of names for each block. Must have the same length as `block_classes`.
        block_trigger_inputs: List of input names that `select_block()` uses to determine which block to run.
            For `ConditionalPipelineBlocks`, this does not need to correspond to `block_names` and `block_classes`. For
            `AutoPipelineBlocks`, this must have the same length as `block_names` and `block_classes`, where each
            element specifies the trigger input for the corresponding block.
        default_block_name: Name of the default block to run when no trigger inputs match.
            If None, this block can be skipped entirely when no trigger inputs are provided.
    Nc                 C   s   t  }t| j| jD ]\}}t|r| ||< q
|||< q
|| _t| jt| jks5td| j	j
 d| jd urQ| j| jvrStd| j	j
 d| j d| j d S d S )NIn z?, the number of block_classes and block_names must be the same.z, default_block_name 'z' must be one of block_names: )r    zipblock_namesblock_classesr   isclassr   ru   r   rj   rk   default_block_namerU   r   
block_nameblockr,   r,   r0   r   L  s   

z"ConditionalPipelineBlocks.__init__c                 C      t t| j jS r+   )nextiterr   rO   r  rd   r,   r,   r0   r  ]     z$ConditionalPipelineBlocks.model_namec                 C   r   Nr   r,   rd   r,   r,   r0   r   a  r   z%ConditionalPipelineBlocks.descriptionc                 C   6   g }| j  D ]}|jD ]}||vr|| qq|S r+   r   rO   r   rT   rU   r   rD  r,  r,   r,   r0   r   e     

z-ConditionalPipelineBlocks.expected_componentsc                 C   rJ  r+   r   rO   r   rT   rU   r   rD  r   r,   r,   r0   r   n  rM  z*ConditionalPipelineBlocks.expected_configsrY   c                 C   sr   | j d u rg S tt| j }tt|dt }t| j dd  D ]}tt|dt }|| q$t|S Nr   r   )	rA  rF  rG  r   rO   rV   r   rt   intersection_update)rU   first_blockrequired_by_allrD  block_requiredr,   r,   r0   r   w  s   
z)ConditionalPipelineBlocks.required_inputsc                 C   sD   dd | j  D }t| }|D ]}|j| jv rd|_qd|_q|S )Nc                 S      g | ]	\}}||j fqS r,   r&  r[   rl   rD  r,   r,   r0   r         z4ConditionalPipelineBlocks.inputs.<locals>.<listcomp>TF)r   r   r#   rl   r   r   )rU   named_inputscombined_inputsr   r,   r,   r0   r     s   z ConditionalPipelineBlocks.inputsc                 C       dd | j  D }t| }|S )Nc                 S   rU  r,   r   rV  r,   r,   r0   r     rW  zBConditionalPipelineBlocks.intermediate_outputs.<locals>.<listcomp>r   r   r$   rU   named_outputscombined_outputsr,   r,   r0   r        z.ConditionalPipelineBlocks.intermediate_outputsc                 C   rZ  )Nc                 S   rU  r,   r)  rV  r,   r,   r0   r     rW  z5ConditionalPipelineBlocks.outputs.<locals>.<listcomp>r[  r\  r,   r,   r0   r     r_  z!ConditionalPipelineBlocks.outputsc                 C   2   i }| j  D ]\}}t|dd r|j||< q|S Nr   r   r   r   r   rU   r   rC  rD  r,   r,   r0   r        
z'ConditionalPipelineBlocks._requirementsc                    s0    fdd dd | j D }| | j |S )zi
        Returns a set of all unique trigger input values found in this block and nested blocks.
        c                    h   t  }| d ur2|  D ]&\}}t|dr$|jd ur$|dd |jD  |jr1 |j}|| q|S )Nblock_trigger_inputsc                 s       | ]	}|d ur|V  qd S r+   r,   r   r,   r,   r0   r         zbConditionalPipelineBlocks._get_trigger_inputs.<locals>.fn_recursive_get_trigger.<locals>.<genexpr>rV   r   rs   rf  updater   r  trigger_valuesrl   rD  nested_triggersfn_recursive_get_triggerr,   r0   ro       

zOConditionalPipelineBlocks._get_trigger_inputs.<locals>.fn_recursive_get_triggerc                 S   s   h | ]}|d ur|qS r+   r,   r   r,   r,   r0   r         z@ConditionalPipelineBlocks._get_trigger_inputs.<locals>.<setcomp>)rf  rj  r   )rU   all_triggersr,   rn  r0   _get_trigger_inputs  s   z-ConditionalPipelineBlocks._get_trigger_inputsc                 K   s   t d| jj d)a  
        Select the block to run based on the trigger inputs. Subclasses must implement this method to define the logic
        for selecting the block.

        Note: When trigger inputs include intermediate outputs from earlier blocks, the selection logic should only
        depend on the presence or absence of the input (i.e., whether it is None or not), not on its actual value. This
        is because `get_execution_blocks()` resolves conditions statically by propagating intermediate output names
        without their runtime values.

        Args:
            **kwargs: Trigger input names and their values from the state.

        Returns:
            str | None: The name of the block to run, or None to use default/skip.
        z	Subclass z* must implement the `select_block` method.r   r   r,   r,   r0   select_block  s   z&ConditionalPipelineBlocks.select_blockr  c              
      s    fdd| j D }| jdi |}|d u r| j}|d u r+td| jj  | fS | j| }ztd|jj  || W S  tyc } zd|jj dt	| dt
  }t|  d }~ww )	Nc                        i | ]}|d ur|  |qS r+   r   r   r  r,   r0   r]     r   z6ConditionalPipelineBlocks.__call__.<locals>.<dictcomp>zskipping conditional block: zRunning block: z
Error in block: z
Error details: 
Traceback:
r,   )rf  rt  rA  loggerinforj   rk   r   	Exceptionr`   	traceback
format_excerror)rU   pipeliner  trigger_kwargsrC  rD  e	error_msgr,   rv  r0   __call__  s,   

z"ConditionalPipelineBlocks.__call__c                    sl    fdd| j D }| jdi |}|du r| j}|du rdS | j| }|jr4t|ts4|jdi  S |S )u  
        Get the block(s) that would execute given the inputs.

        Recursively resolves nested ConditionalPipelineBlocks until reaching either:
        - A leaf block (no sub_blocks or LoopSequentialPipelineBlocks) → returns single `ModularPipelineBlocks`
        - A `SequentialPipelineBlocks` → delegates to its `get_execution_blocks()` which returns
        a `SequentialPipelineBlocks` containing the resolved execution blocks

        Args:
            **kwargs: Input names and values. Only trigger inputs affect block selection.

        Returns:
            - `ModularPipelineBlocks`: A leaf block or resolved `SequentialPipelineBlocks`
            - `None`: If this block would be skipped (no trigger matched and no default)
        c                    ru  r+   r   r   r   r,   r0   r]     r   zBConditionalPipelineBlocks.get_execution_blocks.<locals>.<dictcomp>Nr,   )rf  rt  rA  r   r_   LoopSequentialPipelineBlocksr   )rU   r   r  rC  rD  r,   r   r0   r     s   
z.ConditionalPipelineBlocks.get_execution_blocksc              	   C   s  | j j}| j jd j}|r|dkr| d| dn| d}|  r>|d7 }|d7 }|d7 }|dt|   d7 }|d	7 }| jd}g }|d
|d   t|dkrd|	dd |dd  D  d
|d }t| dg }t|ddd}t| dg }t|ddd}	d}
t| j D ]I\}\}}|| jkrd}nd}|
d| | d|j j d7 }
|jd}|d }t|dkr|dd
dd |dd  D  7 }|
d| d7 }
q| d| }| r|d| 7 }|	 r|d|	 7 }|d|
 d7 }|S )Nr   rg   (
  Class: ry   (
g  ====================================================================================================
N  This pipeline contains blocks that are selected at runtime based on inputs.
  Trigger Inputs: h  ====================================================================================================

  Description: r   c                 s       | ]}d | V  qdS z      Nr,   r[   liner,   r,   r0   r   '      z5ConditionalPipelineBlocks.__repr__.<locals>.<genexpr>r   r   Findent_leveladd_empty_linesr     Sub-Blocks:
z
 [default]r   u       •  ()
c                 s       | ]}d | V  qdS z                   Nr,   r  r,   r,   r0   r   ?             Description: 

rr   )rj   rk   	__bases__rs  sortedr   r   rT   ru   extendr   r   r%   r&   	enumerater   r   rA  strip)rU   r   
base_classheader
desc_linesdescr   components_strr   configs_str
blocks_strirl   rD  addtional_strblock_desc_linesindented_descresultr,   r,   r0   r     sL   $
$z"ConditionalPipelineBlocks.__repr__c                 C   r.  r/  r0  rd   r,   r,   r0   r1  R  r2  zConditionalPipelineBlocks.doc)#rk   r   r   r   r?  r>  rf  rA  r   r7  r  r   r   r   rt   r`   r   r   r   r   r   r   r   r   rV   rs  rt  torchno_gradrM   r  r   r   r   r1  r,   r,   r,   r0   r;  1  sB    



!@r;  c                       s2   e Zd ZdZ fddZdedB fddZ  ZS )AutoPipelineBlocksa  
        A Pipeline Blocks that automatically selects a block to run based on the presence of trigger inputs.

        This is a specialized version of `ConditionalPipelineBlocks` where:
        - Each block has one corresponding trigger input (1:1 mapping)
        - Block selection is automatic: the first block whose trigger input is present gets selected
        - `block_trigger_inputs` must have the same length as `block_names` and `block_classes`
        - Use `None` in `block_trigger_inputs` to specify the default block, i.e the block that will run if no trigger
          inputs are present

        Attributes:
            block_classes:
                List of block classes to be used. Must have the same length as `block_names` and
                `block_trigger_inputs`.
            block_names:
                List of names for each block. Must have the same length as `block_classes` and `block_trigger_inputs`.
            block_trigger_inputs:
                List of input names where each element specifies the trigger input for the corresponding block. Use
                `None` to mark the default block.

        Example:
    ```python
        class MyAutoBlock(AutoPipelineBlocks):
            block_classes = [InpaintEncoderBlock, ImageEncoderBlock, TextEncoderBlock]
            block_names = ["inpaint", "img2img", "text2img"]
            block_trigger_inputs = ["mask_image", "image", None]  # text2img is the default
    ```

        With this definition:
        - As long as `mask_image` is provided, "inpaint" block runs (regardless of `image` being provided or not)
        - If `mask_image` is not provided but `image` is provided, "img2img" block runs
        - Otherwise, "text2img" block runs (default, trigger is `None`)
    c                    s   t    | jd urtd| jj dt| jt| j  kr't| j	ks2n td| jj dd | j	v rE| j	
d }| j| | _d S d S )Nr<  z|, do not set `default_block_name` for AutoPipelineBlocks. Use `None` in `block_trigger_inputs` to specify the default block.zV, the number of block_classes, block_names, and block_trigger_inputs must be the same.)superr   rA  r   rj   rk   ru   r?  r>  rf  index)rU   idxrj   r,   r0   r     s   

(
zAutoPipelineBlocks.__init__rY   Nc                 K   s:   t | j| jD ]\}}|dur||dur|  S qdS )z@Select block based on which trigger input is present (not None).N)r=  rf  r>  rZ   )rU   r   trigger_inputrC  r,   r,   r0   rt    s
   zAutoPipelineBlocks.select_block)rk   r   r   r   r   r`   rt  __classcell__r,   r,   r  r0   r  ^  s    "r  c                   @   sV  e Zd ZdZg Zg Zedd Zedd Zedd Z	edd	 Z
ed
d ZdefddZe	d.deeef dedB dd fddZdd Zdd Zedeeeef  fddZedee fddZedee fddZedee fdd Ze d!edefd"d#Zd$d% Zd/d&d'Zd(d) Z ed*d+ Z!edeeef fd,d-Z"dS )0SequentialPipelineBlocksa.  
    A Pipeline Blocks that combines multiple pipeline block classes into one. When called, it will call each block in
    sequence.

    This class inherits from [`ModularPipelineBlocks`]. Check the superclass documentation for the generic methods the
    library implements for all the pipeline blocks (such as loading or saving etc.)

    > [!WARNING] > This is an experimental feature and is likely to change in the future.

    Attributes:
        block_classes: list of block classes to be used
        block_names: list of prefixes for each block
    c                 C   r   rI  r,   rd   r,   r,   r0   r     r   z$SequentialPipelineBlocks.descriptionc                 C   s   t dd | j D d S )Nc                 s   s     | ]}|j d ur|j V  qd S r+   )r  r[   rD  r,   r,   r0   r         z6SequentialPipelineBlocks.model_name.<locals>.<genexpr>)rF  r   rO   rd   r,   r,   r0   r    s   z#SequentialPipelineBlocks.model_namec                 C   rJ  r+   rK  rL  r,   r,   r0   r     rM  z,SequentialPipelineBlocks.expected_componentsc                 C   rJ  r+   rN  rO  r,   r,   r0   r     rM  z)SequentialPipelineBlocks.expected_configsc                 C   s*   | j d u rtd| jj t| j  S )N@workflows is not supported because _workflow_map is not set for )r5  r   rj   rk   rt   rW   rd   r,   r,   r0   r     s
   
z,SequentialPipelineBlocks.available_workflowsr   c                 C   s\   | j d u rtd| jj || j vrtd| d| jj | j | }| jdi |}|S )Nr  z	Workflow z not found in r,   )r5  r   rj   rk   r   r   )rU   r   trigger_inputsworkflow_blocksr,   r,   r0   r     s   


z%SequentialPipelineBlocks.get_workflowNblocks_dictr   rY   c                 C   sv   |  }t  }| D ]\}}t|r| ||< q
|||< q
dd | D |_t| |_||_	|dur9||_
|S )zCreates a SequentialPipelineBlocks instance from a dictionary of blocks.

        Args:
            blocks_dict: Dictionary mapping block names to block classes or instances

        Returns:
            A new SequentialPipelineBlocks instance
        c                 S   r   r,   r  r  r,   r,   r0   r     r   z=SequentialPipelineBlocks.from_blocks_dict.<locals>.<listcomp>N)r    r   r   r@  rO   r?  rt   rW   r>  r   r   )r   r  r   instancer   rl   rD  r,   r,   r0   from_blocks_dict  s   

z)SequentialPipelineBlocks.from_blocks_dictc                 C   sn   t  }t| j| jD ]\}}t|r| ||< q
|||< q
|| _t| jt| jks5td| j	j
 dd S )Nr<  z?, the number of block_names and block_classes must be the same.)r    r=  r>  r?  r   r@  r   ru   r   rj   rk   rB  r,   r,   r0   r     s   

z!SequentialPipelineBlocks.__init__c                 C   s   g }t  }| j D ]9}|jD ]}|j|vr%|jdd |D vr%|| qd}t|tr4|jd u r4d}|rCdd |j	D }|
| q
|S )Nc                 S      h | ]}|j qS r,   r%  )r[   inputr,   r,   r0   r     r   z7SequentialPipelineBlocks._get_inputs.<locals>.<setcomp>TFc                 S   r   r,   r%  r[   outr,   r,   r0   r     r   z8SequentialPipelineBlocks._get_inputs.<locals>.<listcomp>)rV   r   rO   r   rl   rT   r_   r;  rA  r   rj  )rU   r   r   rD  inpshould_add_outputsblock_intermediate_outputsr,   r,   r0   _get_inputs
  s   


z$SequentialPipelineBlocks._get_inputsc                 C   r   r+   r  rd   r,   r,   r0   r   #  r   zSequentialPipelineBlocks.inputsc                 C   sd   t t| j }tt|dt }t| j dd  D ]}tt|dt }|| qt|S rP  )rF  rG  r   rO   rV   r   rt   rj  )rU   rR  required_by_anyrD  rT  r,   r,   r0   r   '  s   z(SequentialPipelineBlocks.required_inputsc                 C   sL   g }| j  D ]\}}dd |jD }||vr|||jf qt| }|S )Nc                 S   r  r,   r%  r[   r  r,   r,   r0   r   8  r   z@SequentialPipelineBlocks.intermediate_outputs.<locals>.<setcomp>)r   r   r   rT   r   r$   )rU   r]  rl   rD  	inp_namesr^  r,   r,   r0   r   4  s   z-SequentialPipelineBlocks.intermediate_outputsc                 C   r   r+   r   rd   r,   r,   r0   r   A  s   z SequentialPipelineBlocks.outputsr  c                 C   sz   | j  D ]3\}}z	|||\}}W q ty8 } zd| d|jj dt| dt  }t	|  d }~ww ||fS Nz
Error in block: (, z)
Error details: rw  
r   r   rz  rj   rk   r`   r{  r|  rx  r}  )rU   r~  r  rC  rD  r  r  r,   r,   r0   r  F  s   
z!SequentialPipelineBlocks.__call__c                    s    fdd  | j S )zW
        Returns a set of all unique trigger input values found in the blocks.
        c                    re  )Nrf  c                 s   rg  r+   r,   r   r,   r,   r0   r   b  rh  zaSequentialPipelineBlocks._get_trigger_inputs.<locals>.fn_recursive_get_trigger.<locals>.<genexpr>ri  rk  rn  r,   r0   ro  [  rp  zNSequentialPipelineBlocks._get_trigger_inputs.<locals>.fn_recursive_get_trigger)r   rd   r,   rn  r0   rs  V  s   
z,SequentialPipelineBlocks._get_trigger_inputsc                    sN   t |} fdd t }| j D ]\}} |||}|| qt|S )a  
        Get the blocks that would execute given the specified inputs.

        As the traversal walks through sequential blocks, intermediate outputs from resolved blocks are added to the
        active inputs. This means conditional blocks that depend on intermediates (e.g., "run img2img if image_latents
        is present") will resolve correctly, as long as the condition is based on presence/absence (None or not None),
        not on the actual value.


        Args:
            **kwargs: Input names and values. Only trigger inputs affect block selection.

        Returns:
            SequentialPipelineBlocks containing only the blocks that would execute
        c                    s   t  }t| tr| jdi |} | d u r|S | jr@t| ts@| j D ]\}}|||} fdd| D }|| q#|S | | < t| drT| j	D ]}d||j
< qL|S )Nc                    s    i | ]\}}  d | |qS )r   r,   r|   rC  r,   r0   r]     r   z`SequentialPipelineBlocks.get_execution_blocks.<locals>.fn_recursive_traverse.<locals>.<dictcomp>r   Tr,   )r   r_   r;  r   r   r  r   rj  rs   r   rl   )rD  rC  active_inputsresult_blockssub_block_name	sub_blocknested_blocksr  fn_recursive_traverser  r0   r    s    
	

zLSequentialPipelineBlocks.get_execution_blocks.<locals>.fn_recursive_traverse)r   r   r   r   rj  r  r  )rU   r   r  
all_blocksrC  rD  r  r,   r  r0   r   m  s   
z-SequentialPipelineBlocks.get_execution_blocksc              	   C   sN  | j j}| j jd j}|r|dkr| d| dn| d}| jd u rY|  rY|d7 }|d7 }|d7 }|dd	d
 |  D  d7 }tdd |  D }|d| d7 }|d7 }| j}| jd urnt| j}| j d| }|d}g }|	d|d   t
|dkr|dd |dd  D  d|d }t| dg }	t|	ddd}
t| dg }t|ddd}d}t| j D ]@\}\}}|d| d| d|j j d7 }|jd}|d }t
|dkr|dddd |dd  D  7 }|d| d7 }q| d| }|
 r|d|
 7 }| r|d| 7 }|d| d 7 }|S )!Nr   rg   r  ry   r  r  r  r  c                 S   s   g | ]}|d ur|qS r+   r,   r  r,   r,   r0   r     rq  z5SequentialPipelineBlocks.__repr__.<locals>.<listcomp>c                 s   rg  r+   r,   r   r,   r,   r0   r     rh  z4SequentialPipelineBlocks.__repr__.<locals>.<genexpr>zR  Use `get_execution_blocks()` to see selected blocks (e.g. `get_execution_blocks(z	=...)`).
r  r  r  r   c                 s   r  r  r,   r  r,   r,   r0   r     r  r   r   Fr  r   r      [] r  r  c                 s   r  r  r,   r  r,   r,   r0   r     r  r  rr   )rj   rk   r  r5  rs  rF  r   r'   r   rT   ru   r  r   r   r%   r&   r  r   r   r  )rU   r   r  r  example_inputr   workflow_strr  r  r   r  r   r  r  r  rl   rD  r  r  r,   r,   r0   r     sR   $


 $

z!SequentialPipelineBlocks.__repr__c                 C   sJ   | j }| jd urt| j}| j  d| }t| j| j|| jj| j| j	dS )Nr  )r   r   r   r   )
r   r5  r'   r)   r   r   rj   rk   r   r   )rU   r   r  r,   r,   r0   r1    s   

zSequentialPipelineBlocks.docc                 C   r`  ra  rb  rc  r,   r,   r0   r     s   
z&SequentialPipelineBlocks._requirementsr+   )rY   r  )#rk   r   r   r   r?  r>  r7  r   r  r   r   r   r`   r   r6  r   r   r  r   r  rt   r   r   r   r   r   r  r  rM   r  rs  r   r   r1  r   r,   r,   r,   r0   r    sV    






3E
r  c                   @   s  e Zd ZdZdZg Zg ZedefddZ	ede
e fddZede
e fdd	Zede
e fd
dZede
e fddZede
e fddZedd Zedd Zdd Zedd Zede
e fddZede
e fddZede
e fddZedeeef fddZd d! Zed"eeef dd fd#d$Z d%e!fd&d'Z"d%e!de!fd(d)Z#ed*d+ Z$d,d- Z%e&j'j(d2d.d/Z)d0d1 Z*dS )3r  a5  
    A Pipeline blocks that combines multiple pipeline block classes into a For Loop. When called, it will call each
    block in sequence.

    This class inherits from [`ModularPipelineBlocks`]. Check the superclass documentation for the generic methods the
    library implements for all the pipeline blocks (such as loading or saving etc.)

    > [!WARNING] > This is an experimental feature and is likely to change in the future.

    Attributes:
        block_classes: list of block classes to be used
        block_names: list of prefixes for each block
    NrY   c                 C      t d)r   z4description method must be implemented in subclassesr   rd   r,   r,   r0   r        z(LoopSequentialPipelineBlocks.descriptionc                 C   r   r+   r,   rd   r,   r,   r0   loop_expected_components  r   z5LoopSequentialPipelineBlocks.loop_expected_componentsc                 C   r   r+   r,   rd   r,   r,   r0   loop_expected_configs  r   z2LoopSequentialPipelineBlocks.loop_expected_configsc                 C   r   r   r,   rd   r,   r,   r0   loop_inputs  r   z(LoopSequentialPipelineBlocks.loop_inputsc                 C   r   r+   )r  r   rT   rl   r   r,   r,   r0   loop_required_inputs#  s   
z1LoopSequentialPipelineBlocks.loop_required_inputsc                 C   r   r   r,   rd   r,   r,   r0   loop_intermediate_outputs+  r   z6LoopSequentialPipelineBlocks.loop_intermediate_outputsc                 C   T   g }| j  D ]}|jD ]}||vr|| qq| jD ]}||vr'|| q|S r+   )r   rO   r   rT   r  rL  r,   r,   r0   r   1     



z0LoopSequentialPipelineBlocks.expected_componentsc                 C   r  r+   )r   rO   r   rT   r  rO  r,   r,   r0   r   >  r  z-LoopSequentialPipelineBlocks.expected_configsc                 C   s   g }| | j t }| j D ]%\}}|jD ]}|j|vr'||vr'|| qdd |jD }|	| q|D ]}|j| j
v rDd|_q8d|_q8|S )Nc                 S   r   r,   r%  r  r,   r,   r0   r   V  r   z<LoopSequentialPipelineBlocks._get_inputs.<locals>.<listcomp>TF)r  r  rV   r   r   r   rl   rT   r   rj  r   r   )rU   r   r   rl   rD  r  r  r   r,   r,   r0   r  J  s   

z(LoopSequentialPipelineBlocks._get_inputsc                 C   r   r+   r  rd   r,   r,   r0   r   a  r  z#LoopSequentialPipelineBlocks.inputsc                 C   s   t t| j }tt|dt }tt| dt }|| t| j dd  D ]}tt|dt }|| q+t|S )Nr   r  r   )rF  rG  r   rO   rV   r   rj  rt   )rU   rR  r  required_by_looprD  rT  r,   r,   r0   r   g  s   
z,LoopSequentialPipelineBlocks.required_inputsc                 C   sJ   dd | j  D }t| }| jD ]}|jdd |D vr"|| q|S )Nc                 S   rU  r,   r   rV  r,   r,   r0   r   {  rW  zELoopSequentialPipelineBlocks.intermediate_outputs.<locals>.<listcomp>c                 S   r  r,   r%  )r[   outputr,   r,   r0   r   ~  r   zDLoopSequentialPipelineBlocks.intermediate_outputs.<locals>.<setcomp>)r   r   r$   r  rl   rT   )rU   r]  r^  r  r,   r,   r0   r   y  s   

z1LoopSequentialPipelineBlocks.intermediate_outputsc                 C   rE  r+   )rF  reversedr   rO   r   rd   r,   r,   r0   r     rH  z$LoopSequentialPipelineBlocks.outputsc                 C   r`  ra  rb  rc  r,   r,   r0   r     rd  z*LoopSequentialPipelineBlocks._requirementsc              	   C   s   t  }t| j| jD ]\}}t|r| ||< q
|||< q
|| _| j D ]\}}|jr?td| j	j
 d| d|j	j
 dq&d S )Nr<  z9, sub_blocks must be leaf blocks (no sub_blocks). Block 'z' (z) has sub_blocks.)r    r=  r>  r?  r   r@  r   r   r   rj   rk   rB  r,   r,   r0   r     s"   

z%LoopSequentialPipelineBlocks.__init__r  c                 C   sh   |  }t  }| D ]\}}t|r| ||< q
|||< q
dd | D |_t| |_||_	|S )a  
        Creates a LoopSequentialPipelineBlocks instance from a dictionary of blocks.

        Args:
            blocks_dict: Dictionary mapping block names to block instances

        Returns:
            A new LoopSequentialPipelineBlocks instance
        c                 S   r   r,   r  r  r,   r,   r0   r     r   zALoopSequentialPipelineBlocks.from_blocks_dict.<locals>.<listcomp>)
r    r   r   r@  rO   r?  rt   rW   r>  r   )r   r  r  r   rl   rD  r,   r,   r0   r    s   

z-LoopSequentialPipelineBlocks.from_blocks_dictr  c                 K   s   | j  D ]7\}}z|||fi |\}}W q ty< } zd| d|jj dt| dt  }t	|  d }~ww ||fS r  r  )rU   
componentsr  r   rC  rD  r  r  r,   r,   r0   	loop_step  s   
z&LoopSequentialPipelineBlocks.loop_stepc                 C   r  )Nz9`__call__` method needs to be implemented by the subclassr  )rU   r  r  r,   r,   r0   r    s   z%LoopSequentialPipelineBlocks.__call__c                 C   r.  r/  r0  rd   r,   r,   r0   r1    r2  z LoopSequentialPipelineBlocks.docc              	   C   s  | j j}| j jd j}|r|dkr| d| dn| d}| jd}g }|d|d   t|dkrD|dd	 |dd  D  d|d }t	| d
g }t
|ddd}t	| dg }t|ddd}	d}
t| j D ]@\}\}}|
d| d| d|j j d7 }
|jd}|d }t|dkr|dddd	 |dd  D  7 }|
d| d7 }
qn| d| }| r|d| 7 }|	 r|d|	 7 }|d|
 d7 }|S )Nr   rg   r  ry   r  r  r   c                 s   r  r  r,   r  r,   r,   r0   r     r  z8LoopSequentialPipelineBlocks.__repr__.<locals>.<genexpr>r   r   Fr  r   r  r  r  r  r  c                 s   r  r  r,   r  r,   r,   r0   r     r  r  r  rr   )rj   rk   r  r   r   rT   ru   r  r   r   r%   r&   r  r   r   r  )rU   r   r  r  r  r  r   r  r   r  r  r  rl   rD  r  r  r,   r,   r0   r     s:   $ $z%LoopSequentialPipelineBlocks.__repr__c                 C   sr   t | ds	i | _nt| jtstdt| j d|d ur't|fi | jS |d ur5tdd|i| jS td)N_progress_bar_configz=`self._progress_bar_config` should be of type `dict`, but is r   totalz/Either `total` or `iterable` has to be defined.r,   )rs   r  r_   r   r   r   r	   )rU   iterabler  r,   r,   r0   progress_bar  s   
z)LoopSequentialPipelineBlocks.progress_barc                 K   s
   || _ d S r+   )r  r   r,   r,   r0   set_progress_bar_config   s   
z4LoopSequentialPipelineBlocks.set_progress_bar_configNN)+rk   r   r   r   r  r?  r>  r7  r`   r   rt   r   r  r   r  r   r  r  r!   r  r   r   r  r   r   r   r   r   r   r   r6  r   r  rM   r  r  r1  r   r  compilerdisabler  r  r,   r,   r,   r0   r    sV    


	
6r  c                   @   s  e Zd ZdZdZdZdZ						dMdedB dee	j
B dB dedB dedB deeef dB d	eeef dB fd
dZedeeef fddZedee	j
B dB fddZee			dNdee	j
B dB dedB dedB dedB fddZ				dOdee	j
B dededB deeB dB def
ddZedd Zedefdd Zd!d" Zedejfd#d$Zed%d& Zedejfd'd(Zedee fd)d*Z edee fd+d,Z!edee fd-d.Z"edee fd/d0Z#edeeef fd1d2Z$d3ede%fd4d5Z&d6d7 Z'dPd8ee eB dB fd9d:Z(	dQd;ed<ej)j*dB defd=d>Z+de,fd?d@Z-e.dAe%defdBdCZ/e.d3edDeeef de%fdEdFZ0dGdH Z1dRdIe2dJeee B fdKdLZ3dS )Sr  z
    Base class for all Modular pipelines.

    > [!WARNING] > This is an experimental feature and is likely to change in the future.

    Args:
        blocks: ModularPipelineBlocks, the blocks to be used in the pipeline
    zmodular_model_index.jsonNr  r   r	  r
  modular_config_dictr.   c                 K   s&  |du rD|du rD|durD| dd}| dd}	| dd}
| dd}| dd}| dd}||	|
|||d	}| j|fi |\}}|du r|durR|d
}n| j}|durstd}t||d}|du sk|jss| j}t||}|dur{| }n
t	d| j
j  || _|| _|| _dd | jjD | _dd | jjD | _|dur| D ]5\}}|| jv rt|ttfrt|dkr|\}}}| ||}d|_|| j|< q|| jv r|| j| _qnJ|dur+| D ]@\}}|| jv rt|ttfrt|dkr|\}}||||fd}| ||}d|_|| j|< q|| jv r*|| j| _qt|dkr=t	d|  d i }| j D ]\}}|jdkrS| }nd}|||< qD| jdi | i }| j D ]
\}}|j||< qj| jdi | | j| jdur| jj
jndd || _dS )a  
        Initialize a ModularPipeline instance.

        This method sets up the pipeline by:
        - creating default pipeline blocks if not provided
        - gather component and config specifications based on the pipeline blocks's requirement (e.g.
           expected_components, expected_configs)
        - update the loading specs of from_pretrained components based on the modular_model_index.json file from
           huggingface hub if `pretrained_model_name_or_path` is provided
        - create defaultfrom_config components and register everything

        Args:
            blocks: `ModularPipelineBlocks` instance. If None, will attempt to load
                   default blocks based on the pipeline class name.
            pretrained_model_name_or_path: Path to a pretrained pipeline configuration. Can be None if the pipeline
                    does not require any additional loading config. If provided, will first try to load component specs
                    (only for from_pretrained components) and config values from `modular_model_index.json`, then
                    fallback to `model_index.json` for compatibility with standard non-modular repositories.
            components_manager:
                Optional ComponentsManager for managing multiple component cross different pipelines and apply
                offloading strategies.
            collection: Optional collection name for organizing components in the ComponentsManager.
            **kwargs: Additional arguments passed to `load_config()` when loading pretrained configuration.

        Examples:
            ```python
            # Initialize with custom blocks
            pipeline = ModularPipeline(blocks=my_custom_blocks)

            # Initialize from pretrained configuration
            pipeline = ModularPipeline(blocks=my_blocks, pretrained_model_name_or_path="my-repo/modular-pipeline")

            # Initialize with components manager
            pipeline = ModularPipeline(
                blocks=my_blocks, components_manager=ComponentsManager(), collection="my_collection"
            )
            ```

        Notes:
            - If blocks is None, the method will try to find default blocks based on the pipeline class name
            - Components with default_creation_method="from_config" are created immediately, its specs are not included
              in config dict and will not be saved in `modular_model_index.json`
            - Components with default_creation_method="from_pretrained" are set to None and can be loaded later with
              `load_components()` (with or without specific component names)
            - The pipeline's config dict is populated with component specs (only for from_pretrained components) and
              config values, which will be saved as `modular_model_index.json` during `save_pretrained`
            - The pipeline's config dict is also used to store the pipeline blocks's class name, which will be saved as
              `_blocks_class_name` in the config dict
        Nr   r   Fr   r   r   r   r   r   r   r   r   r   _blocks_class_namer  z6`blocks` is `None`, no default blocks class found for c                 S      i | ]}|j t|qS r,   rl   r   r[   specr,   r,   r0   r]     rq  z,ModularPipeline.__init__.<locals>.<dictcomp>c                 S   r  r,   r  r  r,   r,   r0   r]     rq     r   r   )repor   	type_hintr   Unexpected input ''' provided. This input will be ignored.from_config)r  r,   ) r   _load_pipeline_configrZ   default_blocks_namer  r  r   r?  rx  warningrj   rk   _blocks_components_manager_collectionr   _component_specsr   _config_specsr   r_   r   rt   ru   _dict_to_component_specdefault_creation_methodrX   rW   createregister_componentsr  _pretrained_model_name_or_path)rU   r  r   r	  r
  r  r.   r   r   r   r   r   r   r   load_config_kwargsblocks_class_namer  blocks_classrl   rR   libraryr   component_spec_dictcomponent_specregister_components_dictr,  default_configsconfig_specr,   r,   r0   r   7  s   <	


$


*

zModularPipeline.__init__rY   c                 C   s"   i }| j jD ]}|j||j< q|S )z_
        Returns:
            - Dictionary mapping input names to their default values
        )r  r   rX   rl   )rU   paramsr   r,   r,   r0   default_call_parameters  s   z'ModularPipeline.default_call_parametersc              
   K   s   z| j |fi |}|d fW S  ty( } ztd|  W Y d }~nd }~ww ztd ddlm} |j |fi |}d |fW S  tyW } z	td| d|d }~ww )Nz1 modular_model_index.json not found in the repo: z try to load model_index.jsonr   )DiffusionPipelinezFailed to load config from 'zK'. Could not find or load 'modular_model_index.json' or 'model_index.json'.)r   EnvironmentErrorrx  debugr  r  )r   r   r  r  r  r  r.   r,   r,   r0   r    s(   



z%ModularPipeline._load_pipeline_configr   c              
   K   sp  ddl m} ztj|fd|i|}W n ty/ } ztd|  d}W Y d}~nd}~ww |dd}	|dd}
|d	d}|d
d}|dd}|dd}|	|
||||d}| j|fi |\}}|durs|| |d}n5|durddl	m
} td || |d}||j}t|td}||}td}t||}n| }d}|d||||||d|}|S )a  
        Load a ModularPipeline from a huggingface hub repo.

        Args:
            pretrained_model_name_or_path (`str` or `os.PathLike`, optional):
                Path to a pretrained pipeline configuration. It will first try to load config from
                `modular_model_index.json`, then fallback to `model_index.json` for compatibility with standard
                non-modular repositories. If the pretrained_model_name_or_path does not contain any pipeline config, it
                will be set to None during initialization.
            trust_remote_code (`bool`, optional):
                Whether to trust remote code when loading the pipeline, need to be set to True if you want to create
                pipeline blocks based on the custom code in `pretrained_model_name_or_path`
            components_manager (`ComponentsManager`, optional):
                ComponentsManager instance for managing multiple component cross different pipelines and apply
                offloading strategies.
            collection (`str`, optional):`
                Collection name for organizing components in the ComponentsManager.
        r   )_get_pipeline_classr   zEnvironmentError: Nr   r   Fr   r   r   r   r  )r   r   )
_get_modelzB try to determine the modular pipeline class from model_index.jsonr  r  )r  r   r	  r
  r  r.   r,   ) pipelines.pipeline_loading_utilsr  r   r   r  rx  r  r   r  !diffusers.pipelines.auto_pipeliner  rk   r  rZ   r2   r  r  r   )r   r   r   r	  r
  r   r  r  r  r   r   r   r   r   r   r  r  r.   r  r  standard_pipeline_classr  r  r*   r  r~  r,   r,   r0   r     sp   
	



	zModularPipeline.from_pretrainedTFr   safe_serializationvariantmax_shard_sizer   c           %      K   s  | dd}| d|tjjd }|r<| dd}	| dd}
| dd}| d	d}| d
d}t|d|
|dj}| j D ]\}}|j	dkrKqAt
| |d}|du rVqA|j}t|rdt|}|j}d}t D ]D\}}|tjv ryt|}nt| d| d| d|  qj| D ]\}}t
||d}|durt||r|d } nq|dur nqj|du rtd| d| dt| d qAt
||}t|}d|jv }d|jv }d|jv }i }|r||d< |r||d< |r|dur||d< tj||}||fi | || jvrqAt|d p|jdk} |s| r@| j| \}}!}"|r+|n||"d< ||"d< | jd#i |||!|"fi qA| j |d |r}t!| j"}#t#||dt$j%d#i |#d|d}$t&|$|#d d }$|$'tj|d! | j(||||	|d" dS dS )$a  
        Save the pipeline and all its components to a directory, so that it can be re-loaded using the
        [`~ModularPipeline.from_pretrained`] class method.

        Args:
            save_directory (`str` or `os.PathLike`):
                Directory to save the pipeline to. Will be created if it doesn't exist.
            safe_serialization (`bool`, *optional*, defaults to `True`):
                Whether to save the model using `safetensors` or the traditional PyTorch way with `pickle`.
            variant (`str`, *optional*):
                If specified, weights are saved in the format `pytorch_model.<variant>.bin`.
            max_shard_size (`int` or `str`, defaults to `None`):
                The maximum size for a checkpoint before being sharded. Checkpoints shard will then be each of size
                lower than this size. If expressed as a string, needs to be digits followed by a unit (like `"5GB"`).
                If expressed as an integer, the unit is bytes.
            push_to_hub (`bool`, *optional*, defaults to `False`):
                Whether to push the pipeline to the Hugging Face model hub after saving it.
            **kwargs: Additional keyword arguments:
                - `overwrite_modular_index` (`bool`, *optional*, defaults to `False`):
                    When saving a Modular Pipeline, its components in `modular_model_index.json` may reference repos
                    different from the destination repo. Setting this to `True` updates all component references in
                    `modular_model_index.json` so they point to the repo specified by `repo_id`.
                - `repo_id` (`str`, *optional*):
                    The repository ID to push the pipeline to. Defaults to the last component of `save_directory`.
                - `commit_message` (`str`, *optional*):
                    Commit message for the push to hub operation.
                - `private` (`bool`, *optional*):
                    Whether the repository should be private.
                - `create_pr` (`bool`, *optional*, defaults to `False`):
                    Whether to create a pull request instead of pushing directly.
                - `token` (`str`, *optional*):
                    The Hugging Face token to use for authentication.
        overwrite_modular_indexFrepo_idr   commit_messageNprivate	create_prr   update_model_cardT)exist_okr$  r   r   z is not installed. Cannot save z as  from r   zself.=z	 of type z cannot be saved.r  r  r   _diffusers_load_idnullr   r   )r   )r   is_pipelinemodel_description
is_modularr&  tags)r/  z	README.md)r   r#  r%  r,   ))r   r   r9  pathsepr   r"  r  r   r  r   rj   r   r   r   sysmodulesr  r  rx  ry  
issubclassr   r   r   r   r   r   r   rs   r*  r  r  r(   r  r   r   formatr   save_upload_folder)%rU   r   r  r  r   r   r   r!  r"  r#  r$  r%  r   r&  component_namer  r,  	model_clssave_method_namelibrary_namelibrary_classesr  r  save_load_methodsclass_candidatesave_methodsave_method_signaturesave_method_accept_safesave_method_accept_variant!save_method_accept_max_shard_sizesave_kwargscomponent_save_pathhas_no_load_idr   r  card_content
model_cardr,   r,   r0   r   R  s   *

"






zModularPipeline.save_pretrainedc                 C   s   | j jS )zM
        Returns:
            - The docstring of the pipeline blocks
        )r  r1  rd   r,   r,   r0   r1    s   zModularPipeline.docc                 C   s
   t | jS )zF
        Returns:
            - A copy of the pipeline blocks
        )r   r  rd   r,   r,   r0   r    s   
zModularPipeline.blocksc                 K   s  |  D ]\}}| j|}|du rtd| d qt| |}|jdk}|dur1t|\}}nd\}}| |}	||||	fi}
|sh|rM| j	di |
 t
| || |durg|rg| jdurg| j||| j qt| |d}||u r|td| d q|dur|du rtd| d	|jj d
 n!|dur|durt||jr||krtd| dt|j d |r| j	di |
 t
| || |dur|r| jdur| j||| j qdS )a  
        Register components with their corresponding specifications.

        This method is responsible for:
        1. Sets component objects as attributes on the loader (e.g., self.unet = unet)
        2. Updates the config dict, which will be saved as `modular_model_index.json` during `save_pretrained` (only
           for from_pretrained components)
        3. Adds components to the component manager if one is attached (only for from_pretrained components)

        This method is called when:
        - Components are first initialized in __init__:
           - from_pretrained components not loaded during __init__ so they are registered as None;
           - non from_pretrained components are created during __init__ and registered as the object itself
        - Components are updated with the `update_components()` method: e.g. loader.update_components(unet=unet) or
          loader.update_components(guider=guider_spec)
        - (from_pretrained) Components are loaded with the `load_components()` method: e.g.
          loader.load_components(names=["unet"]) or loader.load_components() to load all default components

        Args:
            **kwargs: Keyword arguments where keys are component names and values are component objects.
                      E.g., register_components(unet=unet_model, text_encoder=encoder_model)

        Notes:
            - When registering None for a component, it sets attribute to None but still syncs specs with the config
              dict, which will be saved as `modular_model_index.json` during `save_pretrained`
            - component_specs are updated to match the new component outside of this method, e.g. in
              `update_components()` method
        NzAModularPipeline.register_components: skipping unknown component 'rf   r   r  z%ModularPipeline.register_components: z1 is already registered with same object, skippingz.ModularPipeline.register_components: setting 'z' to None (was rr   z9ModularPipeline.register_components: replacing existing 'z' (same type z, new instance)r,   )r   r  rZ   rx  r   rs   r  r   _component_spec_to_dictr  r   r  addr  r   ry  rj   rk   r_   r  r   )rU   r   rl   r  r  is_registeredis_from_pretrainedr  r   r  register_dictcurrent_moduler,   r,   r0   r	    s`   




z#ModularPipeline.register_componentsc                 C   s4   | j  }dd |D }|D ]}|j  S tdS )zi
        Returns:
            `torch.device`: The torch device on which the pipeline is located.
        c                 S      g | ]}t |tjjr|qS r,   r_   r  nnModuler[   mr,   r,   r0   r   [      z*ModularPipeline.device.<locals>.<listcomp>cpu)r  rO   devicer  rU   r3  r  r,   r,   r0   rW  T  s
   


zModularPipeline.devicec                 C   s   | j  D ]9\}}t|tjjsqt|ds| j  S | D ]}t|dr=t|j	dr=|j	j
dur=t|j	j
    S qq| jS )z
        Returns the device on which the pipeline's models will be executed. After calling
        [`~DiffusionPipeline.enable_sequential_cpu_offload`] the execution device can only be inferred from
        Accelerate's module hooks.
        _hf_hookexecution_deviceN)r  r   r_   r  rQ  rR  rs   rW  r3  rY  rZ  )rU   rl   modelr  r,   r,   r0   _execution_deviceb  s   


z!ModularPipeline._execution_devicec                 C   s0   | j  }dd |D }|D ]}|j  S tjS )zg
        Returns:
            `torch.dtype`: The torch dtype on which the pipeline is located.
        c                 S   rO  r,   rP  rS  r,   r,   r0   r     rU  z)ModularPipeline.dtype.<locals>.<listcomp>)r  rO   ro   r  float32rX  r,   r,   r0   ro   y  s
   

zModularPipeline.dtypec                        fdd j  D S )z]
        Returns:
            - list of names for components that needs to be loaded
        c                    s(   g | ]}t  |rt |d u r|qS r+   rs   r   r   rd   r,   r0   r     s   ( z8ModularPipeline.null_component_names.<locals>.<listcomp>r  rW   rd   r,   rd   r0   null_component_names  s   z$ModularPipeline.null_component_namesc                 C   r   )zI
        Returns:
            - list of names for all components
        )rt   r  rW   rd   r,   r,   r0   r-    s   zModularPipeline.component_namesc                    r^  )zU
        Returns:
            - list of names for from_pretrained components
        c                        g | ]} j | jd kr|qS )r   r  r  r   rd   r,   r0   r     
    z>ModularPipeline.pretrained_component_names.<locals>.<listcomp>r`  rd   r,   rd   r0   pretrained_component_names     
z*ModularPipeline.pretrained_component_namesc                    r^  )zQ
        Returns:
            - list of names for from_config components
        c                    rb  )r  rc  r   rd   r,   r0   r     rd  z:ModularPipeline.config_component_names.<locals>.<listcomp>r`  rd   r,   rd   r0   config_component_names  rf  z&ModularPipeline.config_component_namesc                    r^  )z
        Returns:
            - Dictionary mapping component names to their objects (include both from_pretrained and from_config
              components)
        c                    s"   i | ]}t  |r|t |qS r,   r_  r   rd   r,   r0   r]     r   z.ModularPipeline.components.<locals>.<dictcomp>r`  rd   r,   rd   r0   r    s   zModularPipeline.componentsrl   c                 C   s   t | j| S )zh
        Returns:
            - a copy of the ComponentSpec object for the given component name
        )r   r  )rU   rl   r,   r,   r0   get_component_spec  s   z"ModularPipeline.get_component_specc           
   
      s   fdd| j D } fdd| jD }| D ]z\}}| j | }|jdur>t||js>td| d|jj d|jj  |du rZ|}t	| |rYt
| |durYtd| d	 n|jd
krpt
|dddu rpt|t|d}nt||}|j|jkrtd| d|j d|j d || j |< qt dkrtd    | jdi | i }| D ]\}}	|	| j| _|	||< q| jdi | dS )a  
        Update components and configuration values and specs after the pipeline has been instantiated.

        This method allows you to:
        1. Replace existing components with new ones (e.g., updating `self.unet` or `self.text_encoder`)
        2. Update configuration values (e.g., changing `self.requires_safety_checker` flag)

        In addition to updating the components and configuration values as pipeline attributes, the method also
        updates:
        - the corresponding specs in `_component_specs` and `_config_specs`
        - the `config` dict, which will be saved as `modular_model_index.json` during `save_pretrained`

        Args:
            **kwargs: Component objects or configuration values to update:
                - Component objects: Models loaded with `AutoModel.from_pretrained()` or `ComponentSpec.load()`
                are automatically tagged with loading information. ConfigMixin objects without weights (e.g.,
                schedulers, guiders) can be passed directly.
                - Configuration values: Simple values to update configuration settings
                (e.g., `requires_safety_checker=False`)

        Examples:
            ```python
            # Update pre-trained model
            pipeline.update_components(unet=new_unet_model, text_encoder=new_text_encoder)

            # Update configuration values
            pipeline.update_components(requires_safety_checker=False)
            ```

        Notes:
            - Components loaded with `AutoModel.from_pretrained()` or `ComponentSpec.load()` will have
            loading specs preserved for serialization. Custom or locally loaded components without Hub references will
            have their `modular_model_index.json` entries updated automatically during `save_pretrained()`.
            - ConfigMixin objects without weights (e.g., schedulers, guiders) can be passed directly.
        c                    r   r,   r   r[   r}   r   r,   r0   r]     r   z5ModularPipeline.update_components.<locals>.<dictcomp>c                    r   r,   r   ri  r   r,   r0   r]     r   Nz*ModularPipeline.update_components: adding z with new type: z, previous type: z+ModularPipeline.update_components: setting z to None (spec unchanged)r   r*  rl   r  zKModularPipeline.update_components: changing the default_creation_method of r(  z to r   r   z/Unexpected keyword arguments, will be ignored: r,   )r  r  r   r  r_   rx  ry  rj   rk   rs   r   r   r  r   r   from_componentru   rW   r	  rX   r  )
rU   r   passed_componentspassed_config_valuesrl   r,  current_component_specnew_component_specconfig_to_register	new_valuer,   r   r0   update_components  s@   %


z!ModularPipeline.update_componentsnamesc                    s  |du r fdd j  D }nt|tr|g}nt|ts(tdt|  fdd|D } fdd|D }t|dkrHt	d	|  i }|D ]} j | }i }|
 D ]#\}	}
t|
tsg|
||	< qY||
v rr|
| ||	< qYd
|
v r||
d
 ||	< qYd}d|v r jdur|j jkr|d d}|jstd| d qLz|jdi |||< W qL ty   t }|rd|v rd| d|j d| d j d| d|j d| d| d}nd| d| d| d| }t	| Y qLw  jdi | dS )a  
        Load selected components from specs.

        Args:
            names: list of component names to load. If None, will load all components with
                   default_creation_method == "from_pretrained". If provided as a list or string, will load only the
                   specified components.
            **kwargs: additional kwargs to be passed to `from_pretrained()`.Can be:
             - a single value to be applied to all components to be loaded, e.g. torch_dtype=torch.bfloat16
             - a dict, e.g. torch_dtype={"unet": torch.bfloat16, "default": torch.float32}
             - if potentially override ComponentSpec if passed a different loading field in kwargs, e.g.
               `pretrained_model_name_or_path`, `variant`, `revision`, etc.
             - if potentially override ComponentSpec if passed a different loading field in kwargs, e.g.
               `pretrained_model_name_or_path`, `variant`, `revision`, etc.
        Nc                    s@   g | ]} j | jd kr j | jdurt |ddu r|qS )r   N)r  r  r   r   r   rd   r,   r0   r   #	  s    z3ModularPipeline.load_components.<locals>.<listcomp>zInvalid type for names: c                    s   h | ]	}| j v r|qS r,   r  r   rd   r,   r0   r   /	  rW  z2ModularPipeline.load_components.<locals>.<setcomp>c                    s   h | ]	}| j vr|qS r,   rt  r   rd   r,   r0   r   0	  rW  r   z$Unknown components will be ignored: rX   Fr   TzSkipping component `z&`: no pretrained model path specified.zFailed to load component `z` from external repository `z3`.

`trust_remote_code=True` was not forwarded to `zC` because it comes from a different repository than the pipeline (`a  `). For safety, `trust_remote_code` is only forwarded to components from the same repository as the pipeline.

You need to load this component manually with `trust_remote_code=True` and pass it to the pipeline via `pipe.update_components()`. For example, if it is a custom model:

  z = AutoModel.from_pretrained("z4", trust_remote_code=True)
  pipe.update_components(r)  r  zFailed to create component z:
- Component spec: z
- load() called with kwargs: ze
If this component is not required for your workflow you can safely ignore this message.

Traceback:
r,   )r  rW   r_   r`   rt   r   r   ru   rx  r   r   r   r
  r   r   ry  loadrz  r{  r|  r	  )rU   rs  r   components_to_loadunknown_namescomponents_to_registerrl   r  component_load_kwargsrQ   rR   trust_remote_code_strippedtbwarning_msgr,   rd   r0   load_components	  s   







		zModularPipeline.load_componentsraise_errorr  c                 C   sZ   ddl m} |d u r| j n|g}dd |D }|D ]}||r*|r'td dS qdS )Nr   )_is_group_offload_enabledc                 S   rO  r,   rP  r+  r,   r,   r0   r   y	  rU  zNModularPipeline._maybe_raise_error_if_group_offload_active.<locals>.<listcomp>zYou are trying to apply model/sequential CPU offloading to a pipeline that contains components with group offloading enabled. This is not supported. Please disable group offloading for components of the pipeline to use other offloading methods.TF)hooks.group_offloadingr  r  rO   r   )rU   r~  r  r  r  r,  r,   r,   r0   *_maybe_raise_error_if_group_offload_actives	  s   z:ModularPipeline._maybe_raise_error_if_group_offload_activec                    s2  ddl m  ddlmmm}m} |dd}|dd}|dd}d}d}	t|d	krKt	|d
 t
jr;|d
 }n@|d
 durHt
|d
 nd}	n0t|dkrqt	|d
 t
jr]td|d
 durjt
|d
 nd}	|d	 }n
t|dkr{td|dur|durtd|p|}|dur|	durtd|p|	}|durt
|jnd}
t fdd| j D } fddfddtfdd| j D }| jduot| jd	k}|rtd|
dv r|r|std|rddrtdtfdd| j D }|r |
dv r tdd| j  d |
d krX|d!d"rX| rXd#tjd$< td% d
dl}tt
d rJt
j sNtd&d#tjd'< td( | j }d)d* |D }|ph|}|D ]} |\}}}| j|d+}|s|r|durtd,|j j! d-|rd.nd/ d0| d1|rd.nd/ d2	 |r|durtd,|j j! d3| d4|j d5 | jd|d6r|durtd,|j j! d7| d8 |r|dur|d9d:r|j"|d; n|s|s|s|"|| |jt
j#krt$|d<v r|s|std= qk| S )>uM  
        Performs Pipeline dtype and/or device conversion. A torch.dtype and torch.device are inferred from the
        arguments of `self.to(*args, **kwargs).`

        > [!TIP] > If the pipeline already has the correct torch.dtype and torch.device, then it is returned as is.
        Otherwise, > the returned pipeline is a copy of self with the desired torch.dtype and torch.device.


        Here are the ways to call `to`:

        - `to(dtype, silence_dtype_warnings=False) → DiffusionPipeline` to return a pipeline with the specified
          [`dtype`](https://pytorch.org/docs/stable/tensor_attributes.html#torch.dtype)
        - `to(device, silence_dtype_warnings=False) → DiffusionPipeline` to return a pipeline with the specified
          [`device`](https://pytorch.org/docs/stable/tensor_attributes.html#torch.device)
        - `to(device=None, dtype=None, silence_dtype_warnings=False) → DiffusionPipeline` to return a pipeline with the
          specified [`device`](https://pytorch.org/docs/stable/tensor_attributes.html#torch.device) and
          [`dtype`](https://pytorch.org/docs/stable/tensor_attributes.html#torch.dtype)

        Arguments:
            dtype (`torch.dtype`, *optional*):
                Returns a pipeline with the specified
                [`dtype`](https://pytorch.org/docs/stable/tensor_attributes.html#torch.dtype)
            device (`torch.Device`, *optional*):
                Returns a pipeline with the specified
                [`device`](https://pytorch.org/docs/stable/tensor_attributes.html#torch.device)
            silence_dtype_warnings (`str`, *optional*, defaults to `False`):
                Whether to omit warnings if the target `dtype` is not compatible with the target `device`.

        Returns:
            [`DiffusionPipeline`]: The pipeline converted to specified `dtype` and/or `dtype`.
        r   _check_bnb_status)r   is_accelerate_versionis_hpu_availableis_transformers_versionro   NrW  silence_dtype_warningsFr   r   zbWhen passing two arguments, make sure the first corresponds to `device` and the second to `dtype`.zPPlease make sure to pass at most two arguments (`device` and `dtype`) `.to(...)`zgYou have passed `dtype` both as an argument and as a keyword argument. Please only pass one of the two.zhYou have passed `device` both as an argument and as a keyword argument. Please only pass one of the two.c                 3   s     | ]\}}t  |V  qd S r+   )anyr[   r   r  r  r,   r0   r   	  r  z%ModularPipeline.to.<locals>.<genexpr>c                    sf    rddr
dS  | \}}}|rdS t | do2t| jtjjp2t | jdo2t| jjd tjjS )N<z0.14.0FrY  hooksr   )rs   r_   rY  
accelerater  AlignDevicesHook)r  r   is_loaded_in_8bit_bnb)r  r   r  r,   r0    module_is_sequentially_offloaded	  s   
z<ModularPipeline.to.<locals>.module_is_sequentially_offloadedc                    s.     rddr
dS t | dot| jtjjS )Nr  z0.17.0.dev0FrY  )rs   r_   rY  r  r  
CpuOffloadr  )r   r  r,   r0   module_is_offloaded	  s   z/ModularPipeline.to.<locals>.module_is_offloadedc                 3       | ]	\}} |V  qd S r+   r,   r  )r  r,   r0   r   	  s    
zIt seems like you have activated a device mapping strategy on the pipeline which doesn't allow explicit device placement using `to()`. You can call `reset_device_map()` to remove the existing device map from the pipeline.)cudaxpua7  It seems like you have activated sequential model offloading by calling `enable_sequential_cpu_offload`, but are now attempting to move the pipeline to GPU. This is not compatible with offloading. Please, move your pipeline `.to('cpu')` or consider removing the move altogether if you use sequential offloading.r  z
1.1.0.dev0zYou are trying to call `.to('cuda')` on a pipeline that has models quantized with `bitsandbytes`. Your current `accelerate` installation does not support it. Please upgrade the installation.c                 3   r  r+   r,   r  )r  r,   r0   r   	  rh  a5  It seems like you have activated model offloading by calling `enable_model_cpu_offload`, but are now manually moving the pipeline to GPU. It is strongly recommended against doing so as memory gains from offloading are likely to be lost. Offloading automatically takes care of moving the individual components r  z to GPU when needed. To make sure offloading works as expected, you should consider moving the pipeline back to CPU: `pipeline.to('cpu')` or removing the move altogether if you use offloading.hpuhpu_migrationT1PT_HPU_GPU_MIGRATIONz0Environment variable set: PT_HPU_GPU_MIGRATION=1zBYou are trying to call `.to('hpu')` but HPU device is unavailable.PT_HPU_MAX_COMPOUND_OP_SIZEz7Environment variable set: PT_HPU_MAX_COMPOUND_OP_SIZE=1c                 S   rO  r,   rP  rS  r,   r,   r0   r   
  rU  z&ModularPipeline.to.<locals>.<listcomp>r  zThe module 'z$' has been loaded in `bitsandbytes` 4bit8bitz and conversion to z& is not supported. Module is still in z precision.z:' has been loaded in `bitsandbytes` 8bit and moving it to z2 via `.to()` is not supported. Module is still on r   )r~  r  z&' is group offloaded and moving it to z via `.to()` is not supported.>z4.44.0)rW  )rV  a  Pipelines loaded with `dtype=torch.float16` cannot run with `cpu` device. It is not recommended to move them to `cpu` as running them will fail. Please make sure to use an accelerator to run the pipeline in inference, due to the lack of support for`float16` operations on this device in PyTorch. Please, remove the `torch_dtype=torch.float16` argument, or use another device for inference.)%pipelines.pipeline_utilsr  utilsr   r  r  r  r   ru   r_   r  ro   rW  r   r   r  r  r   hf_device_maprx  r   r   rW   r9  environr  habana_frameworks.torchrs   r  is_availablerO   r  rj   rk   tofloat16r`   )rU   argsr   r  r  ro   rW  r  	dtype_arg
device_argdevice_typepipeline_has_bnb"pipeline_is_sequentially_offloadedis_pipeline_device_mappedpipeline_is_offloadedhabana_frameworksr3  is_offloadedr  r   is_loaded_in_4bit_bnbr  is_group_offloadedr,   )r  r   r  r  r  r0   r  	  s    
 
 





4
zModularPipeline.tor  c                    sV    j dkrdS  jdurt j\}}nd}d} fdd  D }d||fi|S )u  
        Convert a ComponentSpec into a JSON‐serializable dict for saving as an entry in `modular_model_index.json`. If
        the `default_creation_method` is not `from_pretrained`, return None.

        This dict contains:
          - "type_hint": tuple[str, str]
              Library name and class name of the component. (e.g. ("diffusers", "UNet2DConditionModel"))
          - All loading fields defined by `component_spec.loading_fields()`, typically:
              - "pretrained_model_name_or_path": str | None
                  The model pretrained_model_name_or_pathsitory (e.g., "stabilityai/stable-diffusion-xl").
              - "subfolder": str | None
                  A subfolder within the pretrained_model_name_or_path where this component lives.
              - "variant": str | None
                  An optional variant identifier for the model.
              - "revision": str | None
                  A specific git revision (commit hash, tag, or branch).
              - ... any other loading fields defined on the spec.

        Args:
            component_spec (ComponentSpec):
                The spec object describing one pipeline component.

        Returns:
            dict[str, Any]: A mapping suitable for JSON serialization.

        Example:
            >>> from diffusers.pipelines.modular_pipeline_utils import ComponentSpec >>> from diffusers import
            UNet2DConditionModel >>> spec = ComponentSpec(
                ... name="unet", ... type_hint=UNet2DConditionModel, ... config=None, ...
                pretrained_model_name_or_path="path/to/pretrained_model_name_or_path", ... subfolder="subfolder", ...
                variant=None, ... revision=None, ... default_creation_method="from_pretrained",
            ... ) >>> ModularPipeline._component_spec_to_dict(spec) {
                "type_hint": ("diffusers", "UNet2DConditionModel"), "pretrained_model_name_or_path": "path/to/repo",
                "subfolder": "subfolder", "variant": None, "revision": None, "type_hint": ("diffusers",
                "UNet2DConditionModel"), "pretrained_model_name_or_path": "path/to/repo", "subfolder": "subfolder",
                "variant": None, "revision": None,
            }
        r   Nc                    s   i | ]}|t  |qS r,   r   ri  r  r,   r0   r]   q
  rq  z;ModularPipeline._component_spec_to_dict.<locals>.<dictcomp>r  )r  r  r   loading_fields)r  lib_namer  load_spec_dictr,   r  r0   rI  A
  s   
(
z'ModularPipeline._component_spec_to_dict	spec_dictc                 C   sJ   |  }|d\}}|dur|durt||}nd}td| |d|S )a	  
        Reconstruct a ComponentSpec from a loading specdict.

        This method converts a dictionary representation back into a ComponentSpec object. The dict should contain:
          - "type_hint": tuple[str, str]
              Library name and class name of the component. (e.g. ("diffusers", "UNet2DConditionModel"))
          - All loading fields defined by `component_spec.loading_fields()`, typically:
              - "pretrained_model_name_or_path": str | None
                  The model repository (e.g., "stabilityai/stable-diffusion-xl").
              - "subfolder": str | None
                  A subfolder within the pretrained_model_name_or_path where this component lives.
              - "variant": str | None
                  An optional variant identifier for the model.
              - "revision": str | None
                  A specific git revision (commit hash, tag, or branch).
              - ... any other loading fields defined on the spec.

        Args:
            name (str):
                The name of the component.
            specdict (dict[str, Any]):
                A dictionary containing the component specification data.

        Returns:
            ComponentSpec: A reconstructed ComponentSpec object.

        Example:
            >>> spec_dict = { ... "type_hint": ("diffusers", "UNet2DConditionModel"), ...
            "pretrained_model_name_or_path": "stabilityai/stable-diffusion-xl", ... "subfolder": "unet", ... "variant":
            None, ... "revision": None, ... } >>> ModularPipeline._dict_to_component_spec("unet", spec_dict)
            ComponentSpec(
                name="unet", type_hint=UNet2DConditionModel, config=None,
                pretrained_model_name_or_path="stabilityai/stable-diffusion-xl", subfolder="unet", variant=None,
                revision=None, default_creation_method="from_pretrained"
            >>> spec_dict = { ... "type_hint": ("diffusers", "UNet2DConditionModel"), ...
            "pretrained_model_name_or_path": "stabilityai/stable-diffusion-xl", ... "subfolder": "unet", ... "variant":
            None, ... "revision": None, ... } >>> ModularPipeline._dict_to_component_spec("unet", spec_dict)
            ComponentSpec(
                name="unet", type_hint=UNet2DConditionModel, config=None,
                pretrained_model_name_or_path="stabilityai/stable-diffusion-xl", subfolder="unet", variant=None,
                revision=None, default_creation_method="from_pretrained"
            )
        r  Nrj  r,   )copyr   r   r   )rl   r  r  r  r  r,   r,   r0   r  w
  s   .z'ModularPipeline._dict_to_component_specc                 K   s4   | j j D ]\}}t|dr|jdi | qd S )Nr  r,   )r  r   r   rs   r  )rU   r   r  r  r,   r,   r0   r  
  s
   
z'ModularPipeline.set_progress_bar_configr  r  c              	   K   s  |du rt  }nt|}| }| jjD ]H}|j}|j}|j}||v r.|||	|| q|durL||v rL|	|}	|	
 D ]\}
}||
|| q?q|dur\||jvr\|||| qt|dkrntd|  d t ) z
| | |\}}W n ty   d| jjj d}t|  w W d   n1 sw   Y  |du r|S t|tr||S t|ttfr||S td| d)	a  
        Execute the pipeline by running the pipeline blocks with the given inputs.

        Args:
            state (`PipelineState`, optional):
                PipelineState instance contains inputs and intermediate values. If None, a new `PipelineState` will be
                created based on the user inputs and the pipeline blocks's requirement.
            output (`str` or `list[str]`, optional):
                Optional specification of what to return:
                   - None: Returns the complete `PipelineState` with all inputs and intermediates (default)
                   - str: Returns a specific intermediate value from the state (e.g. `output="image"`)
                   - list[str]: Returns a dictionary of specific intermediate values (e.g. `output=["image",
                     "latents"]`)


        Examples:
            ```python
            # Get complete pipeline state
            state = pipeline(prompt="A beautiful sunset", num_inference_steps=20)
            print(state.intermediates)  # All intermediate outputs

            # Get specific output
            image = pipeline(prompt="A beautiful sunset", output="image")

            # Get multiple specific outputs
            results = pipeline(prompt="A beautiful sunset", output=["image", "latents"])
            image, latents = results["image"], results["latents"]

            # Continue from previous state
            state = pipeline(prompt="A beautiful sunset")
            new_state = pipeline(state=state, output="image")  # Continue processing
            ```

        Returns:
            - If `output` is None: Complete `PipelineState` containing all inputs and intermediates
            - If `output` is str: The specific intermediate value from the state (e.g. `output="image"`)
            - If `output` is list[str]: Dictionary mapping output names to their values from the state (e.g.
              `output=["image", "latents"]`)
        Nr   r  r  zError in block: (z):
zOutput 'z' is not a valid output type)rM   r   r  r  r   rl   rX   rS   rV   r   r   rO   ru   warningswarnrW   r  r  rz  rj   rk   rx  r}  r_   r`   rZ   rt   r   r   )rU   r  r  r   passed_kwargsexpected_input_paramrl   rX   rS   kwargs_dictr}   rw   r   r  r,   r,   r0   r  
  sJ   (





zModularPipeline.__call__)NNNNNNr3  )TNNFr+   )FNr  )4rk   r   r   r   r4  r  r  r   r`   r9  r:  r   r   r   r   r7  r  r6  r  r   r8  r   intr   r1  r  r	  r  rW  r\  ro   rt   ra  r-  re  rg  r  r   rh  rr  r}  rQ  rR  r  r
   r  staticmethodrI  r  r  rM   r  r,   r,   r,   r0   r  (  s    	
 
W

 
h
	Qc

 <5 < r  r+   )Or  r   r9  r2  r{  r  collectionsr   r  r   dataclassesr   r   typingr   r  huggingface_hubr   huggingface_hub.utilsr   	tqdm.autor	   typing_extensionsr
   configuration_utilsr   r   r  r   r   r   r   r  r   r   r   utils.dynamic_modules_utilsr   r   utils.hub_utilsr   r   utils.torch_utilsr   r	  r   modular_pipeline_utilsr   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r  
get_loggerrk   rx  r`   r2   r6   r;   r?   r  rM   r   r   r;  r  r  r  r  r,   r,   r,   r0   <module>   s~   @

	













YG    /=  e  ,