§
    æ˜ºh   ã                   ób   — d dl Z d dl mZ d dlmZmZ ddlmZmZ d dlmZ  G d„ de¦  «        Z	dS )	é    N)ÚTensor)ÚIterableÚDicté   )ÚBatchHardTripletLossÚ$BatchHardTripletLossDistanceFunction)ÚSentenceTransformerc                   óv   ‡ — e Zd ZdZej        fdefˆ fd„Zdee	e
ef                  defd„Zdededefd	„Zˆ xZS )
ÚBatchHardSoftMarginTripletLossa~  
    BatchHardSoftMarginTripletLoss takes a batch with (label, sentence) pairs and computes the loss for all possible, valid
    triplets, i.e., anchor and positive must have the same label, anchor and negative a different label. The labels
    must be integers, with same label indicating sentences from the same class. You train dataset
    must contain at least 2 examples per label class. The margin is computed automatically.

    Source: https://github.com/NegatioN/OnlineMiningTripletLoss/blob/master/online_triplet_loss/losses.py
    Paper: In Defense of the Triplet Loss for Person Re-Identification, https://arxiv.org/abs/1703.07737
    Blog post: https://omoindrot.github.io/triplet-loss

    :param model: SentenceTransformer model
    :param distance_metric: Function that returns a distance between two emeddings. The class SiameseDistanceMetric contains pre-defined metrices that can be used


    Example::

       from sentence_transformers import SentenceTransformer,  SentencesDataset, LoggingHandler, losses
       from sentence_transformers.readers import InputExample

       model = SentenceTransformer('distilbert-base-nli-mean-tokens')
       train_examples = [InputExample(texts=['Sentence from class 0'], label=0), InputExample(texts=['Another sentence from class 0'], label=0),
           InputExample(texts=['Sentence from class 1'], label=1), InputExample(texts=['Sentence from class 2'], label=2)]
       train_dataset = SentencesDataset(train_examples, model)
       train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=train_batch_size)
       train_loss = losses.BatchHardSoftMarginTripletLoss(model=model)
    Úmodelc                 ót   •— t          t          | ¦  «                             |¦  «         || _        || _        d S )N)Úsuperr   Ú__init__Úsentence_embedderÚdistance_metric)Úselfr   r   Ú	__class__s      €úƒ/var/www/html/services/rag-service/venv/lib/python3.11/site-packages/sentence_transformers/losses/BatchHardSoftMarginTripletLoss.pyr   z'BatchHardSoftMarginTripletLoss.__init__$   s:   ø€ õ 	Õ,¨dÑ3Ô3×<Ò<¸UÑCÔCÐCØ!&ˆÔØ.ˆÔÐÐó    Úsentence_featuresÚlabelsc                 óp   — |                       |d         ¦  «        d         }|                      ||¦  «        S )Nr   Úsentence_embedding)r   Ú#batch_hard_triplet_soft_margin_loss)r   r   r   Úreps       r   Úforwardz&BatchHardSoftMarginTripletLoss.forward+   s7   € Ø×$Ò$Ð%6°qÔ%9Ñ:Ô:Ð;OÔPˆØ×7Ò7¸ÀÑDÔDÐDr   Ú
embeddingsÚreturnc                 óþ  — |                       |¦  «        }t          j        |¦  «                             ¦   «         }||z  }|                     dd¬¦  «        \  }}t          j        |¦  «                             ¦   «         }|                     dd¬¦  «        \  }	}||	d|z
  z  z   }
|
                     dd¬¦  «        \  }}t          j        t          j	        ||z
  ¦  «        ¦  «        }| 
                    ¦   «         }|S )a6  Build the triplet loss over a batch of embeddings.
        For each anchor, we get the hardest positive and hardest negative to form a triplet.
        Args:
            labels: labels of the batch, of size (batch_size,)
            embeddings: tensor of shape (batch_size, embed_dim)
            squared: Boolean. If true, output is the pairwise squared euclidean distance matrix.
                     If false, output is the pairwise euclidean distance matrix.
        Returns:
            Label_Sentence_Triplet: scalar tensor containing the triplet loss
        r   T)Úkeepdimg      ð?)r   r   Ú get_anchor_positive_triplet_maskÚfloatÚmaxÚ get_anchor_negative_triplet_maskÚminÚtorchÚlog1pÚexpÚmean)r   r   r   Úpairwise_distÚmask_anchor_positiveÚanchor_positive_distÚhardest_positive_distÚ_Úmask_anchor_negativeÚmax_anchor_negative_distÚanchor_negative_distÚhardest_negative_distÚtlÚtriplet_losss                 r   r   zBBatchHardSoftMarginTripletLoss.batch_hard_triplet_soft_margin_loss1   s  € ð ×,Ò,¨ZÑ8Ô8ˆõ  4ÔTÐU[Ñ\Ô\×bÒbÑdÔdÐð  4°mÑCÐð $8×#;Ò#;¸AÀtÐ#;Ñ#LÔ#LÑ Ð˜qõ  4ÔTÐU[Ñ\Ô\×bÒbÑdÔdÐð '4×&7Ò&7¸À4Ð&7Ñ&HÔ&HÑ#Ð  !Ø,Ð/GÈ3ÐQeÑKeÑ/fÑfÐð $8×#;Ò#;¸AÀtÐ#;Ñ#LÔ#LÑ Ð˜qõ
 Œ[�œÐ#8Ð;PÑ#PÑQÔQÑRÔRˆØ—w’w‘y”yˆàÐr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úeucledian_distancer	   r   r   r   Ústrr   r   r   Ú__classcell__)r   s   @r   r   r      s½   ø€ € € € € ðð ð8 ;_Ô:qð/ð /Ø(ð/ð /ð /ð /ð /ð /ðE¨°$°s¸F°{Ô2CÔ)Dð EÈfð Eð Eð Eð Eð)¸&ð )Èfð )ÐY_ð )ð )ð )ð )ð )ð )ð )ð )r   r   )
r&   r   Útypingr   r   r   r   Ú)sentence_transformers.SentenceTransformerr	   r   © r   r   ú<module>r?      s¡   ðØ €€€Ø Ð Ð Ð Ð Ð Ø !Ð !Ð !Ð !Ð !Ð !Ð !Ð !Ø \Ð \Ð \Ð \Ð \Ð \Ð \Ð \Ø IÐ IÐ IÐ IÐ IÐ IðRð Rð Rð Rð RÐ%9ñ Rô Rð Rð Rð Rr   