File size: 6,731 Bytes
90c9164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import streamlit as st
import os
import re
from groq import Groq
import json

# Set up Groq client
client = Groq(api_key="")

# Define main function
def main():
    st.title("AI-powered Resume Scanner")

    # File upload
    uploaded_file = st.file_uploader("Upload a resume", type=["pdf", "docx"])

    # Job role input
    job_role = st.text_input("Enter the job role")

    if uploaded_file is not None and job_role:
        # Process resume and get results
        resume_text = parse_resume(uploaded_file)
        if resume_text:
            #st.write("Extracted Resume Text:")
            #st.write(resume_text)

            # Get resume analysis from the Groq model
            name, degree, cgpa, skills, experience_score, ats_score = analyze_resume(resume_text, job_role)

            # Display the results
            st.write(f"**Candidate Name:** {name}")
            st.write(f"**Degree:** {degree}")
            st.write(f"**Latest CGPA/Percentage:** {cgpa}")
            if skills:
                st.write("**Skills:**")
                for skill in skills:
                    st.write(f"- {skill}")
            st.write(f"**Experience Score out of 10:** {experience_score}")
            st.write(f"**ATS Score for {job_role} out of 10:** {ats_score}")

# Function to parse PDF/Word file
def parse_resume(uploaded_file):
    # If PDF
    if uploaded_file.type == "application/pdf":
        from PyPDF2 import PdfReader
        reader = PdfReader(uploaded_file)
        text = ""
        for page in reader.pages:
            text += page.extract_text()
        return text
    # If Word
    elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
        from docx import Document
        doc = Document(uploaded_file)
        text = "\n".join([para.text for para in doc.paragraphs])
        return text
    else:
        st.error("Unsupported file type!")
        return None

# Function to analyze resume using Groq API and LLaMA 3.1
# Function to analyze resume using Groq API and LLaMA 3.1
import json

# Function to analyze resume using Groq API and LLaMA 3.1
def analyze_resume(text, job_role):
    # Construct prompt for Groq API
    prompt = (
        f"Extract the following details from the given resume text: \n"
        f"1. Candidate's Name \n"
        f"2. Latest Education CGPA or Percentage \n"
        f"3. List of Skills \n"
        f"4. Rate experience (projects, internships) on a scale from 0 to 10 \n"
        f"5. Provide an ATS score for the job role: {job_role}\n"
        f"Resume Text: {text}\n"
        f"Format your response in a JSON object with the following structure: \n"
        f"{{\n"
        f'  "name": "Candidate Name",\n'
        f'  "Degree": "Latest Education qualification or grade:",\n'
        f'  "cgpa": "Latest Education CGPA or Percentage",\n'
        f'  "skills": ["List of skills"],\n'
        f'  "experience_score": "Experience Score (0 to 10)",\n'
        f'  "ats_score": "ATS Score for the job role"\n'
        f"}}"
    )

    # Call Groq API for chat completion
    chat_completion = client.chat.completions.create(
        messages=[{"role": "user", "content": prompt}],
        model="llama3-8b-8192",
        temperature=0.7,
        max_tokens=1024,
        top_p=1,
        stream=False
    )

    # Get the raw output from the LLM
    output = chat_completion.choices[0].message.content
    # Clean up the output to avoid any parsing issues
    cleaned_output = re.search(r'{[^}]*}', output).group()
    # Try parsing the cleaned JSON
    try:
        response_data = json.loads(cleaned_output)
    except json.JSONDecodeError:
        st.error("Failed to parse response from model.")
        st.write("Model Output:")
        st.write(cleaned_output)
        return None, None, None, None, None

    # Extract information from the parsed JSON
    name = response_data.get("name", "Name not found")
    degree = response_data.get("Degree", "Degree not found")
    cgpa = response_data.get("cgpa", "CGPA/Percentage not found")
    skills = response_data.get("skills", "Skills not found")
    experience_score = response_data.get("experience_score", "Experience score not found")
    ats_score = response_data.get("ats_score", "ATS score not found")

    return name, degree, cgpa, skills, experience_score, ats_score



# Function to extract the candidate's name
def extract_name(text):
    name_pattern = re.compile(r"(Name:?\s*)([A-Z][a-z]+(?:\s[A-Z][a-z]+)*)")
    match = name_pattern.search(text)
    if match:
        return match.group(2)
    return "Name not found"

# Function to extract CGPA or Percentage
def extract_cgpa(text):
    cgpa_pattern = re.compile(r"(\bCGPA\b|\bGPA\b|\bPercentage\b):?\s*(\d+\.?\d*)")
    match = cgpa_pattern.search(text)
    if match:
        return match.group(2)
    return "CGPA/Percentage not found"

# Function to extract skills
def extract_skills(text):
    skills_pattern = re.compile(r"Skills:?\s*(.*?)(?:Experience|Education|$)", re.DOTALL)
    match = skills_pattern.search(text)
    if match:
        skills = match.group(1)
        return [skill.strip() for skill in skills.split(",")]
    return "Skills not found"

# Function to extract experience score
def extract_experience_score(text):
    experience_pattern = re.compile(r"Experience Score:?\s*(\d{1,2})")
    match = experience_pattern.search(text)
    if match:
        return int(match.group(1))
    # Heuristic: If no explicit experience score is given, infer it based on keywords
    experience_keywords = ["internship", "project", "work experience", "employment"]
    experience_count = sum(text.lower().count(keyword) for keyword in experience_keywords)
    return min(10, experience_count)  # Cap at 10

# Function to extract ATS score
def extract_ats_score(text):
    ats_pattern = re.compile(r"ATS Score:?\s*(\d+\.?\d*)")
    match = ats_pattern.search(text)
    if match:
        return float(match.group(1))
    # Heuristic to generate a score based on skill-job match
    return generate_ats_score(text)

# Heuristic function to generate ATS score
def generate_ats_score(text):
    # Just a dummy heuristic for now
    skills = extract_skills(text)
    if not skills:
        return 0

    required_skills = ["Python", "Machine Learning", "Data Analysis"]  # Add job role specific required skills
    match_count = sum(1 for skill in required_skills if skill.lower() in [s.lower() for s in skills])
    return round((match_count / len(required_skills)) * 10, 2)

if __name__ == "__main__":
    main()