Spaces:
Sleeping
Sleeping
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()
|