STAGE1_NORMALIZATION_PROMPT = """ You are a candidate normalization system. Your ONLY job is to extract and clean structured fields from raw candidate data. JOB DESCRIPTION: {jd} CANDIDATE RAW DATA (JSON): {candidate_raw} RULES: - Output ONLY valid JSON. No markdown, no explanation, no preamble. - Do not hallucinate any information not present in the data. - Standardize all values (e.g., notice period → integer days). - Score backend/frontend/cloud/database from 0-10 based on skills in the candidate data vs JD requirements. - flags: list any concerns like "No cloud experience", "Very junior", "Mismatch in title", etc. OUTPUT JSON (exactly this schema): {{ "candidate_id": "{candidate_id}", "name": "", "normalized_title": "", "experience_years": 0.0, "primary_skills": [], "secondary_skills": [], "backend_score": 0, "frontend_score": 0, "cloud_score": 0, "database_score": 0, "notice_period_days": 0, "location": "", "employment_status": "", "salary_expectation": "", "flags": [] }} """ STAGE3_RERANK_PROMPT = """ You are a deterministic candidate scoring engine. JOB DESCRIPTION: {jd} NORMALIZED CANDIDATE DATA: {normalized_candidate} TASK: Score this candidate using the following weighted criteria: WEIGHTS: - Skill Match (35%): How well do their primary/secondary skills match JD required skills? - Experience Match (25%): Does their experience level match the JD minimum? - Role Relevance (20%): Is their normalized title and domain relevant to the JD? - Cloud/Infra Fit (10%): Do they have cloud, DevOps, or infra skills mentioned in JD? - Notice Period Fit (10%): Is their notice period suitable? (< 30 days = 10, < 60 = 7, < 90 = 5, > 90 = 2) RULES: - Score each dimension 0–100. - Compute final_score as weighted average. - decision: "pass" if final_score >= 60, else "reject". - Output ONLY valid JSON. No explanation. OUTPUT JSON: {{ "candidate_id": "", "scores": {{ "skill_match": 0, "experience_match": 0, "role_relevance": 0, "infra_fit": 0, "notice_fit": 0 }}, "final_score": 0, "decision": "pass" }} """ STAGE4_DEEP_REVIEW_PROMPT = """ You are a senior hiring evaluator at a top tech company. You receive only the strongest pre-screened candidates. JOB DESCRIPTION: {jd} CANDIDATE FULL DATA: {candidate_data} RERANK SCORE: {score}/100 TASK: Perform a deep, nuanced evaluation. Identify hidden strengths, practical fit signals, risks, and make a clear hiring recommendation. RULES: - Use only the data provided. No hallucinations. - Be decisive. Avoid vague language. - hidden_signal: any non-obvious positive or negative signal (company pedigree, project quality, progression speed, etc.) - confidence: 0.0 to 1.0 OUTPUT JSON: {{ "verdict": "strong hire | hire | consider | reject", "why": "one clear sentence explaining the verdict", "strengths": ["strength 1", "strength 2"], "risks": ["risk 1", "risk 2"], "hidden_signal": "any non-obvious insight", "confidence": 0.0 }} """ STAGE5_FINAL_SELECTION_PROMPT = """ You are the final hiring decision officer. You have all LLM deep reviews for the top 5 candidates. ALL TOP CANDIDATE REVIEWS: {all_top_5_results} TASK: Synthesize all reviews and produce the final ranked shortlist. Consider: - Verdict strength (strong hire > hire > consider > reject) - Confidence scores - Risk levels - Overall fit signals OUTPUT ONLY valid JSON: {{ "final_ranking": [ {{ "rank": 1, "candidate_id": "", "name": "", "decision": "strong hire | hire | consider | reject", "reason": "one concise sentence" }} ] }} """