Spaces:
Sleeping
Sleeping
File size: 9,062 Bytes
92adbc4 787c07d 2880f9e bc30ef4 9b9d05d 945e8e0 66795e6 92adbc4 787c07d 602831a 7b506d9 8a7688c 7b506d9 602831a 059553c f5ad50d 8bacbf3 85068b6 7b506d9 85068b6 51bfd94 059553c 787c07d 1c5cec1 6e4b6bd 1c5cec1 6e4b6bd 1c5cec1 d8f8183 1c5cec1 6e4b6bd 1c5cec1 a5b117b 6e4b6bd d8f8183 6e4b6bd 62df589 7b506d9 51bfd94 4c8469c 51bfd94 1c5cec1 6e4b6bd 787c07d 92adbc4 1423a16 799a461 1423a16 1ca5011 1423a16 50770f3 1423a16 94ae4bb 1423a16 12b39bb 799a461 12b39bb 1423a16 787c07d 92adbc4 787c07d 43fcb2c 787c07d a5b117b 1ca5011 2880f9e 43fcb2c 787c07d 43fcb2c 92adbc4 a5b117b 787c07d 1423a16 94ae4bb f71d1d8 787c07d d8f8183 1423a16 12b39bb 5519b6d 5b20086 5519b6d 5b20086 5519b6d 12b39bb 1423a16 1ca5011 1423a16 43fcb2c 66795e6 43fcb2c 66795e6 43fcb2c 66795e6 43fcb2c 66795e6 12b39bb 92adbc4 787c07d a5b117b |
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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# -*- coding: utf-8 -*-
import streamlit as st
import os
import pandas as pd
import matplotlib.pyplot as plt
from resume_generation_gemini_pro import generate_gemini
from similarity_score_refined import similarity_main
from pdf2image import convert_from_path
# Helper function to save uploaded files temporarily and return their paths
def save_uploaded_file(uploaded_file):
file_path = os.path.join("/tmp", uploaded_file.name)
with open(file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
return file_path
# Custom CSS for styling
st.markdown("""
<style>
.main {
background-color: #f5f5f5;
font-family: Arial, sans-serif;
}
h1, h2 {
color: #4B7BE5;
text-align: center;
}
.stContainer {
# background-color: #000000;
display: flex;
justify-content: center;
align-items: center;
# max-width: 100%;
height: 30%;
width: 45%;
}
.logo-container {
# background-color: black;
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
# max-width: 100%;
}
.logo-container img {
max-width: 60%;
height: 40%;
}
.stButton>button {
# background-color: #4B7BE5;
# color: white;
# font-size: 18px;
appearance: none;
background-color: transparent;
border: 0.125em solid #1A1A1A;
border-radius: 0.9375em;
box-sizing: border-box;
color: #3B3B3B;
cursor: pointer;
display: inline-block;
font-family: Roobert,-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
font-size: 16px;
font-weight: 600;
line-height: normal;
margin: 0;
min-height: 3.75em;
min-width: 0;
outline: none;
padding: 1em 2.3em;
text-align: center;
text-decoration: none;
transition: all 300ms cubic-bezier(.23, 1, 0.32, 1);
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
will-change: transform;
}
.stButton>button:hover {
color: #fff;
background-color: #1A1A1A;
box-shadow: rgba(0, 0, 0, 0.25) 0 8px 15px;
transform: translateY(-2px);
border: none !important;
}
/* From Uiverse.io by e-coders */
# .stButton>btn:disabled {
# pointer-events: none;
# }
.stButton>:active {
box-shadow: none;
transform: translateY(0);
}
</style>
""", unsafe_allow_html=True)
# Add ResumeMagic Logo
# st.image("logo.jpeg", use_container_width=True)
st.markdown('<div class="logo-container"></div>', unsafe_allow_html=True)
st.image("logo.jpeg", width=80)
st.markdown('</div>', unsafe_allow_html=True)
# Title and Description
st.title("Resume Tailoring with Google Generative AI")
st.markdown("### Upload your resume and job description to check similarity and generate a tailored resume.")
# Two columns for file uploaders
col1, col2 = st.columns(2)
with col1:
uploaded_resume = st.file_uploader("Upload Current Resume (.docx or .pdf)", type=["docx", "pdf"], key="resume")
with col2:
uploaded_job_description = st.file_uploader("Upload Job Description (.docx or .pdf)", type=["docx", "pdf"], key="job_description")
def get_score(resume_path, job_description_path):
similarity_score = similarity_main(resume_path, job_description_path)
if isinstance(similarity_score, str) and '%' in similarity_score:
similarity_score = float(similarity_score.replace('%', ''))
# Display messages based on score range
if similarity_score < 50:
st.markdown('<p style="color: red; font-weight: bold;">Low chance, skills gap identified!</p>', unsafe_allow_html=True)
pie_colors = ['#FF4B4B', '#E5E5E5']
elif 50 <= similarity_score < 70:
st.markdown('<p style="color: red; font-weight: bold;">Good chance but you can improve further!</p>', unsafe_allow_html=True)
pie_colors = ['#FFC107', '#E5E5E5']
else:
st.markdown('<p style="color: green; font-weight: bold;">Excellent! You can submit your CV.</p>', unsafe_allow_html=True)
pie_colors = ['#4CAF50', '#E5E5E5']
return similarity_score, pie_colors
def display_score(similarity, colors):
# Display Score as a Pie Chart
st.markdown(f"### Resume - Job Match: {int(similarity_score)}%")
# Pie chart to show similarity
fig, ax = plt.subplots()
# ax.pie([similarity_score, 100 - similarity_score], labels=['Match', 'Difference'], autopct='%1.1f%%', startangle=140, colors=['#4B7BE5', '#E5E5E5'])
ax.pie([similarity_score, 100 - similarity_score], labels=['Match', 'Difference'], autopct='%1.1f%%', startangle=140, colors=pie_colors)
ax.axis('equal')
st.pyplot(fig)
def save_docx_as_pdf(doc_content, output_path='output.pdf'):
# Save document content as a .docx file
temp_doc_path = 'temp.docx'
doc = Document()
doc.add_paragraph(doc_content)
doc.save(temp_doc_path)
# Convert .docx to PDF
from docx2pdf import convert
convert(temp_doc_path, output_path)
os.remove(temp_doc_path)
def display_doc_as_image(pdf_path):
poppler_path = 'usr/bin'
images = convert_from_path(pdf_path, poppler_path=poppler_path)
for img in images:
buf = BytesIO()
img.save(buf, format="PNG")
st.image(buf)
# Process if files are uploaded
if uploaded_resume and uploaded_job_description:
# Save files
resume_path = save_uploaded_file(uploaded_resume)
job_description_path = save_uploaded_file(uploaded_job_description)
# Similarity Score Section
st.markdown("---")
# st.subheader("Check Job Match")
if st.button("Resume-JD Matching"):
with st.spinner("Computing Match"):
similarity_score, pie_colors = get_score(resume_path, job_description_path)
display_score(similarity_score, pie_colors)
#Autoscroll
st.markdown("""
<script>
window.scrollTo(0, document.body.scrollHeight);
</script>
""", unsafe_allow_html=True)
# Generate Tailored Resume Section
st.markdown("---")
# st.subheader("Tailor Resume")
if st.button("Tailor Resume"):
with st.spinner("Generating resume..."):
generated_resume, new_resume_path = generate_gemini(resume_path, job_description_path)
# st.markdown("Generated Tailored Resume:")
# st.write(generated_resume)
#Autoscroll
st.markdown("""
<script>
window.scrollTo(0, document.body.scrollHeight);
</script>
""", unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
st.markdown("### Uploaded Resume:")
# if resume_path.endswith('.docx'):
# save_docx_as_pdf(uploaded_resume.getvalue().decode('utf-8'), 'uploaded_resume.pdf')
if uploaded_resume.type == "application/pdf":
display_doc_as_image(resume_path)
else:
save_docx_as_pdf(resume_path, 'uploaded_resume.pdf')
display_doc_as_image('uploaded_resume.pdf')
with col2:
st.markdown("### Tailored Resume:")
save_docx_as_pdf(generated_resume, 'tailored_resume.pdf')
display_doc_as_image('tailored_resume.pdf')
with st.spinner("Computing Match"):
similarity_score, pie_colors = get_score(resume_path, job_description_path)
display_score(similarity_score, pie_colors)
if generated_resume is not None:
from io import BytesIO
from docx import Document
doc = Document()
doc.add_paragraph(generated_resume)
resume_bytes = BytesIO()
doc.save(resume_bytes)
resume_bytes.seek(0)
st.download_button(
label="Download Resume",
data=resume_bytes,
file_name="tailored_resume.docx",
mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
)
else:
st.warning("Please upload both the resume and job description files.")
|