a
    dR                     @   s  d dl Z d dlZd dlmZmZmZmZmZmZm	Z	m
Z
 d dlZd dlmZ d dlmZ d dlmZ d dlmZmZmZmZmZmZmZ d dlmZ d dlmZmZ d d	lmZm Z  d
Z!e rd dl"m#Z#m$Z$ ddddZ%eree%sdgZ&ndgZ&d.ee'eee
e(ej)f  ee' e*e*e*eeeee(ef gef  e	eef d
ddZ+ee(eedddZ,eeeee	eeef dddZ-d/ee( ee' e*e(dddZ.e(edddZ/e(ed d!d"Z0d0e(ee( ee( ee( ee d$d%d&Z1d1eeeeee' e*e	eeef d'd(d)Z2d2e
e(ee( ee(ef f e
e(ee( ee(ef f ee( ee' e*ee eeeeee(ef gef  e*e*ee
e(ej)f  e'e'e'e*e(e*ee( ee( ee(e
eee3 e(f f d,d-dZ4dS )3    N)AnyCallableDictListOptionalSequenceTupleUnion)Tensor)Module)
DataLoader)TextDatasetTokenizedDataset_check_shape_of_model_output_get_progress_bar_input_data_collator_output_data_collator*_process_attention_mask_for_special_tokens)rank_zero_warn)_SKIP_SLOW_DOCTEST_try_proceed_with_timeout)_TQDM_AVAILABLE_TRANSFORMERS_GREATER_EQUAL_4_4zroberta-large)	AutoModelAutoTokenizer)returnc                   C   s   t t tt dS )zDownload intensive operations.N)r   from_pretrained_DEFAULT_MODELr    r   r   j/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/text/bert.py_download_model*   s    
r    
bert_scoreF)

dataloader
target_lenmodeldevice
num_layers
all_layersidfverboseuser_forward_fnr   c	              	   C   s  g }	g }
t | |D ]X}t  t||}|s|sb||d |d dd}|j|durZ|nd }n|||}t||d  |d}n<|rtd||d |d dd}tjd	d
 |jD dd}W d   n1 s0    Y  ||j	ddd }t
||d |\}}t|}td||}|	|  |r@|d | n
||j}||jddd }|
|  qt|	}t|
}||fS )a<  Calculate sentence embeddings and the inverse-document-frequency scaling factor.

    Args:
        dataloader: dataloader instance.
        target_len: A length of the longest sequence in the data. Used for padding the model output.
        model: BERT model.
        device: A device to be used for calculation.
        num_layers: The layer of representation to use.
        all_layers: An indication whether representation from all model layers should be used for BERTScore.
        idf: An Indication whether normalization using inverse document frequencies should be used.
        verbose: An indication of whether a progress bar to be displayed during the embeddings' calculation.
        user_forward_fn:
            A user's own forward function used in a combination with ``user_model``. This function must
            take ``user_model`` and a python dictionary of containing ``"input_ids"`` and ``"attention_mask"``
            represented by :class:`~torch.Tensor` as an input and return the model's output represented by the single
            :class:`~torch.Tensor`.

    Return:
        A tuple of :class:`~torch.Tensor`s containing the model's embeddings and the normalized tokens IDF.
        When ``idf = False``, tokens IDF is not calculated, and a matrix of mean weights is returned instead.
        For a single sentence, ``mean_weight = 1/seq_len``, where ``seq_len`` is a sum over the corresponding
        ``attention_mask``.

    Raises:
        ValueError:
            If ``all_layers = True`` and a model, which is not from the ``transformers`` package, is used.

    	input_idsattention_maskT)Zoutput_hidden_statesN   zQThe option `all_layers=True` can be used only with default `transformers` models.c                 S   s   g | ]}| d qS )r.   )	unsqueeze).0or   r   r   
<listcomp>p       z1_get_embeddings_and_idf_scale.<locals>.<listcomp>dimzblsd, bs -> blsdinput_ids_idf)Zkeepdim)r   torchZno_gradr   Zhidden_statesr   r/   
ValueErrorcatZnormr   r   einsumappendcputypeZdtypesum)r"   r#   r$   r%   r&   r'   r(   r)   r*   Zembeddings_listZidf_scale_listbatchoutr,   Zprocessed_attention_maskr6   Z
embeddings	idf_scaler   r   r   _get_embeddings_and_idf_scale5   s<    '


8

rB   )cos_simmetricrA   r   c                 C   sB   |dkrdnd}| j |dj}td||d}|dd S )	zOCalculate precision or recall, transpose it and scale it with idf_scale factor.	precision      r4   zbls, bs -> blsr-   r   r.   )maxvaluesr7   r:   r>   Z	transposeZsqueeze)rC   rD   rA   r5   resr   r   r   _get_scaled_precision_or_recall   s    rK   )preds_embeddingstarget_embeddingspreds_idf_scaletarget_idf_scaler   c                 C   sV   t d| |}t|d|}t|d|}d| | ||  }|t |d}|||fS )a  Calculate precision, recall and F1 score over candidate and reference sentences.

    Args:
        preds_embeddings: Embeddings of candidate sentences.
        target_embeddings: Embeddings of reference sentences.
        preds_idf_scale: An IDF scale factor for candidate sentences.
        target_idf_scale: An IDF scale factor for reference sentences.

    Return:
        Tensors containing precision, recall and F1 score, respectively.

    zblpd, blrd -> blprrE   recallrG           )r7   r:   rK   Zmasked_fillisnan)rL   rM   rN   rO   rC   rE   rP   f1_scorer   r   r   _get_precision_recall_f1   s    rT   )model_name_or_pathr&   r(   r   c                 C   s   |  d| |rdnd S )z,Compute `BERT_score`_ (copied and adjusted)._LZ_idfz_no-idfr   )rU   r&   r(   r   r   r   	_get_hash   s    rW   )baseline_pathr   c                 C   s^   t | ,}t|}dd t|D }W d   n1 s:0    Y  t|ddddf S )zqRead baseline from csv file from the local file.

    This method implemented to avoid `pandas` dependency.

    c                 S   s&   g | ]\}}|d krdd |D qS )r   c                 S   s   g | ]}t |qS r   floatr0   itemr   r   r   r2      r3   z8_read_csv_from_local_file.<locals>.<listcomp>.<listcomp>r   r0   idxrowr   r   r   r2      r3   z-_read_csv_from_local_file.<locals>.<listcomp>Nr.   )opencsvreader	enumerater7   tensor)rX   fnameZcsv_filebaseline_listr   r   r   _read_csv_from_local_file   s    

0rg   )baseline_urlr   c                 C   s\   t j| <}dd t|D }t|ddddf W  d   S 1 sN0    Y  dS )ziRead baseline from csv file from URL.

    This method is implemented to avoid `pandas` dependency.

    c                 S   s6   g | ].\}}|d krdd |  ddD qS )r   c                 S   s   g | ]}t |qS r   rY   r[   r   r   r   r2      r3   z1_read_csv_from_url.<locals>.<listcomp>.<listcomp>zutf-8,)stripdecodesplitr]   r   r   r   r2      s   z&_read_csv_from_url.<locals>.<listcomp>Nr.   )urllibrequesturlopenrc   r7   rd   )rh   http_requestrf   r   r   r   _read_csv_from_url   s
    rq   en)langrU   rX   rh   r   c                 C   sX   |rt |}nF|rt|}n8| rH|rHd}| d|  d| d}t|}ntd dS |S )z<Load a CSV file with the baseline values used for rescaling.zWhttps://raw.githubusercontent.com/Tiiiger/bert_score/master/bert_score/rescale_baseline/z.tsvzFBaseline was not successfully loaded. No baseline is going to be used.N)rg   rq   r   )rs   rU   rX   rh   baselineZurl_baser   r   r   _load_baseline   s    


rv   )rE   rP   rS   ru   r&   r'   r   c                 C   sd   |du r|du rd}t j| ||gdd}|r6|dn|| }|| d|  }|d |d |d fS )	z<Rescale the computed metrics with the pre-computed baseline.NFr-   r4   r.   ).r   ).r.   ).rG   )r7   stackr/   )rE   rP   rS   ru   r&   r'   Zall_metricsZbaseline_scaler   r   r   _rescale_metrics_with_baseline   s    	rx      @   )predstargetrU   r&   r'   r$   user_tokenizerr*   r)   r(   r%   
max_length
batch_sizenum_threadsreturn_hashrs   rescale_with_baselinerX   rh   r   c           $   
   C   sJ  t | t |krtdt| tttfs0t| } t|tttfsHt|}|rXtsXtd|du rtsltd|du rt	dt
 d t|pt
}t|pt
}n|}|  ||
 z2|r||jjkrtd| d| d	|jj W n ty   t	d
 Y n0 tdd | |fD }tdd | |fD }tdd | |fD }|rt	d dgdgdgd}|r|dt|||	i |S |rt||||nd}|rt||||	d}t| |||	|jd}n@|rtf i |d|	i}tf i | |	|jd}ntdt|||d}t|||d}t||j||
|||	||	\}}t||j||
|||	||	\}} t||| |\}!}"}#t |!jdkr|!|jj  }!|"|jj  }"|#|jj  }#nLt |!jdkr|!dd|jj f }!|"dd|jj f }"|#dd|jj f }#|durt!|!|"|#|||\}!}"}#|!|"|#d}|rF|dt|||	i |S )a  `Bert_score Evaluating Text Generation`_ for text similirity matching.

    This metric leverages the pre-trained contextual embeddings from BERT and matches words in candidate and reference
    sentences by cosine similarity. It has been shown to correlate with human judgment on sentence-level and
    system-level evaluation. Moreover, BERTScore computes precision, recall, and F1 measure, which can be useful for
    evaluating different language generation tasks.

    This implemenation follows the original implementation from `BERT_score`_.

    Args:
        preds: Either an iterable of predicted sentences or a ``Dict[input_ids, attention_mask]``.
        target: Either an iterable of target sentences or a  ``Dict[input_ids, attention_mask]``.
        model_name_or_path: A name or a model path used to load ``transformers`` pretrained model.
        num_layers: A layer of representation to use.
        all_layers:
            An indication of whether the representation from all model's layers should be used.
            If ``all_layers = True``, the argument ``num_layers`` is ignored.
        model: A user's own model.
        user_tokenizer:
            A user's own tokenizer used with the own model. This must be an instance with the ``__call__`` method.
            This method must take an iterable of sentences (``List[str]``) and must return a python dictionary
            containing ``"input_ids"`` and ``"attention_mask"`` represented by :class:`~torch.Tensor`.
            It is up to the user's model of whether ``"input_ids"`` is a :class:`~torch.Tensor` of input ids
            or embedding vectors. his tokenizer must prepend an equivalent of ``[CLS]`` token and append an equivalent
            of ``[SEP]`` token as `transformers` tokenizer does.
        user_forward_fn:
            A user's own forward function used in a combination with ``user_model``.
            This function must take ``user_model`` and a python dictionary of containing ``"input_ids"``
            and ``"attention_mask"`` represented by :class:`~torch.Tensor` as an input and return the model's output
            represented by the single :class:`~torch.Tensor`.
        verbose: An indication of whether a progress bar to be displayed during the embeddings' calculation.
        idf: An indication of whether normalization using inverse document frequencies should be used.
        device: A device to be used for calculation.
        max_length: A maximum length of input sequences. Sequences longer than ``max_length`` are to be trimmed.
        batch_size: A batch size used for model processing.
        num_threads: A number of threads to use for a dataloader.
        return_hash: An indication of whether the correspodning ``hash_code`` should be returned.
        lang: A language of input sentences. It is used when the scores are rescaled with a baseline.
        rescale_with_baseline:
            An indication of whether bertscore should be rescaled with a pre-computed baseline.
            When a pretrained model from ``transformers`` model is used, the corresponding baseline is downloaded
            from the original ``bert-score`` package from `BERT_score`_ if available.
            In other cases, please specify a path to the baseline csv/tsv file, which must follow the formatting
            of the files from `BERT_score`_
        baseline_path: A path to the user's own local csv/tsv file with the baseline scale.
        baseline_url: A url path to the user's own  csv/tsv file with the baseline scale.

    Returns:
        Python dictionary containing the keys ``precision``, ``recall`` and ``f1`` with corresponding values.

    Raises:
        ValueError:
            If ``len(preds) != len(target)``.
        ModuleNotFoundError:
            If `tqdm` package is required and not installed.
        ModuleNotFoundError:
            If ``transformers`` package is required and not installed.
        ValueError:
            If ``num_layer`` is larger than the number of the model layers.
        ValueError:
            If invalid input is provided.

    Example:
        >>> from pprint import pprint
        >>> from torchmetrics.functional.text.bert import bert_score
        >>> preds = ["hello there", "general kenobi"]
        >>> target = ["hello there", "master kenobi"]
        >>> pprint(bert_score(preds, target))
        {'f1': tensor([1.0000, 0.9961]), 'precision': tensor([1.0000, 0.9961]), 'recall': tensor([1.0000, 0.9961])}

    z=Number of predicted and reference sententes must be the same!zcAn argument `verbose = True` requires `tqdm` package be installed. Install with `pip install tqdm`.Nz`bert_score` metric with default models requires `transformers` package be installed. Either install with `pip install transformers>=4.4` or `pip install torchmetrics[text]`.zThe argument `model_name_or_path` was not specified while it is required when default `transformers` model are used.It is, therefore, used the default recommended model - .znum_layers=z is forbidden for z. Please use num_layers <= zXIt was not possible to retrieve the parameter `num_layers` from the model specification.c                 s   s$   | ]}t |tot|d kV  qdS r   N)
isinstancelistlenr0   textr   r   r   	<genexpr>w  r3   zbert_score.<locals>.<genexpr>c                 s   s2   | ]*}t |to(t|d ko(t |d  tV  qdS r   )r   r   r   strr   r   r   r   r   x  s   c                 s   s&   | ]}t |tot |d  tV  qdS )r+   N)r   dictr
   r   r   r   r   r   {  s   z%Predictions and references are empty.rQ   )rE   rP   f1hash)r(   )r(   
tokens_idfr(   zInvalid input provided.)r   Znum_workersr.   rG   )"r   r8   r   r   r   r   r   ModuleNotFoundErrorr   r   r   r   r   r   evaltoconfigZnum_hidden_layersAttributeErrorallupdaterW   rv   r   r   r   r   rB   r~   rT   shapeZdatasetZsorting_indicesrx   )$r{   r|   rU   r&   r'   r$   r}   r*   r)   r(   r%   r~   r   r   r   rs   r   rX   rh   	tokenizerZ_are_empty_listsZ_are_valid_listsZ_are_valid_tensorsZoutput_dictru   Ztarget_datasetZpreds_datasetZtarget_loaderZpreds_loaderrM   rO   rL   rN   rE   rP   rS   r   r   r   r!      s    \



)NNFFFN)NNF)rr   NNN)NF)NNFNNNFFNry   rz   r   Frr   FNN)5ra   rm   typingr   r   r   r   r   r   r   r	   r7   r
   Ztorch.nnr   Ztorch.utils.datar   Z4torchmetrics.functional.text.helper_embedding_metricr   r   r   r   r   r   r   Ztorchmetrics.utilitiesr   Ztorchmetrics.utilities.checksr   r   Ztorchmetrics.utilities.importsr   r   r   Ztransformersr   r   r    Z__doctest_skip__intr   r%   boolrB   rK   rT   rW   rg   rq   rv   rx   rZ   r!   r   r   r   r   <module>   s   ($	      
Q
                       