a
    h                     @  sj   d dl mZ d dlmZ d dlmZ d dlZd dlmZmZ d dl	m
Z
 d dlmZ G dd	 d	ejZdS )
    )annotations)Iterable)AnyN)Tensornn)util)SentenceTransformerc                      sr   e Zd Zdejfdddd fddZdd	d	d
ddZdd	d	dddZddddZe	ddddZ
  ZS )
CoSENTLossg      4@r   floatNone)modelscalereturnc                   s    t    || _|| _|| _dS )a  
        This class implements CoSENT (Cosine Sentence) loss.
        It expects that each of the InputExamples consists of a pair of texts and a float valued label, representing
        the expected similarity score between the pair.

        It computes the following loss function:

        ``loss = logsum(1+exp(s(i,j)-s(k,l))+exp...)``, where ``(i,j)`` and ``(k,l)`` are any of the input pairs in the
        batch such that the expected similarity of ``(i,j)`` is greater than ``(k,l)``. The summation is over all possible
        pairs of input pairs in the batch that match this condition.

        Anecdotal experiments show that this loss function produces a more powerful training signal than :class:`CosineSimilarityLoss`,
        resulting in faster convergence and a final model with superior performance. Consequently, CoSENTLoss may be used
        as a drop-in replacement for :class:`CosineSimilarityLoss` in any training script.

        Args:
            model: SentenceTransformerModel
            similarity_fct: Function to compute the PAIRWISE similarity
                between embeddings. Default is
                ``util.pairwise_cos_sim``.
            scale: Output of similarity function is multiplied by scale
                value. Represents the inverse temperature.

        References:
            - For further details, see: https://kexue.fm/archives/8847

        Requirements:
            - Sentence pairs with corresponding similarity scores in range of the similarity function. Default is [-1,1].

        Inputs:
            +--------------------------------+------------------------+
            | Texts                          | Labels                 |
            +================================+========================+
            | (sentence_A, sentence_B) pairs | float similarity score |
            +--------------------------------+------------------------+

        Relations:
            - :class:`AnglELoss` is CoSENTLoss with ``pairwise_angle_sim`` as the metric, rather than ``pairwise_cos_sim``.
            - :class:`CosineSimilarityLoss` seems to produce a weaker training signal than CoSENTLoss. In our experiments, CoSENTLoss is recommended.

        Example:
            ::

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

                model = SentenceTransformer("microsoft/mpnet-base")
                train_dataset = Dataset.from_dict({
                    "sentence1": ["It's nice weather outside today.", "He drove to work."],
                    "sentence2": ["It's so sunny.", "She walked to the store."],
                    "score": [1.0, 0.3],
                })
                loss = losses.CoSENTLoss(model)

                trainer = SentenceTransformerTrainer(
                    model=model,
                    train_dataset=train_dataset,
                    loss=loss,
                )
                trainer.train()
        N)super__init__r   similarity_fctr   )selfr   r   r   	__class__ c/var/www/html/assistant/venv/lib/python3.9/site-packages/sentence_transformers/losses/CoSENTLoss.pyr      s    >
zCoSENTLoss.__init__zIterable[dict[str, Tensor]]r   )sentence_featureslabelsr   c                   s    fdd|D }  ||S )Nc                   s   g | ]}  |d  qS )Zsentence_embedding)r   ).0Zsentence_featurer   r   r   
<listcomp>R       z&CoSENTLoss.forward.<locals>.<listcomp>)compute_loss_from_embeddings)r   r   r   
embeddingsr   r   r   forwardQ   s    zCoSENTLoss.forwardzlist[Tensor])r   r   r   c                 C  s   |  |d |d }|| j }|dddf |dddf  }|dddf |dddf k }| }|d| d  }tjtd|j|dfdd}tj	|dd}|S )z
        Compute the CoSENT loss from embeddings.

        Args:
            embeddings: List of embeddings
            labels: Labels indicating the similarity scores of the pairs

        Returns:
            Loss value
        r      Ng   mB)dim)
r   r   r
   torchcatZzerostoZdeviceviewZ	logsumexp)r   r   r   ZscoresZlossr   r   r   r   V   s    
  &z'CoSENTLoss.compute_loss_from_embeddingszdict[str, Any])r   c                 C  s   | j | jjdS )N)r   r   )r   r   __name__r   r   r   r   get_config_dicts   s    zCoSENTLoss.get_config_dictstrc                 C  s   dS )Nz
@online{kexuefm-8847,
    title={CoSENT: A more efficient sentence vector scheme than Sentence-BERT},
    author={Su Jianlin},
    year={2022},
    month={Jan},
    url={https://kexue.fm/archives/8847},
}
r   r   r   r   r   citationv   s    zCoSENTLoss.citation)r'   
__module____qualname__r   Zpairwise_cos_simr   r   r   r(   propertyr*   __classcell__r   r   r   r   r	      s   Cr	   )
__future__r   collections.abcr   typingr   r#   r   r   Zsentence_transformersr   Z)sentence_transformers.SentenceTransformerr   Moduler	   r   r   r   r   <module>   s   