
    Ng6                        d dl mZ d dlZd dlZd dlmZ d dl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 )    )annotationsN)Iterable)Any)Tensornn)SentenceTransformer)CachedGISTEmbedLoss)"CachedMultipleNegativesRankingLossc                  .    e Zd ZddZddZddZdd
ZdS )ForwardDecoratorreturnNonec                L    || _         d | _        g | _        d | _        d| _        d S Nr   )fndimcache	cache_dimidx)selfr   s     g/var/www/html/ai-engine/env/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   tensorr   c                    |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   featuresdict[str, Tensor]c                p   | j         | j         | j        k    r<|                     |          }| j                            |           | j        | _         n| j        | j                 }d|v r|                     |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'')-V<N5O)P)PF%&'+{{6:N3O'P'P#$Ar   N)r   r   )r   r   r   r   )r'   r(   r   r(   )__name__
__module____qualname__r   r   r&   r/    r   r   r   r      sd                      r   r   c                  N     e Zd Z	 	 dd fdZddZddZedd            Z xZS )MatryoshkaLossNr   modelr   loss	nn.Modulematryoshka_dims	list[int]matryoshka_weightslist[float | int] | Nonen_dims_per_stepintr   r   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`.

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

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

        Example:
            ::

                from sentence_transformers import SentenceTransformer, SentenceTransformerTrainer, losses
                from datasets import Dataset

                model = SentenceTransformer("microsoft/mpnet-base")
                train_dataset = Dataset.from_dict({
                    "anchor": ["It's nice weather outside today.", "He drove to work."],
                    "positive": ["It's so sunny.", "He took the car to the office."],
                })
                loss = losses.MultipleNegativesRankingLoss(model)
                loss = losses.MatryoshkaLoss(model, loss, [768, 512, 256, 128, 64])

                trainer = SentenceTransformerTrainer(
                    model=model,
                    train_dataset=train_dataset,
                    loss=loss,
                )
                trainer.train()
        zIMatryoshkaLoss is not compatible with CachedMultipleNegativesRankingLoss.r   )
stacklevelz:MatryoshkaLoss is not compatible with CachedGISTEmbedLoss.Nr,   c                    | d         S r   r3   )xs    r   <lambda>z)MatryoshkaLoss.__init__.<locals>.<lambda>   s    `abc`d r   T)keyreverse)superr   r6   r7   
isinstancer
   warningswarnr	   lenzipsortedr9   r;   r=   )r   r6   r7   r9   r;   r=   dims_weights	__class__s          r   r   zMatryoshkaLoss.__init__8   s    F 	
	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Iterable[dict[str, Tensor]]labelsr   c                   | 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        )r6   forwardr   rangerJ   r9   r=   randomsampler;   r   r7   )
r   rO   rQ   original_forwarddecorated_forwarddim_indicesr7   r   r   weights
             r   rS   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dict[str, Any]c                L    | j         j        j        | j        | j        | j        dS )N)r7   r9   r;   r=   )r7   rN   r0   r9   r;   r=   r   s    r   get_config_dictzMatryoshkaLoss.get_config_dict   s.    I'0#3"&"9#3	
 
 	
r   strc                    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}
}
r3   r]   s    r   citationzMatryoshkaLoss.citation   s    	 	r   )Nr   )r6   r   r7   r8   r9   r:   r;   r<   r=   r>   r   r   )rO   rP   rQ   r   r   r   )r   r[   )r   r_   )	r0   r1   r2   r   rS   r^   propertyra   __classcell__)rN   s   @r   r5   r5   7   s         8<!P/ P/ P/ P/ P/ P/ P/d   (
 
 
 
 
 
 
 X
 
 
 
 
r   r5   )
__future__r   rU   rH   collections.abcr   typingr   torch.nn.functionalr   
functionalr#   torchr   sentence_transformersr   0sentence_transformers.losses.CachedGISTEmbedLossr	   ?sentence_transformers.losses.CachedMultipleNegativesRankingLossr
   r   Moduler5   r3   r   r   <module>rn      s   " " " " " "   $ $ $ $ $ $                        5 5 5 5 5 5 P P P P P P n n n n n n$ $ $ $ $ $ $ $Nz z z z zRY z z z z zr   