
    rh?@                       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 G d	 d
e      Z G d de      Z G d de      Z G d de      Z G d de      Z G d dej                        Zy)    )annotations)LiteralN)Tensornn)CrossEncoder)fullnamec                  ,     e Zd ZdZd fdZddZ xZS )BaseWeightingSchemez<Base class for implementing weighting schemes in LambdaLoss.c                $    t        |   |i | y) N)super__init__)selfargskwargs	__class__s      /var/www/html/ai-insurance-compliance-backend/venv/lib/python3.12/site-packages/sentence_transformers/cross_encoder/losses/LambdaLoss.pyr   zBaseWeightingScheme.__init__   s    $)&)    c                    t         )a  
        Calculate weights for the loss function.

        Args:
            gain: Normalized gains tensor
            discount: Discount tensor
            true_sorted: Sorted ground truth labels

        Returns:
            Tensor: Calculated weights for the loss
        )NotImplementedErrorr   gaindiscounttrue_sorteds       r   forwardzBaseWeightingScheme.forward   s
     "!r   )returnNoner   r   r   r   r   r   r   r   __name__
__module____qualname____doc__r   r   __classcell__r   s   @r   r
   r
      s    F*"r   r
   c                      e Zd ZdZddZy)NoWeightingSchemez6Implementation of no weighting scheme (weights = 1.0).c                D    t        j                  d|j                        S )N      ?device)torchtensorr+   r   s       r   r   zNoWeightingScheme.forward%   s    ||C44r   Nr   r    r!   r"   r#   r    r   r   r'   r'   "   s
    @5r   r'   c                      e Zd ZdZddZy)NDCGLoss1Schemea  Implementation of NDCG Loss1 weighting scheme.

    It is used to optimize for the NDCG metric, but this weighting scheme is not recommended as the
    NDCGLoss2Scheme and NDCGLoss2PPScheme were shown to reach superior performance in the original
    LambdaLoss paper.
    c                     ||z  d d d d d f   S Nr/   r   s       r   r   zNDCGLoss1Scheme.forward1   s    xAt,,r   Nr   r.   r/   r   r   r1   r1   )   s    -r   r1   c                      e Zd ZdZddZy)NDCGLoss2SchemezImplementation of NDCG Loss2 weighting scheme.

    This scheme uses a tighter bound than NDCGLoss1Scheme and was shown to reach
    superior performance in the original LambdaLoss paper. It is used to optimize
    for the NDCG metric.
    c           
     F   t        j                  d|j                  d   dz   |j                        }t        j                  |d d d f   |d d d f   z
        }t        j                  t        j
                  t        j                  |d|dz
  f         d      t        j
                  t        j                  |d|f         d      z
        }|j                         j                          |d d d d d f   t        j                  |d d d d d f   |d d d d d f   z
        z  S )N   r*   r         )r,   arangeshaper+   abspowdiagonalzero_)r   r   r   r   pos_idxs
delta_idxsdeltass          r   r   zNDCGLoss2Scheme.forward=   s    <<4::a=1#4T[[IYYx408D!G3DDE
IIeiiJN): ;<dCii		(1j="9:DAB
 	!dAqj!EIId1a:.>aqjAQ.Q$RRRr   Nr   r.   r/   r   r   r5   r5   5   s    Sr   r5   c                      e Zd ZdZddZy)LambdaRankSchemezoImplementation of LambdaRank weighting scheme.

    This weighting optimizes a coarse upper bound of NDCG.
    c           
        t        j                  t        j                  |d d d d d f   d      t        j                  |d d d d d f   d      z
        t        j                  |d d d d d f   |d d d d d f   z
        z  S )Nr8   )r,   r;   r<   r   s       r   r   zLambdaRankScheme.forwardN   s{    yy8Aq$J#7>8TUW[]^T^K_aeAffgjojsjsAttAtQJ//k
 
 	
r   Nr   r.   r/   r   r   rC   rC   H   s    

r   rC   c                  .     e Zd ZdZdd fdZddZ xZS )NDCGLoss2PPSchemezImplementation of NDCG Loss2++ weighting scheme.

    It is a hybrid weighting scheme that combines the NDCGLoss2 and LambdaRank schemes. It
    was shown to reach the strongest performance in the original LambdaLoss paper.
    c                l    t         |           || _        t               | _        t               | _        y r3   )r   r   mur5   
ndcg_loss2rC   lambda_rank)r   rH   r   s     r   r   zNDCGLoss2PPScheme.__init__[   s*    )++-r   c                r    | j                  |||      }| j                  |||      }| j                  |z  |z   S r3   )rI   rJ   rH   )r   r   r   r   ndcg_weightslambda_weightss         r   r   zNDCGLoss2PPScheme.forwarda   s<    tX{C))$+Fww%66r   )g      $@)rH   floatr   r   r%   s   @r   rF   rF   T   s    .7r   rF   c                       e Zd Z e       dddd ej
                         df	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d	 fdZd
dZddZe	dd       Z
 xZS )
LambdaLossNr)   g|=binaryc	                z   t         	|           || _        |xs
 t               | _        || _        || _        || _        || _        |xs t        j                         | _        || _        | j                  j                  dk7  r9t        | j                  j                    d| j                  j                   d      y)a  
        The LambdaLoss Framework for Ranking Metric Optimization. This loss function implements the LambdaLoss framework for ranking metric optimization,
        which provides various weighting schemes including LambdaRank and NDCG variations.
        The implementation is optimized to handle padded documents efficiently by only
        processing valid documents during model inference.

        .. note::

            The number of documents per query can vary between samples with the ``LambdaLoss``.

        Args:
            model (CrossEncoder): CrossEncoder model to be trained
            weighting_scheme (:class:`~sentence_transformers.cross_encoder.losses.LambdaLoss.BaseWeightingScheme`, optional): Weighting scheme to use for the loss.

                - :class:`~sentence_transformers.cross_encoder.losses.NoWeightingScheme`: No weighting scheme (weights = 1.0)
                - :class:`~sentence_transformers.cross_encoder.losses.NDCGLoss1Scheme`: NDCG Loss1 weighting scheme
                - :class:`~sentence_transformers.cross_encoder.losses.NDCGLoss2Scheme`: NDCG Loss2 weighting scheme
                - :class:`~sentence_transformers.cross_encoder.losses.LambdaRankScheme`: LambdaRank weighting scheme
                - :class:`~sentence_transformers.cross_encoder.losses.NDCGLoss2PPScheme`: NDCG Loss2++ weighting scheme

                Defaults to NDCGLoss2PPScheme. In the original LambdaLoss paper, the NDCGLoss2PPScheme was shown to reach
                the strongest performance, with the NDCGLoss2Scheme following closely.
            k (int, optional): Number of documents to consider for NDCG@K. Defaults to None (use all documents).
            sigma (float): Score difference weight used in sigmoid
            eps (float): Small constant for numerical stability
            reduction_log (str): Type of logarithm to use
                - "natural": Natural logarithm (log)
                - "binary": Binary logarithm (log2)
            activation_fn (:class:`~torch.nn.Module`): Activation function applied to the logits before computing the
                loss. Defaults to :class:`~torch.nn.Identity`.
            mini_batch_size (int, optional): Number of samples to process in each forward pass. This has a significant
                impact on the memory consumption and speed of the training process. Three cases are possible:

                - If ``mini_batch_size`` is None, the ``mini_batch_size`` is set to the batch size.
                - If ``mini_batch_size`` is greater than 0, the batch is split into mini-batches of size ``mini_batch_size``.
                - If ``mini_batch_size`` is <= 0, the entire batch is processed at once.

                Defaults to None.

        References:
            - The LambdaLoss Framework for Ranking Metric Optimization: https://marc.najork.org/papers/cikm2018.pdf
            - Context-Aware Learning to Rank with Self-Attention: https://arxiv.org/abs/2005.10084
            - `Cross Encoder > Training Examples > MS MARCO <../../../examples/cross_encoder/training/ms_marco/README.html>`_

        Requirements:
            1. Query with multiple documents (listwise approach)
            2. Documents must have relevance scores/labels. Both binary and continuous labels are supported.

        Inputs:
            +----------------------------------------+--------------------------------+-------------------------------+
            | Texts                                  | Labels                         | Number of Model Output Labels |
            +========================================+================================+===============================+
            | (query, [doc1, doc2, ..., docN])       | [score1, score2, ..., scoreN]  | 1                             |
            +----------------------------------------+--------------------------------+-------------------------------+

        Recommendations:
            - Use :class:`~sentence_transformers.util.mine_hard_negatives` with ``output_format="labeled-list"``
              to convert question-answer pairs to the required input format with hard negatives.

        Relations:
            - :class:`~sentence_transformers.cross_encoder.losses.LambdaLoss` anecdotally performs better than
              the other losses with the same input format.

        Example:
            ::

                from sentence_transformers.cross_encoder import CrossEncoder, CrossEncoderTrainer, losses
                from datasets import Dataset

                model = CrossEncoder("microsoft/mpnet-base")
                train_dataset = Dataset.from_dict({
                    "query": ["What are pandas?", "What is the capital of France?"],
                    "docs": [
                        ["Pandas are a kind of bear.", "Pandas are kind of like fish."],
                        ["The capital of France is Paris.", "Paris is the capital of France.", "Paris is quite large."],
                    ],
                    "labels": [[1, 0], [1, 1, 0]],
                })
                loss = losses.LambdaLoss(model)

                trainer = CrossEncoderTrainer(
                    model=model,
                    train_dataset=train_dataset,
                    loss=loss,
                )
                trainer.train()
        r7   z< supports a model with 1 output label, but got a model with z output labels.N)r   r   modelr'   weighting_schemeksigmaepsreduction_logr   Identityactivation_fnmini_batch_size
num_labels
ValueErrorr   r    )
r   rS   rT   rU   rV   rW   rX   rZ   r[   r   s
            r   r   zLambdaLoss.__init__h   s    D 	
 0 G4E4G
**;bkkm.::  A%>>**+ ,((,

(=(='>oO  &r   c                l   t        |t              rt        d      t        |      dk7  rt        dt        |       d      |\  }}|D cg c]  }t        |       }}t	        |      }t        |      }||D cg c]  }t        |       c}k7  r)t        d| dD cg c]  }t        |       c} d      t        ||      D 	
cg c]  \  }	}|D ]  }
|	|
f  }}}	}
|s,t        j                  d| j                  j                  d	
      S | j                  xs |}|dk  rt        |      }g }t        dt        |      |      D ]  }||||z    }| j                  j                  |d	d	d      }|j                  | j                  j                        } | j                  di |d   j                  d      }|j                  |        t        j                   |d      }| j#                  |      }t        j$                  ||fd| j                  j                        }t        j                   |D cg c]   }t        j&                  t        |            " c}d      }t        j(                  t        j&                  |      t        j                  |            }||||f<   t        j*                  |t-        d            }t        j                   d      j-                         |||f<   |j                  | j                  j                        }|j/                  d	d      \  }}|j/                  d	d      \  }}t        j0                  |d|      }|dddddf   |dddddf   z
  }t        j2                  |      }t        | j4                  t6              s||dkD  z  }| j8                  xs |}t        j:                  ||ft        j<                  | j                  j                        }d|d|d|f<   |j?                  d       |j?                  d       t        j&                  d|dz         j                  | j                  j                        }t        j@                  d|j-                         z         dddf   } t        jB                  t        jD                  d|      dz
  | z  ddd|f   d      jG                  | jH                        }!t        jD                  d|      dz
  |!dddf   z  }"| j5                  |"| |      }#|dddddf   |dddddf   z
  jG                  dd      }$|$jK                  t        jL                  |$      d       t        jN                  | jP                  |$z        jG                  | jH                        |#z  jG                  | jH                        }%| jR                  dk(  rt        jT                  |%      }&nt        j@                  |%      }&|&||z     }'t        jV                  |'       }(|(S c c}w c c}w c c}w c c}
}}	w c c}w )a/  
        Compute LambdaLoss for a batch of queries and their documents.

        Args:
            inputs: List of (queries, documents_list)
            labels: Ground truth relevance scores, shape (batch_size, num_documents)

        Returns:
            Tensor: LambdaLoss loss over the batch
        z\LambdaLoss expects a list of labels for each sample, but got a single value for each sample.   zALambdaLoss expects two inputs (queries, documents_list), but got z inputs.z)Number of documents per query in inputs (z-) does not match number of labels per query (z).g        T)r+   requires_gradr   pt)padding
truncationreturn_tensors)dimg 7yAr*   z-inf)
descendingrf   r7   )rf   indexN)dtyper+   )minr)   g    חg    חA)rj   maxnaturalr/   ),
isinstancer   r]   lenrk   zipr,   r-   rS   r+   r[   range	tokenizertoviewappendcatrZ   fullr9   repeat_interleave	full_likerN   sortgatherisfiniterT   r1   rU   zerosboolclamp_log2sumr<   clamprW   masked_fill_isnansigmoidrV   rX   logmean))r   inputslabelsqueries	docs_listdocsdocs_per_querymax_docs
batch_sizequerydocumentpairsr[   logits_listimini_batch_pairstokenslogitslogits_matrixdoc_indicesbatch_indiceslabels_matrixlogits_matrix_sortedindices_predlabels_matrix_sorted_true_sorted_by_preds
true_diffspadded_pairs_maskrU   ndcg_at_k_maskr?   r   maxDCGsr   weightsscores_diffsweighted_probaslossesmasked_losseslosss)                                            r   r   zLambdaLoss.forward   s    ff%n  v;!`adekal`mmuvww#09:#d)::~&\
?fc&k??;N;KKx  U[  z\  KQz}  E  {F  z\  y]  ]_  ` 
 7:'96Mcc{ud^bcRZ%"c"cc<<DJJ,=,=TRR..<*a!%jOq#e*o6 	'A$Q_)<=ZZ)) #	 * F YYtzz001FTZZ)&)!,11"5Fv&	' ;A.##F+ 

J#95IZIZ[ iiY OTc$i!8 OUVW//Z0H%,,WeJfg4:m[01 uV}E49IIf!4L4R4R4Tm[01%(():):; .;-?-?4UW-?-X*l"/"4"4""4"Ma  %||MqU)!Q*58LQPTVWZ8XX
!NN:6$//A 1Z!^ D FFhh%9TXT^T^TeTef!"rr2A2v 	###,###,<<8a<033DJJ4E4EF::cHNN$445dAg>))eii+?@1DPRSUWVWUWRWX^`agglpltltgu		!12Q6'!T':JJ ''h8LM -Q4Z8;OPQSWYZPZ;[[bbgkqtbu!!%++l";SA ==l)BCIIdhhIW[bbiinrnvnviw *YY/FZZ0F 0>AB

=))} ; @ z\ d@ !Ps   X:X X%
X*8%X1c                    t        | j                        | j                  | j                  | j                  | j
                  t        | j                        | j                  dS )z
        Get configuration parameters for this loss function.

        Returns:
            Dictionary containing the configuration parameters
        )rT   rU   rV   rW   rX   rZ   r[   )r   rT   rU   rV   rW   rX   rZ   r[   r   s    r   get_config_dictzLambdaLoss.get_config_dictM  sQ     !))>)> ?ZZ88!//%d&8&89#33
 	
r   c                     y)Na^  
@inproceedings{wang2018lambdaloss,
  title={The LambdaLoss Framework for Ranking Metric Optimization},
  author={Wang, Xuanhui and Li, Cheng and Golbandi, Nadav and Bendersky, Michael and Najork, Marc},
  booktitle={Proceedings of the 27th ACM international conference on information and knowledge management},
  pages={1313--1322},
  year={2018}
}
r/   r   s    r   citationzLambdaLoss.citation^  s    r   )rS   r   rT   zBaseWeightingScheme | NonerU   
int | NonerV   rN   rW   rN   rX   zLiteral['natural', 'binary']rZ   znn.Module | Noner[   r   r   r   )r   z list[list[str], list[list[str]]]r   zlist[Tensor]r   r   )r   z#dict[str, float | int | str | None])r   str)r    r!   r"   rF   r   rY   r   r   r   propertyr   r$   r%   s   @r   rP   rP   g   s     8I7J6>*5"++-&*pp 5p 	p
 p p 4p (p $p 
pdqf
" 	 	r   rP   )
__future__r   typingr   r,   r   r   #sentence_transformers.cross_encoderr   sentence_transformers.utilr   Moduler
   r'   r1   r5   rC   rF   rP   r/   r   r   <module>r      s|    "    < /"")) ",5+ 5	-) 	-S) S&	
* 	
7+ 7&A Ar   