Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import requests
|
| 3 |
from PyPDF2 import PdfReader
|
|
@@ -22,6 +23,25 @@ def extract_text_from_docx(docx_file):
|
|
| 22 |
text += para.text + "\n"
|
| 23 |
return text
|
| 24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
def analyze_documents(resume_text, job_description):
|
| 26 |
custom_prompt = f"""
|
| 27 |
Please analyze the following resume in the context of the job description provided. Strictly check every single line in the job description and analyze my resume whether there is a match exactly. Strictly maintain high ATS standards and give scores only to the correct ones. Focus on hard skills which are missing and also soft skills which are missing. Provide the following details.:
|
|
@@ -71,113 +91,67 @@ st.set_page_config(page_title="ATS Resume Evaluation System", layout="wide")
|
|
| 71 |
# Custom styles for headers, buttons, and sections
|
| 72 |
st.markdown("""
|
| 73 |
<style>
|
| 74 |
-
.
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
color: #4CAF50;
|
| 79 |
-
font-family: 'Arial', sans-serif;
|
| 80 |
-
}
|
| 81 |
-
.subtitle {
|
| 82 |
-
text-align: center;
|
| 83 |
-
font-size: 22px;
|
| 84 |
-
color: #6c757d;
|
| 85 |
-
font-family: 'Arial', sans-serif;
|
| 86 |
-
}
|
| 87 |
-
.section-header {
|
| 88 |
-
font-size: 24px;
|
| 89 |
-
color: #333333;
|
| 90 |
-
margin-top: 20px;
|
| 91 |
margin-bottom: 10px;
|
| 92 |
-
font-
|
| 93 |
-
}
|
| 94 |
-
.button {
|
| 95 |
-
background-color: #4CAF50;
|
| 96 |
-
color: white;
|
| 97 |
-
font-size: 18px;
|
| 98 |
-
padding: 12px 24px;
|
| 99 |
-
border-radius: 8px;
|
| 100 |
-
width: 100%;
|
| 101 |
-
margin: 20px 0;
|
| 102 |
-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
| 103 |
-
}
|
| 104 |
-
.button:hover {
|
| 105 |
-
background-color: #45a049;
|
| 106 |
-
cursor: pointer;
|
| 107 |
-
}
|
| 108 |
-
.file-upload {
|
| 109 |
-
background-color: #f8f8f8;
|
| 110 |
-
padding: 20px;
|
| 111 |
-
border-radius: 10px;
|
| 112 |
-
border: 1px solid #e0e0e0;
|
| 113 |
-
}
|
| 114 |
-
.resume-content {
|
| 115 |
-
background-color: #f1f1f1;
|
| 116 |
-
border-radius: 8px;
|
| 117 |
-
padding: 15px;
|
| 118 |
-
margin-top: 10px;
|
| 119 |
}
|
| 120 |
-
.highlight {
|
| 121 |
font-weight: bold;
|
| 122 |
color: #4CAF50;
|
| 123 |
-
font-size: 16px;
|
| 124 |
-
}
|
| 125 |
-
.spinner {
|
| 126 |
-
margin-top: 20px;
|
| 127 |
}
|
| 128 |
</style>
|
| 129 |
""", unsafe_allow_html=True)
|
| 130 |
|
| 131 |
-
#
|
| 132 |
-
st.markdown('<
|
| 133 |
-
st.markdown('<div class="subtitle">Upload your resume and job description to evaluate match with job requirements</div>', unsafe_allow_html=True)
|
| 134 |
|
| 135 |
-
#
|
| 136 |
-
job_description = st.text_area("Job Description:", height=200, placeholder="Paste the job description here..."
|
| 137 |
|
| 138 |
-
#
|
| 139 |
-
st.
|
| 140 |
-
resumes = st.file_uploader("Upload your resumes", type=["pdf", "docx"], accept_multiple_files=True)
|
| 141 |
|
| 142 |
if resumes:
|
| 143 |
st.write("Uploaded Resumes:")
|
| 144 |
for index, resume in enumerate(resumes):
|
| 145 |
st.write(f"📄 {resume.name}")
|
| 146 |
-
display_resume(resume, index)
|
| 147 |
|
| 148 |
-
#
|
| 149 |
-
st.
|
| 150 |
-
if st.button("Analyze Resumes", key="analyze_button", help="Click to analyze the uploaded resumes against the job description"):
|
| 151 |
if job_description and resumes:
|
| 152 |
-
if len(resumes) <= 10:
|
| 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 |
else:
|
| 181 |
st.error("You can upload a maximum of 10 resumes.")
|
| 182 |
else:
|
| 183 |
-
st.error("Please
|
|
|
|
| 1 |
+
import re
|
| 2 |
import streamlit as st
|
| 3 |
import requests
|
| 4 |
from PyPDF2 import PdfReader
|
|
|
|
| 23 |
text += para.text + "\n"
|
| 24 |
return text
|
| 25 |
|
| 26 |
+
def extract_contact_info(resume_text):
|
| 27 |
+
"""Extract name, email, and phone number from resume text."""
|
| 28 |
+
# Regex patterns for email and phone
|
| 29 |
+
email_pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
|
| 30 |
+
phone_pattern = r'\+?\d[\d -]{8,12}\d'
|
| 31 |
+
|
| 32 |
+
# Attempt to extract contact details
|
| 33 |
+
email = re.search(email_pattern, resume_text)
|
| 34 |
+
phone = re.search(phone_pattern, resume_text)
|
| 35 |
+
|
| 36 |
+
# Extract Name (assuming first line of the resume might be the name)
|
| 37 |
+
name = resume_text.splitlines()[0].strip() if resume_text else "Name Not Found"
|
| 38 |
+
|
| 39 |
+
return {
|
| 40 |
+
"name": name,
|
| 41 |
+
"email": email.group() if email else "Email Not Found",
|
| 42 |
+
"phone": phone.group() if phone else "Contact Not Found"
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
def analyze_documents(resume_text, job_description):
|
| 46 |
custom_prompt = f"""
|
| 47 |
Please analyze the following resume in the context of the job description provided. Strictly check every single line in the job description and analyze my resume whether there is a match exactly. Strictly maintain high ATS standards and give scores only to the correct ones. Focus on hard skills which are missing and also soft skills which are missing. Provide the following details.:
|
|
|
|
| 91 |
# Custom styles for headers, buttons, and sections
|
| 92 |
st.markdown("""
|
| 93 |
<style>
|
| 94 |
+
.highlight {
|
| 95 |
+
background-color: #f9f9f9;
|
| 96 |
+
border-left: 6px solid #4CAF50;
|
| 97 |
+
padding: 10px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
margin-bottom: 10px;
|
| 99 |
+
font-size: 16px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
}
|
| 101 |
+
.highlight-bold {
|
| 102 |
font-weight: bold;
|
| 103 |
color: #4CAF50;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
}
|
| 105 |
</style>
|
| 106 |
""", unsafe_allow_html=True)
|
| 107 |
|
| 108 |
+
# Main Title
|
| 109 |
+
st.markdown('<h1 style="text-align: center; color: #4CAF50;">📄🔍 Resume Evaluation System 📊</h1>', unsafe_allow_html=True)
|
|
|
|
| 110 |
|
| 111 |
+
# Job Description Input
|
| 112 |
+
job_description = st.text_area("Job Description:", height=200, placeholder="Paste the job description here...")
|
| 113 |
|
| 114 |
+
# Resume Upload
|
| 115 |
+
resumes = st.file_uploader("Upload Your Resumes (PDF or DOCX)", type=["pdf", "docx"], accept_multiple_files=True)
|
|
|
|
| 116 |
|
| 117 |
if resumes:
|
| 118 |
st.write("Uploaded Resumes:")
|
| 119 |
for index, resume in enumerate(resumes):
|
| 120 |
st.write(f"📄 {resume.name}")
|
| 121 |
+
display_resume(resume, index)
|
| 122 |
|
| 123 |
+
# Analysis Button
|
| 124 |
+
if st.button("Analyze Resumes"):
|
|
|
|
| 125 |
if job_description and resumes:
|
| 126 |
+
if len(resumes) <= 10:
|
| 127 |
+
for index, resume in enumerate(resumes):
|
| 128 |
+
resume.seek(0) # Reset file pointer
|
| 129 |
+
file_type = resume.name.split('.')[-1].lower()
|
| 130 |
+
if file_type == 'pdf':
|
| 131 |
+
resume_text = extract_text_from_pdf(resume)
|
| 132 |
+
elif file_type == 'docx':
|
| 133 |
+
resume_text = extract_text_from_docx(resume)
|
| 134 |
+
|
| 135 |
+
contact_info = extract_contact_info(resume_text)
|
| 136 |
+
analysis = analyze_documents(resume_text, job_description)
|
| 137 |
+
|
| 138 |
+
# Display Contact Info and Match Percentage
|
| 139 |
+
st.markdown(f"""
|
| 140 |
+
<div class="highlight">
|
| 141 |
+
<p><span class="highlight-bold">Name:</span> {contact_info['name']}</p>
|
| 142 |
+
<p><span class="highlight-bold">Email:</span> {contact_info['email']}</p>
|
| 143 |
+
<p><span class="highlight-bold">Contact:</span> {contact_info['phone']}</p>
|
| 144 |
+
</div>
|
| 145 |
+
""", unsafe_allow_html=True)
|
| 146 |
+
|
| 147 |
+
# Display analysis results
|
| 148 |
+
if "candidates" in analysis:
|
| 149 |
+
for candidate in analysis["candidates"]:
|
| 150 |
+
if "content" in candidate and "parts" in candidate["content"]:
|
| 151 |
+
for part in candidate["content"]["parts"]:
|
| 152 |
+
response_text = part["text"]
|
| 153 |
+
st.markdown(response_text)
|
| 154 |
else:
|
| 155 |
st.error("You can upload a maximum of 10 resumes.")
|
| 156 |
else:
|
| 157 |
+
st.error("Please provide the job description and upload resumes.")
|