a
    
dJy                     @   sr  d dl mZ d dlZd dlZd dlZd dlmZ d dl	m  m
Z d dlmZmZmZmZmZmZmZ d dlmZ d dlmZ dd Zdd	 ZG d
d dejZG dd dejZG dd dejeZG dd dejZG dd dejZ G dd dejZ!G dd deZ"G dd dejZ#dd Z$G dd dejZ%G dd dejZ&G d d! d!ejZ'G d"d# d#ejZ(dS )$    )abstractmethodN)
checkpointconv_ndlinearavg_pool_ndzero_modulenormalizationtimestep_embedding)SpatialTransformer)existsc                 C   s   d S N xr   r   {/var/www/html/stable-diffusion-webui/repositories/stable-diffusion-stability-ai/ldm/modules/diffusionmodules/openaimodel.pyconvert_module_to_f16   s    r   c                 C   s   d S r   r   r   r   r   r   convert_module_to_f32   s    r   c                       s6   e Zd ZdZdeeeed fddZdd Z  ZS )	AttentionPool2dzS
    Adapted from CLIP: https://github.com/openai/CLIP/blob/main/clip/model.py
    N)spacial_dim	embed_dimnum_heads_channels
output_dimc                    sp   t    tt||d d |d  | _td|d| d| _td||pN|d| _	|| | _
t| j
| _d S )N      g      ?   )super__init__nn	Parameterthrandnpositional_embeddingr   qkv_projc_proj	num_headsQKVAttention	attention)selfr   r   r   r   	__class__r   r   r   $   s    
$
zAttentionPool2d.__init__c                 C   s   |j ^}}}|||d}tj|jddd|gdd}|| jd d d d d f |j }| |}| 	|}| 
|}|d d d d df S )NT)dimkeepdimr+   r   )shapereshaper   catmeanr!   todtyper"   r&   r#   )r'   r   bc_spatialr   r   r   forward2   s    $


zAttentionPool2d.forward)N)__name__
__module____qualname____doc__intr   r7   __classcell__r   r   r(   r   r      s   	 r   c                   @   s   e Zd ZdZedd ZdS )TimestepBlockzT
    Any module where forward() takes timestep embeddings as a second argument.
    c                 C   s   dS )zJ
        Apply the module to `x` given `emb` timestep embeddings.
        Nr   r'   r   embr   r   r   r7   B   s    zTimestepBlock.forwardN)r8   r9   r:   r;   r   r7   r   r   r   r   r>   =   s   r>   c                   @   s   e Zd ZdZdddZdS )TimestepEmbedSequentialzt
    A sequential module that passes timestep embeddings to the children that
    support it as an extra input.
    Nc                 C   sB   | D ]8}t |tr|||}qt |tr4|||}q||}q|S r   )
isinstancer>   r
   )r'   r   r@   contextlayerr   r   r   r7   O   s    


zTimestepEmbedSequential.forward)N)r8   r9   r:   r;   r7   r   r   r   r   rA   I   s   rA   c                       s*   e Zd ZdZd	 fdd	Zdd Z  ZS )
UpsampleaA  
    An upsampling layer with an optional convolution.
    :param channels: channels in the inputs and outputs.
    :param use_conv: a bool determining if a convolution is applied.
    :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then
                 upsampling occurs in the inner-two dimensions.
    r   Nr   c                    sF   t    || _|p|| _|| _|| _|rBt|| j| jd|d| _d S )Nr   padding)r   r   channelsout_channelsuse_convdimsr   conv)r'   rH   rJ   rK   rI   rG   r(   r   r   r   c   s    

zUpsample.__init__c                 C   st   |j d | jksJ | jdkrPtj||j d |j d d |j d d fdd}ntj|ddd}| jrp| |}|S )Nr   r   r      nearest)mode)scale_factorrO   )r.   rH   rK   FinterpolaterJ   rL   r'   r   r   r   r   r7   l   s    
&
zUpsample.forward)r   Nr   r8   r9   r:   r;   r   r7   r=   r   r   r(   r   rE   Z   s   	rE   c                       s*   e Zd ZdZd fdd	Zdd Z  ZS )	TransposedUpsamplez%Learned 2x upsampling without paddingN   c                    s6   t    || _|p|| _tj| j| j|dd| _d S )Nr   kernel_sizestride)r   r   rH   rI   r   ConvTranspose2dup)r'   rH   rI   ksr(   r   r   r   z   s    

zTransposedUpsample.__init__c                 C   s
   |  |S r   )r[   rS   r   r   r   r7      s    zTransposedUpsample.forward)NrV   rT   r   r   r(   r   rU   x   s   rU   c                       s*   e Zd ZdZd	 fdd	Zdd Z  ZS )

DownsampleaD  
    A downsampling layer with an optional convolution.
    :param channels: channels in the inputs and outputs.
    :param use_conv: a bool determining if a convolution is applied.
    :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then
                 downsampling occurs in the inner-two dimensions.
    r   Nr   c                    sz   t    || _|p|| _|| _|| _|dkr2dnd}|rVt|| j| jd||d| _n | j| jksfJ t|||d| _d S )Nr   r   )r   r   r   )rY   rG   rW   )	r   r   rH   rI   rJ   rK   r   opr   )r'   rH   rJ   rK   rI   rG   rY   r(   r   r   r      s    


zDownsample.__init__c                 C   s   |j d | jksJ | |S )Nr   )r.   rH   r^   rS   r   r   r   r7      s    zDownsample.forward)r   Nr   rT   r   r   r(   r   r]      s   r]   c                       s2   e Zd ZdZd fdd	Zdd Zd	d
 Z  ZS )ResBlocka  
    A residual block that can optionally change the number of channels.
    :param channels: the number of input channels.
    :param emb_channels: the number of timestep embedding channels.
    :param dropout: the rate of dropout.
    :param out_channels: if specified, the number of out channels.
    :param use_conv: if True and out_channels is specified, use a spatial
        convolution instead of a smaller 1x1 convolution to change the
        channels in the skip connection.
    :param dims: determines if the signal is 1D, 2D, or 3D.
    :param use_checkpoint: if True, use gradient checkpointing on this module.
    :param up: if True, use this block for upsampling.
    :param down: if True, use this block for downsampling.
    NFr   c                    sl  t    || _|| _|| _|p"|| _|| _|| _|| _t	
t|t	 t||| jddd| _|	pf|
| _|	rt|d|| _t|d|| _n2|
rt|d|| _t|d|| _nt	  | _| _t	
t	 t||rd| j n| j| _t	
t| jt	 t	j|dtt|| j| jddd| _| j|kr8t	 | _n0|rVt||| jddd| _nt||| jd| _d S )Nr   r   rF   Fr   )p)r   r   rH   emb_channelsdropoutrI   rJ   use_checkpointuse_scale_shift_normr   
Sequentialr   SiLUr   	in_layersupdownrE   h_updx_updr]   Identityr   
emb_layersDropoutr   
out_layersskip_connection)r'   rH   ra   rb   rI   rJ   rd   rK   rc   r[   downr(   r   r   r      sV    



	
zResBlock.__init__c                 C   s   t | j||f|  | jS )a  
        Apply the block to a Tensor, conditioned on a timestep embedding.
        :param x: an [N x C x ...] Tensor of features.
        :param emb: an [N x emb_channels] Tensor of timestep embeddings.
        :return: an [N x C x ...] Tensor of outputs.
        )r   _forward
parametersrc   r?   r   r   r   r7      s    zResBlock.forwardc                 C   s   | j rF| jd d | jd  }}||}| |}| |}||}n
| |}| ||j}t|jt|jk r|d }qb| j	r| j
d | j
dd   }}tj|ddd\}	}
||d|	  |
 }||}n|| }| 
|}| || S )Nr*   ).Nr   r   r   r-   )rh   rg   ri   rj   rl   typer3   lenr.   rd   rn   r   chunkro   )r'   r   r@   in_restin_convhemb_outout_normout_restscaleshiftr   r   r   rq      s$    






zResBlock._forward)NFFr   FFFr8   r9   r:   r;   r   r7   rq   r=   r   r   r(   r   r_      s          @r_   c                       s2   e Zd ZdZd fdd	Zdd Zd	d
 Z  ZS )AttentionBlocka  
    An attention block that allows spatial positions to attend to each other.
    Originally ported from here, but adapted to the N-d case.
    https://github.com/hojonathanho/diffusion/blob/1e0dceb3b3495bbe19116a5e1b3596cd0706c543/diffusion_tf/models/unet.py#L66.
    r   r*   Fc                    s   t    || _|dkr || _n*|| dks@J d| d| || | _|| _t|| _td||d d| _|rt	| j| _
nt| j| _
ttd||d| _d S )Nr*   r   zq,k,v channels z' is not divisible by num_head_channels r   r   )r   r   rH   r$   rc   r   normr   qkvr%   r&   QKVAttentionLegacyr   proj_out)r'   rH   r$   num_head_channelsrc   use_new_attention_orderr(   r   r   r     s     



zAttentionBlock.__init__c                 C   s   t | j|f|  dS )NT)r   rq   rr   rS   r   r   r   r7   9  s    zAttentionBlock.forwardc                 C   sV   |j ^}}}|||d}| | |}| |}| |}|| j||g|R  S )Nr*   )r.   r/   r   r   r&   r   )r'   r   r4   r5   spatialr   rx   r   r   r   rq   =  s    

zAttentionBlock._forward)r   r*   FFr~   r   r   r(   r   r     s   	    r   c                 C   sL   |d j ^}}}tt|}d| |d  | }|  jt|g7  _dS )a(  
    A counter for the `thop` package to count the operations in an
    attention operation.
    Meant to be used like:
        macs, params = thop.profile(
            model,
            inputs=(inputs, timestamps),
            custom_ops={QKVAttention: QKVAttention.count_flops},
        )
    r   r   N)r.   r<   npprod	total_opsr   DoubleTensor)model_xyr4   r5   r   num_spatial
matmul_opsr   r   r   count_flops_attnF  s    r   c                       s4   e Zd ZdZ fddZdd Zedd Z  ZS )r   zh
    A module which performs QKV attention. Matches legacy QKVAttention + input/ouput heads shaping
    c                    s   t    || _d S r   r   r   n_headsr'   r   r(   r   r   r   _  s    
zQKVAttentionLegacy.__init__c                 C   s   |j \}}}|d| j  dks"J |d| j  }||| j |d |j|dd\}}}dtt| }	td||	 ||	 }
tj|
	 dd
|
j}
td|
|}||d|S )z
        Apply QKV attention.
        :param qkv: an [N x (H * 3 * C) x T] tensor of Qs, Ks, and Vs.
        :return: an [N x (H * C) x T] tensor after attention.
        r   r   r   r-   bct,bcs->btsr*   bts,bcs->bct)r.   r   r/   splitmathsqrtr   einsumsoftmaxfloatrs   r3   r'   r   bswidthlengthchqkvr|   weightar   r   r   r7   c  s    (zQKVAttentionLegacy.forwardc                 C   s   t | ||S r   r   r   r   r   r   r   r   count_flopsu  s    zQKVAttentionLegacy.count_flops	r8   r9   r:   r;   r   r7   staticmethodr   r=   r   r   r(   r   r   Z  s
   r   c                       s4   e Zd ZdZ fddZdd Zedd Z  ZS )r%   zP
    A module which performs QKV attention and splits in a different order.
    c                    s   t    || _d S r   r   r   r(   r   r   r     s    
zQKVAttention.__init__c              	   C   s   |j \}}}|d| j  dks"J |d| j  }|jddd\}}}dtt| }	td||	 || j ||||	 || j ||}
tj|
	 dd
|
j}
td|
||| j ||}||d|S )z
        Apply QKV attention.
        :param qkv: an [N x (3 * H * C) x T] tensor of Qs, Ks, and Vs.
        :return: an [N x (H * C) x T] tensor after attention.
        r   r   r   r-   r   r*   r   )r.   r   ru   r   r   r   r   viewr   r   rs   r3   r/   r   r   r   r   r7     s    zQKVAttention.forwardc                 C   s   t | ||S r   r   r   r   r   r   r     s    zQKVAttention.count_flopsr   r   r   r(   r   r%   z  s
   r%   c                       s$   e Zd Z fddZdd Z  ZS )Timestepc                    s   t    || _d S r   )r   r   r+   )r'   r+   r(   r   r   r     s    
zTimestep.__init__c                 C   s   t || jS r   )r	   r+   )r'   tr   r   r   r7     s    zTimestep.forward)r8   r9   r:   r   r7   r=   r   r   r(   r   r     s   r   c                       s<   e Zd ZdZd fd
d	Zdd Zdd ZdddZ  ZS )	UNetModela  
    The full UNet model with attention and timestep embedding.
    :param in_channels: channels in the input Tensor.
    :param model_channels: base channel count for the model.
    :param out_channels: channels in the output Tensor.
    :param num_res_blocks: number of residual blocks per downsample.
    :param attention_resolutions: a collection of downsample rates at which
        attention will take place. May be a set, list, or tuple.
        For example, if this contains 4, then at 4x downsampling, attention
        will be used.
    :param dropout: the dropout probability.
    :param channel_mult: channel multiplier for each level of the UNet.
    :param conv_resample: if True, use learned convolutions for upsampling and
        downsampling.
    :param dims: determines if the signal is 1D, 2D, or 3D.
    :param num_classes: if specified (as an int), then this model will be
        class-conditional with `num_classes` classes.
    :param use_checkpoint: use gradient checkpointing to reduce memory usage.
    :param num_heads: the number of attention heads in each attention layer.
    :param num_heads_channels: if specified, ignore num_heads and instead use
                               a fixed channel width per attention head.
    :param num_heads_upsample: works with num_heads to set a different number
                               of heads for upsampling. Deprecated.
    :param use_scale_shift_norm: use a FiLM-like conditioning mechanism.
    :param resblock_updown: use residual blocks for up/downsampling.
    :param use_new_attention_order: use a different attention pattern for potentially
                                    increased efficiency.
    r   r   r   rM      Tr   NFr*   r   c           -         s  t    |r|d usJ d|d urR|s2J dddlm} t||krRt|}|dkr^|}|dkrv|dksvJ d|dkr|dksJ d|_|_|_|_	t
|trt||g _nt|t|krtd|_|d urt|t|ksJ  d urZt tjksJ tt fdd	tt sDJ td
  d| d |_|_|_|	_|_|_|rtjntj_|rtjnj_|_|_|_ |d u_!|d } t"#t$|| t"% t$| | _&jd urt
jtrt"'|| _(nljdkr8td t")d| _(nHjdkrz|d usRJ t"#t"#t$|| t"% t$| | _(nt t"*t+t,|
||dddg_-|_.|g}!|}"d}#t/|D ]\}$}%tj|$ D ]}&t0|"| ||%| |
||dg}'|%| }"|#|v r|dkr|"| }(n|"| }|}(|r>|r:|"| n|}(t1|rR||$ })nd})t1 rn|& |$ k r|'2|st3|"|||(|dnt4|"||(|||)||d j-2t+|'   j.|"7  _.|!2|" q|$t|d kr|"}*j-2t+|rt0|"| ||*|
||ddnt5|"|	|
|*d |*}"|!2|" |#d9 }# j.|"7  _.q|dkr\|"| }(n|"| }|}(|r|r||"| n|}(t+t0|"| ||
||d|st3|"|||(|dnt4|"||(|||||dt0|"| ||
||d_6 j.|"7  _.t"*g _7tt/|d d d D ]r\}$}%tj|$ d D ]R}+|!8 },t0|"|, | |||% |
||dg}'||% }"|#|v r|dkrz|"| }(n|"| }|}(|r|r|"| n|}(t1|r||$ })nd})t1 r|+ |$ k r|'2|st3|"|||(|dnt4|"||(|||)||d |$rZ|+j|$ krZ|"}*|'2|r@t0|"| ||*|
||ddnt9|"|	|
|*d |#d }#j72t+|'   j.|"7  _.q&q
t"#t:|"t"% t;t,|
||ddd_<j!rt"#t:|"t,|
||d_=d S )NzRFool!! You forgot to include the dimension of your cross-attention conditioning...zYFool!! You forgot to use the spatial transformer for your cross-attention conditioning...r   )
ListConfigr*   z3Either num_heads or num_head_channels has to be setzprovide num_res_blocks either as an int (globally constant) or as a list/tuple (per-level) with the same length as channel_multc                    s   j |   |  kS r   )num_res_blocks)inum_attention_blocksr'   r   r   <lambda>      z$UNetModel.__init__.<locals>.<lambda>z7Constructor of UNetModel received num_attention_blocks=z;. This option has LESS priority than attention_resolutions zz, i.e., in cases where num_attention_blocks[i] > 0 but 2**i not in attention_resolutions, attention will still not be set.rM   
continuousz'setting up linear c_adm embedding layerr   
sequentialr   rF   )rI   rK   rc   rd   F)rc   r$   r   r   )depthcontext_dimdisable_self_attn
use_linearrc   T)rI   rK   rc   rd   rp   )rK   rI   r   )rK   rc   rd   )rI   rK   rc   rd   r[   )>r   r   omegaconf.listconfigr   rs   list
image_sizein_channelsmodel_channelsrI   rB   r<   rt   r   
ValueErrorallmaprangeprintattention_resolutionsrb   channel_multconv_resamplenum_classesrc   r   float16float32r3   bfloat16r$   r   num_heads_upsamplepredict_codebook_idsr   re   r   rf   
time_embed	Embedding	label_embLinear
ModuleListrA   r   input_blocks_feature_size	enumerater_   r   appendr   r
   r]   middle_blockoutput_blockspoprE   r   r   outid_predictor)-r'   r   r   r   rI   r   r   rb   r   r   rK   r   rc   use_fp16Zuse_bf16r$   r   r   rd   resblock_updownr   use_spatial_transformertransformer_depthr   n_embedlegacydisable_self_attentionsr   disable_middle_self_attnuse_linear_in_transformeradm_in_channelsr   time_embed_diminput_block_chansr   dslevelmultnrlayersdim_headdisabled_saout_chr   ichr(   r   r   r     s   !


&












 





zUNetModel.__init__c                 C   s(   | j t | jt | jt dS )z<
        Convert the torso of the model to float16.
        N)r   applyr   r   r   r'   r   r   r   convert_to_fp16  s    zUNetModel.convert_to_fp16c                 C   s(   | j t | jt | jt dS )z<
        Convert the torso of the model to float32.
        N)r   r   r   r   r   r   r   r   r   convert_to_fp32  s    zUNetModel.convert_to_fp32c                 K   s   |du| j duksJ dg }t|| jdd}| |}| j durh|jd |jd ksZJ || | }|| j}	| jD ]}
|
|	||}	|	|	 qz| 
|	||}	| jD ]&}
tj|	| gdd}	|
|	||}	q|	|j}	| jr| |	S | |	S dS )aQ  
        Apply the model to an input batch.
        :param x: an [N x C x ...] Tensor of inputs.
        :param timesteps: a 1-D batch of timesteps.
        :param context: conditioning plugged in via crossattn
        :param y: an [N] Tensor of labels, if class-conditional.
        :return: an [N x C x ...] Tensor of outputs.
        Nz<must specify y if and only if the model is class-conditionalF)repeat_onlyr   r   r-   )r   r	   r   r   r.   r   rs   r3   r   r   r   r   r   r0   r   r   r   r   )r'   r   	timestepsrC   r   kwargshst_embr@   rx   moduler   r   r   r7     s.    	




zUNetModel.forward)r   r   Tr   NFFFr*   r*   r*   FFFFr   NNTNNFFN)NNN)	r8   r9   r:   r;   r   r   r   r7   r=   r   r   r(   r   r     s>   %                          6r   ))abcr   r   numpyr   torchr   torch.nnr   Ztorch.nn.functional
functionalrQ   !ldm.modules.diffusionmodules.utilr   r   r   r   r   r   r	   Zldm.modules.attentionr
   ldm.utilr   r   r   Moduler   r>   re   rA   rE   rU   r]   r_   r   r   r   r%   r   r   r   r   r   r   <module>   s.   $	s1 "	