Ë
    Têñiwj  ã                  óz  — d Z ddlmZ ddl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ZddlZddlmZmZmZmZ 	 ddlmZ 	 dd	lmZmZ  ej8                  e«      Zd
d
d
d
dœZdd„Z dd„Z!dd„Z"dd„Z#dd„Z$dd„Z% G d„ d«      Z&	 d	 	 	 	 	 dd„Z'	 d	 	 	 	 	 dd„Z(dd„Z)y# e$ r dZY Œhw xY w# eef$ r dZdZY Œpw xY w)zAModality detection, input parsing, and message format conversion.é    )ÚannotationsN)Údefaultdict)ÚAnyÚLiteral)Úurlparse)ÚMessageFormatÚModalityÚ	PairInputÚSingleInput)ÚImage)ÚAudioDecoderÚVideoDecoderÚflat)ÚapertusÚdeepseek_v3Úgpt_ossÚseed_ossc                ó0   — | j                  d«      xr d| vS )zQCheck if a string looks like a valid URL (starts with http(s) and has no spaces).)zhttp://zhttps://ú )Ú
startswith©Útexts    úe/var/www/pod-logistic/pod-ai/venv/lib/python3.12/site-packages/sentence_transformers/base/modality.pyÚ_looks_like_urlr   ,   s   € à�?‰?Ð2Ó3ÒG¸À4¸ÐGó    c                ó   — t        | «      r4t        | «      j                  j                  «       }|j	                  |«      S | j                  «       j	                  |«      xr t
        j                  j                  | «      S )zOCheck if a string is a URL or local file path with one of the given extensions.)r   r   ÚpathÚlowerÚendswithÚosÚisfile)r   Ú
extensionsr   s      r   Ú_is_media_url_or_pathr#   1   sZ   € ä�tÔÜ˜‹~×"Ñ"×(Ñ(Ó*ˆØ�}‰}˜ZÓ(Ð(Ø�:‰:‹<× Ñ  Ó,ÒE´·±·±ÀÓ1EÐEr   c                ó>   — | j                  d«      ryt        | d«      S )z:Check if a string is an image URL, file path, or data URI.zdata:image/T)z.jpgz.jpegz.pngz.gifz.bmpz.tiffz.webp)r   r#   r   s    r   Úis_image_url_or_pathr%   9   s   € à‡��}Ô%ØÜ  Ð'bÓcÐcr   c                ód   — t        | d«      ryt        | «      xr t        | «      j                  dv S )z.Check if a string is a video URL or file path.)z.mp4z.aviz.movz.wmvz.flvz.mkvT)zwww.youtube.comzyoutube.comzyoutu.bezm.youtube.com)r#   r   r   Únetlocr   s    r   Úis_video_url_or_pathr(   @   s8   € ä˜TÐ#SÔTØÜ˜4Ó ò ¤X¨d£^×%:Ñ%:ð ?ð &ð r   c                ó   — t        | d«      S )z/Check if a string is an audio URL or file path.)z.mp3z.wavz.oggz.flacz.aac)r#   r   s    r   Úis_audio_url_or_pathr*   L   s   € ä  Ð'PÓQÐQr   c                ó0  — t        | t        t        f«      rt        | «      dk7  ryt        | d   t        «      rt        | d   t        «      ry| D ]E  }t        |t
        «      r
d|v rd|v r yt        |t        «      sŒ.|sŒ1t        |d   t
        «      sŒE y y)a‰  Check if a sample is a non-text pair (2-element tuple/list with at least one non-string element).

    Text pairs ``(str, str)`` are handled natively by tokenizers and detected as ``"text"`` modality
    by :func:`infer_modality`. This helper detects pairs that contain at least one non-string element
    (e.g. an image, audio array, or dict), which require conversion to message format.
    é   Fr   é   ÚroleÚcontentT)Ú
isinstanceÚtupleÚlistÚlenÚstrÚdict)ÚsampleÚelems     r   Ú_is_non_text_pairr8   Q   sˆ   € ô �fœu¤d˜mÔ,´°F³¸qÒ0@Øä�&˜‘)œSÔ!¤j°¸±¼CÔ&@Øàò ˆÜ�dœDÔ! f°¡n¸ÀdÑ9JÙÜ�dœDÕ!¢d¬z¸$¸q¹'Ä4Õ/HÙð	ð
 r   c                  ó®   — e Zd ZdZ	 	 	 d	 	 	 	 	 	 	 dd„Zdd„Z	 	 	 	 dd„Zdd„Zddd„Z	 	 	 	 	 	 dd„Z	e
dd	„«       Zdd
„Z	 	 	 	 	 	 dd„Z	 	 	 	 	 	 dd„Zy)ÚInputFormatteraœ  Handles input parsing, modality detection, and message format conversion.

    This class manages the complete input preprocessing pipeline:
    1. Parsing raw inputs to detect their modality (text, image, audio, video, message)
    2. Converting inputs to different chat template formats
    3. Normalizing mixed-modality inputs

    Different models require different message/chat template formats:
    - **Structured format**: Content is a list of dicts with type annotations
        [{"role": "user", "content": [{"type": "text", "text": "hello"}]}]

    - **Flat format**: Content is the direct value
        [{"role": "user", "content": "hello"}]

    Args:
        model_type: The model type string (e.g. from ``config.model_type``).
        message_format: Message format to use. Options:
            - ``"structured"``: Content is a list of dicts with type/modality keys
            - ``"flat"``: Content is the direct value
            - ``"auto"``: Automatically infer from processor (default)
        processor: Optional processor to infer format from when ``message_format="auto"``.
        supported_modalities: Optional list of modalities supported by the model. When provided,
            string inputs that look like media URLs/paths are only classified as non-text if the
            model actually supports that modality. This prevents text-only models from
            misclassifying text containing media URLs.
    Nc                óˆ   — || _         || _        || _        |dk(  r!|r| j                  |«      | _        y d| _        y || _        y )NÚautoÚ
structured)Ú
model_typeÚ	processorÚsupported_modalitiesÚ_infer_formatÚmessage_format)Úselfr>   rB   r?   r@   s        r   Ú__init__zInputFormatter.__init__‚   sG   € ð %ˆŒØ"ˆŒØ$8ˆÔ!Ø˜VÒ#ÙCL $×"4Ñ"4°YÓ"?ˆDÕÐR^ˆDÕà"0ˆDÕr   c                óÂ   ‡— | j                   t        v rt        | j                      S t        |dd«      Št        ‰t        «      r‰syg d¢}t        ˆfd„|D «       «      ryy)a£  Infer the message format expected by the processor.

        Checks known model types first, then inspects the processor's chat template
        for patterns indicating structured format. Defaults to ``"structured"`` if
        neither approach is conclusive.

        Args:
            processor: The processor/tokenizer to inspect.

        Returns:
            ``"structured"`` or ``"flat"`` message format.
        Úchat_templateNr=   )z
content[0]z.typez'type'z"type"z	item.typezmessage.content[c              3  ó&   •K  — | ]  }|‰v –— Œ
 y ­w©N© )Ú.0ÚpatternÚtemplates     €r   ú	<genexpr>z/InputFormatter._infer_format.<locals>.<genexpr>®   s   øè ø€ ÒF wˆw˜(Ô"ÑFùs   ƒr   )r>   Ú!KNOWN_MODEL_TYPES_MESSAGE_FORMATSÚgetattrr0   r4   Úany)rC   r?   Ústructured_patternsrL   s      @r   rA   zInputFormatter._infer_format‘   s]   ø€ ð �?‰?Ô?Ñ?Ü4°T·_±_ÑEÐEä˜9 o°tÓ<ˆÜ˜(¤CÔ(±Øò
Ðô ÓFÐ2EÔFÔFØàr   c                óâ  — |sddg it        t        «      fS g }t        t        «      }d}|D �]ù  }t        |«      r|j                  d|f«       d}Œ%t	        || j
                  ¬«      }|dk(  r"t        |t        «      r|d   }|d   |d   d<   �n„|dk(  rdt        �^t        |t        «      rN|j                  «       }|j                  j                  d	¬
«      j                  «       }|j                  |d   d<   �n|dk(  r=t        |t        «      r-|d   }|d   j                  dg «      j                  |d   «       nÙ|dk(  r¹t        �³t        |t        «      r£t        |«      }	|j!                  d	|	«      }
|
j                  }|d   j                  dg «      j                  |j"                  j$                  |j"                  j&                  t)        t+        |
j                  j,                  d	   «      «      dœ«       n|dk(  rt        |t        «      r|g}n|}|j                  ||f«       �Œü |rÐg }|D ]Â  \  }}|dk(  r!|j                  | j/                  |«      «       Œ,|dk(  rEt        |t0        t(        f«      r/t        |«      dk(  r!|j                  | j/                  |«      «       Œv|dk(  r|j                  |«       Œ�t        |t0        «      r|n||i}|j                  | j3                  |«      «       ŒÄ dd|i|fS t5        |Ž \  }}t)        |«      }t7        |«      }t        |«      dk(  r\|j9                  «       }t        |t:        «      r||i}nŒ|d	   j=                  «       }|D ��ci c]  }||D �cg c]  }||   ‘Œ	 c}“Œ }}}nUt>        jA                  d|› d�«       d|D ��cg c]*  \  }}| j3                  t        |t0        «      r|n||i«      ‘Œ, c}}i}d}|||fS c c}w c c}}w c c}}w )a-  Parse inputs and group by modality.

        Analyzes a list of inputs to detect their modality (text, image, audio, video, message)
        and groups them appropriately for the processor. Handles mixed modalities by converting
        to message format when necessary.

        Non-text pairs (e.g. ``(image, text)`` or ``(image, image)``) are detected and converted
        to message format with ``"query"``/``"document"`` roles via :meth:`pair_to_messages`.

        Args:
            inputs: List of inputs to parse. Can be:
                - str: Text inputs
                - tuple/list of str: Text pairs (for cross-encoders)
                - tuple/list of mixed types: Non-text pairs (e.g. image + text)
                - dict: Chat messages, audio data, or multimodal inputs
                - PIL.Image.Image: Image inputs
                - np.ndarray/torch.Tensor: Audio (1-2D) or video (3-5D) inputs

        Returns:
            Tuple of (modality, processor_inputs_dict, extra_modality_kwargs) where:
                - modality: Detected modality string (``"text"``, ``"image"``, etc.) or tuple of modalities
                - processor_inputs_dict: Dictionary mapping modality names to input lists
                - extra_modality_kwargs: Extra kwargs per modality (e.g. ``sampling_rate`` for audio)
        r   FÚpairT©r@   ÚaudioÚarrayÚsampling_rater   )ÚdimÚvideoÚvideo_metadata)ÚfpsÚtotal_num_framesÚframes_indicesÚmessager,   r-   zMixed modalities detected: z!. Converting to 'message' format.)!r   r5   r8   ÚappendÚinfer_modalityr@   r0   r   Úget_all_samplesÚdataÚmeanÚnumpyÚsample_rateÚ
setdefaultr   r3   Úget_frames_in_rangeÚmetadataÚaverage_fpsÚ
num_framesr2   ÚrangeÚshapeÚpair_to_messagesr1   Ú
to_messageÚzipÚsetÚpopr4   ÚkeysÚloggerÚdebug)rC   ÚinputsÚtyped_inputsÚextra_modality_kwargsÚ	has_pairsÚitemÚmodalityÚvalueÚsamplesrj   Úframe_batchÚmessagesÚmodÚtypedÚ
modalitiesÚprocessed_inputsÚunique_modalitiesÚordered_keysÚentrys                      r   Úparse_inputszInputFormatter.parse_inputs³   sí  € ñ8 Ø˜F B˜<¬´TÓ):Ð:Ð:àEGˆÜ +¬DÓ 1ÐØˆ	àó (	3ˆDô ! Ô&Ø×#Ñ# V¨T NÔ3Ø �	Øä% dÀ×AZÑAZÔ[ˆHð ˜7Ò"¤z°$¼Ô'=Ø˜W™�ØBFÀÑBWÐ% gÑ.¨Ó?Ø˜WÒ$¬Ð)AÄjÐQUÔWcÔFdØ×.Ñ.Ó0�àŸ™×)Ñ)¨aÐ)Ó0×6Ñ6Ó8�ØBI×BUÑBUÐ% gÑ.¨Ó?Ø˜WÒ$¬°D¼$Ô)?Ø˜W™�Ø% gÑ.×9Ñ9Ð:JÈBÓO×VÑVÐW[Ð\lÑWmÕnØ˜WÒ$¬Ð)AÄjÐQUÔWcÔFdÜ  ›Y�
Ø"×6Ñ6°q¸*ÓE�Ø#×(Ñ(�Ø% gÑ.×9Ñ9Ð:JÈBÓO×VÑVà#Ÿ}™}×8Ñ8Ø,0¯M©M×,DÑ,DÜ*.¬u°[×5EÑ5E×5KÑ5KÈAÑ5NÓ/OÓ*Pñõð ˜YÒ&¬:°d¼DÔ+AØ˜‘à�à×Ñ ¨5Ð 1Ö2ðQ(	3ñZ ØˆHØ*ò 	<‘
��UØ˜&’=Ø—O‘O D×$9Ñ$9¸%Ó$@ÕAØ˜F’]¤z°%¼%Ä¸Ô'GÌCÐPUËJÐZ[ÊOØ—O‘O D×$9Ñ$9¸%Ó$@ÕAØ˜IÒ%Ø—O‘O EÕ*ä%/°´UÔ%;™EÀ#ÀuÀ�EØ—O‘O D§O¡O°EÓ$:Õ;ð	<ð ˜y¨(Ð3Ð5JÐJÐJä'*¨LÐ'9Ñ$ˆ
Ð$ÜÐ 0Ó1ÐÜ 
›OÐäÐ Ó! QÒ&Ø(×,Ñ,Ó.ˆHÜ˜(¤CÔ(Ø$,Ð.>Ð#?Ñ ð  0°Ñ2×7Ñ7Ó9�Ø_k×#lÐX[ CÐBRÖ)S¸¨%°«*Ò)SÑ$SÐ#lÐ Ò#lä�L‰LÐ6Ð7HÐ6IÐIjÐkÔlàà+7÷á'˜ %ð —O‘O¬Z¸Ä%Ô-H¡EÈxÐY^ÐN_Õ`óð Ðð !ˆHàÐ)Ð+@Ð@Ð@ùò *TùÓ#lùós   Í'
O%Í1O Í=O%Î%/O+Ï O%c                ó    — |\  }}t        |«      }t        |«      }| j                  dk(  r
d|dœd|dœgS d„ }d |||«      dœd |||«      dœgS )aò  Convert a pair of inputs to query/document message format.

        Each element of the pair is wrapped in a message with role ``"query"`` (first element)
        or ``"document"`` (second element). The modality of each element is inferred individually
        via :func:`infer_modality`.

        Args:
            pair: A 2-element tuple or list of inputs (e.g. ``(image, text)``).

        Returns:
            List of two message dictionaries with ``"query"`` and ``"document"`` roles.
        r   Úquery©r.   r/   Údocumentc                ó’   — t        | t        «      r,t        |t        «      r| D �cg c]  }||v sŒd||||   i‘Œ c}S d| | |igS c c}w )NÚtype)r0   r1   r5   )rz   ry   r   s      r   Ú_to_contentz4InputFormatter.pair_to_messages.<locals>._to_content@  sT   € ô ˜(¤EÔ*¬z¸$ÄÔ/EØAIÖY¸#ÈSÐTXÊ[˜  c¨4°©9Ò5ÒYÐYØ˜X x°Ð6Ð7Ð7ùò Zs
   ¥	A¯A)r`   rB   )rC   rS   Ú
query_itemÚdoc_itemÚquery_modalityÚdoc_modalityr�   s          r   rm   zInputFormatter.pair_to_messages)  sy   € ð  $Ñˆ
�HÜ'¨
Ó3ˆÜ% hÓ/ˆà×Ñ &Ò(à ¨ZÑ8Ø#°Ñ9ðð ò
	8ð ©°^ÀZÓ)PÑQØ©K¸ÀhÓ,OÑPð
ð 	
r   c           	     ó  — | j                   dk(  rNt        |«      dk(  r+t        t        |j	                  «       «      «      \  }}||dœgS t
        j                  d«       ||j	                  «       D ��cg c]  \  }}d|||i‘Œ c}}dœgS c c}}w )aö  Convert a typed input dictionary to message format.

        Produces a single message with the given ``role``. For pair/multi-value inputs,
        use :meth:`pair_to_messages` instead (which is called automatically by :meth:`parse_inputs`).

        Args:
            typed_input: Dictionary mapping modality to input value (single value per modality).
            role: Role for the message (default: ``"user"``).

        Returns:
            List of message dictionaries (single message).
        r   r-   r‰   zbFlat message format requested but multiple modalities detected. Falling back to structured format.rŒ   )rB   r3   ÚnextÚiterÚitemsrs   Úwarning)rC   Útyped_inputr.   Ú_r{   rz   s         r   rn   zInputFormatter.to_messageL  s˜   € ð ×Ñ &Ò(Ü�;Ó 1Ò$Ü¤ [×%6Ñ%6Ó%8Ó 9Ó:‘��5Ø!%°%Ñ8Ð9Ð9ä—‘ð9ôð ØWb×WhÑWhÓWj×kÁOÀHÈe˜V X¨x¸Ò?Ókñð
ð 	
ùó ls   Á2B	c                óP  — |sddg ifS t        |t        «      r|fn|}t        t        t	        |j                  «       «      «      «      }g }t        |«      D ]Ä  }|D �ci c]  }||v sŒ|||   |   “Œ }}t        |«      dk(  ryt        t	        |j                  «       «      «      }	t        |	t        t        f«      rAt        |	«      dk(  r3t        d„ |	D «       «      r!|j                  | j                  |	«      «       Œ¥|j                  | j                  |«      «       ŒÆ dd|ifS c c}w )ac  Convert a batch of modality-specific inputs into the unified message format.

        Args:
            modality: The modality key (string) or tuple of modality keys.
            processor_inputs: Dictionary mapping modality names to lists of inputs.

        Returns:
            Tuple of ``("message", {"message": [messages_per_sample, ...]})``
        r^   r-   r,   c              3  ó<   K  — | ]  }t        |t        «      –— Œ y ­wrH   )r0   r4   )rJ   Úvs     r   rM   z2InputFormatter.batch_to_message.<locals>.<genexpr>�  s   è ø€ ÒOrÐghÔPZÐ[\Ô^a×PbÑOrùs   ‚)r0   r4   r3   r“   r”   Úvaluesrk   r1   r2   Úallr_   rm   rn   )
rC   rz   Úprocessor_inputsr�   Ú
batch_sizer~   Úir   r—   r{   s
             r   Úbatch_to_messagezInputFormatter.batch_to_messagej  s  € ñ  Ø˜y¨"˜oÐ-Ð-Ü$.¨x¼Ô$=�h‘[À8ˆ
ÜœœdÐ#3×#:Ñ#:Ó#<Ó=Ó>Ó?ˆ
ØˆÜ�zÓ"ò 		:ˆAàDTÖj¸SÐX[Ð_iÒXi˜3Ð 0°Ñ 5°aÑ 8Ñ8ÐjˆKÐjä�;Ó 1Ò$ÜœT +×"4Ñ"4Ó"6Ó7Ó8�Ü˜e¤e¬T ]Ô3¼¸E»
ÀaºÌCÑOrÐlqÔOrÔLrØ—O‘O D×$9Ñ$9¸%Ó$@ÔAØØ�O‰O˜DŸO™O¨KÓ8Õ9ð		:ð ˜9 hÐ/Ð/Ð/ùò ks   Á	D#Á'D#c                ó´   — | D ]S  }|D ]L  }|j                  d«      }t        |t        «      rŒ%t        |t        «      rt	        d„ |D «       «      sŒH  y  y ŒU y)a   Check whether all messages in a batch contain only text content.

        Works with both flat format (``{"content": "hello"}``) and structured format
        (``{"content": [{"type": "text", "text": "hello"}]}``).

        Args:
            messages_batch: List of message lists, one per sample.

        Returns:
            True if every message contains only text, False if any contain non-text content.
        r/   c              3  óF   K  — | ]  }|j                  d d«      dk7  –— Œ y­w)rŒ   r   N)Úget)rJ   ry   s     r   rM   z7InputFormatter.is_text_only_messages.<locals>.<genexpr>š  s    è ø€ ÒRÀ$˜4Ÿ8™8 F¨FÓ3°vÕ=ÑRùs   ‚!FT)r¤   r0   r4   r2   rP   )Úmessages_batchr~   r^   r/   s       r   Úis_text_only_messagesz$InputFormatter.is_text_only_messages‡  s`   € ð 'ò 		!ˆHØ#ò !�Ø!Ÿ+™+ iÓ0�Ü˜g¤sÔ+ØÜ˜g¤tÔ,ÜÑRÈ'ÔRÕRÚ$â ñ!ð		!ð r   c                óp  — g }|D �]-  }d|vsd|vrt         j                  d|› d�«       Œ&|d   }t        |t        «      xr |xr t        |d   t        «      }| j
                  dk(  ri|rgt        |«      dk(  r%d|d   v r|j                  i |¥d|d   d   i¥«       Œ˜t         j                  d	t        |«      › d
�«       |j                  |«       ŒÌ| j
                  dk(  rB|s@t        |t        «      r|j                  i |¥dd|dœgi¥«       �Œ
|j                  |«       �Œ|j                  |«       �Œ0 |S )a;  Normalize messages to the target format (``self.message_format``).

        Extra keys beyond ``"role"`` and ``"content"`` are preserved during conversion.

        Args:
            messages: List of message dictionaries to normalize.

        Returns:
            Normalized list of message dictionaries.
        r.   r/   zInvalid message format: z. Skipping.r   r   r-   r   z;Cannot convert structured message to flat format: contains z# content items. Keeping structured.r=   ©rŒ   r   )	rs   r–   r0   r2   r5   rB   r3   r_   r4   )rC   r~   Ú
normalizedr^   r/   Úis_currently_structureds         r   Únormalize_messagesz!InputFormatter.normalize_messages   sS  € ð ˆ
Øó 	+ˆGØ˜WÑ$¨	¸Ñ(@Ü—‘Ð!9¸'¸À+ÐNÔOØà˜iÑ(ˆGÜ&0°¼$Ó&?Ò&lÀGÒ&lÔPZÐ[bÐcdÑ[eÔgkÓPlÐ#à×"Ñ" fÒ,Ñ1HÜ�w“< 1Ò$¨°7¸1±:Ñ)=Ø×%Ñ%Ð&P¨Ð&P°)¸WÀQ¹ZÈÑ=OÑ&PÕQä—N‘Nð$Ü$'¨£L >Ð1TðVôð ×%Ñ% gÕ.Ø×$Ñ$¨Ò4Ñ=TÜ˜g¤sÔ+Ø×%Ñ%Ð&a¨Ð&a°)ÀvÐW^Ñ>_Ð=`Ñ&aÖbà×%Ñ% gÖ.à×!Ñ! 'Ö*ð/	+ð2 Ðr   c                ó˜   — | j                   dk(  r|D �cg c]  }d|dœg|z   ‘Œ c}S |D �cg c]  }dd|dœgdœg|z   ‘Œ c}S c c}w c c}w )a'  Prepend a system prompt to message format inputs.

        Args:
            messages: List of message lists (each message list represents one input).
            prompt: System prompt to prepend.

        Returns:
            Messages with system prompt prepended to each message list.
        r   Úsystemr‰   r   r¨   )rB   )rC   r~   ÚpromptÚmessage_lists       r   Úprepend_prompt_to_messagesz)InputFormatter.prepend_prompt_to_messagesÇ  sn   € ð ×Ñ &Ò(Ø_gÖhÈ|˜h°6Ñ:Ð;¸lÓJÒhÐhð !)ö
àð °VÀVÑ,LÐ+MÑNÐOÐR^Ó^ò
ð 	
ùò iùò
s
   ”A«Ac           	     ó°   — g }|D ]N  }t        |t        «      r|j                  ||z   «       Œ(|j                  ||d   z   gt        |dd «      z   «       ŒP |S )ab  Prepend a prompt to text format inputs.

        For single texts, prepends the prompt directly.
        For text pairs (cross-encoder inputs), prepends only to the first text.

        Args:
            texts: List of text inputs (strings or pairs)
            prompt: Prompt to prepend

        Returns:
            Texts with prompt prepended
        r   r-   N)r0   r4   r_   r2   )rC   Útextsr®   Úresultr   s        r   Úprepend_prompt_to_textsz&InputFormatter.prepend_prompt_to_textsÚ  sb   € ð ˆØò 	CˆDÜ˜$¤Ô$Ø—‘˜f t™mÕ,à—‘˜v¨¨Q©Ñ/Ð0´4¸¸Q¸R¸³>ÑAÕBð		Cð
 ˆr   )r<   NN)r>   r4   rB   r   r@   úlist[Modality] | NoneÚreturnÚNone)r¶   zLiteral['structured', 'flat'])ru   úlist[SingleInput | PairInput]r¶   zBtuple[Modality, dict[str, list], defaultdict[str, dict[str, Any]]])rS   ztuple | listr¶   úlist[dict[str, Any]])Úuser)r—   zdict[Modality, Any]r.   r4   r¶   r¹   )rz   r	   rž   r5   r¶   z*tuple[Literal['message'], dict[str, list]])r¥   úlist[list[dict[str, Any]]]r¶   Úbool)r~   r¹   r¶   r¹   )r~   r»   r®   r4   r¶   r»   )r²   z'list[str | tuple[str, str] | list[str]]r®   r4   r¶   zlist[str | list[str]])Ú__name__Ú
__module__Ú__qualname__Ú__doc__rD   rA   r†   rm   rn   r¡   Ústaticmethodr¦   r«   r°   r´   rI   r   r   r:   r:   f   sÞ   „ ñð< )/ØØ6:ð1àð1ð &ð1ð
 4ð1ð 
ó1ó ðDtAà-ðtAð 
LótAól!
ôF
ð<0Ø ð0Ø48ð0à	3ó0ð: òó ðó0%ðN
Ø2ð
Ø<?ð
à	#ó
ð&Ø<ðØFIðà	ôr   r:   c                óž  — t         �t        | t         «      ryt        �t        | t        «      ryt        �t        | t        «      ry| xt        d˜ x�\   t        | «      r
 |�d|vryy xt        d˜ x�\   t        | «      r
 |�d|vryy xt        d˜ x�\   t        | «      r
 |�d|vryy xxt        d˜ x�\     y x  r! dk(  r\  t        d˜ x�\   t        d˜ x�\     y  x  r! dk(  r\  t        d˜ x�\   t        d˜ x�\     y   xt        d˜ x�\   d| v rd| v r y	 xt        d˜ x�'\   | r$t        | d
   t        «      rd| d
   v r
d| d
   v r y	 xt        d˜ x�\   d| v rd| v r y xt        d˜ x�\   d| v rd| v r y xt        d˜ x�,\   d| v r' t        dt        | j                  «       «      › �«      ‚ xt        d˜ x�Z\   | rW h d£}t        | j                  «       «      |z
  }|rt        d|› d|› �«      ‚t        t        | j                  «       «      «      S  xt        d˜ x�\    t        d«      ‚ xt        j                   d˜ x�\   n xt"        j$                  d˜ x�\   n  nH | j&                  dv ry| j&                  dk(  ry| j&                  dv ryt        d| j&                  › d�«      ‚	 t        dt)        | «      j*                  › d�«      ‚)a  Infer the modality of a single input sample by inspecting its type/structure.

    Pure type-based detection, does not require a processor or tokenizer.

    Args:
        sample: A single input sample to inspect.
        supported_modalities: Optional list of modalities the model supports. When provided,
            string inputs that would be classified as image/video/audio based on URL/path
            heuristics are instead classified as ``"text"`` if that modality is not supported.
            This prevents misclassification of text that happens to contain media URLs.

    Returns:
        The detected modality string, or a tuple of modality strings for multimodal dict inputs.

    Raises:
        ValueError: If the input type/structure is not recognized.
    ÚimagerU   rY   rI   r   r,   r.   r/   r^   r   rV   rW   rZ   zuDict input with 'array' key must also include 'sampling_rate' (for audio) or 'video_metadata' (for video). Got keys: >   r   rU   rÃ   rY   z;Multimodal dict input contains unrecognized modality keys: z. Expected keys from: z-Empty dict input is not a valid input sample.)r-   r,   é   )é   é   z#Unsupported tensor dimensionality: z<D. Expected 1-2D for audio, 3D for image, or 4-5D for video.zUnsupported input type: zG. Expected one of: str, dict, PIL.Image.Image, np.ndarray, torch.Tensor)ÚPILImager0   r   r   r4   r%   r(   r*   r5   r2   Ú
ValueErrorrp   rr   r1   ÚsortedÚnpÚndarrayÚtorchÚTensorÚndimrŒ   r½   )r6   r@   Úvalid_modalitiesÚinvalid_keyss       r   r`   r`   ò  s  € ô, Ð¤
¨6´8Ô <ØäÐ¤J¨v´|Ô$DØäÐ¤J¨v´|Ô$DØà
ØŒS�UÔ*¨6Ô2ˆUØ#Ð/°GÐCWÑ4WØØð ð ŒS�UÔ*¨6Ô2ˆUØ#Ð/°GÐCWÑ4WØØð ð ŒS�UÔ*¨6Ô2ˆUØ#Ð/°GÐCWÑ4WØØð ð 5ˆUŒS�UÑ4Øð —^‘^”c•eœS�UÑ4Øñ $§n¡n¤s¥u¬c­eÑ4Øñ '5Ð4àŒT�V�v Ñ'¨I¸Ñ,?ˆVØð àŒT�V‘v¤*¨V°A©Y¼Ô"=À&ÈFÐSTÉIÑBUÐZcÐgmÐnoÑgpÑZpˆVØð àŒT�V�w &Ñ(¨_ÀÑ-FˆVØð àŒT�V�w &Ñ(Ð-=ÀÑ-GˆVØð àŒT�V�w &Ñ(ˆVÜðä  §¡£Ó/Ð0ð2óð ð ð ŒT�V‘vˆVâBÐÜ˜vŸ{™{›}Ó-Ð0@Ñ@ˆLÙÜ ØQÐR^ÐQ_ð `+Ø+;Ð*<ð>óð ô œ §¡£Ó.Ó/Ð/ð ð ŒTŽVÜÐLÓMÐMð àŒR�Z‰Z�\˜NœEŸL™LŸNÒ*Ø�{‰{˜fÑ$ØØ—‘ Ò!ØØ—‘ Ñ&Øä Ø9¸&¿+¹+¸ð GPð Qóð ð ÜØ*¬4°«<×+@Ñ+@Ð*Að BXð Yóð r   c                ó†   — | sy| D �ch c]  }t        ||¬«      ’Œ }}t        |«      dk(  r|j                  «       S dS c c}w )a�  Infer the modality of a batch of input samples.

    If all samples share the same modality, that modality is returned. If the batch contains
    mixed modalities, ``"message"`` is returned, consistent with how :class:`InputFormatter`
    handles mixed-modality batches in :meth:`~InputFormatter.parse_inputs`.

    Args:
        samples: List of input samples to inspect.
        supported_modalities: Optional list of modalities the model supports. Passed through
            to :func:`infer_modality` to prevent misclassification of text as media modalities.

    Returns:
        The detected modality, or ``"message"`` for mixed-modality batches.
    r   rT   r-   r^   )r`   r3   rq   )r|   r@   r6   r�   s       r   Úinfer_batch_modalityrÒ   M  sI   € ñ$ ØØbiÖjÐX^”. Ð>RÖSÐj€JÐjÜ" :›°!Ò3ˆ:�>‰>ÓÐB¸ÐBùò ks   ˆ>c                óH   — t        | t        «      rdj                  | «      S | S )zSFormat a modality for display, e.g. ``("text", "image")`` becomes ``"text+image"``.ú+)r0   r1   Újoin)rz   s    r   Úformat_modalityrÖ   e  s    € ä�(œEÔ"Ø�x‰x˜Ó!Ð!Ø€Or   )r   r4   r¶   r¼   )r   r4   r"   ztuple[str, ...]r¶   r¼   )r6   r   r¶   r¼   rH   )r6   zSingleInput | PairInput | Anyr@   rµ   r¶   r	   )r|   r¸   r@   rµ   r¶   r	   )rz   r	   r¶   r4   )*rÀ   Ú
__future__r   Úloggingr    Úcollectionsr   Útypingr   r   Úurllib.parser   rd   rÊ   rÌ   Ú)sentence_transformers.base.modality_typesr   r	   r
   r   Ú	PIL.Imager   rÇ   ÚImportErrorÚtorchcodec.decodersr   r   ÚOSErrorÚ	getLoggerr½   rs   rN   r   r#   r%   r(   r*   r8   r:   r`   rÒ   rÖ   rI   r   r   ú<module>râ      s  ðÙ Gå "ã Û 	Ý #ß Ý !ã Û ÷ó ðÝ+ðß>ð
 
ˆ×	Ñ	˜8Ó	$€ð
 ØØØñ	%Ð !óHó
Fódó	óRó
÷*Iñ Ið\ 37ðXØ)ðXà/ðXð óXðz 37ðCØ*ðCà/ðCð óCô0øð] ò Ø‚Hðûð
 	�WÐò Ø€LØ‚Lðús#   ºB ÁB, ÂB)Â(B)Â,B:Â9B: