o
    )i?-                     @   s  d dl mZ d dlmZ d dlmZmZ d dlZd dlm	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 erRd dlmZ G dd dZeG dd dZdededdfddZdejdeej dejfddZ dejdeej dejfddZ!	d)de"e#e#f de$e d e"e#ejf d!ee$e$e   ddf
d"d#Z%d e"e#ejf d$e"e#d%f d&e$ej ddfd'd(Z&dS )*    )defaultdict)	dataclass)TYPE_CHECKINGOptionalN)AttentionBackend)ModelConfigSchedulerConfig)MultiModalEmbeddings)extract_layer_index)MultiModalRegistry)AttentionMetadataBuilder)compute_encoder_budget)KVCacheGroupSpec)	Attentionc                       s|   e Zd ZdZdedededededdf fd	d
Zde	e
ef fddZdefddZde
dede	eef fddZ  ZS )MultiModalBudgetzDHelper class to calculate budget information for multi-modal models.model_configscheduler_configmm_registrymax_model_lenmax_num_reqsreturnNc                   s   t    || _|| _|| _t|||d\}}|| _|| _|| _|| _	|
|| _tttf  }tttf  }	||}
|
 D ]\}}| ||\}}|||< ||	|< q@|
| _|| _|	| _d S )N)r   r   r   )super__init__r   r   r   r   max_num_encoder_input_tokensencoder_cache_sizer   r   Zget_mm_limits_per_prompt	mm_limitsdictstrintZ+get_max_tokens_per_item_by_nonzero_modalityitemsget_max_itemsmax_tokens_by_modality max_items_per_prompt_by_modalitymax_items_per_batch_by_modality)selfr   r   r   r   r   Zencoder_compute_budgetr   r"   r#   r!   modality
max_tokensmax_items_per_promptmax_items_per_batch	__class__ `/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/vllm/v1/worker/utils.pyr      s:   
	



zMultiModalBudget.__init__c                 C   s&   | j }t| dd d\}}||fS )Nc                 S   s   | d S )N   r+   )itemr+   r+   r,   <lambda>K   s    z?MultiModalBudget.get_modality_with_max_tokens.<locals>.<lambda>)key)r!   maxr   )r$   r!   r%   r&   r+   r+   r,   get_modality_with_max_tokensH   s
   
z-MultiModalBudget.get_modality_with_max_tokensc                 C   s   t | j| jS N)minr   r   )r$   r+   r+   r,   get_encoder_budgetO   s   z#MultiModalBudget.get_encoder_budgetr%   max_tokens_per_itemc                 C   s   |dkrdS |   }|dkrdS || }| j| }tdt|| j| }| j}| j}|js5t||j| }|| }	tdt||	}
||
fS )Nr   )r   r   r-   )	r5   r   r1   r4   r   r   r   Zenable_chunked_prefillZmax_num_batched_tokens)r$   r%   r6   Zencoder_budgetZmax_encoder_items_per_batchZmm_limitr'   r   r   Zmax_decoder_items_per_batchr(   r+   r+   r,   r    R   s0   
zMultiModalBudget.get_max_items)__name__
__module____qualname____doc__r   r   r   r   r   tupler   r2   r5   r    __classcell__r+   r+   r)   r,   r      s0    /
r   c                   @   s.   e Zd ZU ee ed< eed< ee ed< dS )AttentionGroupbackendZmetadata_builderlayer_namesN)	r7   r8   r9   typer   __annotations__r   listr   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.get_multimodal_embeddings`][].
    z`Expected multimodal embeddings to be a list/tuple of 2D tensors, or a single 3D tensor, but got zp instead. This is most likely due to incorrect implementation of the model's `get_multimodal_embeddings` 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.0er+   r+   r,   	<genexpr>   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+   )shaperG   r+   r+   r,   
<listcomp>   s    z3sanity_check_mm_encoder_outputs.<locals>.<listcomp>N)
isinstancerB   r;   torchTensorr@   lenall)rC   rD   r+   r+   r,   sanity_check_mm_encoder_outputs   s"   rR   embedsis_embedc                 C   s8   |du r| S | j |jd | jd ftjd}| ||< |S )a  
    Scatter the multimodal embeddings into a contiguous tensor that represents
    the placeholder tokens.

    [`vllm.multimodal.processing.PromptUpdateDetails.is_embed`][].

    Args:
        embeds: The multimodal embeddings.
          Shape: `(num_embeds, embed_dim)`
        is_embed: A boolean mask indicating which positions in the placeholder
          tokens need to be filled with multimodal embeddings.
          Shape: `(num_placeholders, num_embeds)`
    Nr   )Z
fill_value)Znew_fullrK   rN   nan)rS   rT   placeholdersr+   r+   r,   scatter_mm_placeholders   s   rX   rW   c                 C   s   |du r| S | | S )z}
    Reconstructs the embeddings from the placeholder tokens.

    This is the operation of [scatter_mm_placeholders][].
    Nr+   )rW   rT   r+   r+   r,   gather_mm_placeholders   s   	rY   shared_kv_cache_layerskv_cache_groups	kv_cachesattn_groupsc                 C   s   i }|r#t |D ]\}}t |D ]\}}|jD ]}	||f||	< qqqnt |D ]\}}
|
jD ]}	|df||	< q.q'|  D ]*\}	}|| ||	< || d }|| j|	 |rf|| d }|| | j|	 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.
        kv_caches: The allocated kv_caches with layer names as keys.
            Note that layers in shared_kv_cache_layers.keys() are not
            originally included as it only contains layers which have its own
            KV cache allocation.
        attn_groups: Optional list of attention groups. Layers in the same KV
            cache group may be placed in different attention groups if they
            have different attention backends.  Currently only provided by 
            GPU model runner.
    r   r-   N)	enumerater?   r   append)rZ   r[   r\   r]   Zlayer_to_attn_group_idxZkv_cache_group_idxZkv_attn_groupsZattn_group_idxZ
attn_group
layer_nameZkv_cache_groupZtarget_layer_namer+   r+   r,   "initialize_kv_cache_for_kv_sharing   s4   


ra   forward_contextr   runner_kv_cachesc                 C   s   t |dksJ tt}| D ]}|t| | qt| D ]}|| }t |dkr.t|d }|| |  q |  D ]
\}}|g|| _	q>dS )aw  
    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)
rP   r   rB   r
   r_   sortedkeysNotImplementedErrorr   kv_cache)r\   rb   rc   Z
index2namer`   Zlayer_indexr?   rg   r+   r+   r,   bind_kv_cache  s   rh   r3   )'collectionsr   dataclassesr   typingr   r   rN   Z vllm.attention.backends.abstractr   Zvllm.configr   r   Z%vllm.model_executor.models.interfacesr	   Z vllm.model_executor.models.utilsr
   Zvllm.multimodal.registryr   Z vllm.v1.attention.backends.utilsr   Z"vllm.v1.core.encoder_cache_managerr   Zvllm.v1.kv_cache_interfacer   Zvllm.attention.layerr   r   r=   r   rR   rO   rX   rY   r   r   rB   ra   rh   r+   r+   r+   r,   <module>   sv   j




5
