§
    +�’j·<  ã                  ó6  — d dl mZ d dlmZmZ d dlZd dlZd dlm	Z	 d dlm
Z
mZ d0d
„Zd1d„Zd1d„Zd2d„Zd1d„Zd3d„Zed4d„¦   «         Zed5d„¦   «         Zd6d„Zed7d„¦   «         Zed8d„¦   «         Zed9d„¦   «         Zd:d„Zd;d"„Zd<d&„Zd<d'„Zd=d+„Zd>d.„Zd?d/„ZdS )@é    )Úannotations)ÚAnyÚoverloadN)Ú
coo_matrix)ÚTensorÚdeviceÚaú
np.ndarrayÚreturnr   c                óŒ   — | j         j        r%	 t          j        | ¦  «        S # t          $ r Y nw xY wt          j        | ¦  «        S )aå  View a numpy array as a tensor without copying its buffer, which on a corpus of embeddings
    costs as much as the scoring it feeds. Two kinds of array cannot be viewed and are copied with
    :func:`torch.tensor` instead: read-only buffers (memmaps, broadcast views), and dtypes with no
    torch equivalent. Arrays with a negative stride are rejected outright by both routes.

    The returned tensor aliases the caller's array, so consumers must write only into fresh outputs.
    )ÚflagsÚ	writeableÚtorchÚ
from_numpyÚ	TypeErrorÚtensor©r	   s    úOC:\Projects\DSCons\.venv\Lib\site-packages\sentence_transformers\util\tensor.pyÚ_wrap_numpyr      sU   € ð 	„wÔð ð	ÝÔ# AÑ&Ô&Ð&øÝð 	ð 	ð 	ØˆDð	øøøåŒ<˜‰?Œ?Ðs   Ž" ¢
/®/úlist | np.ndarray | Tensorc                ó0  — t          | t          ¦  «        r†t          d„ | D ¦   «         ¦  «        rt          j        d„ | D ¦   «         ¦  «        S | r8t          d„ | D ¦   «         ¦  «        rt          j        d„ | D ¦   «         ¦  «        } nht          j        | ¦  «        } nSt          | t          j        ¦  «        rt          | ¦  «        } n)t          | t          ¦  «        st          j        | ¦  «        } | j
        r |                      t          j        ¬¦  «        S | S )a–  
    Converts the input `a` to a PyTorch tensor if it is not already a tensor. Lists are stacked into
    one tensor: a list of sparse tensors keeps its sparsity, and a list of numpy arrays is viewed
    rather than read element by element (see :func:`_wrap_numpy`).

    Args:
        a (Union[list, np.ndarray, Tensor]): The input array or tensor.

    Returns:
        Tensor: The converted tensor.
    c              3  óN   K  — | ] }t          |t          ¦  «        o|j        V — Œ!d S ©N)Ú
isinstancer   Ú	is_sparse©Ú.0Úxs     r   ú	<genexpr>z%_convert_to_tensor.<locals>.<genexpr>)   s3   è è € Ð@Ð@¸�z˜!�VÑ$Ô$Ð4¨¬Ð@Ð@Ð@Ð@Ð@Ð@ó    c                ór   — g | ]4}|                      ¦   «                              t          j        ¬ ¦  «        ‘Œ5S )©Údtype)ÚcoalesceÚtor   Úfloat32r   s     r   ú
<listcomp>z&_convert_to_tensor.<locals>.<listcomp>+   s0   € ÐPÐPÐPÈ §
¢
¡¤§¢µe´m Ñ DÔ DÐPÐPÐPr    c              3  óJ   K  — | ]}t          |t          j        ¦  «        V — Œd S r   )r   ÚnpÚndarrayr   s     r   r   z%_convert_to_tensor.<locals>.<genexpr>,   s.   è è € Ð<Ð<°Q•z !¥R¤ZÑ0Ô0Ð<Ð<Ð<Ð<Ð<Ð<r    c                ó,   — g | ]}t          |¦  «        ‘ŒS © )r   r   s     r   r'   z&_convert_to_tensor.<locals>.<listcomp>/   s   € Ð7Ð7Ð7°�[¨™^œ^Ð7Ð7Ð7r    r"   )r   ÚlistÚallr   Ústackr   r)   r*   r   r   r   r%   r&   r   s    r   Ú_convert_to_tensorr0      s  € õ �!•TÑÔð åÐ@Ð@¸aÐ@Ñ@Ô@Ñ@Ô@ð 	 å”;ÐPÐPÈaÐPÑPÔPÑQÔQÐQØð 	 •3Ð<Ð<¸!Ð<Ñ<Ô<Ñ<Ô<ð 	 õ ”Ð7Ð7°QÐ7Ñ7Ô7Ñ8Ô8ˆAˆAå”˜Q‘”ˆAˆAÝ	�A•r”zÑ	"Ô	"ð Ý˜‰NŒNˆˆÝ˜�6Ñ"Ô"ð ÝŒL˜‰OŒOˆØ„{ð )Ø�tŠt�%œ-ˆtÑ(Ô(Ð(Ø€Hr    c                óÎ   — t          | ¦  «        } t          j        | ¦  «        rAt          j        | j        ¦  «        j        dk     r|                      t          j        ¦  «        } | S )a  
    Converts like :func:`_convert_to_tensor`, then upcasts sub-float32 floats (fp8, float16,
    bfloat16) to float32: matmul rounds its output to the input dtype, bucketing nearby similarity
    scores into spurious ties. The multi-vector scoring path instead accumulates in float32 and
    keeps :func:`_convert_to_tensor`.

    Args:
        a (Union[list, np.ndarray, Tensor]): The input array or tensor.

    Returns:
        Tensor: The converted tensor, in float32 for any sub-float32 floating input.
    é    )r0   r   Úis_floating_pointÚfinfor#   Úbitsr%   r&   r   s    r   Ú_convert_to_float_tensorr6   ;   sU   € õ 	˜1ÑÔ€AÝÔ˜qÑ!Ô!ð  ¥e¤k°!´'Ñ&:Ô&:Ô&?À"Ò&DÐ&DØ�DŠD•”ÑÔˆØ€Hr    c                ó`   — |                       ¦   «         dk    r|                      d¦  «        } | S )zÊ
    If the tensor `a` is 1-dimensional, it is unsqueezed to add a batch dimension.

    Args:
        a (Tensor): The input tensor.

    Returns:
        Tensor: The tensor with a batch dimension.
    é   r   )ÚdimÚ	unsqueezer   s    r   Ú_convert_to_batchr;   N   s)   € ð 	‡u‚u�w„w�!‚|€|Ø�KŠK˜‰NŒNˆØ€Hr    c                ó~   — t          | ¦  «        } |                      ¦   «         dk    r|                      d¦  «        } | S )a}  
    Converts the input data to a tensor with a batch dimension, stacking lists as
    :func:`_convert_to_tensor` does.

    Args:
        a (Union[list, np.ndarray, Tensor]): The input data to be converted.

    Returns:
        Tensor: The converted tensor with a batch dimension, in float32 for any sub-float32
        floating input (see :func:`_convert_to_float_tensor`).
    r8   r   )r6   r9   r:   r   s    r   Ú_convert_to_batch_tensorr=   ]   s6   € õ 	! Ñ#Ô#€AØ‡u‚u�w„w�!‚|€|Ø�KŠK˜‰NŒNˆØ€Hr    Ú
embeddingsc                ó~  — | j         s't          j        j                             | dd¬¦  «        S |                      ¦   «         } |                      ¦   «         |                      ¦   «         }}t          j        |  	                    d¦  «        | j
        ¬¦  «        }|                     d|d         |dz  ¦  «         t          j        |¦  «                             d|d         ¦  «        }|dk    }|                     ¦   «         }||xx         ||         z  cc<   t          j        |||  	                    ¦   «         ¦  «        S )zá
    Normalizes the embeddings matrix, so that each sentence embedding has unit length.

    Args:
        embeddings (Tensor): The input embeddings matrix.

    Returns:
        Tensor: The normalized embeddings matrix.
    é   r8   )Úpr9   r   ©r   )r   r   ÚnnÚ
functionalÚ	normalizer$   ÚindicesÚvaluesÚzerosÚsizer   Ú
index_add_ÚsqrtÚindex_selectÚcloneÚsparse_coo_tensor)r>   rF   rG   Ú	row_normsÚmaskÚnormalized_valuess         r   Únormalize_embeddingsrR   o   s#  € ð Ôð EÝŒxÔ"×,Ò,¨Z¸1À!Ð,ÑDÔDÐDà×$Ò$Ñ&Ô&€JØ ×(Ò(Ñ*Ô*¨J×,=Ò,=Ñ,?Ô,?ˆV€Gõ ”˜JŸOšO¨AÑ.Ô.°zÔ7HÐIÑIÔI€IØ×Ò˜˜G AœJ¨°©	Ñ2Ô2Ð2Ý”
˜9Ñ%Ô%×2Ò2°1°g¸a´jÑAÔA€Ið �qŠ=€DØŸš™œÐØ�dÐÐÔ˜y¨œÑ.ÐÐÑåÔ" 7Ð,=¸z¿ºÑ?PÔ?PÑQÔQÐQr    Útruncate_dimú
int | Nonec                ó   — d S r   r,   ©r>   rS   s     r   Útruncate_embeddingsrW   Œ   ó   € ØY\ÐY\r    útorch.Tensorc                ó   — d S r   r,   rV   s     r   rW   rW   �   ó   € Ø]`Ð]`r    únp.ndarray | torch.Tensorc                ó   — | dd|…f         S )a¼  
    Truncates the embeddings matrix.

    Args:
        embeddings (Union[np.ndarray, torch.Tensor]): Embeddings to truncate.
        truncate_dim (Optional[int]): The dimension to truncate sentence embeddings to. `None` does no truncation.

    Example:
        >>> from sentence_transformers import SentenceTransformer
        >>> from sentence_transformers.util import truncate_embeddings
        >>> model = SentenceTransformer("tomaarsen/mpnet-base-nli-matryoshka")
        >>> embeddings = model.encode(["It's so nice outside!", "Today is a beautiful day.", "He drove to work earlier"])
        >>> embeddings.shape
        (3, 768)
        >>> model.similarity(embeddings, embeddings)
        tensor([[1.0000, 0.8100, 0.1426],
                [0.8100, 1.0000, 0.2121],
                [0.1426, 0.2121, 1.0000]])
        >>> truncated_embeddings = truncate_embeddings(embeddings, 128)
        >>> truncated_embeddings.shape
        >>> model.similarity(truncated_embeddings, truncated_embeddings)
        tensor([[1.0000, 0.8092, 0.1987],
                [0.8092, 1.0000, 0.2716],
                [0.1987, 0.2716, 1.0000]])

    Returns:
        Union[np.ndarray, torch.Tensor]: Truncated embeddings.
    .Nr,   rV   s     r   rW   rW   ”   s   € ð: �c˜=˜L˜=Ð(Ô)Ð)r    Úmax_active_dimsÚintc                ó   — d S r   r,   ©r>   r^   s     r   Úselect_max_active_dimsrb   ´   s   € ØilÐilr    ÚNonec                ó   — d S r   r,   ra   s     r   rb   rb   ¸   rX   r    c                ó   — d S r   r,   ra   s     r   rb   rb   ¼   r[   r    c                ó¨  — |€| S |dk    rt          d|› d�¦  «        ‚t          | t          j        ¦  «        rt	          j        | ¦  «        } | j        d         }t	          j        t	          j        | ¦  «        t          ||¦  «        d¬¦  «        \  }}t	          j
        | ¦  «        }|                     d||                      d|¦  «        ¦  «         |S )aÿ  
    Returns a new tensor with only the top-k values (in absolute terms) of each embedding, all others set to zero.

    The input embeddings are never modified in place.

    Args:
        embeddings (Union[np.ndarray, torch.Tensor]): Embeddings to sparsify by keeping only the largest values.
        max_active_dims (Optional[int]): Number of values to keep as non-zeros per embedding. `None` keeps all
            values, returning the embeddings as-is.

    Raises:
        ValueError: If `max_active_dims` is 0 or negative.

    Returns:
        Union[np.ndarray, torch.Tensor]: A new dense tensor of the same shape, with all but the top-k values per
            embedding set to zero. If `max_active_dims` is `None`, the embeddings are returned unchanged.
    Nr   z0max_active_dims must be a positive integer, got ú.éÿÿÿÿ)Úkr9   )Ú
ValueErrorr   r)   r*   r   r   ÚshapeÚtopkÚabsÚminÚ
zeros_likeÚscatter_Úgather)r>   r^   Úembedding_dimÚ_Útop_indicesÚselecteds         r   rb   rb   À   sÕ   € ð( ÐØÐØ˜!ÒÐÝÐ^ÈOÐ^Ð^Ð^Ñ_Ô_Ð_å�*�bœjÑ)Ô)ð .Ý”\ *Ñ-Ô-ˆ
àÔ$ RÔ(€Mõ ”Z¥¤	¨*Ñ 5Ô 5½¸_ÈmÑ9\Ô9\ÐbdÐeÑeÔe�N€A€{õ Ô 
Ñ+Ô+€HØ×Ò�b˜+ z×'8Ò'8¸¸[Ñ'IÔ'IÑJÔJÐJà€Or    Úfeaturesúdict[str, Any]c           	     óL  ‡‡— | d                               ¦   «         }| d         d         Š| d         d         Št          j        j        j                             ˆfd„t          |dd…         |dd…         ¦  «        D ¦   «         d	d
¬¦  «        | d<   t          j        j        j                             ˆfd„t          |dd…         |dd…         ¦  «        D ¦   «         d	d¬¦  «        | d<   t          j        d„ t          |dd…         |dd…         ¦  «        D ¦   «         ‰j        ¬¦  «        }| d         j	        d         }t          j
        |‰j        ¬¦  «                             d¦  «        |                     d¦  «        k     | d<   dD ]}|                      |d¦  «         Œ| S )a  Reverse FA2 input flattening on a features dict, in place.

    When :class:`Transformer` runs with FA2 unpadding, ``DataCollatorWithFlattening`` flattens the
    batch into ``token_embeddings: (1, sum_lens, D)`` / ``input_ids: (1, sum_lens)``, drops
    ``attention_mask``, and writes ``cu_seq_lens_q`` to mark sequence boundaries. This function
    reverses that: pad ``token_embeddings`` and ``input_ids`` back to ``(B, T_max, ...)``, rebuild
    ``attention_mask`` from the cumulative lengths, and drop the FA2-specific keys. Caller is
    responsible for gating on ``cu_seq_lens_q in features``.

    Args:
        features: Features dict containing flat FA2 outputs. Mutated in place.

    Returns:
        The same ``features`` dict, with the standard ``(B, T_max, ...)`` shape restored.
    Úcu_seq_lens_qÚtoken_embeddingsr   Ú	input_idsc                ó*   •— g | ]\  }}‰||…         ‘ŒS r,   r,   )r   ÚsÚeÚflat_embs      €r   r'   z,repad_flattened_features.<locals>.<listcomp>ü   ó%   ø€ Ð8Ð8Ð8™4˜1˜aˆ�!�A�#ŒÐ8Ð8Ð8r    Nrh   r8   Tg        )Úbatch_firstÚpadding_valuec                ó*   •— g | ]\  }}‰||…         ‘ŒS r,   r,   )r   r}   r~   Úflat_idss      €r   r'   z,repad_flattened_features.<locals>.<listcomp>ÿ   r€   r    c                ó   — g | ]
\  }}||z
  ‘ŒS r,   r,   )r   r}   r~   s      r   r'   z,repad_flattened_features.<locals>.<listcomp>  s    € ÐCÐCÐC¡d a¨˜A ™EÐCÐCÐCr    rB   Úattention_mask)ry   Úcu_seq_lens_kÚmax_length_qÚmax_length_kÚseq_idxÚposition_ids)Útolistr   rC   ÚutilsÚrnnÚpad_sequenceÚzipr   r   rk   Úaranger:   Úpop)rv   ÚcuÚlengthsÚT_maxÚkeyr   r„   s        @@r   Úrepad_flattened_featuresr—   è   sµ  øø€ ð  
�/Ô	"×	)Ò	)Ñ	+Ô	+€BØÐ*Ô+¨AÔ.€HØ˜Ô$ QÔ'€HÝ#(¤8¤>Ô#5×#BÒ#BØ8Ð8Ð8Ð8¥3 r¨#¨2¨#¤w°°1°2°2´Ñ#7Ô#7Ð8Ñ8Ô8ÀdÐZ]ð $Cñ $ô $€HÐÑ õ "œHœNÔ.×;Ò;Ø8Ð8Ð8Ð8¥3 r¨#¨2¨#¤w°°1°2°2´Ñ#7Ô#7Ð8Ñ8Ô8ÀdÐZ[ð <ñ ô €Hˆ[Ñõ ŒlÐCÐC­c°"°S°b°S´'¸2¸a¸b¸b¼6Ñ.BÔ.BÐCÑCÔCÈHÌOÐ\Ñ\Ô\€GØ�[Ô!Ô'¨Ô*€EÝ!&¤¨e¸H¼OÐ!LÑ!LÔ!L×!VÒ!VÐWXÑ!YÔ!YÐ\c×\mÒ\mÐnoÑ\pÔ\pÒ!p€HÐÑØlð  ð  ˆØ�Š�S˜$ÑÔÐÐØ€Or    úlist[Tensor]Úmasksútuple[Tensor, Tensor]c                óü   ‡— t          d„ | D ¦   «         ¦  «        Št          ˆfd„| D ¦   «         ¦  «        rˆfd„| D ¦   «         } ˆfd„|D ¦   «         }t          j        | d¬¦  «        t          j        |d¬¦  «        fS )a  Stack a list of ``(B, T_i, D)`` token embeddings and their ``(B, T_i)`` masks along
    ``dim=1``, padding each column up to the batch-wide max token count.

    Used by multi-vector / late-interaction losses to assemble a ``(B, N, T_max, D)`` document
    tensor plus matching ``(B, N, T_max)`` mask. ``F.pad``'s tail-axis padding handles the token
    dimension (the embedding and batch dims are left alone). Padded positions must be excluded
    downstream via the returned mask (MaxSim already honours it).

    Skips the pad and does a plain stack when every column already shares ``T`` (e.g. a single
    document column). Pads when columns differ, as with independently-padded text columns
    (different per-column batch-longest) or ragged-token-count VLMs (Qwen2-VL family).
    c              3  ó@   K  — | ]}|                      d ¦  «        V — ŒdS ©r8   N©rI   ©r   r~   s     r   r   z0stack_padded_token_embeddings.<locals>.<genexpr>  ó,   è è € Ð.Ð.˜a�—’�q‘	”	Ð.Ð.Ð.Ð.Ð.Ð.r    c              3  óJ   •K  — | ]}|                      d ¦  «        ‰k    V — ŒdS r�   rž   ©r   r~   r•   s     €r   r   z0stack_padded_token_embeddings.<locals>.<genexpr>  ó2   øè è € Ð
2Ð
2 !ˆ1�6Š6�!‰9Œ9˜ÒÐ
2Ð
2Ð
2Ð
2Ð
2Ð
2r    c                óŽ   •— g | ]A}t           j        j                             |d d d ‰|                     d¦  «        z
  f¦  «        ‘ŒBS ©r   r8   ©r   rC   rD   ÚpadrI   r¢   s     €r   r'   z1stack_padded_token_embeddings.<locals>.<listcomp>  óG   ø€ ÐcÐcÐcÐST•e”hÔ)×-Ò-¨a°!°Q¸¸5À1Ç6Â6È!Á9Ä9Ñ;LÐ1MÑNÔNÐcÐcÐcr    c           
     óŠ   •— g | ]?}t           j        j                             |d ‰|                     d¦  «        z
  f¦  «        ‘Œ@S r¥   r¦   ©r   Úmr•   s     €r   r'   z1stack_padded_token_embeddings.<locals>.<listcomp>  óB   ø€ ÐSÐSÐSÈ•”Ô$×(Ò(¨¨Q°¸¿º¸q¹	¼	Ñ0AÐ,BÑCÔCÐSÐSÐSr    r8   ©r9   )ÚmaxÚanyr   r/   ©r>   r™   r•   s     @r   Ústack_padded_token_embeddingsr±   	  s£   ø€ õ Ð.Ð. :Ð.Ñ.Ô.Ñ.Ô.€EÝ
Ð
2Ð
2Ð
2Ð
2 zÐ
2Ñ
2Ô
2Ñ2Ô2ð TØcÐcÐcÐcÐXbÐcÑcÔcˆ
ØSÐSÐSÐSÈUÐSÑSÔSˆÝŒ;�z qÐ)Ñ)Ô)­5¬;°uÀ!Ð+DÑ+DÔ+DÐDÐDr    c                óü   ‡— t          d„ | D ¦   «         ¦  «        Št          ˆfd„| D ¦   «         ¦  «        rˆfd„| D ¦   «         } ˆfd„|D ¦   «         }t          j        | d¬¦  «        t          j        |d¬¦  «        fS )a¡  Concatenate ``(B_i, T_i, D)`` token-embedding chunks and ``(B_i, T_i)`` mask chunks along
    ``dim=0``, padding each chunk up to the chunk-wide max token count.

    Used by GradCache-style multi-vector losses where each mini-batch is encoded independently
    and the resulting per-mini-batch chunks must be assembled into a single
    ``(sum(B_i), T_max, D)`` tensor + ``(sum(B_i), T_max)`` mask. Native-resolution VLMs
    (Qwen2-VL family) may emit a different ``T`` per mini-batch within the same column.

    Skips the pad entirely when all chunks already share the same ``T`` (text and fixed-resolution
    VLMs), paying a pad only for ragged-token-count VLMs.
    c              3  ó@   K  — | ]}|                      d ¦  «        V — ŒdS r�   rž   rŸ   s     r   r   z.cat_padded_token_embeddings.<locals>.<genexpr>)  r    r    c              3  óJ   •K  — | ]}|                      d ¦  «        ‰k    V — ŒdS r�   rž   r¢   s     €r   r   z.cat_padded_token_embeddings.<locals>.<genexpr>*  r£   r    c                óŽ   •— g | ]A}t           j        j                             |d d d ‰|                     d¦  «        z
  f¦  «        ‘ŒBS r¥   r¦   r¢   s     €r   r'   z/cat_padded_token_embeddings.<locals>.<listcomp>+  r¨   r    c           
     óŠ   •— g | ]?}t           j        j                             |d ‰|                     d¦  «        z
  f¦  «        ‘Œ@S r¥   r¦   rª   s     €r   r'   z/cat_padded_token_embeddings.<locals>.<listcomp>,  r¬   r    r   r­   )r®   r¯   r   Úcatr°   s     @r   Úcat_padded_token_embeddingsr¸     s£   ø€ õ Ð.Ð. :Ð.Ñ.Ô.Ñ.Ô.€EÝ
Ð
2Ð
2Ð
2Ð
2 zÐ
2Ñ
2Ô
2Ñ2Ô2ð TØcÐcÐcÐcÐXbÐcÑcÔcˆ
ØSÐSÐSÐSÈUÐSÑSÔSˆÝŒ9�Z QÐ'Ñ'Ô'­¬°5¸aÐ)@Ñ)@Ô)@Ð@Ð@r    ÚbatchÚtarget_devicer   c                ó‚   — | D ];}t          | |         t          ¦  «        r| |                              |¦  «        | |<   Œ<| S )au  
    Send a PyTorch batch (i.e., a dictionary of string keys to Tensors) to a device (e.g. "cpu", "cuda", "mps").

    Args:
        batch (Dict[str, Tensor]): The batch to send to the device.
        target_device (torch.device): The target device (e.g. "cpu", "cuda", "mps").

    Returns:
        Dict[str, Tensor]: The batch with tensors sent to the target device.
    )r   r   r%   )r¹   rº   r–   s      r   Úbatch_to_devicer¼   0  sH   € ð ð 6ð 6ˆÝ�e˜C”j¥&Ñ)Ô)ð 	6Ø˜sœŸš }Ñ5Ô5ˆE�#‰JøØ€Lr    r   r   c                óV  — |                       ¦   «         } |                      ¦   «                              ¦   «                              ¦   «         }|                      ¦   «                              ¦   «                              ¦   «         }t          ||d         |d         ff| j        ¬¦  «        S )ac  
    Converts a sparse PyTorch tensor to a SciPy COO sparse matrix.

    Args:
        x (torch.Tensor): A 2-dimensional sparse PyTorch tensor in COO layout.

    Example:
        >>> import torch
        >>> from sentence_transformers.util import to_scipy_coo
        >>> x = torch.sparse_coo_tensor([[0, 1], [1, 0]], [1.0, 2.0], (3, 3))
        >>> to_scipy_coo(x).toarray()
        array([[0., 1., 0.],
               [2., 0., 0.],
               [0., 0., 0.]], dtype=float32)

    Returns:
        scipy.sparse.coo_matrix: A SciPy COO matrix with the same shape, indices and values as the input tensor.
    r   r8   )rk   )r$   rF   ÚcpuÚnumpyrG   r   rk   )r   rF   rG   s      r   Úto_scipy_coorÀ   A  s~   € ð& 	
�
Š
‰Œ€AØ�iŠi‰kŒk�oŠoÑÔ×%Ò%Ñ'Ô'€GØ�XŠX‰ZŒZ�^Š^ÑÔ×#Ò#Ñ%Ô%€FÝ�v ¨¤
¨G°A¬JÐ7Ð8ÀÄÐHÑHÔHÐHr    c                ó¾  — | j         s|                      ¦   «         } |                      ¦   «         } t          j        |                      d¦  «        | j        t          j        ¬¦  «        }|                      ¦   «         dk    r+d||  	                    ¦   «          
                    ¦   «         <   |S |                      ¦   «         dk    rv|                      ¦   «                              ¦   «         dk    rJ|  	                    ¦   «         }t          j        |d         d¬¦  «        \  }}|                     ¦   «         ||<   |S t          d|                      ¦   «         › d	�¦  «        ‚)
a  
    Compute count vector from sparse embeddings indicating how many samples have non-zero values in each dimension.

    Args:
        embeddings: Sparse tensor of shape (batch_size, vocab_size) or (vocab_size,)

    Returns:
        Count vector of shape (vocab_size,)
    rh   )r   r#   r8   r@   r   T)Úreturn_countszExpected 1D or 2D tensor, got ÚD)r   Ú	to_sparser$   r   rH   rI   r   Úint32r9   rF   ÚsqueezerG   ÚnumelÚuniquer_   rj   )r>   Úcount_vectorrF   Úunique_dimsÚcountss        r   Úcompute_count_vectorrÌ   Z  s;  € ð Ôð ,Ø×)Ò)Ñ+Ô+ˆ
ð ×$Ò$Ñ&Ô&€Jå”;˜zŸš¨rÑ2Ô2¸:Ô;LÕTYÔT_Ð`Ñ`Ô`€LØ‡~‚~ÑÔ˜1ÒÐà78ˆ�Z×'Ò'Ñ)Ô)×1Ò1Ñ3Ô3Ñ4ØÐØ	�ŠÑ	Ô	˜QÒ	Ð	à×ÒÑÔ×$Ò$Ñ&Ô&¨Ò*Ð*Ø ×(Ò(Ñ*Ô*ˆGå"'¤,¨w°q¬zÈÐ"NÑ"NÔ"NÑˆK˜Ø(.¯
ª
©¬ˆL˜Ñ%àÐåÐM¸*¿.º.Ñ:JÔ:JÐMÐMÐMÑNÔNÐNr    )r	   r
   r   r   )r	   r   r   r   )r	   r   r   r   )r>   r   r   r   )r>   r
   rS   rT   r   r
   )r>   rY   rS   rT   r   rY   )r>   r\   rS   rT   r   r\   )r>   r\   r^   r_   r   rY   )r>   r
   r^   rc   r   r
   )r>   rY   r^   rc   r   rY   )r>   r\   r^   rT   r   r\   )rv   rw   r   rw   )r>   r˜   r™   r˜   r   rš   )r¹   rw   rº   r   r   rw   )r   r   r   r   )r>   rY   r   rY   )Ú
__future__r   Útypingr   r   r¿   r)   r   Úscipy.sparser   r   r   r   r0   r6   r;   r=   rR   rW   rb   r—   r±   r¸   r¼   rÀ   rÌ   r,   r    r   ú<module>rÐ      s"  ðØ "Ð "Ð "Ð "Ð "Ð "à  Ð  Ð  Ð  Ð  Ð  Ð  Ð  à Ð Ð Ð Ø €€€Ø #Ð #Ð #Ð #Ð #Ð #Ø  Ð  Ð  Ð  Ð  Ð  Ð  Ð  ðð ð ð ð ð ð ð ð@ð ð ð ð&ð ð ð ðð ð ð ð$Rð Rð Rð Rð: 
Ø \Ð \Ð \ñ 
„Ø \ð 
Ø `Ð `Ð `ñ 
„Ø `ð*ð *ð *ð *ð@ 
Ø lÐ lÐ lñ 
„Ø lð 
Ø \Ð \Ð \ñ 
„Ø \ð 
Ø `Ð `Ð `ñ 
„Ø `ð%ð %ð %ð %ðPð ð ð ðBEð Eð Eð Eð(Að Að Að Að&ð ð ð ð"Ið Ið Ið Ið2Oð Oð Oð Oð Oð Or    