-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
177 lines (126 loc) · 6.73 KB
/
Copy pathmain.py
File metadata and controls
177 lines (126 loc) · 6.73 KB
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
import streamlit as st # For Web Interface (Front-End)
from pdfminer.high_level import extract_text # To Extract Text from Resume PDF
from sentence_transformers import SentenceTransformer # To generate Embeddings of text
from sklearn.metrics.pairwise import cosine_similarity # To get Similarity Score of Resume and Job Description
from groq import Groq # API to use LLM's
import re # To perform Regular Expression Functions
from dotenv import load_dotenv # Loading API Key from .env file
import os
# Load environment variables from .env
load_dotenv()
# Fetch the key from the environment
api_key = os.getenv("GROQ_API_KEY")
# Session States to store values
if "form_submitted" not in st.session_state:
st.session_state.form_submitted = False
if "resume" not in st.session_state:
st.session_state.resume=""
if "job_desc" not in st.session_state:
st.session_state.job_desc=""
# Title of the Project, change according to your style
st.title("AI Resume Analyzer 📝")
# <------- Defining Functions ------->
# Function to extract text from PDF
def extract_pdf_text(uploaded_file):
try:
extracted_text = extract_text(uploaded_file)
return extracted_text
except Exception as e:
st.error(f"Error extracting text from PDF: {str(e)}")
return "Could not extract text from the PDF file."
# Function to calculate similarity
def calculate_similarity_bert(text1, text2):
ats_model = SentenceTransformer('sentence-transformers/all-mpnet-base-v2') # Use BERT or SBERT or any model you want
# Encode the texts directly to embeddings
embeddings1 = ats_model.encode([text1])
embeddings2 = ats_model.encode([text2])
# Calculate cosine similarity without adding an extra list layer
similarity = cosine_similarity(embeddings1, embeddings2)[0][0]
return similarity
def get_report(resume,job_desc):
client = Groq(api_key=api_key)
# Change the prompt to get the results in your style
prompt=f"""
# Context:
- You are an AI Resume Analyzer, you will be given Candidate's resume and Job Description of the role he is applying for.
# Instruction:
- Analyze candidate's resume based on the possible points that can be extracted from job description,and give your evaluation on each point with the criteria below:
- Consider all points like required skills, experience,etc that are needed for the job role.
- Calculate the score to be given (out of 5) for every point based on evaluation at the beginning of each point with a detailed explanation.
- If the resume aligns with the job description point, mark it with ✅ and provide a detailed explanation.
- If the resume doesn't align with the job description point, mark it with ❌ and provide a reason for it.
- If a clear conclusion cannot be made, use a ⚠️ sign with a reason.
- The Final Heading should be "Suggestions to improve your resume:" and give where and what the candidate can improve to be selected for that job role.
# Inputs:
Candidate Resume: {resume}
---
Job Description: {job_desc}
# Output:
- Each any every point should be given a score (example: 3/5 ).
- Mention the scores and relevant emoji at the beginning of each point and then explain the reason.
"""
chat_completion = client.chat.completions.create(
messages=[{"role": "user", "content": prompt}],
model="llama-3.3-70b-versatile",
)
return chat_completion.choices[0].message.content
def extract_scores(text):
# Regular expression pattern to find scores in the format x/5, where x can be an integer or a float
pattern = r'(\d+(?:\.\d+)?)/5'
# Find all matches in the text
matches = re.findall(pattern, text)
# Convert matches to floats
scores = [float(match) for match in matches]
return scores
# <--------- Starting the Work Flow --------->
# Displays Form only if the form is not submitted
if not st.session_state.form_submitted:
with st.form("my_form"):
# Taking input a Resume (PDF) file
resume_file = st.file_uploader(label="Upload your Resume/CV in PDF format", type="pdf")
# Taking input Job Description
st.session_state.job_desc = st.text_area("Enter the Job Description of the role you are applying for:",placeholder="Job Description...")
# Form Submission Button
submitted = st.form_submit_button("Analyze")
if submitted:
# Allow only if Both Resume and Job Description are Submitted
if st.session_state.job_desc and resume_file:
st.info("Extracting Information")
st.session_state.resume = extract_pdf_text(resume_file) # Calling the function to extract text from Resume
st.session_state.form_submitted = True
st.rerun() # Refresh the page to close the form and give results
# Donot allow if not uploaded
else:
st.warning("Please Upload both Resume and Job Description to analyze")
if st.session_state.form_submitted:
score_place = st.info("Generating Scores...")
# Call the function to get ATS Score
ats_score = calculate_similarity_bert(st.session_state.resume,st.session_state.job_desc)
col1,col2 = st.columns(2,border=True)
with col1:
st.write("Few ATS uses this score to shortlist candidates, Similarity Score:")
st.subheader(str(ats_score))
# Call the function to get the Analysis Report from LLM (Groq)
report = get_report(st.session_state.resume,st.session_state.job_desc)
# Calculate the Average Score from the LLM Report
report_scores = extract_scores(report) # Example : [3/5, 4/5, 5/5,...]
avg_score = sum(report_scores) / (5*len(report_scores)) # Example: 2.4
with col2:
st.write("Total Average score according to our AI report:")
st.subheader(str(avg_score))
score_place.success("Scores generated successfully!")
st.subheader("AI Generated Analysis Report:")
# Displaying Report
st.markdown(f"""
<div style='text-align: left; background-color: #000000; padding: 10px; border-radius: 10px; margin: 5px 0;'>
{report}
</div>
""", unsafe_allow_html=True)
# Download Button
st.download_button(
label="Download Report",
data=report,
file_name="report.txt",
icon=":material/download:",
)
# <-------------- End of the Work Flow --------------->