
    ij2                     l    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  ed       G d de             Z	y	)
    )backend)ops)keras_export)KerasTensor)Layerzkeras.layers.Attentionc                        e Zd ZdZ	 	 	 	 d fd	Zd Zd ZddZd Z	 	 	 	 ddZ	ddZ
d	 Z	 	 	 	 dd
ZddZ fdZ xZS )	Attentiona  Dot-product attention layer, a.k.a. Luong-style attention.

    Inputs are a list with 2 or 3 elements:
    1. A `query` tensor of shape `(batch_size, Tq, dim)`.
    2. A `value` tensor of shape `(batch_size, Tv, dim)`.
    3. A optional `key` tensor of shape `(batch_size, Tv, dim)`. If none
        supplied, `value` will be used as a `key`.

    The calculation follows the steps:
    1. Calculate attention scores using `query` and `key` with shape
        `(batch_size, Tq, Tv)`.
    2. Use scores to calculate a softmax distribution with shape
        `(batch_size, Tq, Tv)`.
    3. Use the softmax distribution to create a linear combination of `value`
        with shape `(batch_size, Tq, dim)`.

    Args:
        use_scale: If `True`, will create a scalar variable to scale the
            attention scores.
        dropout: Float between 0 and 1. Fraction of the units to drop for the
            attention scores. Defaults to `0.0`.
        seed: A Python integer to use as random seed in case of `dropout`.
        score_mode: Function to use to compute attention scores, one of
            `{"dot", "concat"}`. `"dot"` refers to the dot product between the
            query and key vectors. `"concat"` refers to the hyperbolic tangent
            of the concatenation of the `query` and `key` vectors.

    Call arguments:
        inputs: List of the following tensors:
            - `query`: Query tensor of shape `(batch_size, Tq, dim)`.
            - `value`: Value tensor of shape `(batch_size, Tv, dim)`.
            - `key`: Optional key tensor of shape `(batch_size, Tv, dim)`. If
                not given, will use `value` for both `key` and `value`, which is
                the most common case.
        mask: List of the following tensors:
            - `query_mask`: A boolean mask tensor of shape `(batch_size, Tq)`.
                If given, the output will be zero at the positions where
                `mask==False`.
            - `value_mask`: A boolean mask tensor of shape `(batch_size, Tv)`.
                If given, will apply the mask such that values at positions
                 where `mask==False` do not contribute to the result.
        return_attention_scores: bool, it `True`, returns the attention scores
            (after masking and softmax) as an additional output argument.
        training: Python boolean indicating whether the layer should behave in
            training mode (adding dropout) or in inference mode (no dropout).
        use_causal_mask: Boolean. Set to `True` for decoder self-attention. Adds
            a mask such that position `i` cannot attend to positions `j > i`.
            This prevents the flow of information from the future towards the
            past. Defaults to `False`.

    Output:
        Attention outputs of shape `(batch_size, Tq, dim)`.
        (Optional) Attention scores after masking and softmax with shape
            `(batch_size, Tq, Tv)`.
    c                     t        |   di | || _        || _        || _        || _        | j                  dkD  r%t        j                  j                  |      | _	        | j                  dvrt        d|       y )Nr   seed)dotconcatz_Invalid value for argument score_mode. Expected one of {'dot', 'concat'}. Received: score_mode= )super__init__	use_scale
score_modedropoutr   r   randomSeedGeneratorseed_generator
ValueError)selfr   r   r   r   kwargs	__class__s         y/var/www/html/emotional.easysim.app/public_html/venv/lib/python3.12/site-packages/keras/src/layers/attention/attention.pyr   zAttention.__init__B   s     	"6""$	<<!")..">">D">"ID??"33((2|5  4    c                    | j                  |       d | _        d | _        | j                  r%| j	                  ddd| j
                  d      | _        | j                  dk(  r&| j	                  ddd| j
                  d      | _        y y )Nscaler   onesT)nameshapeinitializerdtype	trainabler   concat_score_weight)_validate_inputsr   r&   r   
add_weightr$   r   )r   input_shapes     r   buildzAttention.buildY   s    k*
#' >>"jj ) DJ ??h&'+*"jj (7 (D$ 'r   c                    | j                   dk(  rYt        j                  |t        j                  |dd            }| j                   t        j
                  || j                        }|S | j                   dk(  rt        j                  |d      }t        j                  |d      }| j                  I| j                  t        j                  t        j                  | j                  ||z   z        d      z  }|S | j                  t        j                  t        j                  ||z         d      z  }|S t        d      )a  Calculates attention scores as a query-key dot product.

        Args:
            query: Query tensor of shape `(batch_size, Tq, dim)`.
            key: Key tensor of shape `(batch_size, Tv, dim)`.

        Returns:
            Tensor of shape `(batch_size, Tq, Tv)`.
        r   r   axiszscores not computed)r   r   matmulswapaxesr   multiplyexpand_dimsr&   sumtanhr   )r   querykeyscores
q_reshaped
k_reshapeds         r   _calculate_scoreszAttention._calculate_scoresn   s    ??e#ZZs||CR'@AFzz%fdjj9$ # __( R8J26Jzz%11CGGHHTZZ:
+BCD25   11CGGHHZ*45B5   233r   c                    |qt        j                  |      }|j                  dk(  rdnd}t        |j                        dk(  rt        j
                  |d      }t        j                  |||z
  |      }t        j                  |d      }|rE| j                  dkD  r6t        j                  j                  || j                  | j                  	      }t        j                  ||      |fS )
a  Applies attention scores to the given value tensor.

        To use this method in your attention layer, follow the steps:

        * Use `query` tensor of shape `(batch_size, Tq)` and `key` tensor of
            shape `(batch_size, Tv)` to calculate the attention `scores`.
        * Pass `scores` and `value` tensors to this method. The method applies
            `scores_mask`, calculates
            `attention_distribution = softmax(scores)`, then returns
            `matmul(attention_distribution, value).
        * Apply `query_mask` and return the result.

        Args:
            scores: Scores float tensor of shape `(batch_size, Tq, Tv)`.
            value: Value tensor of shape `(batch_size, Tv, dim)`.
            scores_mask: A boolean mask tensor of shape `(batch_size, 1, Tv)`
                or `(batch_size, Tq, Tv)`. If given, scores at positions where
                `scores_mask==False` do not contribute to the result. It must
                contain at least one `True` value in each line along the last
                dimension.
            training: Python boolean indicating whether the layer should behave
                in training mode (adding dropout) or in inference mode
                (no dropout).

        Returns:
            Tensor of shape `(batch_size, Tq, dim)`.
            Attention scores after masking and softmax with shape
                `(batch_size, Tq, Tv)`.
        float16g     @g    eA   r,   r.   r-   r   r   )r   logical_notr$   lenr"   r4   wheresoftmaxr   r   r   r   r1   )r   r9   valuescores_masktrainingpadding_mask	max_valueweightss           r   _apply_scoreszAttention._apply_scores   s    < "??;7L $*<<9#<%I<%%&!+"|"EYY|Vi-?HF++f2.q(nn,,(( - G
 zz'5)722r   c                 b   |rt        j                  |      }d|d   |d   f}t        j                  |d      }t        j                  |d      }t        j                  |d      }t        j                  ||      }	|-t        j
                  |d      }t        j                  ||	      S |	S |S )N   r,   r-   int32)r"   r$   r.   )r   r"   r    cumsumgreater_equalr4   logical_and)
r   r9   v_maskuse_causal_maskscore_shape
mask_shape	ones_mask	row_index	col_indexcausal_masks
             r   _calculate_score_maskzAttention._calculate_score_mask   s     ))F+K[_k"o>JzAI

926I

926I++IyAK!b9v{;; Mr   c                 v   | j                  ||       |d   }|d   }t        |      dkD  r|d   n|}|r|d   nd }	|r|d   nd }
| j                  ||      }| j                  ||
|      }| j	                  ||||      \  }}|	.t        j                  |	d      }	t        j                  |	|d      }|r||fS |S )	Ninputsmaskr   rL   r?   )r7   r8   )r9   rD   rE   rF   r-   r.   )r'   rA   r<   rY   rJ   r   r4   rB   )r   r\   r]   rF   return_attention_scoresrR   qvkq_maskrQ   r9   rE   attention_outputattention_scoress                  r   callzAttention.call   s     	V$71I1IVqF1Ia ad ad''aQ'700FO
 .2-?-?h .@ .
** __V"5F"yy1A1E"$&677##r   c                 h    | j                  ||       ||d   y t        j                  |d         S )Nr[   r   )r'   r   convert_to_tensor)r   r\   r]   s      r   compute_maskzAttention.compute_mask   s:    V$7<47?$$T!W--r   c                 0    |d   }|d   }g |d d |d   S )Nr   rL   r-   r   )r   r)   query_shapevalue_shapes       r   compute_output_shapezAttention.compute_output_shape   s/    !!n!!n3Sb!3;r?33r   c                 r   | j                  ||       |d   }|d   }t        |      dkD  r|d   n|}| j                  |j                  |j                  |j                  g      }	t	        |	| j
                        }
|r:g |j                  d d |j                  d   }|
t	        || j
                        fS |
S )Nr   rL   r?   )r$   r-   r,   )r'   rA   rl   r"   r   compute_dtype)r   r\   r]   r^   rF   rR   r7   rD   r8   output_shapeoutput_specscores_shapes               r   compute_output_speczAttention.compute_output_spec   s     	fd+q	q	v;?fQi00[[%++syy1
 ",d6H6HI"Sb!		"L D$6$6!   r   c                    | j                   j                  }t        |t              st	        | d| d      t        |      dk  st        |      dkD  rt	        | dt        |       d      |Rt        |t              st	        | d| d      t        |      dk  st        |      dkD  rt	        | d| d	| d      yy)
z'Validates arguments of the call method.zj layer must be called on a list of inputs, namely [query, value] or [query, value, key]. Received: inputs=.r?      zl layer accepts inputs list of length 2 or 3, namely [query, value] or [query, value, key]. Received length: NzL layer mask must be a list, namely [query_mask, value_mask]. Received: mask=z< layer accepts mask list of length 2 or 3. Received: inputs=z, mask=)r   __name__
isinstancelistr   rA   )r   r\   r]   
class_names       r   r'   zAttention._validate_inputs  s    ^^,,
&$', $$*81. 
 v;?c&kAo, $$'K=3 
 dD) !l #GGKfAO  4y1}D	A !l #((.xwtfA?  !. r   c                     t         |          }| j                  | j                  | j                  | j
                  d}i ||S )N)r   r   r   r   )r   
get_configr   r   r   r   )r   base_configconfigr   s      r   r{   zAttention.get_config7  sE    g(*//||II	
 )+(((r   )Fr   g        N)NF)NFFF)N)NFNF)rv   
__module____qualname____doc__r   r*   r<   rJ   rY   re   rh   rl   rr   r'   r{   __classcell__)r   s   @r   r	   r	      sq    6t .*B.3`4  %$<.4  %:6) )r   r	   N)
	keras.srcr   r   keras.src.api_exportr   keras.src.backendr   keras.src.layers.layerr   r	   r   r   r   <module>r      s8      - ) ( &'v) v) (v)r   