
    si                         d dl Z d dlZd dlmZmZmZmZmZmZ d dl	m
c mZ d dlmZm
Z
 d dlmZ d dlmZ d dlmZ  G d d          Z G d	 d
e
j                  ZdS )    N)AnyDictIterableListOptionalUnion)Tensornn)SentenceTransformer)CachedGISTEmbedLoss)"CachedMultipleNegativesRankingLossc                   ^    e Zd Zd	dZd	dZdedefdZdeeef         deeef         fdZ	dS )
ForwardDecoratorreturnNc                 L    || _         d | _        g | _        d | _        d| _        d S Nr   )fndimcache	cache_dimidx)selfr   s     ^/var/www/icac/venv/lib/python3.11/site-packages/sentence_transformers/losses/MatryoshkaLoss.py__init__zForwardDecorator.__init__   s)    
    c                 "    || _         d| _        d S r   )r   r   )r   r   s     r   set_dimzForwardDecorator.set_dim   s    r   tensorc                     |j         d         }| j        |k    rt          d| j         d|           |dd | j        f         }t          j        |dd          }|S )Nz
Dimension zL in matryoshka_dims cannot be greater than the model's embedding dimension: .   )pr   )shaper   
ValueErrorF	normalize)r   r   
tensor_dims      r   shrinkzForwardDecorator.shrink   st    \"%
8j  TXs}   ZtxZ(Vqb111r   featuresc                 h   | j         | j         | j        k    r<|                     |          }| j                            |           | j        | _         n| j        | j                 }|                     |d                   |d<   |                     |d                   |d<   | xj        dz  c_        |S )Ntoken_embeddingssentence_embedding   )r   r   r   r   appendr   r(   )r   r)   outputs      r   __call__zForwardDecorator.__call__$   s    >!T^tx%?%?WWX&&FJf%%%!XDNN Z)F%)[[8J1K%L%L!"'+{{6:N3O'P'P#$Ar   )r   N)
__name__
__module____qualname__r   r   r	   r(   r   strr0    r   r   r   r      s              V     c6k!2 tCK7H      r   r   c                        e Zd Z	 	 ddedej        dee         deee	e
ef                           deddf fd	Zd
eeeef                  dedefdZdeeef         fdZedefd            Z xZS )MatryoshkaLossNr    modellossmatryoshka_dimsmatryoshka_weightsn_dims_per_stepr   c                    t                                                       || _        || _        t	          |t
                    rt          j        dd           t	          |t                    rt          j        dd           |dgt          |          z  }t          ||          }t          t          |d d	           \  | _        | _        || _        dS )
a  
        The MatryoshkaLoss can be seen as a loss *modifier* that allows you to use other loss functions at various
        different embedding dimensions. This is useful for when you want to train a model where users have the option
        to lower the embedding dimension to improve their embedding comparison speed and costs.

        Args:
            model: SentenceTransformer model
            loss: The loss function to be used, e.g.
                :class:`MultipleNegativesRankingLoss`,
                :class:`CoSENTLoss`, etc.
            matryoshka_dims: A list of embedding dimensions to be used
                for the loss function, e.g. [768, 512, 256, 128, 64].
            matryoshka_weights: A list of weights to be used for the
                loss function, e.g. [1, 1, 1, 1, 1]. If None, then the
                weights will be set to 1 for all dimensions.
            n_dims_per_step: The number of dimensions to use per step.
                If -1, then all dimensions are used. If > 0, then a
                random sample of n_dims_per_step dimensions are used per
                step. The default value is -1.

        References:
            - The concept was introduced in this paper: https://arxiv.org/abs/2205.13147
            - `Matryoshka Embeddings <../../examples/training/matryoshka/README.html>`_

        Requirements:
            1. The base loss cannot be :class:`CachedMultipleNegativesRankingLoss` or :class:`CachedGISTEmbedLoss`.

        Relations:
            - :class:`Matryoshka2dLoss` uses this loss in combination with :class:`AdaptiveLayerLoss` which allows for
                layer reduction for faster inference.

        Input:
            +---------------------------------------+--------+
            | Texts                                 | Labels |
            +=======================================+========+
            | any                                   | any    |
            +---------------------------------------+--------+

        Example:
            ::

                from sentence_transformers import SentenceTransformer, losses, InputExample
                from torch.utils.data import DataLoader

                model = SentenceTransformer("microsoft/mpnet-base")
                train_examples = [
                    InputExample(texts=['Anchor 1', 'Positive 1']),
                    InputExample(texts=['Anchor 2', 'Positive 2']),
                ]
                train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=32)
                train_loss = losses.MultipleNegativesRankingLoss(model=model)
                train_loss = losses.MatryoshkaLoss(model, train_loss, [768, 512, 256, 128, 64])
                model.fit(
                    [(train_dataloader, train_loss)],
                    epochs=10,
                )
        zIMatryoshkaLoss is not compatible with CachedMultipleNegativesRankingLoss.r!   )
stacklevelz:MatryoshkaLoss is not compatible with CachedGISTEmbedLoss.Nr-   c                     | d         S r   r5   )xs    r   <lambda>z)MatryoshkaLoss.__init__.<locals>.<lambda>   s    `abc`d r   T)keyreverse)superr   r8   r9   
isinstancer   warningswarnr   lenzipsortedr:   r;   r<   )r   r8   r9   r:   r;   r<   dims_weights	__class__s          r   r   zMatryoshkaLoss.__init__4   s    B 	
	d>?? 	uMersttttd/00 	fMVcdeeee%"#s?';';!;?,>??8;VLVdVdnr=s=s=s8t5d5.r   sentence_featureslabelsc                    | j         j        }	 t          |          }|| j         _        t          t	          | j                            }| j        dk    r2| j        t	          |          k     rt          j        || j                  }d}|D ]M}| j        |         }| j	        |         }	|
                    |           ||	|                     ||          z  z  }N	 || j         _        n# || j         _        w xY w|S )Nr   g        )r8   forwardr   rangerH   r:   r<   randomsampler;   r   r9   )
r   rM   rN   original_forwarddecorated_forwarddim_indicesr9   r   r   weights
             r   rP   zMatryoshkaLoss.forward   s   :-	2 01A B B!2DJD$8 9 9::K#a''D,@3{CSCS,S,S$mK9MNND" F F*3/05!))#...+<f!E!EEE	F "2DJ!1DJ1111s   CC' 'C5c                 L    | j         j        j        | j        | j        | j        dS )N)r9   r:   r;   r<   )r9   rL   r1   r:   r;   r<   r   s    r   get_config_dictzMatryoshkaLoss.get_config_dict   s.    I'0#3"&"9#3	
 
 	
r   c                     dS )Na  
@misc{kusupati2024matryoshka,
    title={Matryoshka Representation Learning}, 
    author={Aditya Kusupati and Gantavya Bhatt and Aniket Rege and Matthew Wallingford and Aditya Sinha and Vivek Ramanujan and William Howard-Snyder and Kaifeng Chen and Sham Kakade and Prateek Jain and Ali Farhadi},
    year={2024},
    eprint={2205.13147},
    archivePrefix={arXiv},
    primaryClass={cs.LG}
}
r5   rY   s    r   citationzMatryoshkaLoss.citation   s    	 	r   )Nr    )r1   r2   r3   r   r
   Moduler   intr   r   floatr   r   r   r4   r	   rP   r   rZ   propertyr\   __classcell__)rL   s   @r   r7   r7   3   s/        AE!N/ N/"N/ iN/ c	N/
 %T%s
*;%<=N/ N/ 
N/ N/ N/ N/ N/ N/`$sF{2C)D f Y_    (
c3h 
 
 
 
 
# 
 
 
 X
 
 
 
 
r   r7   )rR   rF   typingr   r   r   r   r   r   torch.nn.functionalr
   
functionalr%   torchr	   sentence_transformersr   0sentence_transformers.losses.CachedGISTEmbedLossr   ?sentence_transformers.losses.CachedMultipleNegativesRankingLossr   r   r]   r7   r5   r   r   <module>ri      s     = = = = = = = = = = = = = = = =                  5 5 5 5 5 5 P P P P P P n n n n n n# # # # # # # #Lx x x x xRY x x x x xr   