Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -24,48 +24,6 @@ import streamlit.components.v1 as components
|
|
24 |
# Create temporary directories
|
25 |
temp_dir = tempfile.mkdtemp()
|
26 |
|
27 |
-
|
28 |
-
import subprocess
|
29 |
-
|
30 |
-
# Helper function to save uploaded files temporarily and return their paths
|
31 |
-
def save_uploaded_file(content):
|
32 |
-
if hasattr(content, 'name'): # Check if it's a file-like object
|
33 |
-
file_path = os.path.join("/tmp", content.name)
|
34 |
-
with open(file_path, "wb") as f:
|
35 |
-
f.write(content.read())
|
36 |
-
else: # It's a string (the file contents)
|
37 |
-
file_path = os.path.join("/tmp", "temp_upload")
|
38 |
-
with open(file_path, "w") as f:
|
39 |
-
f.write(str(content))
|
40 |
-
return file_path
|
41 |
-
|
42 |
-
def save_docx_as_pdf0(input_path, output_path='output.pdf'):
|
43 |
-
if input_path.lower().endswith('.docx'):
|
44 |
-
try:
|
45 |
-
# Convert .docx to .pdf using pypandoc
|
46 |
-
pypandoc.convert_file(input_path, 'pdf', outputfile=output_path)
|
47 |
-
if not os.path.exists(output_path):
|
48 |
-
raise FileNotFoundError("Conversion failed; output PDF not found.")
|
49 |
-
except Exception as e:
|
50 |
-
st.error(f"Failed to convert DOCX to PDF: {str(e)}")
|
51 |
-
elif input_path.lower().endswith('.pdf'):
|
52 |
-
shutil.copy(input_path, output_path)
|
53 |
-
else:
|
54 |
-
raise ValueError("Unsupported file format. Please upload a .docx or .pdf file.")
|
55 |
-
|
56 |
-
def display_docx_content(file):
|
57 |
-
doc = docx.Document(file)
|
58 |
-
full_text = []
|
59 |
-
for para in doc.paragraphs:
|
60 |
-
full_text.append(para.text)
|
61 |
-
return '\n'.join(full_text)
|
62 |
-
|
63 |
-
# def save_uploaded_file(uploaded_file):
|
64 |
-
# file_path = os.path.join("/tmp", uploaded_file.name)
|
65 |
-
# with open(file_path, "wb") as f:
|
66 |
-
# f.write(uploaded_file.getbuffer())
|
67 |
-
# return file_path
|
68 |
-
|
69 |
# Custom CSS for styling
|
70 |
st.markdown("""
|
71 |
<style>
|
@@ -162,6 +120,26 @@ st.markdown('</div>', unsafe_allow_html=True)
|
|
162 |
st.title("Resume Tailoring with Google Generative AI")
|
163 |
st.markdown("### Upload your resume and job description to check similarity and generate a tailored resume.")
|
164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
# Two columns for file uploaders
|
166 |
col1, col2 = st.columns(2)
|
167 |
with col1:
|
@@ -199,19 +177,14 @@ def display_score(similarity, colors):
|
|
199 |
ax.axis('equal')
|
200 |
st.pyplot(fig)
|
201 |
|
202 |
-
|
203 |
-
def
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
with open(file_path, "w") as f:
|
211 |
-
f.write(uploaded_file)
|
212 |
-
return file_path
|
213 |
-
|
214 |
-
import tempfile
|
215 |
|
216 |
# Function to save a file from BytesIO to a temporary file
|
217 |
def save_bytes_to_tempfile(bytes_data, suffix):
|
@@ -240,7 +213,7 @@ def save_bytes_as_pdf(docx_bytes, output_path='output.pdf'):
|
|
240 |
os.remove(output_path)
|
241 |
|
242 |
|
243 |
-
def display_content_with_page_numbers(content, words_per_page=
|
244 |
# Split content into words
|
245 |
words = content.split()
|
246 |
total_pages = (len(words) // words_per_page) + (1 if len(words) % words_per_page != 0 else 0)
|
@@ -251,9 +224,10 @@ def display_content_with_page_numbers(content, words_per_page=500):
|
|
251 |
end_index = start_index + words_per_page
|
252 |
page_content = ' '.join(words[start_index:end_index])
|
253 |
|
254 |
-
st.markdown(f"#### Page {i + 1}")
|
255 |
-
st.write(page_content)
|
256 |
-
|
|
|
257 |
def save_docx_as_pdf(input_path, output_path='output.pdf'):
|
258 |
if input_path.lower().endswith('.docx'):
|
259 |
try:
|
@@ -269,28 +243,7 @@ def save_docx_as_pdf(input_path, output_path='output.pdf'):
|
|
269 |
raise ValueError("Unsupported file format. Please upload a .docx or .pdf file.")
|
270 |
|
271 |
|
272 |
-
|
273 |
-
# def save_docx_as_pdf(input_path, output_path='output.pdf'):
|
274 |
-
# if input_path.lower().endswith('.docx'):
|
275 |
-
# from docx2pdf import convert
|
276 |
-
# convert(input_path, output_path)
|
277 |
-
# elif input_path.lower().endswith('.pdf'):
|
278 |
-
# shutil.copy(input_path, output_path)
|
279 |
-
# else:
|
280 |
-
# raise ValueError("Unsupported file format. Please upload a .docx or .pdf file.")
|
281 |
-
|
282 |
-
|
283 |
-
def save_docx_as_pdf1(input_path, output_path='output.pdf'):
|
284 |
-
if input_path.lower().endswith('.docx'):
|
285 |
-
from docx2pdf import convert
|
286 |
-
convert(input_path, output_path)
|
287 |
-
elif input_path.lower().endswith('.pdf'):
|
288 |
-
shutil.copy(input_path, output_path)
|
289 |
-
else:
|
290 |
-
raise ValueError("Unsupported file format. Please upload a .docx or .pdf file.")
|
291 |
-
|
292 |
-
|
293 |
-
def display_pdf_page1(pdf_path):
|
294 |
try:
|
295 |
# Open PDF file
|
296 |
with open(pdf_path, 'rb') as file:
|
@@ -326,22 +279,6 @@ def display_pdf_pages_as_images(pdf_path):
|
|
326 |
except Exception as e:
|
327 |
st.error(f"Failed to display PDF as image: {str(e)}")
|
328 |
|
329 |
-
def display_pdf_page(pdf_path, page_number=1):
|
330 |
-
with open(pdf_path, 'rb') as file:
|
331 |
-
reader = PyPDF2.PdfReader(file)
|
332 |
-
page = reader.pages[page_number]
|
333 |
-
x_object = page.extract_text()
|
334 |
-
|
335 |
-
# Convert text to image (using PIL)
|
336 |
-
img = Image.new('RGB', (800, 1000))
|
337 |
-
draw = ImageDraw.Draw(img)
|
338 |
-
font = ImageFont.truetype("arial.ttf", 20)
|
339 |
-
|
340 |
-
# Draw text on the image
|
341 |
-
draw.text((10, 10), x_object[:500], fill=(255, 255, 255), font=font)
|
342 |
-
|
343 |
-
# Display the image
|
344 |
-
display(img)
|
345 |
|
346 |
def display_doc_as_image2(pdf_path):
|
347 |
iframe_code = f"""
|
@@ -365,27 +302,19 @@ if uploaded_resume and uploaded_job_description:
|
|
365 |
with st.spinner("Computing Match"):
|
366 |
similarity_score, pie_colors = get_score(resume_path, job_description_path)
|
367 |
display_score(similarity_score, pie_colors)
|
368 |
-
|
369 |
-
|
370 |
#Autoscroll
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
|
|
|
|
376 |
|
377 |
# Generate Tailored Resume Section
|
378 |
st.markdown("---")
|
379 |
# st.subheader("Tailor Resume")
|
380 |
-
|
381 |
-
|
382 |
-
# iframe_code = f"""
|
383 |
-
# <iframe src="{resume_path}" width="100%" height="600px"></iframe>
|
384 |
-
# """
|
385 |
-
# st.markdown(iframe_code, unsafe_allow_html=True)
|
386 |
-
|
387 |
-
# st.components.v1.iframe(resume_path, width=800, height=600)
|
388 |
-
|
389 |
|
390 |
if st.button("Tailor Resume"):
|
391 |
with st.spinner("Generating resume..."):
|
@@ -420,18 +349,11 @@ if uploaded_resume and uploaded_job_description:
|
|
420 |
# Save the .docx to a temporary file
|
421 |
gen_docx_path = save_bytes_to_tempfile(resume_bytes.getvalue(), 'docx')
|
422 |
|
423 |
-
|
424 |
# Convert the generated .docx to a .pdf
|
425 |
-
# gen_pdf_path = '/tmp/tailored_resume.pdf'
|
426 |
gen_pdf_path = save_uploaded_file(gen_docx_path)
|
427 |
# st.write(display_docx_content(gen_pdf_path))
|
428 |
|
429 |
-
# save_docx_as_pdf0(gen_docx_path, gen_pdf_path)
|
430 |
-
# save_bytes_as_pdf(gen_docx_path, gen_pdf_path)
|
431 |
-
# save_docx_as_pdf2(gen_docx_path, gen_pdf_path)
|
432 |
-
|
433 |
# Display uploaded and generated resumes side-by-side
|
434 |
-
# if st.button("View Uploaded Resume"):
|
435 |
col1, col2 = st.columns(2)
|
436 |
with col1:
|
437 |
st.markdown("### Uploaded Resume:")
|
@@ -440,36 +362,26 @@ if uploaded_resume and uploaded_job_description:
|
|
440 |
with col2:
|
441 |
st.markdown("### Tailored Resume:")
|
442 |
# display_pdf_pages_as_images(gen_pdf_path)
|
|
|
443 |
st.write(generated_resume)
|
444 |
# display_content_with_page_numbers(generated_resume, 290)
|
|
|
445 |
st.success(f"Download tailored resume")
|
446 |
-
st.
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
# label="Generated Resume (PDF)",
|
462 |
-
# data=open(gen_pdf_path, 'rb').read(),
|
463 |
-
# file_name="generated_resume.pdf",
|
464 |
-
# mime="application/pdf"
|
465 |
-
# )
|
466 |
-
# st.download_button(
|
467 |
-
# label="Generated Resume (Word)",
|
468 |
-
# data=resume_bytes,
|
469 |
-
# file_name="tailored_resume.docx",
|
470 |
-
# mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
471 |
-
# )
|
472 |
-
|
473 |
|
474 |
|
475 |
else:
|
|
|
24 |
# Create temporary directories
|
25 |
temp_dir = tempfile.mkdtemp()
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
# Custom CSS for styling
|
28 |
st.markdown("""
|
29 |
<style>
|
|
|
120 |
st.title("Resume Tailoring with Google Generative AI")
|
121 |
st.markdown("### Upload your resume and job description to check similarity and generate a tailored resume.")
|
122 |
|
123 |
+
|
124 |
+
# Helper function to save uploaded files temporarily and return their paths
|
125 |
+
def save_uploaded_file(content):
|
126 |
+
if hasattr(content, 'name'):
|
127 |
+
file_path = os.path.join("/tmp", content.name)
|
128 |
+
with open(file_path, "wb") as f:
|
129 |
+
f.write(content.read())
|
130 |
+
else:
|
131 |
+
file_path = os.path.join("/tmp", "temp_upload")
|
132 |
+
with open(file_path, "w") as f:
|
133 |
+
f.write(str(content))
|
134 |
+
return file_path
|
135 |
+
|
136 |
+
# def save_uploaded_file(uploaded_file):
|
137 |
+
# file_path = os.path.join("/tmp", uploaded_file.name)
|
138 |
+
# with open(file_path, "wb") as f:
|
139 |
+
# f.write(uploaded_file.getbuffer())
|
140 |
+
# return file_path
|
141 |
+
|
142 |
+
|
143 |
# Two columns for file uploaders
|
144 |
col1, col2 = st.columns(2)
|
145 |
with col1:
|
|
|
177 |
ax.axis('equal')
|
178 |
st.pyplot(fig)
|
179 |
|
180 |
+
|
181 |
+
def display_docx_content(file):
|
182 |
+
doc = docx.Document(file)
|
183 |
+
full_text = []
|
184 |
+
for para in doc.paragraphs:
|
185 |
+
full_text.append(para.text)
|
186 |
+
return '\n'.join(full_text)
|
187 |
+
|
|
|
|
|
|
|
|
|
|
|
188 |
|
189 |
# Function to save a file from BytesIO to a temporary file
|
190 |
def save_bytes_to_tempfile(bytes_data, suffix):
|
|
|
213 |
os.remove(output_path)
|
214 |
|
215 |
|
216 |
+
def display_content_with_page_numbers(content, words_per_page=290):
|
217 |
# Split content into words
|
218 |
words = content.split()
|
219 |
total_pages = (len(words) // words_per_page) + (1 if len(words) % words_per_page != 0 else 0)
|
|
|
224 |
end_index = start_index + words_per_page
|
225 |
page_content = ' '.join(words[start_index:end_index])
|
226 |
|
227 |
+
# st.markdown(f"#### Page {i + 1}")
|
228 |
+
# st.write(page_content)
|
229 |
+
st.markdown(f"#### Page {total_pages}")
|
230 |
+
|
231 |
def save_docx_as_pdf(input_path, output_path='output.pdf'):
|
232 |
if input_path.lower().endswith('.docx'):
|
233 |
try:
|
|
|
243 |
raise ValueError("Unsupported file format. Please upload a .docx or .pdf file.")
|
244 |
|
245 |
|
246 |
+
def display_pdf_page(pdf_path):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
try:
|
248 |
# Open PDF file
|
249 |
with open(pdf_path, 'rb') as file:
|
|
|
279 |
except Exception as e:
|
280 |
st.error(f"Failed to display PDF as image: {str(e)}")
|
281 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
|
283 |
def display_doc_as_image2(pdf_path):
|
284 |
iframe_code = f"""
|
|
|
302 |
with st.spinner("Computing Match"):
|
303 |
similarity_score, pie_colors = get_score(resume_path, job_description_path)
|
304 |
display_score(similarity_score, pie_colors)
|
305 |
+
|
|
|
306 |
#Autoscroll
|
307 |
+
components.html("""
|
308 |
+
<script>
|
309 |
+
window.onload = function() {
|
310 |
+
window.scrollTo(0, document.body.scrollHeight);
|
311 |
+
};
|
312 |
+
</script>
|
313 |
+
""")
|
314 |
|
315 |
# Generate Tailored Resume Section
|
316 |
st.markdown("---")
|
317 |
# st.subheader("Tailor Resume")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
|
319 |
if st.button("Tailor Resume"):
|
320 |
with st.spinner("Generating resume..."):
|
|
|
349 |
# Save the .docx to a temporary file
|
350 |
gen_docx_path = save_bytes_to_tempfile(resume_bytes.getvalue(), 'docx')
|
351 |
|
|
|
352 |
# Convert the generated .docx to a .pdf
|
|
|
353 |
gen_pdf_path = save_uploaded_file(gen_docx_path)
|
354 |
# st.write(display_docx_content(gen_pdf_path))
|
355 |
|
|
|
|
|
|
|
|
|
356 |
# Display uploaded and generated resumes side-by-side
|
|
|
357 |
col1, col2 = st.columns(2)
|
358 |
with col1:
|
359 |
st.markdown("### Uploaded Resume:")
|
|
|
362 |
with col2:
|
363 |
st.markdown("### Tailored Resume:")
|
364 |
# display_pdf_pages_as_images(gen_pdf_path)
|
365 |
+
display_content_with_page_numbers(generated_resume, 290)
|
366 |
st.write(generated_resume)
|
367 |
# display_content_with_page_numbers(generated_resume, 290)
|
368 |
+
|
369 |
st.success(f"Download tailored resume")
|
370 |
+
col1, col2 = st.columns(2)
|
371 |
+
with col1:
|
372 |
+
st.download_button(
|
373 |
+
label="Generated Resume (PDF)",
|
374 |
+
data=open(gen_pdf_path, 'rb').read(),
|
375 |
+
file_name="tailored_resume.pdf",
|
376 |
+
mime="application/pdf"
|
377 |
+
)
|
378 |
+
with col2:
|
379 |
+
st.download_button(
|
380 |
+
label="Generated Resume (Word)",
|
381 |
+
data=resume_bytes,
|
382 |
+
file_name="tailored_resume.docx",
|
383 |
+
mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
384 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
|
386 |
|
387 |
else:
|