ó
    — óh¦  ã                  óZ   • S SK Jr  S SKJr  S SKJr  S SKJrJr  S SK	J
r
   " S S\5      rg)	é    )Úannotations)ÚIterable)ÚTensor)ÚTripletDistanceMetricÚTripletLoss)ÚSparseEncoderc                  ó\   ^ • \ rS rSr\R
                  S4     SU 4S jjjrSS jrSrU =r	$ )ÚSparseTripletLossé   é   c                ó"   >• [         TU ]  XUS9  g)a  
This class implements triplet loss. Given a triplet of (anchor, positive, negative),
the loss minimizes the distance between anchor and positive while it maximizes the distance
between anchor and negative. It compute the following loss function:

``loss = max(||anchor - positive|| - ||anchor - negative|| + margin, 0)``.

Margin is an important hyperparameter and needs to be tuned respectively.

Args:
    model: SparseEncoder
    distance_metric: Function to compute distance between two
        embeddings. The class TripletDistanceMetric contains
        common distance metrices that can be used.
    triplet_margin: The negative should be at least this much
        further away from the anchor than the positive.

References:
    - For further details, see: https://en.wikipedia.org/wiki/Triplet_loss

Requirements:
    1. Need to be used in SpladeLoss or CSRLoss as a loss function.
    2. (anchor, positive, negative) triplets

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

Example:
    ::

        from datasets import Dataset

        from sentence_transformers.sparse_encoder import SparseEncoder, SparseEncoderTrainer, losses

        model = SparseEncoder("distilbert/distilbert-base-uncased")
        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."],
                "negative": ["It's quite rainy, sadly.", "She walked to the store."],
            }
        )
        loss = losses.SpladeLoss(
            model=model, loss=losses.SparseTripletLoss(model), document_regularizer_weight=3e-5, query_regularizer_weight=5e-5
        )

        trainer = SparseEncoderTrainer(model=model, train_dataset=train_dataset, loss=loss)
        trainer.train()
)Údistance_metricÚtriplet_marginN)ÚsuperÚ__init__)ÚselfÚmodelr   r   Ú	__class__s       €Úw/home/james-whalen/.local/lib/python3.13/site-packages/sentence_transformers/sparse_encoder/losses/SparseTripletLoss.pyr   ÚSparseTripletLoss.__init__   s   ø€ ôp 	‰Ñ˜ÐP^ÐÒ_ó    c                ó   • [        S5      e)NzNSparseTripletLoss should not be used alone. Use it with SpladeLoss or CSRLoss.)ÚAttributeError)r   Úsentence_featuresÚlabelss      r   ÚforwardÚSparseTripletLoss.forwardF   s   € ÜÐmÓnÐnr   © )r   r   r   ÚfloatÚreturnÚNone)r   zIterable[dict[str, Tensor]]r   r   r    r   )
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r   Ú	EUCLIDEANr   r   Ú__static_attributes__Ú__classcell__)r   s   @r   r
   r
      sC   ø† à4I×4SÑ4SÐmnð8`Ø"ð8`Øejð8`à	÷8`ð 8`÷toò or   r
   N)Ú
__future__r   Úcollections.abcr   Útorchr   Ú(sentence_transformers.losses.TripletLossr   r   Ú2sentence_transformers.sparse_encoder.SparseEncoderr   r
   r   r   r   Ú<module>r.      s"   ðÝ "å $å ç WÝ Lô<o˜õ <or   