
    siL1                         d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
mZmZ d dlmZ d dlmZ erd dlmZ  ej        e          Z G d d	e          ZdS )
    N)defaultdict)nullcontext)TYPE_CHECKINGDictListOptionalTuple)SentenceEvaluator)paraphrase_mining)SentenceTransformerc                       e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 d"deeef         deeeef                  deeeeef         f         dede	de	de	de	dede	dedede
e	         f fdZ	 d#dddede	de	deeef         f
d Zed!             Z xZS )$ParaphraseMiningEvaluatora  
    Given a large set of sentences, this evaluator performs paraphrase (duplicate) mining and
    identifies the pairs with the highest similarity. It compare the extracted paraphrase pairs
    with a set of gold labels and computes the F1 score.

    Example:
        ::

            from datasets import load_dataset
            from sentence_transformers.SentenceTransformer import SentenceTransformer
            from sentence_transformers.evaluation import ParaphraseMiningEvaluator

            # Load a model
            model = SentenceTransformer('all-mpnet-base-v2')

            # Load the Quora Duplicates Mining dataset
            questions_dataset = load_dataset("sentence-transformers/quora-duplicates-mining", "questions", split="dev")
            duplicates_dataset = load_dataset("sentence-transformers/quora-duplicates-mining", "duplicates", split="dev")

            # Create a mapping from qid to question & a list of duplicates (qid1, qid2)
            qid_to_questions = dict(zip(questions_dataset["qid"], questions_dataset["question"]))
            duplicates = list(zip(duplicates_dataset["qid1"], duplicates_dataset["qid2"]))

            # Initialize the paraphrase mining evaluator
            paraphrase_mining_evaluator = ParaphraseMiningEvaluator(
                sentences_map=qid_to_questions,
                duplicates_list=duplicates,
                name="quora-duplicates-dev",
            )
            results = paraphrase_mining_evaluator(model)
            '''
            Paraphrase Mining Evaluation of the model on the quora-duplicates-dev dataset:
            Number of candidate pairs: 250564
            Average Precision: 56.51
            Optimal threshold: 0.8325
            Precision: 52.76
            Recall: 59.19
            F1: 55.79
            '''
            print(paraphrase_mining_evaluator.primary_metric)
            # => "quora-duplicates-dev_average_precision"
            print(results[paraphrase_mining_evaluator.primary_metric])
            # => 0.5650940787776353
    NF  順   d       Tsentences_mapduplicates_listduplicates_dictadd_transitive_closurequery_chunk_sizecorpus_chunk_size	max_pairstop_kshow_progress_bar
batch_sizename	write_csvtruncate_dimc           
         t                                                       g | _        g | _        |                                D ]9\  }}| j                            |           | j                            |           :|| _        |	| _        |
| _        || _	        || _
        || _        || _        || _        ||nt          d           | _        |0|D ]-\  }}||v r$||v r d| j        |         |<   d| j        |         |<   .|r|                     | j                  | _        t#                      }| j        D ]q}| j        |         D ]a}||v r[||v rW| j        |         |         s| j        |         |         r1|                    t'          t)          ||g                               brt+          |          | _        |rd|z   }d|z   dz   | _        g d| _        || _        d| _        dS )	a	  
        Initializes the ParaphraseMiningEvaluator.

        Args:
            sentences_map (Dict[str, str]): A dictionary that maps sentence-ids to sentences.
                For example, sentences_map[id] => sentence.
            duplicates_list (List[Tuple[str, str]], optional): A list with id pairs [(id1, id2), (id1, id5)]
                that identifies the duplicates / paraphrases in the sentences_map. Defaults to None.
            duplicates_dict (Dict[str, Dict[str, bool]], optional): A default dictionary mapping [id1][id2]
                to true if id1 and id2 are duplicates. Must be symmetric, i.e., if [id1][id2] => True,
                then [id2][id1] => True. Defaults to None.
            add_transitive_closure (bool, optional): If true, it adds a transitive closure,
                i.e. if dup[a][b] and dup[b][c], then dup[a][c]. Defaults to False.
            query_chunk_size (int, optional): To identify the paraphrases, the cosine-similarity between
                all sentence-pairs will be computed. As this might require a lot of memory, we perform
                a batched computation. query_chunk_size sentences will be compared against up to
                corpus_chunk_size sentences. In the default setting, 5000 sentences will be grouped
                together and compared up-to against 100k other sentences. Defaults to 5000.
            corpus_chunk_size (int, optional): The corpus will be batched, to reduce the memory requirement.
                Defaults to 100000.
            max_pairs (int, optional): We will only extract up to max_pairs potential paraphrase candidates.
                Defaults to 500000.
            top_k (int, optional): For each query, we extract the top_k most similar pairs and add it to a sorted list.
                I.e., for one sentence we cannot find more than top_k paraphrases. Defaults to 100.
            show_progress_bar (bool, optional): Output a progress bar. Defaults to False.
            batch_size (int, optional): Batch size for computing sentence embeddings. Defaults to 16.
            name (str, optional): Name of the experiment. Defaults to "".
            write_csv (bool, optional): Write results to CSV file. Defaults to True.
            truncate_dim (Optional[int], optional): The dimension to truncate sentence embeddings to.
                `None` uses the model's current truncation dimension. Defaults to None.
        Nc                  *    t          t                    S )N)r   bool     m/var/www/icac/venv/lib/python3.11/site-packages/sentence_transformers/evaluation/ParaphraseMiningEvaluator.py<lambda>z4ParaphraseMiningEvaluator.__init__.<locals>.<lambda>   s    bmnrbsbs r&   T_paraphrase_mining_evaluationz_results.csv)epochsteps	precisionrecallf1	thresholdaverage_precisionr1   )super__init__	sentencesidsitemsappendr   r   r   r   r   r   r   r!   r   
duplicatesr   setaddtuplesortedlentotal_num_duplicatescsv_filecsv_headersr    primary_metric)selfr   r   r   r   r   r   r   r   r   r   r   r    r!   idsentenceid1id2positive_key_pairskey1key2	__class__s                        r'   r3   z"ParaphraseMiningEvaluator.__init__?   s=   ^ 	)//11 	  	 LBN!!(+++HOOB	!2$ 0!2"
(-<-H//kZsZsNtNt&+ 5 5S-''C=,@,@04DOC(-04DOC(- " 	K"99$/JJDO UUO 	H 	HD- H HM))--.t4 .8<8Md8S . '**5t1E1E+F+FGGGH %((:$;$;! 	:D;dB^Slll"1r&   modelr   output_pathr+   r,   returnc                    |dk    r|dk    rd| }nd| d| d}nd}| j         |d| j          dz  }t                              d	| j         d
| d           | j         t	                      n|                    | j                   5  t          || j        | j        | j	        | j
        | j        | j        | j                  }d d d            n# 1 swxY w Y   t                              dt          t          |                    z              dx}}d}	dx}
x}}d}t!          t          |                    D ]}||         \  }}}| j        |         }| j        |         }|dz  }| j        |         |         s| j        |         |         rt|dz  }||z  }|| j        z  }d|z  |z  ||z   z  }||z  }||
k    rG|}
|}|}||         d         |t)          |dz   t          |          dz
                     d         z   dz  }	|| j        z  }t                              d                    |dz                       t                              d                    |	                     t                              d                    |dz                       t                              d                    |dz                       t                              d                    |
dz                       || j        rt.          j                            || j                  }t.          j                            |          svt9          |ddd          5 }t;          j        |          }|                    | j                    |                    |||||
|	|g           d d d            n# 1 swxY w Y   n[t9          |ddd          5 }t;          j        |          }|                    |||||
|	|g           d d d            n# 1 swxY w Y   ||
|||	d}| !                    || j                  }| "                    ||           |S )NrK   z after epoch z
 in epoch z after z stepsr   z (truncated to )z1Paraphrase Mining Evaluation of the model on the z dataset:zNumber of candidate pairs: r         zAverage Precision: {:.2f}r   zOptimal threshold: {:.4f}zPrecision: {:.2f}zRecall: {:.2f}zF1: {:.2f}
wzutf-8)newlinemodeencodinga)r1   r/   r-   r.   r0   )#r!   loggerinfor   r   truncate_sentence_embeddingsr   r4   r   r   r   r   r   r   strr=   ranger5   r8   r>   minformatr    ospathjoinr?   isfileopencsvwriterwriterowr@   prefix_name_to_metrics store_metrics_in_model_card_data)rB   rL   rM   r+   r,   out_txt
pairs_list	n_extract	n_correctr0   best_f1best_recallbest_precisionr1   idxscoreijrE   rF   r-   r.   r/   csv_pathfrf   metricss                              r'   __call__z"ParaphraseMiningEvaluator.__call__   se    B;;{{1%11BuBBUBBBG(=):====Ge	ee[beeefff #/7[]]]U=_=_`d`q=r=r 
	 
	*&%&
	 	J
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 
	 	1CJ4H4HHIII !"!	I	1222+Z)) 	l 	lC$S/KE1a(1+C(1+C NIs#C( 
lDOC,@,E 
lQ	%	1	"T%>>]V+y6/AB!Y.!<< G%.N"(K!+C!3jS1WcR\oo`aNaAbAb6cde6f!fjk kI-0II/667H37NOOPPP/66yAABBB'..~/CDDEEE$++K#,=>>???N))'C-88999"t~"w||K??H7>>(++ x(BS7KKK xq Z]]FOOD$4555OOUE>;PWYbdu$vwwwx x x x x x x x x x x x x x x
 (BS7KKK xq Z]]FOOUE>;PWYbdu$vwwwx x x x x x x x x x x x x x x
 "3'!"
 
 --gtyAA--eW===s7   	:CCCAN33N7:N71PPPc                 6   t                      }t          |                                           D ]g}||vr_t                      }|                    |           t          | |                   }t	          |          dk    r\|                    d          }||vr0|                    |           |                    | |                    t	          |          dk    \t          |          }t          t	          |          dz
            D ]}t          |dz   t	          |                    D ]f}d| ||                  ||         <   d| ||                  ||         <   |                    ||                    |                    ||                    gi| S )Nr   rR   T)r9   listkeysr:   r=   popextendr]   )graphnodes_visitedrX   connected_subgraph_nodesneighbor_nodes_queuenoders   rt   s           r'   r   z0ParaphraseMiningEvaluator.add_transitive_closure   s   ejjll## 	G 	GA%%+.55((,,Q/// (,E!H~~$.//!33/33A66D#;;;044T:::,33E$K@@@	 .//!33 ,00H+I+I(s#;<<q@AA G GA"1q5#.F*G*GHH G GZ^6q9:;STU;VWZ^6q9:;STU;VW%))*B1*EFFF%))*B1*EFFFFG r&   )NNFr   r   r   r   Fr   r   TN)NrK   rK   )__name__
__module____qualname____doc__r   r\   r   r	   r$   intr   r3   floatrx   staticmethodr   __classcell__)rJ   s   @r'   r   r      s       + +` 266:', $!'"'&*]2 ]2CH~]2 eCHo.]2 c4T	?23	]2
 !%]2 ]2 ]2 ]2 ]2  ]2 ]2 ]2 ]2 sm]2 ]2 ]2 ]2 ]2 ]2@ dfU U*U9<ULOU]`U	c5j	U U U Un   \    r&   r   )re   loggingr`   collectionsr   
contextlibr   typingr   r   r   r   r	   2sentence_transformers.evaluation.SentenceEvaluatorr
   sentence_transformers.utilr   )sentence_transformers.SentenceTransformerr   	getLoggerr   rY   r   r%   r&   r'   <module>r      s    



  				 # # # # # # " " " " " " = = = = = = = = = = = = = = P P P P P P 8 8 8 8 8 8 NMMMMMM		8	$	$} } } } } 1 } } } } }r&   