2. 实现精确匹配评估器

任务目标

实现一个精确匹配(Exact Match, EM)评估器,用于判断模型输出与参考答案是否完全一致(忽略大小写与首尾空白),并计算一组样本上的精确匹配率。

核心实现

def exact_match_evaluator(predictions, references):
    """
    计算精确匹配率(EM)。
    
    参数:
        predictions: list[str],模型输出列表
        references:  list[str],参考答案列表
    
    返回:
        float: 精确匹配率,取值范围 [0.0, 1.0]
    """
    if len(predictions) != len(references):
        raise ValueError("predictions 和 references 长度必须一致")
    if len(predictions) == 0:
        return 0.0
    
    def normalize(text):
        # 去除首尾空白并统一为小写
        return text.strip().lower()
    
    correct = 0
    for pred, ref in zip(predictions, references):
        if normalize(pred) == normalize(ref):
            correct += 1
    
    return correct / len(predictions)

# 最小调用示例
if __name__ == "__main__":
    preds = ["Paris", "paris ", "London", "Berlin"]
    refs  = ["Paris", "Paris", "London", "Rome"]
    
    em_score = exact_match_evaluator(preds, refs)
    print(f"EM Score: {em_score:.2f}")

运行与验证

运行方式:将上述代码保存为 exact_match.py,在终端执行:

python exact_match.py

预期输出:

EM Score: 0.75

判定标准:

  • 第1组 "Paris" vs "Paris":完全一致,匹配 ✓
  • 第2组 "paris " vs "Paris":忽略大小写和首尾空白后一致,匹配 ✓
  • 第3组 "London" vs "London":完全一致,匹配 ✓
  • 第4组 "Berlin" vs "Rome":不一致,不匹配 ✗

因此 4 组中匹配 3 组,EM = 3/4 = 0.75。若输出与此一致,则评估器实现正确。

边界情况说明

  • 输入为空列表时返回 0.0,避免除零错误。
  • 两个列表长度不一致时抛出 ValueError,防止静默错位比较。
  • 归一化仅处理大小写和首尾空白,不处理内部多余空格或标点——如需更宽松的匹配,可在此基础上扩展。