
    Wi ^                         d dl mZ d dlmZ d dl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mZ de
defdZ	 ddej(                  dee   dee   deddf
dZe G d d             Z G d d      Zy)    )	dataclass)partial)count)AnyN)PretrainedConfig   )traced   )PagedAttentionCache)TMP_TOKEN_IDRequestStateconfigreturnc                     | j                   dv S )z:Checks if attention mask is needed for the given (config).)zpaged|eagerz
paged|sdpa)_attn_implementation)r   s    /home/sietch6/trending-topics-pipeline/venv/lib/python3.12/site-packages/transformers/generation/continuous_batching/input_ouputs.pyattn_mask_is_neededr      s    &&*GGG    attention_maskcumulative_seqlens_qcumulative_seqlens_ksliding_windowc                 J   t        j                  | j                        j                  }t	        t        |      dz
        D ]  }||dz      ||   z
  }||dz      ||   z
  }||k  r|dk\  r	||z
  dz   }nd}t        ||   ||dz            }	t        ||   ||dz            }
t        j                  | d|	|
f   j                  || j                  | j                        }t        j                  ||      }|dkD  r"||z
  |z
  }|t        j                  ||      z  }|| d|	|
f<    y)u  Builds an attention mask inplace using the cumulative seqlens of the query and key. If given a sliding window, it
    will also apply a sliding window mask on top. The attention mask is not boolean, it uses zeroes and -inf (or its
    equivalent) so it's more of an attention score bias tensor.
    The attention mask is a block-diagonal matrix, with each block an attention mask for a single query-key pair.
    Each of those block is built from a causal mask and, if there is a sliding window, a sliding window mask.

    An example is represented below, with seqlen_k = 8, seqlen_q = 4 and sliding_window = 6:

    CAUSAL MASK:

           █ █ █ █ █ ░ ░ ░
           █ █ █ █ █ █ ░ ░
           █ █ █ █ █ █ █ ░
           █ █ █ █ █ █ █ █

    SLIDING WINDOW MASK:
         ┌──────────────────────── seqlen_k - seqlen_q - sliding_window = 8 - 4 - 6 = -2 offset to the left
       <─┴─>
     ░ █ | █ █ █ █ █ █ █ █
     ░ ░ | █ █ █ █ █ █ █ █
     ░ ░ | ░ █ █ █ █ █ █ █
     ░ ░ | ░ ░ █ █ █ █ █ █

    ATTENTION MASK (sum of causal and sliding window masks):

           █ █ █ █ █ ░ ░ ░
           █ █ █ █ █ █ ░ ░
           ░ █ █ █ █ █ █ ░
           ░ ░ █ █ █ █ █ █

    Another example with seqlen_k = 5, seqlen_q = 3 and sliding_window = 2:

    CAUSAL MASK:

           █ █ █ ░ ░
           █ █ █ █ ░
           █ █ █ █ █

    SLIDING WINDOW MASK:
         ┌──────────────────────── seqlen_k - seqlen_q - sliding_window = 5 - 3 - 2 = 0 offset to the left
        <┴>
         | ░ █ █ █ █
         | ░ ░ █ █ █
         | ░ ░ ░ █ █

    ATTENTION MASK (sum of causal and sliding window masks):

           ░ █ █ ░ ░
           ░ ░ █ █ ░
           ░ ░ ░ █ █

    r
   .dtypedevice)diagonalN)torchfinfor   minrangelenslicefullshaper   triutril)r   r   r   r   	min_valueiseqlen_qseqlen_kcausal_diagonalquery_range	key_range	minus_infmaskedsliding_diagonals                 r   build_attention_maskr2   !   sS   t N00155I3+,q01 ='A.1Ea1HH'A.1Ea1HHh8q=&1A5OO035I!a%5PQ.q13GA3NO	JJ3Y67== &&!((	
	 I@A'(2^Cejj5EFFF6<sK23-=r   c                      e Zd ZU dZej
                  ed<   ej
                  eeej
                  f   z  dz  ed<   ej
                  ed<   ej
                  ed<   ej
                  eeej
                  f   z  ed<   e	ed<   e	eee	f   z  ed	<   e
ej
                     ed
<   e
ej
                     ed<   ej
                  ed<   eed<   dZeed<   deeef   fdZy)PagedAttentionArgsa  Dataclass containing the keyword arguments for a forward pass using paged attention.

    Attributes:
        input_ids: Input token IDs tensor of shape `(1, total_query_tokens)`.
        attention_mask: Attention mask tensor or dictionary mapping layer types to masks. Can be `None` if the
            attention implementation doesn't require explicit masks.
        position_ids: Position IDs tensor of shape `(1, total_query_tokens)`.
        cu_seq_lens_q: Cumulative sequence lengths for queries, used for variable-length batching.
        cu_seq_lens_k: Cumulative sequence lengths for keys/values. Can be a tensor or dictionary mapping layer
            types (e.g., "full_attention", "sliding_attention") to tensors for hybrid models.
        max_seqlen_q: Maximum query sequence length in the batch.
        max_seqlen_k: Maximum key/value sequence length. Can be an int or dictionary for hybrid models.
        write_index: List of tensors indicating where to write new KV states in the cache, one per attention group.
        read_index: List of tensors indicating which cache positions to read from, one per attention group.
        logits_indices: Tensor indicating which positions in the output should be used for next-token prediction.
        cache: The [`PagedAttentionCache`] instance managing the KV cache.
        use_cache: Whether to use caching (always `False` in continuous batching as the cache is managed externally).
    	input_idsNr   position_idscu_seq_lens_qcu_seq_lens_kmax_seqlen_qmax_seqlen_kwrite_index
read_indexlogits_indicescacheF	use_cacher   c                    | j                   | j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  | j                  dS )Nr5   r   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   rA   )selfs    r   asdictzPagedAttentionArgs.asdict   sp    "11 --!//!// -- --++//"11ZZ
 	
r   )__name__
__module____qualname____doc__r   Tensor__annotations__dictstrintlistr   r?   boolr   rC    r   r   r4   r4   u   s    & ||LL4U\\(9#::TAA,,<<<<$sELL'8"999S#X&&ell##U\\""LL It
S#X 
r   r4   c            
           e Zd ZdZdededej                  dej                  ddf
dZ	 e
d	
      dd       Ze
 ej                         ddeddfd              Ze
dee   ddfd       Zddededeeef   fdZy)ContinuousBatchingIOsa?  Manages input/output tensors for continuous batching generation. This class handles the allocation and management
    of static tensors used during generation steps in continuous batching mode. Allocation is done once at init time.

    The class is responsible for:
    - Setting up static tensor storage for all generation inputs/outputs
    - Preparing batch tensors from a list of request states before each forward pass
    - Building model keyword arguments with optional padding for CUDA graphs/torch.compile
    - Resetting tensors between batches while minimizing memory operations

    It keeps track of the requests in the current batch as well as the actual number of tokens (Q and KV), sequences in
    the batch and sizes of indices. This is useful when using padded inputs, for CUDA graphs and/or torch.compile.
    r>   r   r   model_dtyper   Nc                 R   || _         || _        || _        || _        t	        |dd      dn|j
                  | _        g | _        d| _        d| _        d| _	        t        |j                        D cg c]  }d c}| _        | j                          | j                  d       yc c}w )aF  Initialize the continuous batching I/O manager.

        Args:
            cache: The [`PagedAttentionCache`] instance managing the KV cache.
            config: The model's pretrained configuration.
            device: The device to allocate tensors on.
            model_dtype: The data type for model computations.
        r   Nr
   r   r   r   T)
full_reset)r>   r   r   rR   getattrr   requests_in_batchactual_query_lengthactual_key_lengthactual_batch_sizer!   
num_groupsactual_index_sizessetup_static_tensorsreset_static_tensors)rB   r>   r   r   rR   _s         r   __init__zContinuousBatchingIOs.__init__   s     
&#*63CT#J#RaX^XmXm57#$ !"!"389I9I3J"Ka6"K!!#!!T!2 #Ls   0	B$T)
standalonec                    | j                   j                  | j                   j                  z  }t        j                  d| j                   j
                  ft        j                  | j                        | _        t        j                  d| j                   j
                  ft        j                  | j                        | _	        t        j                  | j                   j
                  dz   ft        j                  | j                        | _
        d| _        t        j                  | j                   j
                  ft        j                  | j                        | _        t        j                  | j                   j
                  ft        j                  | j                        | _        i | _        | j                   j                  rUt        j                  | j                   j
                  dz   ft        j                  | j                        | j                  d<   | j                   j                   rUt        j                  | j                   j
                  dz   ft        j                  | j                        | j                  d<   t"        j%                  | j                  j'                         d      | _        t+        | j,                        ri | _        | j                  j'                         D ]j  }t        j                  dd| j                   j
                  || j                   j
                  z   f| j0                  | j                        | j.                  |<   l nd| _        t3        | j                   j4                        D cg c]G  }t        j                  | j                   j
                  ft        j                  | j                        I c}| _        t3        | j                   j4                        D cg c]I  }t        j                  || j                   j
                  z   t        j                  | j                        K c}| _        yc c}w c c}w )a  Allocates static tensors for generation inputs and outputs. This is called only once at init time, to avoid
        repeated allocations and enable CUDA graphs. All tensors are allocated with maximum possible sizes.
        The allocated tensors are:

        - `input_ids` and `position_ids`: Query token information
        - `cumulative_seqlens_q` and `cumulative_seqlens_k`: Sequence length tracking for FlashAttention-style batching
        - `attention_mask`: Optional attention masks (only for eager/SDPA implementations)
        - `write_index` and `read_index` storage: Cache indexing tensors for each attention group
        - `output_ids`: Storage for generated token IDs
        r
   r   r   full_attentionsliding_attention)sizer   r   N)r>   
num_blocks
block_sizer   emptymax_batch_tokensint32r   r5   r6   r   r9   r=   
output_idsr   num_full_attention_groupsnum_sliding_attention_groupsrJ   fromkeyskeysr:   r   r   r   rR   r!   r[   write_index_storageread_index_storage)rB   	num_pages
layer_typer_   s       r   r]   z*ContinuousBatchingIOs.setup_static_tensors   s    JJ))DJJ,A,AA	 a)D)D%EU[[aealalm!KKDJJ,G,G(HPUP[P[dhdodop$)KKZZ((1,.ekk$++%
! #kk4::+F+F*HPUP[P[dhdodop++tzz'B'B&DEKK`d`k`kl >@!:://:?++,,q02%++dkk;D%%&67 ::22=B[[,,q02%++dkk>D%%&9: !MM$*C*C*H*H*JANt{{+"$D"77<<> 
27++Q

 ; ;YIdId=de**;;3##J/ #'D
 4::001$
 KK446ekkRVR]R]^$
  4::001#
 KKTZZ%@%@@]a]h]hi#
	$
#
s   AQ=AQrU   c                 x   |r| j                   d   j                  d      n| j                  }|r| j                  d   j                  d      n| j                  }|r| j                   d   j                  d      n| j
                  }| j                  ddd|f   j                          | j                  ddd|f   j                          | j                  d|dz    j                          d| _
        | j                  d| j                  d       | j                  d| j                  d       | j                  D ]  }| j                  |   d|dz    j                          d| j                  |<   | j                   B| j                   |   ddddd|d|f   j                  t#        j$                  | j&                        j(                          t+        | j,                  j.                        D ]G  }| j                   |   d| j                  d       | j                  |   d||z    j                  d       I y)aA  Reset static tensors for the next batch. For efficiency, this only resets the portions of tensors that were
        actually used in the previous batch, using the attributes actual_query_length, actual_key_length, and
        actual_batch_size. If a (full_reset) is requested, the entire tensor storage is reset.
        r   Nr
   )rp   re   rX   rq   rY   rZ   r5   zero_r6   r   r9   r=   fill_rk   r   r:   r   r   r   rR   r    r!   r>   r[   )rB   rU   q_lenk_lenb_sizers   r)   s          r   r^   z*ContinuousBatchingIOs.reset_static_tensors  s    9C((+004H`H`7A''*//3tG]G]8B))!,11!4H^H^ 	q&5&y!'')!VeV)$**,!!,FQJ/557FU#))"-%%b) 33 	oJ%%j1,FQJ?EEG,-Dj)"".##J/1fuffuf0DEKKEKKX\XhXhLiLmLmn		o tzz,,- 	BA$$Q'/55b9##A&7==bA	Br   rW   c                 $	   || _         | j                   st        d      | j                          d| _        d| _        d| _        g }g }dg}g }| j                  j                         D ci c]  }|dg }}t        | j                  j                        D cg c]  }g  }	}t        | j                  j                        D cg c]  }g  }
}| j                   D ]  }|j                  }t        |j                        }| j                  j                  ||      }| xj                  |z  c_        | xj                  t        |j!                               z  c_        | xj
                  dz  c_        |xj                  |z  c_        |j#                  |j                         |j#                  t        |||z                |j%                  |d   |z          t        | j&                  |      | _        |j)                         D ]H  \  }}||   j%                  ||   d   |z          t        | j*                  |   |      | j*                  |<   J | j                  j-                  |j.                  |||	|
       |j0                  r|j%                  |d   dz
         |j2                  j%                  t4                t7        t8        j:                  t8        j<                  | j>                        } ||      | j@                  dddt        |      f<    ||      | jB                  dddt        |      f<    ||      | jD                  dt        |        ||      | jF                  dt        |       |d   | _$        |j)                         D ]`  \  }} ||      | j                  |   dt        |       | jJ                  4tM        | jJ                  |   |||dk(  r| jN                  nd       b g | _(        g | _)        tU        tW               |	|
      D ]k  \  }}} ||      | jX                  |   dt        |        ||      | jZ                  |   dt        |       t        |      t        |      f| j\                  |<   m yc c}w c c}w c c}w )	a  Prepare tensors and metadata for the next model forward pass, using the given requests as data. This method:

        1. Resets the static tensors from the previous batch
        2. Iterates through requests to accumulate input_ids, position_ids, and sequence lengths
        3. Extends read/write indices for cache management
        4. Builds attention masks if needed (for eager/SDPA implementations)
        5. Converts accumulated lists to tensors and copies them to static storage

        This method also modifies the `position_offset` attribute of each request to track progress and adds a
        temporary token at the end of the requests for which there will a new token.
        zNo requests in batchr   r
   ru   r   Nrd   )r   r   r   r   )/rW   
ValueErrorr^   rX   rY   rZ   r   ro   r!   r>   r[   position_offsetr"   tokens_to_processget_seqlens_kmaxvaluesextendappendr9   itemsr:   extend_read_and_write_indices
request_idremaining_prefill_tokensgenerated_tokensr   r   r   tensorrj   r   r5   r6   r   r=   total_seqlen_qr   r2   r   r<   r;   zipr   rq   rp   r\   )rB   rW   r5   r6   r   r=   rs   r   r_   r<   r;   statepast_lengthquery_length	seqlens_klayer_type_seqlen_k	to_tensorlayer_type_seqlens_kr)   group_read_indicesgroup_write_indicess                        r   prepare_batch_tensorsz+ContinuousBatchingIOs.prepare_batch_tensors+  sj    "3%%344 	!!##$ !"!" 	 !sBFB[B[B`B`BbcJ
QCcc"'

(=(=">?Qb?
?#()>)>#?@ar@@ ++ !	<E//Ku667L

00lKI $$4$""c)*:*:*<&=="""a'"!!\1! U445k;3M NO ''(<R(@<(OP #D$5$5| DD 4=??3D h/
/$Z0778LZ8XY[8\_r8rs03D4E4Ej4QSf0g!!*-h
 JJ44  +|Z
 11%%&:2&>&BC&&--l;C!	<J ELLDKKP	 /8	.Bq*C	N**+4=l4K!0s<0001AJK_A`!!"=C(<$=>5>~5N1c.12226 1E0J0J0L 	,J,QZ[oQpD%%j12MC8L4MN"".$#'#6#6z#B)=)=:DH[:[4#6#6ab		 :=egzS^:_ 	]6A!#6DMN`DaD##A&'@-?)@AFOPcFdD$$Q'(B#.A*BC*-.@*A3GZC[)\D##A&	]C  d?@s   )R	R	Rpadded_q_sizepadded_kv_cache_sizec                    |dkD  xr |dkD  }|r|n| j                   }|r|n| j                  }||z   }t        | j                  ddd|f   | j                  ddd|f   | j
                  d|dz    | j                  | j                  d| i i i g g | j                  d      }|rUt        | j                  || j                  z
        | _        | j                  |_        || j
                  | j                  dz   d t        | j                        D ]j  \  }\  }	}
|r|n|	}	|r|n|
}
|j                  j                  | j                  |   d|	        |j                   j                  | j"                  |   d|
        l t%        | j&                  j)                               }t+        |      dkD  ri |_        i |_        i |_        | j&                  j3                         D ]r  \  }}|d|dz    |j.                  |<   | j,                  |   |j,                  |<   | j0                  D|r|n||   }| j0                  |   dd|d|f   |j0                  |<   t ns|d   }| j&                  |   d|dz    |_        | j,                  |   |_        | j0                  4|r|n| j&                  |   |   }| j0                  |   dd|d|f   |_        | j0                  d|_        |j5                         S )a6  Get model keyword arguments for the current batch, eventually padding the query dimension to (padded_q_size)
        and the keys/values dimension to (padded_kv_cache_size). The padding is only useful if we want static shapes,
        like when using cuda graphs AND only activated if both Q and KV are padded.r   Nr
   F)r5   r6   r7   r9   r=   r8   r:   r   r<   r;   r>   r?   .)rX   rZ   r4   r5   r6   r   r9   r=   r>   r   r   	enumerater\   r<   r   rq   r;   rp   rM   r   ro   r"   r:   r8   r   r   rC   )rB   r   r   use_paddingry   r{   padded_kv_sizekwargsr)   read_index_sizewrite_index_sizelayer_typesrs   r   rz   s                  r   get_model_kwargsz&ContinuousBatchingIOs.get_model_kwargs  s5   
 $a'D,@1,D!,$2J2J"-43I3I&)== $nnQY/**1fuf9533LfqjA**..v6**
$  #D$5$5ut?R?R7R SD"&"3"3FFKD%%d&<&<q&@&BC 7@@W@W6X 	V2A2!10;nO0;}AQ$$T%<%<Q%?@P%QR%%d&>&>q&ABSCS&TU		V 44499;<{a24F<>F =?F!)-)B)B)H)H)J m%
I3<\vz3J$$Z0262C2CJ2O##J/&&2.9Ny?PE8<8K8KJ8WX[]c^c]cekfkekXk8lF))*5m %QJ#'#<#<Z#H6TU:#VF "&"3"3J"?F"".*54;T;TU_;`ag;h(,(;(;J(GVeVU[V[U[H[(\%&$(F!}}r   )r   N)FrT   )rD   rE   rF   rG   r   r   r   r   r   r`   r	   r]   no_gradrN   r^   rM   r   r   rL   rJ   rK   r   r   rO   r   r   rQ   rQ      s    3(32B3LQLL3glgrgr3	36 t6
 6
r U]]_Bt B B  B< a]tL7I a]d a] a]FAc AS AY]^acf^fYg Ar   rQ   )r
   )dataclassesr   	functoolsr   	itertoolsr   typingr   r    transformers.configuration_utilsr   utils.metricsr	   r>   r   requestsr   r   rN   r   rH   rM   rL   r2   r4   rQ   rO   r   r   <module>r      s    "     = # & 0H 0 HT H 	Q=LLQ=s)Q= s)Q= 	Q=
 
Q=h /
 /
 /
dh hr   