File size: 2,959 Bytes
35709fb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

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
        }