Source code for lalandre_rag.scoring

"""Shared score helpers and source score contract."""

import math
from typing import Any, Dict

SCORE_SCALE_NORMALIZED_0_1 = "normalized_0_1"
SCORE_SCALE_BINARY_EVIDENCE = "binary_evidence"

SCORE_KIND_RELEVANCE = "relevance"
SCORE_KIND_EVIDENCE = "evidence"


[docs] def coerce_finite_float(value: Any) -> float | None: """Return a finite float when possible, otherwise ``None``.""" try: result = float(value) except (TypeError, ValueError): return None if not math.isfinite(result): return None return result
[docs] def clamp_unit_interval(value: Any, *, default: float = 0.0) -> float: """Clamp a value to the normalized 0..1 range.""" result = coerce_finite_float(value) if result is None: return default return max(0.0, min(1.0, result))
[docs] def non_negative(value: Any, *, default: float = 0.0) -> float: """Clamp a value to the non-negative range.""" result = coerce_finite_float(value) if result is None: return default return max(0.0, result)
[docs] def normalize_by_max(value: Any, max_value: Any, *, default: float = 0.0) -> float: """Normalize a non-negative value by a positive maximum.""" denominator = non_negative(max_value, default=1.0) if denominator <= 0.0: return default return clamp_unit_interval(non_negative(value) / denominator, default=default)
[docs] def round_score(value: Any, digits: int = 4) -> float: """Round a finite score after clamping it to a numeric value.""" result = coerce_finite_float(value) if result is None: return 0.0 return round(result, digits)
[docs] def build_relevance_score_payload( score: Any, *, rank_score: Any | None = None, ) -> Dict[str, Any]: """Build a normalized relevance score payload for user-facing sources.""" normalized_score = clamp_unit_interval(score) normalized_rank = normalized_score if rank_score is None else clamp_unit_interval(rank_score) return { "score": normalized_score, "rank_score": normalized_rank, "score_kind": SCORE_KIND_RELEVANCE, "score_scale": SCORE_SCALE_NORMALIZED_0_1, }
[docs] def build_evidence_score_payload() -> Dict[str, str]: """Build a payload for tangible but non-scored evidence.""" return { "score_kind": SCORE_KIND_EVIDENCE, "score_scale": SCORE_SCALE_BINARY_EVIDENCE, }