Spaces:
Runtime error
Runtime error
Download backend/services/learning_predictor.py from hemish22/hiresense-api: direct link, hf CLI and curl.
- Browser
- Download file 7 kB
-
https://huggingface.co/spaces/hemish22/hiresense-api/resolve/main/backend/services/learning_predictor.py
- Command line
-
hf download hf://spaces/hemish22/hiresense-api/backend/services/learning_predictor.py
-
curl -L -o learning_predictor.py https://huggingface.co/spaces/hemish22/hiresense-api/resolve/main/backend/services/learning_predictor.py
7 kB
| """ | |
| HireSense AI — Learning Ability Predictor | |
| Estimates how quickly a candidate can learn missing skills. | |
| """ | |
| from backend.services.skill_dictionary import get_skill_category, SKILL_CATEGORIES | |
| class LearningPredictor: | |
| """Predicts learning ability based on skill graph and activity patterns.""" | |
| def predict( | |
| self, | |
| candidate_skills: list[str], | |
| missing_skills: list[str], | |
| github_data: dict = None, | |
| leetcode_data: dict = None, | |
| ) -> dict: | |
| """ | |
| Predict learning ability and time-to-learn for missing skills. | |
| """ | |
| if not missing_skills: | |
| return { | |
| "learning_score": 95.0, | |
| "predictions": [], | |
| "factors": { | |
| "base_score": 50, | |
| "skill_breadth_bonus": 20, | |
| "consistency_bonus": 15, | |
| "problem_solving_bonus": 10, | |
| }, | |
| "explanation": "Candidate already has all required skills. Excellent readiness.", | |
| } | |
| # Per-skill predictions | |
| predictions = [] | |
| for skill in missing_skills: | |
| pred = self._estimate_learning_time(skill, candidate_skills) | |
| predictions.append(pred) | |
| # Calculate factor bonuses | |
| factors = self._calculate_factors(candidate_skills, github_data, leetcode_data) | |
| # Overall learning score | |
| learning_score = self._calculate_learning_score(predictions, factors) | |
| explanation = self._generate_explanation(learning_score, predictions, factors) | |
| return { | |
| "learning_score": round(learning_score, 1), | |
| "predictions": predictions, | |
| "factors": factors, | |
| "explanation": explanation, | |
| } | |
| def _estimate_learning_time(self, skill: str, existing_skills: list[str]) -> dict: | |
| """Estimate learning time for a specific skill.""" | |
| target_category = get_skill_category(skill) | |
| # Count existing skills in the same category | |
| related = [s for s in existing_skills if get_skill_category(s) == target_category] | |
| if len(related) >= 3: | |
| months = 1.5 | |
| confidence = "high" | |
| reason = ( | |
| f"Already proficient in {len(related)} skills in '{target_category}' " | |
| f"({', '.join(related[:3])}). Transfer learning will be fast." | |
| ) | |
| elif len(related) >= 1: | |
| months = 3.0 | |
| confidence = "medium" | |
| reason = ( | |
| f"Has {len(related)} related skill(s) in '{target_category}' " | |
| f"({', '.join(related)}). Foundation exists to build upon." | |
| ) | |
| else: | |
| # Check cross-category transfers | |
| unique_categories = set(get_skill_category(s) for s in existing_skills) | |
| if len(unique_categories) >= 4: | |
| months = 4.0 | |
| confidence = "medium" | |
| reason = ( | |
| f"No direct '{target_category}' experience, but has skills across " | |
| f"{len(unique_categories)} categories — demonstrated versatility suggests adaptability." | |
| ) | |
| else: | |
| months = 6.0 | |
| confidence = "low" | |
| reason = ( | |
| f"No experience in '{target_category}' and limited breadth. " | |
| f"Will require structured learning and mentorship." | |
| ) | |
| return { | |
| "skill": skill, | |
| "estimated_months": months, | |
| "confidence": confidence, | |
| "reason": reason, | |
| "related_existing": related[:5], | |
| } | |
| def _calculate_factors( | |
| self, | |
| candidate_skills: list[str], | |
| github_data: dict = None, | |
| leetcode_data: dict = None, | |
| ) -> dict: | |
| """Calculate bonus factors for learning score.""" | |
| # Skill breadth bonus | |
| unique_categories = set(get_skill_category(s) for s in candidate_skills) | |
| skill_breadth_bonus = min(20, len(unique_categories) * 4) | |
| # GitHub consistency bonus | |
| consistency_bonus = 0 | |
| if github_data: | |
| gh_scores = github_data.get("scores", {}) | |
| consistency = gh_scores.get("consistency", 0) | |
| if consistency >= 70: | |
| consistency_bonus = 15 | |
| elif consistency >= 40: | |
| consistency_bonus = 8 | |
| # LeetCode problem-solving bonus | |
| problem_solving_bonus = 0 | |
| if leetcode_data: | |
| lc_scores = leetcode_data.get("scores", {}) | |
| lc_overall = lc_scores.get("overall", 0) | |
| if lc_overall >= 70: | |
| problem_solving_bonus = 15 | |
| elif lc_overall >= 40: | |
| problem_solving_bonus = 8 | |
| return { | |
| "base_score": 50, | |
| "skill_breadth_bonus": skill_breadth_bonus, | |
| "consistency_bonus": consistency_bonus, | |
| "problem_solving_bonus": problem_solving_bonus, | |
| } | |
| def _calculate_learning_score(self, predictions: list, factors: dict) -> float: | |
| """Calculate the overall learning ability score.""" | |
| score = factors["base_score"] | |
| score += factors["skill_breadth_bonus"] | |
| score += factors["consistency_bonus"] | |
| score += factors["problem_solving_bonus"] | |
| # Penalty for hard-to-learn skills | |
| for pred in predictions: | |
| if pred["estimated_months"] > 4: | |
| score -= 5 | |
| elif pred["estimated_months"] > 2: | |
| score -= 2 | |
| return max(0, min(100, score)) | |
| def _generate_explanation( | |
| self, score: float, predictions: list, factors: dict | |
| ) -> str: | |
| """Generate human-readable learning ability explanation.""" | |
| if score >= 80: | |
| verdict = "High learning potential" | |
| elif score >= 60: | |
| verdict = "Good learning potential" | |
| elif score >= 40: | |
| verdict = "Moderate learning potential" | |
| else: | |
| verdict = "Learning may be challenging" | |
| fast = [p for p in predictions if p["estimated_months"] <= 2] | |
| slow = [p for p in predictions if p["estimated_months"] > 4] | |
| parts = [f"{verdict} ({score:.0f}/100)."] | |
| if fast: | |
| parts.append( | |
| f"Can quickly pick up: {', '.join(p['skill'] for p in fast)}." | |
| ) | |
| if slow: | |
| parts.append( | |
| f"Will need more time for: {', '.join(p['skill'] for p in slow)}." | |
| ) | |
| bonuses = [] | |
| if factors["consistency_bonus"] > 0: | |
| bonuses.append("consistent GitHub activity") | |
| if factors["problem_solving_bonus"] > 0: | |
| bonuses.append("strong problem-solving skills") | |
| if factors["skill_breadth_bonus"] >= 16: | |
| bonuses.append("diverse skill set") | |
| if bonuses: | |
| parts.append(f"Positive signals: {', '.join(bonuses)}.") | |
| return " ".join(parts) | |