codekingpro/portable-devtools
114k
1from typing import Any, Callable, Literal, Optional2 3from typing_extensions import TypedDict4 5METRICS = Literal[6 "damerau_levenshtein",7 "levenshtein",8 "jaro",9 "jaro_winkler",10 "hamming",11 "indel",12]13 14 15class EditDistanceConfig(TypedDict, total=False):16 metric: METRICS17 normalize_score: bool18 19 20class EditDistance:21 def __init__(22 self,23 config: Optional[EditDistanceConfig] = None,24 ):25 config = config or {}26 metric = config.get("metric") or "damerau_levenshtein"27 self.metric = self._get_metric(28 metric, normalize_score=config.get("normalize_score", True)29 )30 31 def evaluate(32 self,33 prediction: str,34 reference: Optional[str] = None,35 ) -> float:36 return self.metric(prediction, reference)37 38 @staticmethod39 def _get_metric(distance: str, normalize_score: bool = True) -> Callable:40 try:41 from rapidfuzz import ( # type: ignore[import-not-found]42 distance as rf_distance,43 )44 except ImportError:45 raise ImportError(46 "This operation requires the rapidfuzz library to use."47 "Please install it with `pip install -U rapidfuzz`."48 )49 50 module_map: dict[str, Any] = {51 "damerau_levenshtein": rf_distance.DamerauLevenshtein,52 "levenshtein": rf_distance.Levenshtein,53 "jaro": rf_distance.Jaro,54 "jaro_winkler": rf_distance.JaroWinkler,55 "hamming": rf_distance.Hamming,56 "indel": rf_distance.Indel,57 }58 if distance not in module_map:59 raise ValueError(60 f"Invalid distance metric: {distance}"61 f"\nMust be one of: {list(module_map)}"62 )63 module = module_map[distance]64 if normalize_score:65 return module.normalized_distance66 else:67 return module.distance68 