1616
1717
1818class BleuScore (TypedDict ):
19- """BLEU score"""
19+ """BLEU score components returned by :func:`bleu_score`. """
2020
2121 bleu : float # BLEU score as a percentage (0.0 to 100.0)
2222 precisions : list [float ]
@@ -26,6 +26,14 @@ class BleuScore(TypedDict):
2626 ref_length : int
2727
2828
29+ class RougeScore (TypedDict ):
30+ """Precision, recall, and F-measure for a single ROUGE type."""
31+
32+ precision : float
33+ recall : float
34+ fmeasure : float
35+
36+
2937def _get_ngrams (tokens : list [str ], n : int ) -> list [tuple [str , ...]]:
3038 """
3139 Get n-grams from a list of tokens.
@@ -249,7 +257,7 @@ def rouge_score(
249257 hypothesis : str ,
250258 tokenize : str = "newmm" ,
251259 rouge_types : Optional [list [str ]] = None ,
252- ) -> dict [str , tuple [ float , float , float ] ]:
260+ ) -> dict [str , RougeScore ]:
253261 """
254262 Calculate ROUGE scores for Thai text with automatic tokenization.
255263
@@ -269,8 +277,9 @@ def rouge_score(
269277 :param Optional[list[str]] rouge_types: list of ROUGE types to calculate.
270278 Default is ["rouge1", "rouge2", "rougeL"]
271279
272- :return: dictionary mapping ROUGE type to (precision, recall, fmeasure)
273- :rtype: dict[str, tuple[float, float, float]]
280+ :return: dictionary mapping ROUGE type to a :class:`RougeScore` typed dict
281+ with ``'precision'``, ``'recall'``, and ``'fmeasure'`` keys.
282+ :rtype: dict[str, RougeScore]
274283
275284 :Example:
276285 ::
@@ -280,9 +289,9 @@ def rouge_score(
280289 reference = "สวัสดีครับ วันนี้อากาศดีมาก"
281290 hypothesis = "สวัสดีค่ะ วันนี้อากาศดี"
282291 scores = rouge_score(reference, hypothesis)
283- print(f"ROUGE-1 F-measure: {scores['rouge1'][2 ]:.4f}")
284- print(f"ROUGE-2 F-measure: {scores['rouge2'][2 ]:.4f}")
285- print(f"ROUGE-L F-measure: {scores['rougeL'][2 ]:.4f}")
292+ print(f"ROUGE-1 F-measure: {scores['rouge1']['fmeasure' ]:.4f}")
293+ print(f"ROUGE-2 F-measure: {scores['rouge2']['fmeasure' ]:.4f}")
294+ print(f"ROUGE-L F-measure: {scores['rougeL']['fmeasure' ]:.4f}")
286295 """
287296 from pythainlp .tokenize import word_tokenize
288297
@@ -297,7 +306,7 @@ def rouge_score(
297306 hypothesis , engine = tokenize , keep_whitespace = False
298307 )
299308
300- result : dict [str , tuple [ float , float , float ] ] = {}
309+ result : dict [str , RougeScore ] = {}
301310
302311 for rouge_type in rouge_types :
303312 if rouge_type == "rouge1" :
@@ -309,9 +318,12 @@ def rouge_score(
309318 ref_count = len (ref_tokens )
310319 hyp_count = len (hyp_tokens )
311320
312- result [ rouge_type ] = _calculate_precision_recall_fmeasure (
321+ precision , recall , fmeasure = _calculate_precision_recall_fmeasure (
313322 overlap , hyp_count , ref_count
314323 )
324+ result [rouge_type ] = RougeScore (
325+ precision = precision , recall = recall , fmeasure = fmeasure
326+ )
315327
316328 elif rouge_type == "rouge2" :
317329 # Bigram-based
@@ -325,19 +337,25 @@ def rouge_score(
325337 ref_count = len (ref_bigrams )
326338 hyp_count = len (hyp_bigrams )
327339
328- result [ rouge_type ] = _calculate_precision_recall_fmeasure (
340+ precision , recall , fmeasure = _calculate_precision_recall_fmeasure (
329341 overlap , hyp_count , ref_count
330342 )
343+ result [rouge_type ] = RougeScore (
344+ precision = precision , recall = recall , fmeasure = fmeasure
345+ )
331346
332347 elif rouge_type == "rougeL" :
333348 # Longest Common Subsequence-based
334349 lcs_len = _lcs_length (ref_tokens , hyp_tokens )
335350 ref_count = len (ref_tokens )
336351 hyp_count = len (hyp_tokens )
337352
338- result [ rouge_type ] = _calculate_precision_recall_fmeasure (
353+ precision , recall , fmeasure = _calculate_precision_recall_fmeasure (
339354 lcs_len , hyp_count , ref_count
340355 )
356+ result [rouge_type ] = RougeScore (
357+ precision = precision , recall = recall , fmeasure = fmeasure
358+ )
341359
342360 return result
343361
0 commit comments