o
    ۷i}F                     @  s   d dl mZ d dlZd dlmZ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mZmZ er:dd	lmZ d
ZeeZG dd deeZG dd deZdddZdS )    )annotationsN)TYPE_CHECKINGAny)validate_hf_hub_args)Self   )ConfigMixin)
BaseOutputPushToHubMixin
get_logger
BlockStatezguider_config.jsonc                      s  e Zd ZdZeZdZdZdQdRddZdd Z	dd Z
dd ZdSddZdTddZdU fd!d"ZdVd%d&ZdVd'd(ZdWd,d-ZdXd0d1ZdYd3d4ZdZd5d6Zed[d7d8Zed[d9d:Zed\d;d<Zed]d@dAZed^dBdCZee			Dd_d`dJdKZdadbdOdPZ  ZS )cBaseGuidancezGBase class providing the skeleton for implementing guidance techniques.N__guidance_identifier__              ?Tstartfloatstopenabledboolc                 C  s   t d || _|| _d | _d | _d | _d| _d | _|| _	d|  kr'dk s0n t
d| d||  kr:dksFn t
d| d| d| jd u sQt| jtsUt
d	d S )
NzGuiders are currently an experimental feature under active development. The API is subject to breaking changes in future releases.r   r   r   z4Expected `start` to be between 0.0 and 1.0, but got .zExpected `stop` to be between z and 1.0, but got z\`_input_predictions` must be a list of required prediction names for the guidance technique.)loggerwarning_start_stop_step_num_inference_steps	_timestep_count_prepared_input_fields_enabled
ValueError_input_predictions
isinstancelist)selfr   r   r    r'   T/home/ubuntu/vllm_env/lib/python3.10/site-packages/diffusers/guiders/guider_utils.py__init__-   s(   zBaseGuidance.__init__c                 K  s   | j j| jfi |S )a  
        Creates a copy of this guider instance, optionally with modified configuration parameters.

        Args:
            **kwargs: Configuration parameters to override in the new instance. If no kwargs are provided,
                returns an exact copy with the same configuration.

        Returns:
            A new guider instance with the same (or updated) configuration.

        Example:
            ```python
            # Create a CFG guider
            guider = ClassifierFreeGuidance(guidance_scale=3.5)

            # Create an exact copy
            same_guider = guider.new()

            # Create a copy with different start step, keeping other config the same
            new_guider = guider.new(guidance_scale=5)
            ```
        )	__class__from_configconfig)r&   kwargsr'   r'   r(   newE   s   zBaseGuidance.newc                 C  
   d| _ d S )NFr!   r&   r'   r'   r(   disable^      
zBaseGuidance.disablec                 C  r/   )NTr0   r1   r'   r'   r(   enablea   r3   zBaseGuidance.enablestepintnum_inference_stepstimesteptorch.LongTensorreturnNonec                 C  s   || _ || _|| _d| _d S )Nr   )r   r   r   r   )r&   r5   r7   r8   r'   r'   r(   	set_stated   s   
zBaseGuidance.set_statedict[str, Any]c                 C  s"   | j | j| j| j| j| jd}|S )an  
        Returns the current state of the guidance technique as a dictionary. The state variables will be included in
        the __repr__ method. Returns:
            `dict[str, Any]`: A dictionary containing the current state variables including:
                - step: Current inference step
                - num_inference_steps: Total number of inference steps
                - timestep: Current timestep tensor
                - count_prepared: Number of times prepare_models has been called
                - enabled: Whether the guidance is enabled
                - num_conditions: Number of conditions
        )r5   r7   r8   count_preparedr   num_conditions)r   r   r   r   r!   r?   )r&   stater'   r'   r(   	get_statej   s   zBaseGuidance.get_statestrc           	        s   t   }|  }g }| D ]0\}}t|}d|v r4|d}|d d ddd |dd D  }|d| d|  qd|}| d	| S )
zq
        Returns a string representation of the guidance object including both config and current state.
        
r   c                 S  s   g | ]}d | qS )z    r'   ).0liner'   r'   r(   
<listcomp>   s    z)BaseGuidance.__repr__.<locals>.<listcomp>   Nz  z: z
State:
)super__repr__rA   itemsrB   splitjoinappend)	r&   str_reprr@   state_lineskvv_strv_lines	state_strr*   r'   r(   rI      s   

(
zBaseGuidance.__repr__denoisertorch.nn.Modulec                 C  s   |  j d7  _ dS )z
        Prepares the models for the guidance technique on a given batch of data. This method should be overridden in
        subclasses to implement specific model preparation logic.
        rG   N)r   r&   rV   r'   r'   r(   prepare_models   s   zBaseGuidance.prepare_modelsc                 C  s   dS )a*  
        Cleans up the models for the guidance technique after a given batch of data. This method should be overridden
        in subclasses to implement specific model cleanup logic. It is useful for removing any hooks or other stateful
        modifications made during `prepare_models`.
        Nr'   rX   r'   r'   r(   cleanup_models   s   zBaseGuidance.cleanup_modelsdata'BlockState'list['BlockState']c                 C     t d)Nz?BaseGuidance::prepare_inputs must be implemented in subclasses.NotImplementedError)r&   r[   r'   r'   r(   prepare_inputs      zBaseGuidance.prepare_inputsinput_fields dict[str, str | tuple[str, str]]c                 C  r^   )NzPBaseGuidance::prepare_inputs_from_block_state must be implemented in subclasses.r_   )r&   r[   rc   r'   r'   r(   prepare_inputs_from_block_state   s   z,BaseGuidance.prepare_inputs_from_block_stater   c                   sf   t dd |D stdt| jkr"td j dt| d fdd|D } jd	i |S )
Nc                 s  s    | ]}t |d V  qdS )
noise_predN)hasattrrD   dr'   r'   r(   	<genexpr>   s    z(BaseGuidance.__call__.<locals>.<genexpr>z1Expected all data to have `noise_pred` attribute.z	Expected z data items, but got z. Please check the input data.c                   s   i | ]
}t | j|jqS r'   )getattr_identifier_keyrf   rh   r1   r'   r(   
<dictcomp>   s    z)BaseGuidance.__call__.<locals>.<dictcomp>r'   )allr"   lenr?   forward)r&   r[   forward_inputsr'   r1   r(   __call__   s   zBaseGuidance.__call__c                 O  r^   )Nz8BaseGuidance::forward must be implemented in subclasses.r_   )r&   argsr-   r'   r'   r(   rp      rb   zBaseGuidance.forwardc                 C  r^   )Nz?BaseGuidance::is_conditional must be implemented in subclasses.r_   r1   r'   r'   r(   is_conditional      zBaseGuidance.is_conditionalc                 C  s   | j  S )N)rt   r1   r'   r'   r(   is_unconditional   ru   zBaseGuidance.is_unconditionalc                 C  r^   )Nz?BaseGuidance::num_conditions must be implemented in subclasses.r_   r1   r'   r'   r(   r?      ru   zBaseGuidance.num_conditions,dict[str, tuple[torch.Tensor, torch.Tensor]]tuple_index
identifierc              	   C  s   ddl m} i }| D ]8\}}z"t|tjr|||< nt|tr(|| ||< n	tdt| W q tyD   t	
d| d Y qw ||| j< |di |S )  
        Prepares a batch of data for the guidance technique. This method is used in the `prepare_inputs` method of the
        `BaseGuidance` class. It prepares the batch based on the provided tuple index.

        Args:
            input_fields (`dict[str, str | tuple[str, str]]`):
                A dictionary where the keys are the names of the fields that will be used to store the data once it is
                prepared with `prepare_inputs`. The values can be either a string or a tuple of length 2, which is used
                to look up the required data provided for preparation. If a string is provided, it will be used as the
                conditional data (or unconditional if used with a guidance method that requires it). If a tuple of
                length 2 is provided, the first element must be the conditional data identifier and the second element
                must be the unconditional data identifier or None.
            data (`BlockState`):
                The input data to be prepared.
            tuple_index (`int`):
                The index to use when accessing input fields that are tuples.

        Returns:
            `BlockState`: The prepared batch of data.
        r   r   zInvalid value type: "`data` does not have attribute(s) , skipping.Nr'   )"modular_pipelines.modular_pipeliner   rJ   r$   torchTensortupler"   typer   debugrl   )clsr[   rx   ry   r   
data_batchkeyvaluer'   r'   r(   _prepare_batch   s   


zBaseGuidance._prepare_batchc           	   	   C  s   ddl m} i }| D ]5\}}zt|trt||||< nt|tr-t||| ||< n	 W q tyA   t	d| d Y qw ||| j
< |di |S )rz   r   r   r{   r|   Nr'   )r}   r   rJ   r$   rB   rk   r   AttributeErrorr   r   rl   )	r   rc   r[   rx   ry   r   r   r   r   r'   r'   r(   _prepare_batch_from_block_state   s   


z,BaseGuidance._prepare_batch_from_block_stateFpretrained_model_name_or_pathstr | os.PathLike | None	subfolder
str | Noner   c                 K  s6   | j d||ddd|\}}}| j|fd|i|S )a   
        Instantiate a guider from a pre-defined JSON configuration file in a local directory or Hub repository.

        Parameters:
            pretrained_model_name_or_path (`str` or `os.PathLike`, *optional*):
                Can be either:

                    - A string, the *model id* (for example `google/ddpm-celebahq-256`) of a pretrained model hosted on
                      the Hub.
                    - A path to a *directory* (for example `./my_model_directory`) containing the guider configuration
                      saved with [`~BaseGuidance.save_pretrained`].
            subfolder (`str`, *optional*):
                The subfolder location of a model file within a larger model repository on the Hub or locally.
            return_unused_kwargs (`bool`, *optional*, defaults to `False`):
                Whether kwargs that are not consumed by the Python class should be returned or not.
            cache_dir (`str | os.PathLike`, *optional*):
                Path to a directory where a downloaded pretrained model configuration is cached if the standard cache
                is not used.
            force_download (`bool`, *optional*, defaults to `False`):
                Whether or not to force the (re-)download of the model weights and configuration files, overriding the
                cached versions if they exist.

            proxies (`dict[str, str]`, *optional*):
                A dictionary of proxy servers to use by protocol or endpoint, for example, `{'http': 'foo.bar:3128',
                'http://hostname': 'foo.bar:4012'}`. The proxies are used on each request.
            output_loading_info(`bool`, *optional*, defaults to `False`):
                Whether or not to also return a dictionary containing missing keys, unexpected keys and error messages.
            local_files_only(`bool`, *optional*, defaults to `False`):
                Whether to only load local model weights and configuration files or not. If set to `True`, the model
                won't be downloaded from the Hub.
            token (`str` or *bool*, *optional*):
                The token to use as HTTP bearer authorization for remote files. If `True`, the token generated from
                `diffusers-cli login` (stored in `~/.huggingface`) is used.
            revision (`str`, *optional*, defaults to `"main"`):
                The specific model version to use. It can be a branch name, a tag name, a commit id, or any identifier
                allowed by Git.

        > [!TIP] > To use private or [gated models](https://huggingface.co/docs/hub/models-gated#gated-models), log-in
        with `hf > auth login`. You can also activate the special >
        ["offline-mode"](https://huggingface.co/diffusers/installation.html#offline-mode) to use this method in a >
        firewalled environment.

        T)r   r   return_unused_kwargsreturn_commit_hashr   Nr'   )load_configr+   )r   r   r   r   r-   r,   commit_hashr'   r'   r(   from_pretrained!  s   4zBaseGuidance.from_pretrainedsave_directorystr | os.PathLikepush_to_hubc                 K  s   | j d||d| dS )a:  
        Save a guider configuration object to a directory so that it can be reloaded using the
        [`~BaseGuidance.from_pretrained`] class method.

        Args:
            save_directory (`str` or `os.PathLike`):
                Directory where the configuration JSON file will be saved (will be created if it does not exist).
            push_to_hub (`bool`, *optional*, defaults to `False`):
                Whether or not to push your model to the Hugging Face Hub after saving it. You can specify the
                repository you want to push to with `repo_id` (will default to the name of `save_directory` in your
                namespace).
            kwargs (`dict[str, Any]`, *optional*):
                Additional keyword arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.
        )r   r   Nr'   )save_config)r&   r   r   r-   r'   r'   r(   save_pretrained^  s   zBaseGuidance.save_pretrained)r   r   T)r   r   r   r   r   r   )r5   r6   r7   r6   r8   r9   r:   r;   )r:   r=   )r:   rB   )rV   rW   r:   r;   )r[   r\   r:   r]   )r[   r\   rc   rd   r:   r]   )r[   r]   r:   r   )r:   r   )r:   r   )r:   r6   )r[   rw   rx   r6   ry   rB   r:   r\   )
rc   rd   r[   r\   rx   r6   ry   rB   r:   r\   )NNF)r   r   r   r   r:   r   )F)r   r   r   r   ) __name__
__module____qualname____doc__GUIDER_CONFIG_NAMEconfig_namer#   rl   r)   r.   r2   r4   r<   rA   rI   rY   rZ   ra   re   rr   rp   propertyrt   rv   r?   classmethodr   r   r   r   r   __classcell__r'   r'   rU   r(   r   &   sF    








*,;r   c                   @  s&   e Zd ZU ded< ded< ded< dS )GuiderOutputztorch.Tensorpredztorch.Tensor | None	pred_condpred_uncondN)r   r   r   __annotations__r'   r'   r'   r(   r   p  s   
 r   r   c                 C  sX   |j ttd|jdd}| j ttd| jdd}| ||  }|| d| |   } | S )a  
    Rescales `noise_cfg` tensor based on `guidance_rescale` to improve image quality and fix overexposure. Based on
    Section 3.4 from [Common Diffusion Noise Schedules and Sample Steps are
    Flawed](https://huggingface.co/papers/2305.08891).

    Args:
        noise_cfg (`torch.Tensor`):
            The predicted noise tensor for the guided diffusion process.
        noise_pred_text (`torch.Tensor`):
            The predicted noise tensor for the text-guided diffusion process.
        guidance_rescale (`float`, *optional*, defaults to 0.0):
            A rescale factor applied to the noise predictions.
    Returns:
        noise_cfg (`torch.Tensor`): The rescaled noise prediction tensor.
    rG   T)dimkeepdim)stdr%   rangendim)	noise_cfgnoise_pred_textguidance_rescalestd_textstd_cfgnoise_pred_rescaledr'   r'   r(   rescale_noise_cfgv  s
   r   )r   )
__future__r   ostypingr   r   r~   huggingface_hub.utilsr   typing_extensionsr   configuration_utilsr   utilsr	   r
   r   r}   r   r   r   r   r   r   r   r'   r'   r'   r(   <module>   s"     L