a
    dU                     @   s0  U d dl Z d dlm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mZ d dlmZ d dlmZ ddgiZd	d
ddddddddddZeeeeef f ed< dZddddZee	e dddZeeeeeef dddZdAe	e e	e eeee	e	e  f d!d"d#Ze	e	e  e	e e	e e	e d$d%d&Ze	e	e  e	e e	e d'd(d)ZdBeee eeegef  eeege	e f  e	e d*d+d,Z e	e e	e eeeef d-d.d/Z!e	e e	e eeef d0d1d2Z"e	e	e  e	e	e  eeef d0d3d4Z#dCe	e e	e	e  eeeef  eee eeegef  eeege	e f  eeeef eeeef  f d5d6d7Z$eeee f eeef d8d9d:Z%dDeee	e f eee	e e	e	e  f ed eeeegef  eeege	e f  eee
ed=f f eeef d>d?d@Z&dS )E    N)Counter)AnyCallableDictListOptionalSequenceTupleUnion)Tensortensor)Literal)_NLTK_AVAILABLE)rouge_score_rouge_score_updatenltk                        	   LLsum)rouge1rouge2Zrouge3Zrouge4Zrouge5Zrouge6Zrouge7Zrouge8Zrouge9rougeL	rougeLsumALLOWED_ROUGE_KEYS)avgbest)returnc                  C   sx   ddl } z| jd W nZ tyr   z| jdddddd W n. tyl } ztd|W Y d}~n
d}~0 0 Y n0 dS )	zyCheck whether `nltk` `punkt` is downloaded.

    If not, try to download if a machine is connected to the internet.

    r   Nztokenizers/punktZpunktTF)quietforceZhalt_on_errorZraise_on_errorzz`nltk` resource `punkt` is not available on a disk and cannot be downloaded as a machine is not connected to the internet.)r   datafindLookupErrordownload
ValueErrorOSError)r   err r.   k/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torchmetrics/functional/text/rouge.py _ensure_nltk_punkt_is_downloaded*   s    r0   )xr$   c                 C   s2   t stdddl}t  tdd|  || S )z]Split sentence to get rougeLsum scores matching published rougeL scores for BART and PEGASUS.zQROUGE-Lsum calculation requires that `nltk` is installed. Use `pip install nltk`.r   Nz<n> )r   ModuleNotFoundErrorr   r0   resubZsent_tokenize)r1   r   r.   r.   r/   _split_sentence>   s    r6   )hits_or_lcspred_len
target_lenr$   c                 C   sl   | | }| | }||  kr$dkr@n nt dt dt ddS d| | ||  }t |t |t |dS )a  Compute overall metrics.

    This function computes precision, recall and F1 score based on hits/lcs, the length of lists of tokenizer
    predicted and target sentences.

    Args:
        hits_or_lcs: A number of matches or a length of the longest common subsequence.
        pred_len: A length of a tokenized predicted sentence.
        target_len: A length of a tokenized target sentence.

            	precisionrecallfmeasurer   )r   )r7   r8   r9   r<   r=   r>   r.   r.   r/   _compute_metricsJ   s    r?   F)pred_tokenstarget_tokensreturn_full_tabler$   c                    s    fddt t|d D }t dt|d D ]}t dt d D ]h}||d   |d  kr||d  |d  d || |< qFt||d  | || |d  || |< qFq0|r|S |d d S )a0  DP algorithm to compute the length of the longest common subsequence.

    Args:
        pred_tokens: A tokenized predicted sentence.
        target_tokens: A tokenized target sentence.
        return_full_table: If the full table of logest common subsequence should be returned or just the largest

    c                    s   g | ]}d gt  d  qS )r   r   )len).0_r@   r.   r/   
<listcomp>j       z_lcs.<locals>.<listcomp>r   )rangerC   max)r@   rA   rB   lcsijr.   rF   r/   _lcs_   s    ".rO   )	lcs_tabler@   rA   r$   c                 C   s   t |}t |}g }|dkr|dkr||d  ||d  kr^|d|d  |d8 }|d8 }q| | |d  | |d  | kr|d8 }q|d8 }q|S )zBacktrack LCS table.

    Args:
        lcs_table: A table containing information for the calculation of the longest common subsequence.
        pred_tokens: A tokenized predicted sentence.
        target_tokens: A tokenized target sentence.

    r   r   )rC   insert)rP   r@   rA   rM   rN   Zbacktracked_lcsr.   r.   r/   _backtracked_lcsv   s    
 

rR   )pred_tokens_listrA   r$   c                    sd   t t t t t t ddd t t t  t t ddd} fdd| D }fd	d||D S )
zFind union LCS between a target sentence and iterable of predicted tokens.

    Args:
        pred_tokens_list: A tokenized predicted sentence split by ``'\n'``.
        target_tokens: A tokenized single part of target sentence split by ``'\n'``.

    )r@   rA   r$   c                 S   s   t | |dd}t|| |S )zRReturn one of the longest of longest common subsequence via backtracked lcs table.T)rB   )rO   rR   )r@   rA   rP   r.   r.   r/   lcs_ind   s    z_union_lcs.<locals>.lcs_ind)
lcs_tablesr$   c                 S   s   t t j|  S )z#Find union LCS given a list of LCS.)sortedsetunion)rU   r.   r.   r/   
find_union   s    z_union_lcs.<locals>.find_unionc                    s   g | ]} |qS r.   r.   )rD   r@   rT   rA   r.   r/   rG      rH   z_union_lcs.<locals>.<listcomp>c                    s   g | ]} | qS r.   r.   rD   rM   )rA   r.   r/   rG      rH   )r   strint)rS   rA   rY   rU   r.   rZ   r/   
_union_lcs   s    	r^   )textstemmer
normalizer	tokenizerr$   c                    sb   t |r|| ntdd|  } t |r2|| n
td| } rT fdd|D }dd |D S )a  Rouge score should be calculated only over lowercased words and digits.

    Optionally, Porter stemmer can be used to strip word suffixes to improve matching. The text normalization follows
    the implemantion from `Rouge score_Text Normalizition`_.

    Args:
        text: An input sentence.
        stemmer: Porter stemmer instance to strip word suffixes to improve matching.
        normalizer: A user's own normalizer function.
            If this is ``None``, replacing any non-alpha-numeric characters with spaces is default.
            This function must take a ``str`` and return a ``str``.
        tokenizer:
            A user's own tokenizer function. If this is ``None``, splitting by spaces is default
            This function must take a ``str`` and return ``Sequence[str]``

    z
[^a-z0-9]+ z\s+c                    s&   g | ]}t |d kr |n|qS )r   )rC   stemrD   r1   r`   r.   r/   rG      rH   z0_normalize_and_tokenize_text.<locals>.<listcomp>c                 S   s&   g | ]}t |trt|d kr|qS )r   )
isinstancer\   rC   re   r.   r.   r/   rG      rH   )callabler4   r5   lowersplit)r_   r`   ra   rb   tokensr.   rf   r/   _normalize_and_tokenize_text   s
    "rl   )predtargetn_gramr$   c                    s   t t ttddd}|| ||||  t  t  }}d||fv rjtdtdtddS t fddt D }t|t	|d	t	|d	S )
zCompute precision, recall and F1 score for the Rouge-N metric.

    Args:
        pred: A predicted sentence.
        target: A target sentence.
        n_gram: N-gram overlap.

    )rk   nr$   c                    sD   t  } fddtt  d D D ]}||  d7  < q*|S )Nc                 3   s"   | ]}t ||   V  qd S N)tupler[   rp   rk   r.   r/   	<genexpr>   rH   z9_rouge_n_score.<locals>._create_ngrams.<locals>.<genexpr>r   )r   rJ   rC   )rk   rp   ngramsZngramr.   rs   r/   _create_ngrams   s    (z&_rouge_n_score.<locals>._create_ngramsr   r:   r;   c                 3   s    | ]}t  | | V  qd S rq   )min)rD   wZpred_ngramsZtarget_ngramsr.   r/   rt      rH   z!_rouge_n_score.<locals>.<genexpr>r   )
r   r\   r]   r   sumvaluesr   rW   r?   rK   )rm   rn   ro   rv   r8   r9   hitsr.   ry   r/   _rouge_n_score   s    
r}   )rm   rn   r$   c                 C   sL   t | t | }}d||fv r6tdtdtddS t| |}t|||S )zCompute precision, recall and F1 score for the Rouge-L metric.

    Args:
        pred: A predicted sentence.
        target: A target sentence.

    r   r:   r;   )rC   r   rO   r?   )rm   rn   r8   r9   rL   r.   r.   r/   _rouge_l_score   s
    
r~   c                 C   s   t tt| }t tt|}d||fv r@tdtdtddS ttt  tddd}|| }||}d}|D ]X}t| |}	|	D ]D}
||
 dkr||
 dkr|d7 }||
  d8  < ||
  d8  < qqpt|||S )a>  Compute precision, recall and F1 score for the Rouge-LSum metric.

    More information can be found in Section 3.2 of the referenced paper [1]. This implementation follow the official
    implementation from:
    https://github.com/google-research/google-research/blob/master/rouge/rouge_scorer.py.

    Args:
        pred: An iterable of predicted sentence split by '\n'.
        target: An iterable target sentence split by '\n'.

    References:
        [1] ROUGE: A Package for Automatic Evaluation of Summaries by Chin-Yew Lin. https://aclanthology.org/W04-1013/

    r   r:   r;   )	sentencesr$   c                 S   s   t  }| D ]}|| q
|S rq   )r   update)r   ru   Zsentencer.   r.   r/   _get_token_counts	  s    z,_rouge_lsum_score.<locals>._get_token_countsr   )	rz   maprC   r   r   r\   r   r^   r?   )rm   rn   r8   r9   r   Zpred_tokens_countZtarget_tokens_countr|   tgtrL   tokenr.   r.   r/   _rouge_lsum_score   s     
r   )predsrn   rouge_keys_values
accumulater`   ra   rb   r$   c                    s   dd |D }t | |D ] \}}	dd |D }
dd |D }g }t|}d|v rrfddt|D }|	D ]}t|}d|v rfddt|D }|D ]X}t|trt|||}n&|d	krt||}n|dkrt||}||
|< || | q||
	  qv|d
krx|d t
fdd|D }tt
| }|D ]}|| || |  qXq|dkrdd |D }| D ]d\}}i  |D ]:}| D ]*\}}| vrg  |<  | | qq fdd D ||< q|D ]}|| ||  q q|S )a
  Update the rouge score with the current set of predicted and target sentences.

    Args:
        preds: An iterable of predicted sentences.
        target: An iterable of iterable of target sentences.
        rouge_keys_values: List of N-grams/'L'/'Lsum' arguments.
        accumulate: Useful incase of multi-reference rouge score.
            ``avg`` takes the avg of all references with respect to predictions
            ``best`` takes the best fmeasure score obtained between prediction and multiple corresponding references.
            Allowed values are ``avg`` and ``best``.
        stemmer: Porter stemmer instance to strip word suffixes to improve matching.
        normalizer:
            A user's own normalizer function.
            If this is ``None``, replacing any non-alpha-numeric characters with spaces is default.
            This function must take a `str` and return a `str`.
        tokenizer:
            A user's own tokenizer function. If this is ``None``, spliting by spaces is default
            This function must take a `str` and return `Sequence[str]`

    Example:
        >>> preds = "My name is John".split()
        >>> target = "Is your name John".split()
        >>> from pprint import pprint
        >>> score = _rouge_score_update(preds, target, rouge_keys_values=[1, 2, 3, 'L'], accumulate='best')
        >>> pprint(score)
        {1: [{'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)}],
         2: [{'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)}],
         3: [{'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
             {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)}],
         'L': [{'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
               {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
               {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)},
               {'fmeasure': tensor(0.), 'precision': tensor(0.), 'recall': tensor(0.)}]}

    c                 S   s   i | ]
}|g qS r.   r.   rD   	rouge_keyr.   r.   r/   
<dictcomp>S  rH   z'_rouge_score_update.<locals>.<dictcomp>c                 S   s   i | ]
}|i qS r.   r.   r   r.   r.   r/   r   V  rH   c                 S   s   i | ]
}|g qS r.   r.   r   r.   r.   r/   r   W  rH   r   c                    s   g | ]}t | qS r.   rl   )rD   Zpred_sentencera   r`   rb   r.   r/   rG   [  s   z'_rouge_score_update.<locals>.<listcomp>c                    s   g | ]}t | qS r.   r   )rD   Ztgt_sentencer   r.   r/   rG   d  s   r   r#   r   c                    s   g | ]}|  d  qS )r>   r.   )rD   v)key_currr.   r/   rG   v  rH   r"   c                 S   s   i | ]
}|i qS r.   r.   r   r.   r.   r/   r   }  s   c                    s    i | ]}|t  |  qS r.   )torchr   mean)rD   _type)_dict_metric_score_batchr.   r/   r     s   )ziprl   r6   rg   r]   r}   r~   r   appendcopyr   r   Zargmaxitemitems)r   rn   r   r   r`   ra   rb   resultsZpred_rawZ
target_rawZresult_innerZ
result_avgZlist_resultsrm   Z	pred_lsumZtarget_raw_innerr   Ztarget_lsumr   ZscoreZall_fmeasureZhighest_idxZnew_result_avgmetricsmetricr   valuer.   )r   r   ra   r`   rb   r/   r     sb    4




r   )sentence_resultsr$   c                 C   s8   i }| i kr|S |   D ]\}}t| ||< q|S )zCompute the combined ROUGE metric for all the input set of predicted and target sentences.

    Args:
        sentence_results: Rouge-N/Rouge-L/Rouge-LSum metrics calculated for single sentence.

    )r   r   r   r   )r   r   r   Zscoresr.   r.   r/   _rouge_score_compute  s    r   r#   r   r   r   r    .)r   rn   r   use_stemmerra   rb   
rouge_keysr$   c              	   C   sR  |rt stdddl}|r(|jj nd}t|ts<|f}|D ],}	|	t	 vr@t
d|	 dtt	  q@dd |D }
t|trtdd	 |D rt| tr|gnd
d |D }t| tr| g} t|tr|gg}t| ||
||||d}dd |
D }| D ]D\}}|D ]4}| D ]$\}}|d| d|  | qqqt|S )ax	  Calculate `Calculate Rouge Score`_ , used for automatic summarization.

    Args:
        preds: An iterable of predicted sentences or a single predicted sentence.
        target:
            An iterable of iterables of target sentences or an iterable of target sentences or a single target sentence.
        accumulate:
            Useful incase of multi-reference rouge score.

            - ``avg`` takes the avg of all references with respect to predictions
            - ``best`` takes the best fmeasure score obtained between prediction and multiple corresponding references.

        use_stemmer: Use Porter stemmer to strip word suffixes to improve matching.
        normalizer: A user's own normalizer function.
            If this is ``None``, replacing any non-alpha-numeric characters with spaces is default.
            This function must take a ``str`` and return a ``str``.
        tokenizer: A user's own tokenizer function. If this is ``None``, spliting by spaces is default
            This function must take a ``str`` and return ``Sequence[str]``
        rouge_keys: A list of rouge types to calculate.
            Keys that are allowed are ``rougeL``, ``rougeLsum``, and ``rouge1`` through ``rouge9``.

    Return:
        Python dictionary of rouge scores for each input rouge key.

    Example:
        >>> from torchmetrics.functional.text.rouge import rouge_score
        >>> preds = "My name is John"
        >>> target = "Is your name John"
        >>> from pprint import pprint
        >>> pprint(rouge_score(preds, target))
        {'rouge1_fmeasure': tensor(0.7500),
         'rouge1_precision': tensor(0.7500),
         'rouge1_recall': tensor(0.7500),
         'rouge2_fmeasure': tensor(0.),
         'rouge2_precision': tensor(0.),
         'rouge2_recall': tensor(0.),
         'rougeL_fmeasure': tensor(0.5000),
         'rougeL_precision': tensor(0.5000),
         'rougeL_recall': tensor(0.5000),
         'rougeLsum_fmeasure': tensor(0.5000),
         'rougeLsum_precision': tensor(0.5000),
         'rougeLsum_recall': tensor(0.5000)}


    Raises:
        ModuleNotFoundError:
            If the python package ``nltk`` is not installed.
        ValueError:
            If any of the ``rouge_keys`` does not belong to the allowed set of keys.

    References:
        [1] ROUGE: A Package for Automatic Evaluation of Summaries by Chin-Yew Lin. https://aclanthology.org/W04-1013/

    zBStemmer requires that `nltk` is installed. Use `pip install nltk`.r   NzGot unknown rouge key z. Expected to be one of c                 S   s   g | ]}t | qS r.   )r!   )rD   keyr.   r.   r/   rG     rH   zrouge_score.<locals>.<listcomp>c                 s   s   | ]}t |tV  qd S rq   )rg   r\   rD   r   r.   r.   r/   rt     rH   zrouge_score.<locals>.<genexpr>c                 S   s   g | ]
}|gqS r.   r.   r   r.   r.   r/   rG     rH   )r`   ra   rb   r   c                 S   s(   i | ] }d D ]}d| d| g qqS ))r>   r<   r=   rougerE   r.   )rD   r   tpr.   r.   r/   r     s   zrouge_score.<locals>.<dictcomp>r   rE   )r   r3   r   rd   ZporterZPorterStemmerrg   rr   r!   keysr+   listallr\   r   r   r   r   )r   rn   r   r   ra   rb   r   r   r`   r   r   r   outputr   r   r   r   r   r.   r.   r/   r     sD    ?



&r   )F)NNN)NNN)r#   FNNr   )'r4   collectionsr   typingr   r   r   r   r   r   r	   r
   r   r   r   Ztyping_extensionsr   Ztorchmetrics.utilities.importsr   Z__doctest_requires__r!   r\   r]   __annotations__ZALLOWED_ACCUMULATE_VALUESr0   r6   r?   boolrO   rR   r^   rl   r}   r~   r   r   r   r   r.   r.   r.   r/   <module>   s   
(
 "   $$"*0   
s$     
