VALID_ROLES = [ "Frontend Developer", "Backend Developer", "Full Stack Developer", "AI/ML Engineer", "Data Scientist", "Data Analyst", "Data Engineer", "Unknown", ] VALID_LEVELS = [ "Fresh", "Junior", "Senior", ] ROLE_KEYWORDS = { "Frontend Developer": [ "frontend", "front-end", "react", "next.js", "nextjs", "vue", "angular", "javascript", "typescript", "html", "css", ], "Backend Developer": [ "backend", "back-end", "api", "node.js", "nodejs", "express", "fastapi", "django", "flask", "spring", "laravel", "postgresql", "mysql", ], "Full Stack Developer": [ "full stack", "fullstack", "mern", "mean", "react", "node.js", "express", "mongodb", ], "AI/ML Engineer": [ "machine learning", "ml engineer", "artificial intelligence", "ai engineer", "deep learning", "tensorflow", "pytorch", "llm", "nlp", "computer vision", ], "Data Scientist": [ "data scientist", "predictive modeling", "feature engineering", "statistics", "scikit-learn", ], "Data Analyst": [ "data analyst", "power bi", "tableau", "excel", "dashboard", "reporting", "sql", ], "Data Engineer": [ "data engineer", "etl", "elt", "data pipeline", "airflow", "spark", "hadoop", "warehouse", ], } def map_role(raw_role): """ Map extracted role text into one of supported system roles. """ if not raw_role: return "Unknown" role = str(raw_role).lower() for canonical_role, keywords in ROLE_KEYWORDS.items(): if any(keyword in role for keyword in keywords): return canonical_role return "Unknown" def infer_role_from_skills(skills, current_role=""): """ Infer the most likely supported role from title and detected skills. """ mapped_role = map_role(current_role) if mapped_role != "Unknown": return mapped_role if not isinstance(skills, list): return "Unknown" skill_text = " ".join(str(skill).lower() for skill in skills) scores = {role: 0 for role in ROLE_KEYWORDS} for role, keywords in ROLE_KEYWORDS.items(): for keyword in keywords: if keyword in skill_text: scores[role] += 1 best_role = max(scores, key=scores.get) return best_role if scores[best_role] > 0 else "Unknown" def normalize_level(level, years_of_experience=0): """ Normalize the experience level to supported buckets. """ if isinstance(level, str): lowered = level.strip().lower() if lowered in {"fresh", "fresher", "intern", "entry", "entry-level"}: return "Fresh" if lowered in {"junior", "jr", "mid", "associate"}: return "Junior" if lowered in {"senior", "sr", "lead", "principal"}: return "Senior" if years_of_experience >= 3: return "Senior" if years_of_experience >= 1: return "Junior" return "Fresh"