import os import json import numpy as np from typing import List, Dict, Any from google import genai import google.genai.types as types from src.embeddings.local_embedder import generate_embedding, generate_list_embedding, get_model # Initialize Gemini Client client = genai.Client(api_key="AIzaSyB2Dw-nep3SwQav5S_1qJ2FoVc4I83a2yk") def cosine_similarity(v1, v2): v1 = np.array(v1) v2 = np.array(v2) return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)) def identify_missing_skills(job_skills: List[str], profile_skills: List[str], threshold: float = 0.7) -> List[str]: """ Identifies skills required by the job but missing (semantically) in the profile. """ if not job_skills: return [] if not profile_skills: return job_skills # Generate embeddings for profile skills model = get_model() profile_embeddings = model.encode(profile_skills, normalize_embeddings=True) job_embeddings = model.encode(job_skills, normalize_embeddings=True) missing_skills = [] for i, job_skill in enumerate(job_skills): job_vec = job_embeddings[i] # Find max similarity with any profile skill similarities = [np.dot(job_vec, prof_vec) for prof_vec in profile_embeddings] max_sim = max(similarities) if similarities else 0 if max_sim < threshold: missing_skills.append(job_skill) return missing_skills def generate_ai_analysis(profile_text: str, job_description: str) -> Dict[str, Any]: """ Uses Gemini to generate a professional summary and evaluation. """ system_prompt = """ You are an expert HR Analyst. Analyze the provided candidate resume text against the job description. Return a JSON object with: - "summary": A 2-3 sentence professional summary of why the candidate is or isn't a good fit. - "strengths": A list of top 3 core strengths matching the job. - "weaknesses": A list of top 2-3 areas for improvement or missing qualifications. - "score": An overall suitability score from 0 to 100 based on their experience and skills relative to the job requirements. Be objective, professional, and concise. """ user_content = f"JOB DESCRIPTION:\n{job_description}\n\nCANDIDATE RESUME:\n{profile_text}" try: response = client.models.generate_content( model="gemini-2.5-flash-lite", # Updated to confirmed model name contents=system_prompt + "\n\n" + user_content, config=types.GenerateContentConfig( temperature=0.2, response_mime_type="application/json" ) ) return json.loads(response.text) except Exception as e: print(f"❌ AI Analysis failed: {e}") return { "summary": "Analysis currently unavailable.", "strengths": [], "weaknesses": [], "score": 0 }