o
    i$                     @   st  d dl Z d dlmZ d dlmZmZ d dlZd dlmZm	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 d d
lmZmZ d dlmZmZ d dlmZmZ eeZeG dd dZdede ddfddZ!dedede fddZ"	d(de#e$e$f de%e de&e$ dB ddfddZ'	d)de#e$ej(f de#e$ef d e%ej( d!e ddf
d"d#Z)d$e	d%e de*fd&d'Z+dS )*    N)defaultdict)	dataclassfield)CacheConfig
VllmConfig)init_logger)	Attention)MultiModalEmbeddings)extract_layer_index)current_platform)MemorySnapshot
format_gib)AttentionBackendAttentionMetadataBuilder)KVCacheGroupSpecKVCacheSpecc                   @   s~   e Zd ZU ee ed< ee ed< eed< e	ed< e
dd dZee ed< 		dd
e	dB de	fddZdde	defddZdS )AttentionGroupbackendlayer_nameskv_cache_speckv_cache_group_idc                   C   s   g S N r   r   r   J/home/ubuntu/vllm_env/lib/python3.10/site-packages/vllm/v1/worker/utils.py<lambda>    s    zAttentionGroup.<lambda>)default_factorymetadata_builders   kernel_block_sizeNnum_metadata_buildersc                    s<   |d ur
j |nj  fddt|D _d S )Nc                    s"   g | ]}j  j qS r   )r   get_builder_clsr   ).0_devicekv_cache_spec_builderselfvllm_configr   r   
<listcomp>/   s    z;AttentionGroup.create_metadata_builders.<locals>.<listcomp>)r   copy_with_new_block_sizeranger   )r&   r'   r$   r   r   r   r#   r   create_metadata_builders#   s   	z'AttentionGroup.create_metadata_buildersr   	ubatch_idreturnc                 C   s   t | j|ks	J | j| S r   )lenr   )r&   r,   r   r   r   get_metadata_builder9   s   
z#AttentionGroup.get_metadata_builderr   )r   )__name__
__module____qualname__typer   __annotations__liststrr   intr   r   r   r+   r/   r   r   r   r   r      s   
 	
r   mm_embeddingsexpected_num_itemsr-   c                 C   s|   t | tttjfsJ dt|  dt| |ks&J d| dt| dtdd | D s<J ddd	 | D  dd
S )z{
    Perform sanity checks for the result of
    [`vllm.model_executor.models.SupportsMultiModal.embed_multimodal`][].
    z`Expected multimodal embeddings to be a list/tuple of 2D tensors, or a single 3D tensor, but got zg instead. This is most likely due to incorrect implementation of the model's `embed_multimodal` method.zIExpected number of multimodal embeddings to match number of input items: z, but got len(mm_embeddings)=c                 s   s    | ]}|j d kV  qdS )   N)ndimr!   er   r   r   	<genexpr>T   s    z2sanity_check_mm_encoder_outputs.<locals>.<genexpr>z[Expected multimodal embeddings to be a sequence of 2D tensors, but got tensors with shapes c                 S   s   g | ]}|j qS r   )shaper=   r   r   r   r(   V   s    z3sanity_check_mm_encoder_outputs.<locals>.<listcomp>N)
isinstancer6   tupletorchTensorr4   r.   all)r9   r:   r   r   r   sanity_check_mm_encoder_outputs>   s"   rF   init_snapshotcache_configc                 C   s\   t | j|j }| j|k r,td| j dt| j dt| j d|j dt| d|S )z
    Calculate the amount of memory required by vLLM, then validate
    that the current amount of free memory is sufficient for that.
    zFree memory on device z (/z> GiB) on startup is less than desired GPU memory utilization (z, zT GiB). Decrease GPU memory utilization or reduce GPU memory used by other processes.)mathceiltotal_memorygpu_memory_utilizationfree_memory
ValueErrordevice_r   )rG   rH   requested_memoryr   r   r   request_memory\   s    



rR   shared_kv_cache_layerskv_cache_groupsrunner_only_attn_layersc                 C   s^   i }|D ]}|j D ]}|||< q	q|  D ]\}}|| }|j | |dur,|| qdS )a  
    Sets up KV cache sharing by reusing the allocated KV caches in `kv_caches`
    for layers that do not allocate its own KV cache, based on the mapping in
    `shared_kv_cache_layers`. Adds these layers to the corresponding KV cache
    group, which is needed to ensure that attention metadata is assigned later.

    Args:
        shared_kv_cache_layers: Layer pairings for cross-layer KV sharing.
            If an Attention layer `layer_name` is in the keys of this dict, it
            means this layer will perform attention using the keys and values
            from the KV cache of `shared_kv_cache_layers[layer_name]`.
        kv_cache_groups: The KV cache groups of the model.
    N)r   itemsappendadd)rS   rT   rU   layer_to_kv_cache_groupkv_cache_group
layer_nametarget_layer_nametgt_kv_cache_groupr   r   r   (add_kv_sharing_layers_to_kv_cache_groupss   s   


r^   r   	kv_cachesforward_contextrunner_kv_cachesnum_attn_modulec           	      C   s   t |dksJ tt}| D ]}|t|| | qt| D ]'}|| }t |dkr<t s9t	 s9t
 r:nt|D ]	}|| |  q>q!|  D ]
\}}|g|| _qMdS )a{  
    Bind the allocated KV cache to both ModelRunner and forward context so
    that the KV cache can be used in the forward pass.

    This function:
      1) Fills the ModelRunner's kv cache list (`runner_kv_caches`) with
         kv_caches.
      2) Associates each attention layer in the `forward_context` with its
         corresponding KV cache in kv_caches.

    Args:
        kv_caches: The allocated kv_caches with layer names as keys.
        forward_context: The global forward context containing all Attention
            layers with layer names as keys.
        runner_kv_caches: The kv_cache declared by ModelRunner.
    r   r   N)r.   r   r6   r
   rW   sortedkeysr   is_cuda_alikeis_xpuis_cpuNotImplementedErrorrV   kv_cache)	r_   r`   ra   rb   
index2namer[   layer_indexr   ri   r   r   r   bind_kv_cache   s*   	rl   r'   num_input_tokensc                 C   sb   | j jjsdS | jj}|dkrdS || dksJ | j jr!| j jr#dS | j j}|du r-dS ||v S )a  Check if the residual tensor is scattered for sequence parallelism.

    The residual tensor is scattered across tensor parallel ranks when sequence
    parallelism and tensor parallelism is enabled.

    This follows the same logic as SequenceParallelismPass.is_applicable_for_range():
    - In full-graph compilation mode (no splitting ops or using inductor graph
      partition), SP is always applied
    - Otherwise, SP is only applied for specific shapes in compile_sizes
    Fr   r   TN)compilation_configpass_config	enable_spparallel_configtensor_parallel_sizesplitting_opsuse_inductor_graph_partitioncompile_sizes)r'   rm   tpru   r   r   r   is_residual_scattered_for_sp   s   
rw   r   r0   ),rJ   collectionsr   dataclassesr   r   rC   vllm.configr   r   vllm.loggerr   $vllm.model_executor.layers.attentionr   %vllm.model_executor.models.interfacesr	    vllm.model_executor.models.utilsr
   vllm.platformsr   vllm.utils.mem_utilsr   r   vllm.v1.attention.backendr   r   vllm.v1.kv_cache_interfacer   r   r1   loggerr   r8   rF   rR   dictr7   r6   setr^   rD   rl   boolrw   r   r   r   r   <module>   sj   '



#

<