
    Ng                        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	ej                  ZdS )
    )annotations)Iterable)AnyN)Tensornn)util)SentenceTransformerc                  @     e Zd Zdej        fd fdZddZddZ xZS )%MultipleNegativesSymmetricRankingLossg      4@modelr	   scalefloatreturnNonec                    t                                                       || _        || _        || _        t          j                    | _        dS )a  
        Given a list of (anchor, positive) pairs, this loss sums the following two losses:

        1. Forward loss: Given an anchor, find the sample with the highest similarity out of all positives in the batch.
           This is equivalent to :class:`MultipleNegativesRankingLoss`.
        2. Backward loss: Given a positive, find the sample with the highest similarity out of all anchors in the batch.

        For example with question-answer pairs, :class:`MultipleNegativesRankingLoss` just computes the loss to find
        the answer given a question, but :class:`MultipleNegativesSymmetricRankingLoss` additionally computes the
        loss to find the question given an answer.

        Note: If you pass triplets, the negative entry will be ignored. A anchor is just searched for the positive.

        Args:
            model: SentenceTransformer model
            scale: Output of similarity function is multiplied by scale
                value
            similarity_fct: similarity function between sentence
                embeddings. By default, cos_sim. Can also be set to dot
                product (and then set scale to 1)

        Requirements:
            1. (anchor, positive) pairs

        Inputs:
            +---------------------------------------+--------+
            | Texts                                 | Labels |
            +=======================================+========+
            | (anchor, positive) pairs              | none   |
            +---------------------------------------+--------+

        Recommendations:
            - Use ``BatchSamplers.NO_DUPLICATES`` (:class:`docs <sentence_transformers.training_args.BatchSamplers>`) to
              ensure that no in-batch negatives are duplicates of the anchor or positive samples.

        Relations:
            - Like :class:`MultipleNegativesRankingLoss`, but with an additional loss term.
            - :class:`CachedMultipleNegativesSymmetricRankingLoss` is equivalent to this loss, but it uses caching that
              allows for much higher batch sizes (and thus better performance) without extra memory usage. However, it
              is slightly slower.

        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.MultipleNegativesSymmetricRankingLoss(model)

                trainer = SentenceTransformerTrainer(
                    model=model,
                    train_dataset=train_dataset,
                    loss=loss,
                )
                trainer.train()
        N)super__init__r   r   similarity_fctr   CrossEntropyLosscross_entropy_loss)selfr   r   r   	__class__s       ~/var/www/html/ai-engine/env/lib/python3.11/site-packages/sentence_transformers/losses/MultipleNegativesSymmetricRankingLoss.pyr   z.MultipleNegativesSymmetricRankingLoss.__init__   sI    | 	

,"$"5"7"7    sentence_featuresIterable[dict[str, Tensor]]labelsr   c                     fd|D             }|d         }t          j        |dd                    }                     ||           j        z  }t          j        t          t          |                    t           j        |j                  }|d d dt          |d                   f         } 	                    ||          } 	                    |
                    dd          |          }	||	z   dz  S )Nc                F    g | ]}                     |          d          S )sentence_embedding)r   ).0sentence_featurer   s     r   
<listcomp>zAMultipleNegativesSymmetricRankingLoss.forward.<locals>.<listcomp>S   s-    mmmGW

+,,-ABmmmr   r      )dtypedevice   )torchcatr   r   tensorrangelenlongr&   r   	transpose)
r   r   r   repsanchor
candidatesscoresanchor_positive_scoresforward_lossbackward_losss
   `         r   forwardz-MultipleNegativesSymmetricRankingLoss.forwardR   s    mmmm[lmmmaYtABBx((
$$VZ884:E#f++ej
 
 
 "(1s47||+;(;!<..vv>>//0F0P0PQRTU0V0VX^__},11r   dict[str, Any]c                *    | j         | j        j        dS )N)r   r   )r   r   __name__)r   s    r   get_config_dictz5MultipleNegativesSymmetricRankingLoss.get_config_dicta   s    t7J7STTTr   )r   r	   r   r   r   r   )r   r   r   r   r   r   )r   r7   )	r9   
__module____qualname__r   cos_simr   r6   r:   __classcell__)r   s   @r   r   r      s        BFW[Wc B8 B8 B8 B8 B8 B8 B8H2 2 2 2U U U U U U U Ur   r   )
__future__r   collections.abcr   typingr   r(   r   r   sentence_transformersr   )sentence_transformers.SentenceTransformerr	   Moduler    r   r   <module>rF      s    " " " " " " $ $ $ $ $ $                & & & & & & I I I I I IUU UU UU UU UUBI UU UU UU UU UUr   