o
    )i                     @   s   d dl mZmZ d dlmZ d dlmZmZmZm	Z	m
Z
mZ d dlmZmZ d dlmZ d dlmZ d dlmZmZmZmZmZmZmZmZ d dl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'm(Z( d dl)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/ ddl0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7 ddl8m9Z9m:Z:m;Z;m<Z< erd dl=m>Z> d dl?m@Z@ d dlAmBZB ddlCmDZD e$eEZFedeGeHeI ZJeeGeHeI f ZK	 eG dd dZLG dd dZMeeKeLf ZN	 eG dd deeJ ZOeeKeOf ZP	 eeeIgePf ePf ZQ	 G dd deGeZReG d d! d!eZSeG d"d# d#eSZTeG d$d% d%eSZUed&d'dd(d)e&d*eGd+eeV d,eHeI fd-d.ZWed&d'dd/d)e&d0eXeId1f d2eeV d,eGfd3d4ZYG d5d6 d6eZZG d7d8 d8eZ[ed9eeZe[f d:Z\d;e	e\ d,eeGeHe\ f fd<d=Z]eG d>d? d?Z^eG d@dA dAZ_eG dBdC dCZ`G dDdE dEeZad0eHeI dFeHeI d,eea fdGdHZbd0eHeI dFeHeI dIeHeI d,eHeI fdJdKZcedLdMG dNdO dOeZdedLdMG dPdQ dQedZeedLdMG dRdS dSedZfedLdMG dTdU dUedZgeG dVdW dWZhdXeHeI dYee` d,eed fdZd[ZidXeGdYee` d,eed fd\d]ZjdXeKd^e
eGeed f d,eHed fd_d`ZkdXeJd^e
eGeed f dae
eGeIf d,eHeJ fdbdcZldXeHeI d^e
eGeed f dae
eGeIf d,eHeI fdddeZmdXeGd^e
eGeed f dae
eGeIf d,eGfdfdgZndhe
eGee` f dXeHeI dae
eGeIf d,e	eh fdidjZodhe
eGee` f dXeHeI dae
eGeIf d,e
eGeHeh f fdkdlZpG dmdn dne-Zqee6eGf ZrG dodp dpZsedqesd:ZteueGeHeG f Zv	 G drds dseeet ZwG dtdu duewet ZxdS )v    )ABCabstractmethod)defaultdict)Callable	Generator	ItemsViewIterableMappingSequence)	dataclassfield)Enum)	lru_cache)TYPE_CHECKINGGeneric
NamedTupleOptionalProtocolTypeVarUnioncastN)assert_never)InputProcessingContext)init_logger)AnyTokenizerdecode_tokensencode_tokens)flatten_2d_listsfull_groupby   )MultiModalCache)MultiModalHasher)MultiModalDataDictMultiModalEncDecInputsMultiModalFieldConfigMultiModalInputsMultiModalKwargsMultiModalKwargsItemPlaceholderRange)DictEmbeddingItemsEmbeddingItemsMultiModalDataItemsMultiModalDataParser)PretrainedConfig)BatchFeature)ProcessorMixin)BaseDummyInputsBuilder_Sc                   @   s*   e Zd ZU dZeeegee f e	d< dS )PromptIndexz#Resolves to an index in the prompt.get_match_indexN)
__name__
__module____qualname____doc__r   r   	PromptSeqr   int__annotations__ r;   r;   f/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/vllm/multimodal/processing.pyr2   .   s   
 r2   c                   @   sF   e Zd ZedefddZededefddZedefddZd	S )
PromptIndexTargetsreturnc                   C      t dd S )z
        Resolves to the start of the prompt (before the first token).

        This results in a match even if the prompt is empty.
        c                 S      dS Nr   r;   tokpromptr;   r;   r<   <lambda>=       z*PromptIndexTargets.start.<locals>.<lambda>r2   r;   r;   r;   r<   start6      zPromptIndexTargets.startseqc                    s&   dt dtdtt f fdd}t|S )zN
        Resolves to a location in the prompt after the given prefix.
        	tokenizerrD   r>   c                    s\    }t |trt |tst| |}nt |trt| |dd}t|}|d | |kr,|S d S NFadd_special_tokens)
isinstancestrr   r   len)rK   rD   prefix	match_idxrJ   r;   r<   r3   E   s   



z2PromptIndexTargets.prefix.<locals>.get_match_index)r   r8   r   r9   r2   )rJ   r3   r;   rT   r<   rR   ?   s   zPromptIndexTargets.prefixc                   C   r?   )z
        Resolves to the end of the prompt (after the last token).

        This results in a match even if the prompt is empty.
        c                 S   s   t |S NrQ   rB   r;   r;   r<   rE   b   s    z(PromptIndexTargets.end.<locals>.<lambda>rG   r;   r;   r;   r<   end[   rI   zPromptIndexTargets.endN)	r4   r5   r6   staticmethodr2   rH   r8   rR   rW   r;   r;   r;   r<   r=   4   s    r=   c                   @   s   e Zd ZU dZeed< 	 dZeedge	j
f  ed< 	 ededdfd	d
ZedededdfddZedededdfddZdS )PromptUpdateDetailszEDetails about the token sequence or text that are part of the update.fullN_BoundPromptSequenceis_embedrJ   r>   zPromptUpdateDetails[_S]c                 C   s
   t | dS )N)rZ   rY   rT   r;   r;   r<   from_seq~      
zPromptUpdateDetails.from_seq
embed_textc                    s$   dddt jf fdd}t| |dS )NrZ   r[   r>   c                    s&   t | j }tt| jt|S rU   )r   rK   torchisintensor	token_ids)rZ   Zembed_token_idsr`   r;   r<   r\      s
   
z1PromptUpdateDetails.select_text.<locals>.is_embedrZ   r\   )ra   TensorrY   )rJ   r`   r\   r;   re   r<   select_text   s   zPromptUpdateDetails.select_textembed_token_idc                    s   t |  fdddS )Nc                    s   t | j kS rU   )ra   rc   rd   )fri   r;   r<   rE      s    z5PromptUpdateDetails.select_token_id.<locals>.<lambda>rf   r]   )rJ   ri   r;   rk   r<   select_token_id   s   
z#PromptUpdateDetails.select_token_id)r4   r5   r6   r7   r1   r:   r\   r   r   ra   rg   rX   r^   rP   rh   r9   rl   r;   r;   r;   r<   rY   k   s0   
 rY   c                   @   s   e Zd ZdZdZdS )
UpdateModeinsertreplaceN)r4   r5   r6   INSERTREPLACEr;   r;   r;   r<   rm      s    rm   c                   @   sd   e Zd ZU dZeed< 	 eed< 	 eede	fddZ
eedefddZd	edd
fddZdS )PromptUpdatezA
    Defines how to update a prompt with placeholder tokens.
    modalitytargetr>   c                 C      t z3The placeholder tokens that are part of the update.NotImplementedErrorselfr;   r;   r<   content      zPromptUpdate.contentc                 C   ru   z!Defines how to update the prompt.rw   ry   r;   r;   r<   mode   r|   zPromptUpdate.moderK   BoundPromptUpdatec                 C   s   t | |dS )N)_originrK   r   )rz   rK   r;   r;   r<   bind   s   zPromptUpdate.bindN)r4   r5   r6   r7   rP   r:   PromptTargetpropertyr   PromptUpdateContentr{   rm   r~   r   r   r;   r;   r;   r<   rr      s   
 rr   c                   @   J   e Zd ZU dZeddZeed< 	 edefddZ	ede
fdd	Zd
S )PromptInsertiona  
    Defines how to insert placeholder tokens into a prompt.

    Example:

    For each image, insert a number of ``<image>`` feature placeholders
    equal to the feature size of the vision encoder after the ``<s>`` token:

    ```python
    PromptInsertion(
        modality="image",
        target="<s>",
        insertion="<image>" * image_feature_size,
    )
    ```

    Insert these tokens at the start of the prompt:

    ```python
    PromptInsertion(
        modality="image",
        target=PromptIndexTargets.start(),
        insertion="<image>" * image_feature_size,
    )
    ```

    Insert these tokens after a prefix ``Images:``:

    ```python
    PromptInsertion(
        modality="image",
        target=PromptIndexTargets.prefix("Images:"),
        insertion="<image>" * image_feature_size,
    )
    ```

    Insert these tokens at the end of the prompt:

    ```python
    PromptInsertion(
        modality="image",
        target=PromptIndexTargets.end(),
        insertion="<image>" * image_feature_size,
    )
    ```
    Frepr	insertionr>   c                 C      | j S rU   )r   ry   r;   r;   r<   r{        zPromptInsertion.contentc                 C      t jS rU   )rm   rp   ry   r;   r;   r<   r~     r   zPromptInsertion.modeN)r4   r5   r6   r7   r   r   r   r:   r   r{   rm   r~   r;   r;   r;   r<   r      s   
 /
r   c                   @   r   )PromptReplacementa  
    Defines how to replace portions of an input prompt with placeholder tokens.

    Example:

    For each image, replace one ``<image>`` input placeholder in the prompt
    with a number of ``<image>`` feature placeholders
    equal to the feature size of the vision encoder:

    ```python
    PromptReplacement(
        modality="image",
        target="<image>",
        replacement="<image>" * image_feature_size,
    )
    ```

    As above, but further pad the feature placeholders with ``<image_bos>``
    and `<image_eos>``, which are not supposed to be passed to the vision
    encoder:

    ```python
    PromptReplacement(
        modality="image",
        target="<image>",
        replacement=PromptUpdateDetails(
            full="".join([
                "<image_bos>",
                "<image>" * image_feature_size,
                "<image_eos>",
            ]),
            features="<image>" * image_feature_size,
        ),
    )
    ```

    To avoid unnecessary tokenization during prompt replacement,
    we recommended passing token sequences instead of text:

    ```python
    PromptReplacement(
        modality="image",
        target=[image_token_id],
        replacement=PromptUpdateDetails(
            full=([image_bos_id] + [image_token_id] * image_feature_size
                    + [image_eos_id]),
            features=[image_token_id] * image_feature_size,
        ),
    )
    ```
    Fr   replacementr>   c                 C   r   rU   )r   ry   r;   r;   r<   r{   \  r   zPromptReplacement.contentc                 C   r   rU   )rm   rq   ry   r;   r;   r<   r~   `  r   zPromptReplacement.modeN)r4   r5   r6   r7   r   r   r   r:   r   r{   rm   r~   r;   r;   r;   r<   r     s   
 4
r   i   )maxsizerM   rK   textrN   r>   c                C   s   t | ||dS )NrM   )r   )rK   r   rN   r;   r;   r<   _cached_encodee  s   r   skip_special_tokensrd   .r   c                C   s   t | t||dS )Nr   )r   list)rK   rd   r   r;   r;   r<   _cached_decodeq  s   r   c                   @   s   e Zd ZU eed< dS )_HasModalityAttrrs   N)r4   r5   r6   rP   r:   r;   r;   r;   r<   r   }  s   
 r   c                   @   s   e Zd ZedefddZdS )_HasModalityPropr>   c                 C   s   d S rU   r;   ry   r;   r;   r<   rs        z_HasModalityProp.modalityN)r4   r5   r6   r   rP   rs   r;   r;   r;   r<   r     s    r   _M)boundvaluesc                 C   s   t | dd dS )z^Convenience function to apply [`full_groupby`][vllm.utils.full_groupby]
    based on modality.c                 S   r   rU   rs   xr;   r;   r<   rE         z'full_groupby_modality.<locals>.<lambda>key)r   )r   r;   r;   r<   full_groupby_modality  s   r   c                   @   s   e Zd ZU dZeddZeed< ee	 ed< ee
e  ed< edededd fd	d
ZdddZede	fddZede
e fddZdS )r[   z
    A [`_PromptSeq`][vllm.multimodal.processing.PromptSeq] bound
    to a tokenizer to automatically
    convert between token sequence and text representations.
    Fr   rK   _text
_token_idsrJ   r>   c                 C   s.   t | t|tr	|nd t|tr|dS d dS )N)rK   r   r   )r[   rO   rP   r   )rK   rJ   r;   r;   r<   r^     s   z_BoundPromptSequence.from_seqNc                 C   s$   | j d u r| jd u rtdd S d S )Nz8At least one of 'text' and 'token_ids' must be specified)r   r   
ValueErrorry   r;   r;   r<   __post_init__  s   z"_BoundPromptSequence.__post_init__c                 C   s2   | j d u r| jd usJ t| jt| j| _ | j S rU   )r   r   r   rK   tuplery   r;   r;   r<   r     s   
z_BoundPromptSequence.textc                 C   s2   | j d u r| jd usJ t| j| jdd| _ | j S rL   )r   r   r   rK   ry   r;   r;   r<   rd     s   
z_BoundPromptSequence.token_idsr>   N)r4   r5   r6   r7   r   rK   r   r:   r   rP   r   r9   rX   r8   r^   r   r   r   rd   r;   r;   r;   r<   r[     s$   
 

r[   c                   @   s.   e Zd ZU eed< eedgejf  ed< dS )_BoundPromptContentrZ   r[   r\   N)	r4   r5   r6   r[   r:   r   r   ra   rg   r;   r;   r;   r<   r     s   
 r   c                   @   s   e Zd ZU dZeed< eddZeed< ddd	Z	e
defd
dZe
deeef fddZe
defddZe
defddZdedefddZdS )r   aK  
    A [`PromptUpdate`][vllm.multimodal.processing.PromptUpdate] bound
    to a tokenizer to automatically convert
    [`target`][vllm.multimodal.processing.PromptUpdate.target] and the result of
    [`get_content`][vllm.multimodal.processing.BoundPromptUpdate.get_content]
    between token sequence and text representations.
    r   Fr   rK   r>   Nc                 C   s   t ttf  | _d S rU   )dictr9   r   _content_cachery   r;   r;   r<   r     s   zBoundPromptUpdate.__post_init__c                 C      | j jS rU   r   rs   ry   r;   r;   r<   rs        zBoundPromptUpdate.modalityc                 C   s$   | j j}t|tr|S t| j|S )z'The token sequence (or text) to update.)r   rt   rO   r2   r[   r^   rK   )rz   rt   r;   r;   r<   rt     s   
zBoundPromptUpdate.targetc                 C   r   rv   )r   r{   ry   r;   r;   r<   r{        zBoundPromptUpdate.contentc                 C   r   r}   )r   r~   ry   r;   r;   r<   r~     r   zBoundPromptUpdate.modeitem_idxc                 C   s|   | j }t|r|}|| jv r| j| S ||}nd}t|ts$t|}t| j|j}t	||j
d}|dur<|| j|< |S )z
        Given the index of the processed item within
        [`modality`][vllm.multimodal.processing.PromptUpdate.modality],
        output the token sequence (or text) to update.
        Nrf   )r{   callabler   rO   rY   r^   r[   rK   rZ   r   r\   )rz   r   r{   	cache_keyZ
bound_fullZbound_contentr;   r;   r<   get_content  s$   





zBoundPromptUpdate.get_contentr   )r4   r5   r6   r7   rr   r:   r   rK   r   r   r   rP   rs   r   r[   r2   rt   r   r{   rm   r~   r9   r   r   r;   r;   r;   r<   r     s   
 
	r   c                   @   s   e Zd ZU eed< eed< dS )_TokenMatch	start_idxend_idxN)r4   r5   r6   r9   r:   r;   r;   r;   r<   r     s   
 r   	match_idsc                 c   s~    t | }t |}|dkrdS d}||| d k r=|| }| || |kr/t||dV  |}n|d7 }||| d k sdS dS )zh
    Yield each occurrence of `match_ids` in `token_ids`.

    Note that empty matches are ignored.
    r   Nr   )r   r   )rQ   r   )rd   r   
prompt_lenZ	match_lenr   r   r;   r;   r<   iter_token_matches  s   	r   new_idsc                 C   sh   t t t   }d}t| |D ]}|j}|j}|| ||  || |}q|| |d  t|S )z}
    Replace each occurrence of `match_ids` in `token_ids`
    with `new_ids`.

    Note that empty matches are ignored.
    r   N)r   r9   r   r   r   appendr   )rd   r   r   out_seqsprev_end_idxmatchr   r   r;   r;   r<   replace_token_matches,  s   
r   Fr   c                   @   sb   e Zd ZU eed< edefddZeede	fddZ
eede	fddZdefd	d
ZdS )PromptTargetMatchr   r>   c                 C   r   rU   r   ry   r;   r;   r<   rs   K  r   zPromptTargetMatch.modalityc                 C   ru   rU   rw   ry   r;   r;   r<   r   O     zPromptTargetMatch.start_idxc                 C   ru   rU   rw   ry   r;   r;   r<   r   T  r   zPromptTargetMatch.end_idxc                 C   s(   t | j d| jd| jd| jdS )Nz
(modality=z, start_idx=z
, end_idx=))typer4   rs   r   r   ry   r;   r;   r<   __repr__Y  s
   zPromptTargetMatch.__repr__N)r4   r5   r6   r   r:   r   rP   rs   r   r9   r   r   r   r;   r;   r;   r<   r   G  s   
 r   c                   @   s:   e Zd ZU eed< edefddZedefddZdS )_PromptTargetIndexMatchrS   r>   c                 C   r   rU   rS   ry   r;   r;   r<   r   b  r   z!_PromptTargetIndexMatch.start_idxc                 C   r   rU   r   ry   r;   r;   r<   r   f  r   z_PromptTargetIndexMatch.end_idxN)r4   r5   r6   r9   r:   r   r   r   r;   r;   r;   r<   r   ^     
 r   c                   @   s:   e Zd ZU eed< edefddZedefddZdS )_PromptTargetTokenMatchr   r>   c                 C   r   rU   )r   r   ry   r;   r;   r<   r   o  r   z!_PromptTargetTokenMatch.start_idxc                 C   r   rU   )r   r   ry   r;   r;   r<   r   s  r   z_PromptTargetTokenMatch.end_idxN)	r4   r5   r6   r   r:   r   r9   r   r   r;   r;   r;   r<   r   k  r   r   c                   @   s@   e Zd ZU eje ed< edefddZ	edefddZ
dS )_PromptTargetTextMatchr   r>   c                 C   
   | j  S rU   )r   rH   ry   r;   r;   r<   r   |  r_   z _PromptTargetTextMatch.start_idxc                 C   r   rU   )r   rW   ry   r;   r;   r<   r     r_   z_PromptTargetTextMatch.end_idxN)r4   r5   r6   reMatchrP   r:   r   r9   r   r   r;   r;   r;   r<   r   x  s   
 r   c                   @   s`   e Zd ZU eed< eed< eed< ee ed< eej	 ed< e
defddZdefd	d
ZdS )PlaceholderFeaturesInfors   r   r   tokensr\   r>   c                 C   s
   t | jS rU   )rQ   r   ry   r;   r;   r<   length  r_   zPlaceholderFeaturesInfo.lengthc                 C   s   t | j| j| jdS )N)offsetr   r\   )r(   r   r   r\   ry   r;   r;   r<   to_range  s
   z PlaceholderFeaturesInfo.to_rangeN)r4   r5   r6   rP   r:   r9   r   r   ra   rg   r   r   r(   r   r;   r;   r;   r<   r     s   
 r   rD   prompt_updatesc                    $   dt ffdd  fdd|D S )9Return each target of `prompt_updates` found in `prompt`.updatec                    sP    j }t|tr| j}|d u rg S t |gS  fddt|jD S )Nc                       g | ]}t  |qS r;   )r   .0r   r   r;   r<   
<listcomp>      z;find_token_matches.<locals>.get_matches.<locals>.<listcomp>)rt   rO   r2   r3   rK   r   r   rd   r   rt   rS   rD   r   r<   get_matches  s   


z'find_token_matches.<locals>.get_matchesc                       g | ]} |D ]}|qqS r;   r;   r   r   r   r   r;   r<   r     
    z&find_token_matches.<locals>.<listcomp>r   rD   r   r;   r   rD   r<   find_token_matches     
r   c                    r   )r   r   c                    sX    j }t|tr| j}|d u rg S t |gS  fddtt|j	D S )Nc                    r   r;   )r   r   r   r;   r<   r     r   z:find_text_matches.<locals>.get_matches.<locals>.<listcomp>)
rt   rO   r2   r3   rK   r   r   finditerescaper   r   r   r   r<   r     s   

z&find_text_matches.<locals>.get_matchesc                    r   r;   r;   r   r   r;   r<   r     r   z%find_text_matches.<locals>.<listcomp>r   r   r;   r   r<   find_text_matches  r   r   
mm_matchesc                 C   s   dd |  D }dgt|  }|D ](}t|j|jD ]}|| dur5td||  d| d| d|  |||< qqt|dd	 d
S )z
    Resolve `mm_matches` to ensure that there are no overlapping matches,
    and sort them such that earlier matches take priority over later ones.
    c                 S      g | ]	}|D ]}|qqS r;   r;   )r   matchesmr;   r;   r<   r     s    z$_resolve_matches.<locals>.<listcomp>NzFound overlapping matches (z and z) at index=z of prompt=c                 S   r   rU   )r   r   r;   r;   r<   rE     r   z"_resolve_matches.<locals>.<lambda>r   )r   rQ   ranger   r   r   sorted)rD   r   r   Zseen_matchesr   idxr;   r;   r<   _resolve_matches  s"   
r   mm_item_countsc                 C   sV  t ttt t f   }d}tttf dd }t| |D ]~}|j}|| }||d}	||	kr0q|j}
|j	}|j
}|j}|tjkrM|| ||  |	}n|tjkrd|| ||
  |
|kra|	nd}nt| t|| |	}t||D ]}||}t| tr|jjn|jj}|| qt|}||  || 7  < q|| |d  tt t |S ).Apply the updates in `mm_matches` to `prompt`.r   c                   S   r@   rA   r;   r;   r;   r;   r<   rE     rF   z _apply_matches.<locals>.<lambda>r   N)r   r   rP   r9   r   r   rs   getr   r   r   r~   rm   rp   r   rq   r   minr   r   rO   rZ   r   rd   r   r1   )rD   r   r   r   r   Znext_idx_by_modalityr   rs   Zitem_start_idxZmax_item_countr   r   originr~   Znum_insertsZitem_end_idxr   r{   Z
insert_seqr;   r;   r<   _apply_matches  s>   


r   c                 C   s   |s| S t | ||}t|S )r   )r   r   )rD   r   r   Ztoken_id_seqsr;   r;   r<   apply_token_matches  s   r   c                 C   s   |s| S t | ||}d|S )r    )r   join)rD   r   r   Ztextsr;   r;   r<   apply_text_matches&  s   
r   mm_prompt_updatesc              	   c   s   t |}tttf dd }d}||k rd}|  D ]`\}}|| }	|	||dkr,q|D ]H}
|
|	}|jj}t |}|| }|dksI||krJq.||| |krv|j	}|dur^||j}t
||	|||dV  |}||  d7  < d} nq.|r{ nq|s|d7 }||k sdS dS )	a&  
    Yield each set of placeholder tokens found in `prompt`.

    Matches are exclusive even when multiple modalities share
    the same placeholder tokens. In that case, the modality that
    appears earlier in `mm_prompt_updates` takes priority.

    Note that empty matches are ignored.
    c                   S   r@   rA   r;   r;   r;   r;   r<   rE   C  rF   z$_iter_placeholders.<locals>.<lambda>r   FN)rs   r   r   r   r\   r   T)rQ   r   rP   r9   itemsr   r   rZ   rd   r\   r   )r   rD   r   r   Zitem_idx_by_modalityr   foundrs   Zmodality_updatesr   Zupdate_infor{   Zcontent_tokens_fullZcontent_len_fullZend_idx_fullZcontent_is_embedr;   r;   r<   _iter_placeholders4  sN   

	r   c                 C   s   t | ||}tt|S rU   )r   r   r   )r   rD   r   itr;   r;   r<   find_mm_placeholdersq  s   r  c                       s&   e Zd Zdeddf fddZ  ZS )ProcessingCachecapacity_gbr>   Nc                    s:   t    | |t| _| jj| _| jj| _| jj| _d S rU   )	super__init__Zget_lru_cacher'   _cacher   putclearreset)rz   r  	__class__r;   r<   r  |  s
   


zProcessingCache.__init__)r4   r5   r6   floatr  __classcell__r;   r;   r  r<   r  z  s    r  c                	       s   e Zd ZdZdeddf fddZedefddZde	fd	d
Z
dddZdeddfddZedeeee f fddZdeeef fddZdedeeef deeeef  fddZ  ZS )BaseProcessingInfozDBase class to provide the information necessary for data processing.ctxr>   Nc                    s   t    || _d S rU   )r  r  r  )rz   r  r  r;   r<   r    s   

zBaseProcessingInfo.__init__c                 C   s
   | j jjS rU   )r  Zmodel_configmodelry   r;   r;   r<   model_id  r_   zBaseProcessingInfo.model_idc                 C   r   rU   )r  rK   ry   r;   r;   r<   get_tokenizer  s   z BaseProcessingInfo.get_tokenizerr-   c                 C   r   rU   )r  get_hf_configry   r;   r;   r<   r    s   
z BaseProcessingInfo.get_hf_configkwargsr/   c                 K   s   | j jdi |S )zy
        Subclasses can override this method to handle
        specific kwargs from model config or user inputs.
        Nr;   )r  get_hf_processor)rz   r  r;   r;   r<   r    s   z#BaseProcessingInfo.get_hf_processorc                 C   ru   )z
        Return the maximum supported number of items for each modality.

        A value of `None` means unlimited number of items.

        Omitting a modality from the returned dictionary means that
        it is not supported at all.
        rw   ry   r;   r;   r<   get_supported_mm_limits     
z*BaseProcessingInfo.get_supported_mm_limitsc                 C   sZ   |   }| j }tttf  }| D ]\}}||}|du r#|nt||||< q|S )z=Return the maximum allowed number of items for each modality.N)	r  r  Zget_mm_configr   rP   r9   r   Zget_limit_per_promptr   )rz   supported_mm_limitsZ	mm_configZallowed_limitsrs   supported_limitZ
user_limitr;   r;   r<   get_allowed_mm_limits  s   

z(BaseProcessingInfo.get_allowed_mm_limitsseq_len	mm_countsc                 C   r@   )a  
        Return the maximum number of tokens per item of for each modality.
        
        When `None` (the default) is returned, vLLM will generate dummy inputs
        (images/videos) at maximum possible sizes and process them to determine
        the maximum token count per modality.

        This approach works but can be very slow for certain models (e.g.,
        Qwen2.5-VL), leading to very long startup time. For better performance,
        each model can override this method to return pre-computed maximum token
        counts, avoiding the need for dummy input generation and processing.

        Note:
            The maximum number of tokens per item of each modality returned 
            from this function should respect the model's maximum sequence
            length and the maximum number of items of each modality allowed,
            and agree with dummy inputs (images/videos) at maximum possible
            sizes.
        Nr;   )rz   r  r  r;   r;   r<   get_mm_max_tokens_per_item  s   z-BaseProcessingInfo.get_mm_max_tokens_per_item)r>   r-   )r4   r5   r6   r7   r   r  r   rP   r  r   r  r  objectr  r   r	   r   r9   r  r  r  r  r;   r;   r  r<   r    s$    

r  _Ic                       s  e Zd ZdZdddedddee ddf fd	d
Zedd Z	edd Z
dededeeef defddZdefddZdededdfddZdedefddZedddeeef deeef fddZed edeeef d!edee fd"d#Zd$eeee f d%ee d&eeef deeee  f fd'd(Z!d ede"eeef eeef f fd)d*Z#dedeeef d+eeef d,eeef ddf
d-d.Z$d/ed edeeef d0eeef de%f
d1d2Z&d/ed edeeef d0eeef de"ee de%f f
d3d4Z'd/ed0eeef dee fd5d6Z(d7ee dee fd8d9Z)d edeeef d0eeef ddfd:d;Z*de+eee f d edeeef d0eeef d<e%de"ee de%f fd=d>Z,ded?ed@e-de"e.eee/ f ef fdAdBZ0d edeeef d0eeef de-fdCdDZ1dedEe.eee/ f dFede.eee2 f fdGdHZ3de+eee f d?edeeef d0eeef dIe%de"ee eee- e%f fdJdKZ4de+eee f d?edeeef d0eeef dIe%de"ee eee- e%f fdLdMZ5dNee de.eee f fdOdPZ6dee dQeeee7 f d&eeef dee fdRdSZ8dedQeeee7 f d&eeef defdTdUZ9dVee d$eeee f d&eeef de"ee eeeee  f f fdWdXZ:d+ed&eeef ddfdYdZZ;d[eeee  f d&eeef ddfd\d]Z<d edeeef d^ee d+ed_e%de"ee eeeee  f f fd`daZ=		bdede+eee f dedeeef d0eeeef  dIe%defdcddZ>  Z?S )fBaseMultiModalProcessorz
    Abstract base class to process multi-modal inputs to be used in vLLM.

    Not to be confused with `transformers.ProcessorMixin`.
    N)cacheinfodummy_inputszBaseDummyInputsBuilder[_I]r"  r>   c                   sB   t    || _|| _|| _|  | _| j | _| j	 | _
d S rU   )r  r  r#  r$  r"  _get_data_parserdata_parserr  _supported_mm_limitsr  _allowed_mm_limits)rz   r#  r$  r"  r  r;   r<   r    s   

z BaseMultiModalProcessor.__init__c                 C   r   rU   )r'  ry   r;   r;   r<   r    r   z+BaseMultiModalProcessor.supported_mm_limitsc                 C   r   rU   )r(  ry   r;   r;   r<   allowed_mm_limits  r   z)BaseMultiModalProcessor.allowed_mm_limitsrD   mm_datahf_processor_mm_kwargsc                 C   s   |  |||S rU   )apply)rz   rD   r*  r+  r;   r;   r<   __call__   s   z BaseMultiModalProcessor.__call__c                 C   s   t  S )a  
        Construct a parser to preprocess multi-modal data items
        before passing them to
        [`_get_hf_mm_data`][vllm.multimodal.processing.BaseMultiModalProcessor._get_hf_mm_data].

        You can support additional modalities by creating a subclass
        of [`MultiModalDataParser`][vllm.multimodal.parse.MultiModalDataParser]
        that has additional subparsers.
        )r,   ry   r;   r;   r<   r%    s   
z(BaseMultiModalProcessor._get_data_parserrs   	num_itemsc                 C   sh   | j |d}| j|d}|d u r|}t||}||kr2d| d| d}||kr.|d7 }t|d S )Nr   zAt most  z"(s) may be provided in one prompt.z4 Set `--limit-mm-per-prompt` to increase this limit.)r  r   r)  r   r   )rz   rs   r.  r  Zallowed_limitlimitmsgr;   r;   r<   validate_num_items  s   
z*BaseMultiModalProcessor.validate_num_itemsc                 C   s2   | j |}| D ]\}}| |t| q
|S )a3  
        Normalize
        [`MultiModalDataDict`][vllm.multimodal.inputs.MultiModalDataDict]
        to [`MultiModalDataItems`][vllm.multimodal.parse.MultiModalDataItems]
        before passing them to
        [`_get_hf_mm_data`][vllm.multimodal.processing.BaseMultiModalProcessor._get_hf_mm_data].
        )r&  Zparse_mm_datar   r2  rQ   )rz   r*  mm_itemsrs   r   r;   r;   r<   _to_mm_items*  s   z$BaseMultiModalProcessor._to_mm_items	hf_inputsr.   c                 C   ru   )z?Given the HF-processed data, output the metadata of each field.rw   )rz   r5  r+  r;   r;   r<   _get_mm_fields_config<  s   z-BaseMultiModalProcessor._get_mm_fields_configr3  out_mm_kwargsc                 C   ru   )aZ  
        Given the original multi-modal items for this modality
        and HF-processed data, output the updates to perform.

        The information returned by this method is used to update token inputs
        which bypass the HF processor. It is also used to update the output of
        HF processor if the HF process does not apply prompt updates to text
        inputs.

        Moreover, this information is critical to determine the token positions
        in order to construct
        [`PlaceholderRange`][vllm.multimodal.inputs.PlaceholderRange]
        for each multi-modal item.
        rw   )rz   r3  r+  r7  r;   r;   r<   _get_prompt_updatesE  s   z+BaseMultiModalProcessor._get_prompt_updatesr   new_token_idsr   c                 C      t |||S rU   )r  )rz   r   r9  r   r;   r;   r<   _find_mm_placeholders\  s   z-BaseMultiModalProcessor._find_mm_placeholdersc                 C   sN   t ttf  }t ttf  }| D ]}||  ||  q||fS rU   )r   rP   r  r   r   Zget_processor_dataZget_passthrough_data)rz   r3  processor_datapassthrough_datar   r;   r;   r<   _get_hf_mm_datae  s   z'BaseMultiModalProcessor._get_hf_mm_data	mm_kwargs
tok_kwargsc                 C   s<   | j j| j jdi |tdd|i|tdi ||S )zc
        Call the HF processor on the prompt text and
        associated multi-modal data.
        r   Nr;   )r#  r  Zcall_hf_processorr  r   )rz   rD   r*  r?  r@  r;   r;   r<   _call_hf_processorr  s
   z*BaseMultiModalProcessor._call_hf_processorprompt_texttokenization_kwargsc                 C   s   t dd | D  S )z
        Return whether the HF processor applies prompt updates.

        For most HF processors, this should be `True` when multi-modal
        data items are passed, but `False` when multi-modal embeddings
        are passed.
        c                 s   s    | ]
}t |ttfV  qd S rU   )rO   r*   r)   r   r   r;   r;   r<   	<genexpr>  s
    
zHBaseMultiModalProcessor._hf_processor_applies_updates.<locals>.<genexpr>)anyr   )rz   rB  r3  r+  rC  r;   r;   r<   _hf_processor_applies_updates  s   
z5BaseMultiModalProcessor._hf_processor_applies_updatesc           
      C   sV   |  |\}}| j||||d}|| |d \}| j||||d}	|||	fS )z
        Apply the HF processor on the prompt text and multi-modal data
        together.

        In addition, return whether prompt updates have been applied.
        )rD   r*  r?  r@  Z	input_idsrB  r3  r+  rC  )r>  rA  r   poptolistrG  )
rz   rB  r3  r+  rC  r<  r=  Zprocessed_data
prompt_idsis_update_appliedr;   r;   r<   _apply_hf_processor_text_mm  s    

z3BaseMultiModalProcessor._apply_hf_processor_text_mmc                 C   s    | j |ti i |d\}}}|S )z
        Apply the HF processor on the prompt text only.

        Since HF processor requires that text and multi-modal items
        correspond to each other, we create dummy multi-modal items
        to go along with the text.
        rH  )rM  r+   )rz   rB  rC  rK  _r;   r;   r<   _apply_hf_processor_text_only  s   z5BaseMultiModalProcessor._apply_hf_processor_text_onlyprompt_tokensc                 C      |S )a  
        Apply the HF processor on the prompt tokens only.

        Most HF processors accept prompt text but not prompt tokens.
        If the HF processor adds or removes tokens that are not related to
        multi-modal data, you should override this method so it is consistent
        with the output of
        [`_apply_hf_processor_text_only`][vllm.multimodal.processing.BaseMultiModalProcessor._apply_hf_processor_text_only]
        on the
        corresponding text.
        r;   )rz   rP  r;   r;   r<   _apply_hf_processor_tokens_only  s   z7BaseMultiModalProcessor._apply_hf_processor_tokens_onlyc                 C   s,   |  }| j| j||||d\}}}|S )aJ  
        Apply the HF processor on the multi-modal data only.

        Since HF processor requires that text and multi-modal items
        correspond to each other, we generate dummy text using
        [`DummyInputsBuilder`][vllm.multimodal.profiling.BaseDummyInputsBuilder]
        to go along with the multi-modal data.
        rH  )get_all_countsrM  r$  Zget_dummy_text)rz   r3  r+  rC  r  rN  mm_processed_datar;   r;   r<   _apply_hf_processor_mm_only  s   
z3BaseMultiModalProcessor._apply_hf_processor_mm_onlyenable_hf_prompt_updatec                C   sR   t |tr|r| j||||dS | ||}n| |}| j|||d}||dfS )a  
        Apply the HF processor on the prompt text and multi-modal data.

        In addition, return whether prompt updates have been applied
        (for most HF processors, this should be `True`).

        Note:
            If `enable_hf_prompt_update=False`, we use HF processor
            to perform prompt updates if available; HF processor requires
            that the prompt corresponds to multi-modal items.
        rH  )r3  r+  rC  F)rO   rP   rM  rO  rR  rU  )rz   rD   r3  r+  rC  rV  rK  rT  r;   r;   r<   _apply_hf_processor_main  s$   


z0BaseMultiModalProcessor._apply_hf_processor_mainmm_data_items	mm_hashesc                    sN    fdd|  D }dd |  D }fdd|  D }|| |fS )Nc                    s&   i | ]\}}| fd d|D qS )c                    s&   g | ]}  | d u r|nqS rU   r   )r   hr"  vr;   r<   r   )  s    OBaseMultiModalProcessor._get_cache_missing_items.<locals>.<dictcomp>.<listcomp>r;   )r   rs   hashesr\  r;   r<   
<dictcomp>(  s    zDBaseMultiModalProcessor._get_cache_missing_items.<locals>.<dictcomp>c                 S   s$   i | ]\}}|d d t |D qS )c                 S   s   g | ]\}}t |tr|qS r;   )rO   rP   )r   r   item_or_hashr;   r;   r<   r   /  s    r^  )	enumerate)r   rs   items_or_hashesr;   r;   r<   r`  .  s    c                    s&   i | ]\ }  fd d|D qS )c                    s   g | ]}  | qS r;   r;   )r   r   )rX  rs   r;   r<   r   6  s    r^  r;   )r   Zidxs)rX  r   r<   r`  5  s    )r   r4  )rz   r"  rX  rY  mm_cache_items_or_hashesZmm_missing_idxsZmm_missing_datar;   )r"  rX  r]  r<   _get_cache_missing_items"  s   
z0BaseMultiModalProcessor._get_cache_missing_itemsc                    s"   | j j fdd| D S )z2Create MM hashes to be returned (only used in V1).c                    s*   i | ]\ }  fd d|D qS )c                    s,   g | ]}t jdd i|i qS )r  r;   )r!   Zhash_kwargsr   item)r+  rs   r  rC  r;   r<   r   F  s    zEBaseMultiModalProcessor._hash_mm_items.<locals>.<dictcomp>.<listcomp>r;   rD  r+  r  rC  r   r<   r`  E  s    z:BaseMultiModalProcessor._hash_mm_items.<locals>.<dictcomp>)r#  r  r   )rz   r3  r+  rC  r;   rh  r<   _hash_mm_items<  s   z&BaseMultiModalProcessor._hash_mm_itemsrd  mm_missing_kwargsc           
      C   s   t ttf dd }t ttt f t}| D ].\}}|D ]'}t|tr<|||| }	|||	 ||  d7  < n|}	|| 	|	 qqt
|S )Nc                   S   r@   rA   r;   r;   r;   r;   r<   rE   V  rF   z:BaseMultiModalProcessor._merge_mm_kwargs.<locals>.<lambda>r   )r   rP   r9   r   r'   r   rO   Zget_itemr  r   r   )
rz   r"  rd  rj  Zmm_missing_next_idxZmerged_itemsrs   rc  ra  Zkw_itemr;   r;   r<   _merge_mm_kwargsP  s   
z(BaseMultiModalProcessor._merge_mm_kwargsreturn_mm_hashesc                C   sP   | j ||||dd\}}}t|| ||}	|r | |||nd }
||	|
|fS )NTrD   r3  r+  rC  rV  )rW  r&   from_hf_inputsr6  ri  )rz   rD   rX  r+  rC  rl  rK  rT  rL  r?  rY  r;   r;   r<   _apply_hf_processori  s0   	
z+BaseMultiModalProcessor._apply_hf_processorc                C   s   | j }| |\}}|du s|r| j|||||dS | |||}	| j|||	d\}
}|r/|	nd}| j||||dd\}}}t|| ||}| j	||
|d}tdd |
 D }||||fS )	zy
        Apply the HF processor on the full prompt text,
        caching the results and reusing cached results.
        N)rD   rX  r+  rC  rl  )r"  rX  rY  Frm  )rd  rj  c                 S   r   r;   r;   )r   Zcache_itemsrg  r;   r;   r<   r     s    zFBaseMultiModalProcessor._cached_apply_hf_processor.<locals>.<listcomp>)r"  r>  ro  ri  re  rW  r&   rn  r6  rk  r   )rz   rD   rX  r+  rC  rl  r"  rN  r=  rY  rd  Zmm_missing_data_itemsZmm_hashes_to_returnrK  Zmm_missing_processed_datarL  rj  Zmm_cache_items_mergedr?  r;   r;   r<   _cached_apply_hf_processor  s`   		z2BaseMultiModalProcessor._cached_apply_hf_processorr   c                    s(   | j    fdd|D }tt|S )Nc                 3   s    | ]}|  V  qd S rU   )r   )r   r   rK   r;   r<   rE    s    zBBaseMultiModalProcessor._bind_and_group_updates.<locals>.<genexpr>)r#  r  r   r   )rz   r   r  r;   rq  r<   _bind_and_group_updates  s   
z/BaseMultiModalProcessor._bind_and_group_updatesr   c                 C   r:  rU   )r   rz   rD   r   r   r;   r;   r<   _apply_token_matches     z,BaseMultiModalProcessor._apply_token_matchesc                 C   r:  rU   )r   rs  r;   r;   r<   _apply_text_matches  ru  z+BaseMultiModalProcessor._apply_text_matchesrd   c           	         s   | j  }fdd| D }dd | D  t fdd| D r<| ||t|dd | D }n't|fdd| D }| ||t|dd	d
d | D }| ||}|fS )Nc                       i | ]
\}}|t  |qS r;   )r   r   rs   Zupdates)rd   r;   r<   r`        
zABaseMultiModalProcessor._apply_prompt_updates.<locals>.<dictcomp>c                 S   s   i | ]	\}}|t |qS r;   rV   )r   rs   r   r;   r;   r<   r`    s    c                 3   s$    | ]\}}  |d |kV  qdS )r   NrZ  )r   rs   
item_count)mm_match_countsr;   r<   rE    s
    
z@BaseMultiModalProcessor._apply_prompt_updates.<locals>.<genexpr>c                 S       i | ]\}}|d d |D qS )c                 S      g | ]}|j qS r;   r   r   r;   r;   r<   r         LBaseMultiModalProcessor._apply_prompt_updates.<locals>.<dictcomp>.<listcomp>r;   r   rs   Ztoken_matchesr;   r;   r<   r`        c                    rw  r;   )r   rx  )r   r;   r<   r`    ry  FrM   c                 S   r|  )c                 S   r}  r;   r~  r   r;   r;   r<   r   &  r  r  r;   r  r;   r;   r<   r`  %  r  )	r#  r  r   allrt  r   rv  r   r;  )	rz   rd   r   r   rK   Zmm_token_matchesZmatched_updatesZmm_text_matchesplaceholdersr;   )r{  r   rd   r<   _apply_prompt_updates  sR   





z-BaseMultiModalProcessor._apply_prompt_updatesc                 C   sh   |  D ]-\}}||jv r||}ng }t||kr1td| d| d| d| dt| dqd S )NExpected there to be r/  z- items in keyword arguments corresponding to z data items, but only found z! There is likely a problem with your implementation of merged multi-modal processor for this model (usually arising from an inconsistency between `_call_hf_processor` and `_get_mm_fields_config`).)r   Z
modalitiesZ	get_itemsrQ   RuntimeError)rz   r?  r   rs   rz  r   r;   r;   r<   _validate_mm_kwargs2  s    
z+BaseMultiModalProcessor._validate_mm_kwargsmm_placeholdersc                 C   sT   |  D ]#\}}||g }t||kr'td| d| d| dt| d	qd S )Nr  z! prompt updates corresponding to r/  z items, but instead found z prompt updates! This is likely because you forgot to include input placeholder tokens (e.g., `<image>`, `<|image_pad|>`) in the prompt. If the model has a chat template, make sure you have applied it before calling `LLM.generate`.)r   r   rQ   r  )rz   r  r   rs   rz  r  r;   r;   r<   _validate_mm_placeholdersG  s   z1BaseMultiModalProcessor._validate_mm_placeholdersrK  rL  c                 C   s   |  |||}| |}| }| || |r0| |||}	| |	| | j }
t|
|}n| 	|||\}}}	| |	| |||	fS rU   )
r8  rr  rS  r  r;  r  r#  r  r   r  )rz   r3  r+  rK  r?  rL  Zunbound_prompt_updatesr   r   r  rK   rD   r;   r;   r<   _maybe_apply_prompt_updates\  s<   

z3BaseMultiModalProcessor._maybe_apply_prompt_updatesFc                 C   sr   |  |}|du ri }| j|||||d\}}}	}
| j|||||
d\}}}dd | D }td||||	|dS )a"  
        Process multi-modal inputs to be used in vLLM.

        The main steps are:

        1. Apply HF Processor on prompt text and multi-modal data together,
           outputting token IDs and processed tensors.
        2. Find and update sequences in the token IDs with placeholder tokens.
           The number of placeholder tokens equals the feature size of the
           multi-modal data outputted by the multi-modal encoder.
        3. Extract information about the placeholder tokens from the
           processed token IDs.
        N)rC  rl  )r3  r+  rK  r?  rL  c                 S   r|  )c                 S   s   g | ]}|  qS r;   )r   rf  r;   r;   r<   r     s    z<BaseMultiModalProcessor.apply.<locals>.<dictcomp>.<listcomp>r;   )r   rs   r  r;   r;   r<   r`    r  z1BaseMultiModalProcessor.apply.<locals>.<dictcomp>Z
multimodal)r   rD   prompt_token_idsr?  rY  r  )r4  rp  r  r   r%   )rz   rD   r*  r+  rC  rl  r3  rK  r?  rY  rL  r  Zmm_placeholder_rangesr;   r;   r<   r,    sB   

zBaseMultiModalProcessor.applyNF)@r4   r5   r6   r7   r   r   r  r  r   r  r)  rP   r"   r	   r  r%   r-  r,   r%  r9   r2  r+   r4  r   r$   r6  r&   r
   rr   r8  r   r   r   r;  r   r>  rA  boolrG  rM  rO  rR  rU  r   rW  MultiModalHashesr   _CacheItemOrHashre  ri  r'   rk  ro  rp  rr  r   rt  rv  r  r  r  r  r,  r  r;   r;   r  r<   r!    s   











	










"








*







!


H
	





G





0
r!  c                       s   e Zd Zedeeee f dedeeee f fddZ	e
defddZdeeee f dedeeee f fdd	Zdeeee f ded
efddZ		ddeeee f dedeeef deeeef  dedef fddZ  ZS )EncDecMultiModalProcessorrD   r*  r>   c                 C   ru   )z
        Create input prompt for the encoder. HF processor will be applied on
        this prompt during profiling and generation.
        rw   rz   rD   r*  r;   r;   r<   create_encoder_prompt  r  z/EncDecMultiModalProcessor.create_encoder_promptc                 C   r@   r  r;   ry   r;   r;   r<   pad_dummy_encoder_prompt  r   z2EncDecMultiModalProcessor.pad_dummy_encoder_promptc                 C   rQ  )z$Create input prompt for the decoder.r;   r  r;   r;   r<   create_decoder_prompt  s   z/EncDecMultiModalProcessor.create_decoder_promptencoder_inputsc                 C   sn   | j  }| ||}t|trt||dd}n|}t||}td|d |d d|}|||d |S )NFrM   rD   r  )encoder_promptZencoder_prompt_token_ids)rD   r  r;   )	r#  r  r  rO   rP   r   r   r#   r   )rz   rD   r*  r  rK   Zdecoder_promptZdecoder_prompt_idsZ	mm_inputsr;   r;   r<   _get_enc_dec_inputs  s(   


z-EncDecMultiModalProcessor._get_enc_dec_inputsNFr+  rC  rl  c                    s0   |  ||}t |||||}| j|||dS )a;  
        Process multi-modal inputs to be used in vLLM.
        The main processing steps are modified to fit encoder-decoder model:
        1. Create encoder prompt from input prompt text.
        2. Apply the HF processor on encoder prompt.
        3. Copy the input prompt text as decoder prompt inputs.
        )rD   r*  r  )r  r  r,  r  )rz   rD   r*  r+  rC  rl  r  r  r  r;   r<   r,    s   zEncDecMultiModalProcessor.applyr  )r4   r5   r6   r   r   rP   r   r9   r"   r  r   r  r  r  r%   r  r	   r  r   r#   r,  r  r;   r;   r  r<   r    sP    


r  )yabcr   r   collectionsr   collections.abcr   r   r   r   r	   r
   dataclassesr   r   enumr   	functoolsr   typingr   r   r   r   r   r   r   r   regexr   ra   Ztyping_extensionsr   Zvllm.inputsr   Zvllm.loggerr   Z!vllm.transformers_utils.tokenizerr   r   r   Z
vllm.utilsr   r   r"  r    Zhasherr!   Zinputsr"   r#   r$   r%   r&   r'   r(   parser)   r*   r+   r,   Z transformers.configuration_utilsr-   Z%transformers.feature_extraction_utilsr.   Ztransformers.processing_utilsr/   Z	profilingr0   r4   loggerrP   r   r9   r1   r8   r2   r=   r   rY   ZPromptUpdateInfor   rm   rr   r   r   r  r   r   r   r   r   r   r   r[   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r   r   r  r!  r  r;   r;   r;   r<   <module>   sr   ($11
DI
".D






1





=

	N     k