Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from src.core.config import get_scoring_config | |
| from src.core.models import MatchScores | |
| from src.matching.confidence import compute_confidence | |
| DIM_TO_ACTUAL: dict[str, str] = { | |
| "skill_match": "skill_match", | |
| "experience_match": "experience_match", | |
| "education_match": "education_match", | |
| "assessment_score": "cross_encoder_score", | |
| "behavioral_signals": "behavioral_score", | |
| "cultural_fit": "semantic_similarity", | |
| } | |
| DEFAULT_SLIDER_WEIGHTS: dict[str, float] = { | |
| "skill_match": 0.25, | |
| "experience_match": 0.20, | |
| "education_match": 0.10, | |
| "assessment_score": 0.15, | |
| "behavioral_signals": 0.20, | |
| "cultural_fit": 0.10, | |
| } | |
| # All known match-score dimension names that CandidateScorer can consume. | |
| _ALL_DIMS = [ | |
| "semantic_similarity", | |
| "keyword_match", | |
| "skill_match", | |
| "experience_match", | |
| "location_match", | |
| "education_match", | |
| "cross_encoder_score", | |
| "behavioral_score", | |
| "career_trajectory_score", | |
| "skill_proficiency_score", | |
| "behavioral_signals", | |
| "cultural_fit", | |
| ] | |
| class CandidateScorer: | |
| def __init__(self) -> None: | |
| config = get_scoring_config() | |
| self.weights = config["scoring_weights"] | |
| self.slider_defaults = config.get("slider_weights", DEFAULT_SLIDER_WEIGHTS) | |
| def compute_overall( | |
| self, | |
| scores: dict[str, float | None], | |
| slider_weights: dict[str, float] | None = None, | |
| ) -> MatchScores: | |
| total_weight = 0.0 | |
| weighted_sum = 0.0 | |
| components: dict[str, float | None] = {} | |
| effective_weights: dict[str, float] = {} | |
| if slider_weights: | |
| for slider_dim, actual_dim in DIM_TO_ACTUAL.items(): | |
| if slider_dim in slider_weights and slider_weights[slider_dim] > 0: | |
| effective_weights[actual_dim] = slider_weights[slider_dim] / 100.0 | |
| for dim, w in self.slider_defaults.items(): | |
| actual = DIM_TO_ACTUAL.get(dim, dim) | |
| if actual not in effective_weights: | |
| effective_weights[actual] = w | |
| else: | |
| effective_weights = dict(self.weights) | |
| for dim in _ALL_DIMS: | |
| score = scores.get(dim) | |
| if score is not None: | |
| weight = effective_weights.get(dim, 0.0) | |
| total_weight += weight | |
| weighted_sum += weight * score | |
| components[dim] = score | |
| overall = weighted_sum / total_weight if total_weight > 0 else 0.0 | |
| overall = max(0.0, min(1.0, overall)) | |
| confidence = compute_confidence({k: v for k, v in components.items() if v is not None}) | |
| return MatchScores( | |
| overall=overall, | |
| semantic_similarity=components.get("semantic_similarity", 0.0) or 0.0, | |
| keyword_match=components.get("keyword_match", 0.0) or 0.0, | |
| skill_match=components.get("skill_match", 0.0) or 0.0, | |
| experience_match=components.get("experience_match", 0.0) or 0.0, | |
| location_match=components.get("location_match"), | |
| education_match=components.get("education_match"), | |
| cross_encoder_score=components.get("cross_encoder_score"), | |
| behavioral_score=components.get("behavioral_score"), | |
| career_trajectory_score=components.get("career_trajectory_score"), | |
| skill_proficiency_score=components.get("skill_proficiency_score"), | |
| confidence=confidence, | |
| ) | |