1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
| import numpy as np from rouge_score import rouge_scorer from bert_score import score as bert_score from typing import Dict, List, Tuple import difflib
class MeetingMinutesEvaluator: def __init__(self): self.rouge_scorer = rouge_scorer.RougeScorer( ['rouge1', 'rouge2', 'rougeL'], use_stemmer=True )
def evaluate_summary( self, predicted: str, reference: str ) -> Dict[str, float]: """评估摘要质量"""
rouge_scores = self.rouge_scorer.score(reference, predicted)
P, R, F1 = bert_score( [predicted], [reference], lang="zh", verbose=False )
return { "rouge1_f1": rouge_scores['rouge1'].fmeasure, "rouge2_f1": rouge_scores['rouge2'].fmeasure, "rougeL_f1": rouge_scores['rougeL'].fmeasure, "bert_score_f1": F1.item(), "combined_score": ( rouge_scores['rougeL'].fmeasure * 0.4 + F1.item() * 0.6 ) }
def evaluate_key_points( self, predicted: List[str], reference: List[str] ) -> Dict[str, float]: """评估关键要点提取"""
matched_count = 0 total_similarity = 0.0
for ref_point in reference: best_match_score = 0.0 for pred_point in predicted: similarity = difflib.SequenceMatcher( None, ref_point, pred_point ).ratio() best_match_score = max(best_match_score, similarity)
if best_match_score > 0.6: matched_count += 1 total_similarity += best_match_score
recall = matched_count / len(reference) if reference else 0 precision = matched_count / len(predicted) if predicted else 0 f1 = ( 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0 )
return { "precision": precision, "recall": recall, "f1_score": f1, "avg_similarity": total_similarity / len(reference) if reference else 0 }
def evaluate_action_items( self, predicted: List[ActionItem], reference: List[ActionItem] ) -> Dict[str, float]: """评估行动项识别"""
pred_descriptions = [item.description for item in predicted] ref_descriptions = [item.description for item in reference]
base_score = self.evaluate_key_points( pred_descriptions, ref_descriptions )
structure_scores = [] for pred_item in predicted: best_match = None best_similarity = 0
for ref_item in reference: sim = difflib.SequenceMatcher( None, pred_item.description, ref_item.description ).ratio() if sim > best_similarity: best_similarity = sim best_match = ref_item
if best_match and best_similarity > 0.6: assignee_match = pred_item.assignee == best_match.assignee priority_match = pred_item.priority == best_match.priority structure_scores.append( (assignee_match + priority_match) / 2 )
structure_accuracy = ( np.mean(structure_scores) if structure_scores else 0 )
return { **base_score, "structure_accuracy": structure_accuracy, "weighted_f1": base_score['f1_score'] * 0.7 + structure_accuracy * 0.3 }
def evaluate_full_output( self, predicted: GroundTruth, reference: GroundTruth ) -> Dict[str, any]: """完整评估"""
results = { "meeting_id": reference.meeting_id, "summary_scores": self.evaluate_summary( predicted.summary, reference.summary ), "key_points_scores": self.evaluate_key_points( predicted.key_points, reference.key_points ), "action_items_scores": self.evaluate_action_items( predicted.action_items, reference.action_items ) }
results["overall_score"] = ( results["summary_scores"]["combined_score"] * 0.30 + results["key_points_scores"]["f1_score"] * 0.35 + results["action_items_scores"]["weighted_f1"] * 0.35 )
return results
|