o
    sh                     @   s   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
  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 dZG d	d
 d
e
jZdS )    N)AnyDictIterableListOptionalUnion)Tensornn)SentenceTransformer)CachedGISTEmbedLoss)"CachedMultipleNegativesRankingLossc                   @   sT   e Zd ZdddZdddZdedefdd	Zd
eeef deeef fddZ	dS )ForwardDecoratorreturnNc                 C   s"   || _ d | _g | _d | _d| _d S Nr   )fndimcache	cache_dimidx)selfr    r   i/var/www/html/alpaca_bot/venv/lib/python3.10/site-packages/sentence_transformers/losses/MatryoshkaLoss.py__init__   s
   
zForwardDecorator.__init__c                 C   s   || _ d| _d S r   )r   r   )r   r   r   r   r   set_dim   s   
zForwardDecorator.set_dimtensorc                 C   sP   |j d }| j|krtd| j d| |dd | jf }tj|d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_dimr   r   r   shrink   s   

zForwardDecorator.shrinkfeaturesc                 C   sx   | j d u s| j | jkr| |}| j| | j| _ n| j| j }| |d |d< | |d |d< |  jd7  _|S )Ntoken_embeddingssentence_embedding   )r   r   r   r   appendr   r#   )r   r$   outputr   r   r   __call__$   s   

zForwardDecorator.__call__)r   N)
__name__
__module____qualname__r   r   r   r#   r   strr*   r   r   r   r   r      s
    

&
r   c                       s   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	d
Zdeeeef  dedefddZdeeef fddZedefddZ  ZS )MatryoshkaLossNr   modellossmatryoshka_dimsmatryoshka_weightsn_dims_per_stepr   c                    s   t    || _|| _t|trtjddd t|tr#tjddd |du r.dgt	| }t
||}t
t|dd 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                 S   s   | d S r   r   )xr   r   r   <lambda>   s    z)MatryoshkaLoss.__init__.<locals>.<lambda>T)keyreverse)superr   r0   r1   
isinstancer   warningswarnr   lenzipsortedr2   r3   r4   )r   r0   r1   r2   r3   r4   dims_weights	__class__r   r   r   4   s   
A



zMatryoshkaLoss.__init__sentence_featureslabelsc           
      C   s   | j j}zIt|}|| j _tt| j}| jdkr'| jt|k r't|| j}d}|D ]}| j| }| j	| }	|
| ||	| || 7 }q+W || j _|S || j _w )Nr   g        )r0   forwardr   ranger>   r2   r4   randomsampler3   r   r1   )
r   rD   rE   original_forwarddecorated_forwarddim_indicesr1   r   r   weightr   r   r   rF      s"   



zMatryoshkaLoss.forwardc                 C   s   | j jj| j| j| jdS )N)r1   r2   r3   r4   )r1   rC   r+   r2   r3   r4   r   r   r   r   get_config_dict   s
   zMatryoshkaLoss.get_config_dictc                 C   s   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}
}
r   rN   r   r   r   citation   s   zMatryoshkaLoss.citation)Nr   )r+   r,   r-   r
   r	   Moduler   intr   r   floatr   r   r   r.   r   rF   r   rO   propertyrP   __classcell__r   r   rB   r   r/   3   s(    "Pr/   )rH   r<   typingr   r   r   r   r   r   torch.nn.functionalr	   
functionalr    torchr   sentence_transformersr
   0sentence_transformers.losses.CachedGISTEmbedLossr   ?sentence_transformers.losses.CachedMultipleNegativesRankingLossr   r   rQ   r/   r   r   r   r   <module>   s     &