Spaces:
Build error
Build error
| import json | |
| import logging | |
| from agents import function_tool | |
| logger = logging.getLogger(__name__) | |
| async def extract_resume_info(resume_text: str) -> str: | |
| """ | |
| Extract structured information from raw resume text. | |
| Returns a JSON string with candidate name, skills, experience years, | |
| education level, and certifications. | |
| """ | |
| result = { | |
| "candidate_name": "Unknown", | |
| "skills": [], | |
| "experience_years": 0, | |
| "education": "Unknown", | |
| "certifications": [] | |
| } | |
| logger.debug("extract_resume_info called with %d chars of resume text", len(resume_text)) | |
| return json.dumps(result) | |
| async def match_skills(resume_skills: str, required_skills: str) -> str: | |
| """ | |
| Compare resume skills against required job skills. | |
| Args: | |
| resume_skills: comma-separated list of skills found in the resume | |
| required_skills: comma-separated list of skills required for the job | |
| Returns: | |
| JSON string with matched_skills, missing_skills, and match_percentage | |
| """ | |
| resume_set = {s.strip().lower() for s in resume_skills.split(",") if s.strip()} | |
| required_set = {s.strip().lower() for s in required_skills.split(",") if s.strip()} | |
| if not required_set: | |
| return json.dumps({ | |
| "matched_skills": [], | |
| "missing_skills": [], | |
| "match_percentage": 0.0 | |
| }) | |
| matched = sorted(resume_set & required_set) | |
| missing = sorted(required_set - resume_set) | |
| match_percentage = round((len(matched) / len(required_set)) * 100, 2) | |
| result = { | |
| "matched_skills": matched, | |
| "missing_skills": missing, | |
| "match_percentage": match_percentage | |
| } | |
| logger.debug("match_skills: %d/%d matched (%.1f%%)", len(matched), len(required_set), match_percentage) | |
| return json.dumps(result) | |
| async def calculate_ats_score( | |
| skill_match_percentage: float, | |
| experience_years_candidate: int, | |
| experience_years_required: int, | |
| education_level: str, | |
| resume_quality: str | |
| ) -> str: | |
| """ | |
| Calculate ATS score (0–100) based on multiple criteria. | |
| """ | |
| skill_match_percentage = max(0.0, min(100.0, float(skill_match_percentage))) | |
| skill_score = round(50 * skill_match_percentage / 100, 2) | |
| if experience_years_candidate >= experience_years_required: | |
| experience_score = 25 | |
| elif experience_years_required > 0 and experience_years_candidate >= experience_years_required / 2: | |
| experience_score = 12 | |
| else: | |
| experience_score = 0 | |
| education_map = { | |
| "phd": 15, "masters": 15, "master": 15, | |
| "bachelors": 12, "bachelor": 12, "diploma": 8, | |
| } | |
| education_score = education_map.get(education_level.strip().lower(), 4) | |
| quality_map = {"good": 10, "average": 6, "poor": 2} | |
| quality_score = quality_map.get(resume_quality.strip().lower(), 6) | |
| ats_score = round(skill_score + experience_score + education_score + quality_score, 2) | |
| ats_score = max(0, min(100, ats_score)) | |
| result = { | |
| "ats_score": ats_score, | |
| "breakdown": { | |
| "skill_score": skill_score, | |
| "experience_score": experience_score, | |
| "education_score": education_score, | |
| "quality_score": quality_score | |
| } | |
| } | |
| logger.debug("calculate_ats_score: total=%.2f", ats_score) | |
| return json.dumps(result) | |
| async def make_decision( | |
| ats_score: int, | |
| candidate_name: str, | |
| missing_skills: str, | |
| job_title: str | |
| ) -> str: | |
| """ | |
| Make a hiring decision based on ATS score. | |
| """ | |
| missing_list = [s.strip() for s in missing_skills.split(",") if s.strip()] | |
| if ats_score >= 70: | |
| status = "selected" | |
| recommendation_message = ( | |
| f"Congratulations, {candidate_name}! Your profile is a strong match for the " | |
| f"{job_title} position. Our recruitment team will be in touch with next steps shortly." | |
| ) | |
| else: | |
| status = "rejected" | |
| if missing_list: | |
| skills_str = ", ".join(missing_list) | |
| recommendation_message = ( | |
| f"Thank you for applying, {candidate_name}. Unfortunately your profile did not meet " | |
| f"the minimum requirements for the {job_title} role at this time. " | |
| f"We recommend strengthening the following areas: {skills_str}." | |
| ) | |
| else: | |
| recommendation_message = ( | |
| f"Thank you for applying, {candidate_name}. Unfortunately your profile did not meet " | |
| f"the minimum requirements for the {job_title} role at this time." | |
| ) | |
| result = { | |
| "status": status, | |
| "ats_score": ats_score, | |
| "missing_skills": missing_list, | |
| "recommendation_message": recommendation_message | |
| } | |
| logger.debug("make_decision: %s (score=%d)", status, ats_score) | |
| return json.dumps(result) | |