Bur3hani commited on
Commit
25f8daa
Β·
verified Β·
1 Parent(s): cfc4901

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -1
app.py CHANGED
@@ -369,4 +369,102 @@ Upload a CV (PDF, DOCX, TXT) and paste the job description text to get an instan
369
 
370
  # Input for CV
371
  st.header("1. Upload Your CV")
372
- uploaded_cv_file = st.file_uploader("Choose a CV file (PDF, DOCX, TXT)", type=["pdf", "docx", "txt"],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
 
370
  # Input for CV
371
  st.header("1. Upload Your CV")
372
+ uploaded_cv_file = st.file_uploader("Choose a CV file (PDF, DOCX, TXT)", type=["pdf", "docx", "txt"], key="cv_uploader")
373
+ cv_text_area = st.text_area("Or paste your CV text here (overrides file upload)", height=250, key="cv_text_area")
374
+
375
+ cv_content = ""
376
+ if uploaded_cv_file is not None:
377
+ if uploaded_cv_file.name.endswith('.pdf'):
378
+ cv_content = extract_text_from_pdf(uploaded_cv_file)
379
+ elif uploaded_cv_file.name.endswith('.docx'):
380
+ cv_content = extract_text_from_docx(uploaded_cv_file)
381
+ elif uploaded_cv_file.name.endswith('.txt'):
382
+ cv_content = uploaded_cv_file.read().decode("utf-8")
383
+ st.success("CV file uploaded and parsed successfully!")
384
+ elif cv_text_area: # If text area has content and no file uploaded
385
+ cv_content = cv_text_area
386
+
387
+ # Input for Job Description
388
+ st.header("2. Input Job Description")
389
+ job_desc_text_area = st.text_area("Paste the Job Description text here", height=250, key="jd_text_area")
390
+
391
+ # Analyze Button
392
+ st.markdown("---")
393
+ if st.button("✨ Analyze CV Match ✨", use_container_width=True):
394
+ if not cv_content:
395
+ st.error("🚨 Please upload a CV file or paste your CV text to proceed.")
396
+ if not job_desc_text_area:
397
+ st.error("🚨 Please paste the Job Description text to proceed.")
398
+
399
+ if cv_content and job_desc_text_area:
400
+ with st.spinner("πŸš€ Analyzing your documents... This might take a moment!"):
401
+ try:
402
+ analysis_results = perform_cv_job_analysis(cv_content, job_desc_text_area)
403
+
404
+ st.subheader("πŸ’‘ Analysis Results Summary πŸ’‘")
405
+
406
+ # Display KPIs in columns
407
+ col1, col2, col3 = st.columns(3)
408
+ with col1:
409
+ st.metric(label="Overall Match Score", value=f"{analysis_results['overall_match_score']}%")
410
+ with col2:
411
+ st.metric(label="Skill Match", value=f"{analysis_results['skill_match_percentage']}%")
412
+ with col3:
413
+ exp_status = analysis_results['experience_match_status']
414
+ if "Meets" in exp_status or "Exceeds" in exp_status:
415
+ st.metric(label="Experience Match", value=exp_status, delta="Good!")
416
+ else:
417
+ st.metric(label="Experience Match", value=exp_status, delta="Needs attention")
418
+
419
+ st.markdown("---")
420
+
421
+ st.subheader("πŸ“Š Visual Insights")
422
+
423
+ # Overall Match Plot
424
+ fig_overall = create_overall_match_plot(analysis_results['overall_match_score'])
425
+ st.pyplot(fig_overall)
426
+ plt.close(fig_overall) # Close figure to free memory
427
+
428
+ # Skill Match Plot
429
+ fig_skill = create_skill_match_plot(analysis_results['matched_skills'], analysis_results['missing_skills'])
430
+ if fig_skill:
431
+ st.pyplot(fig_skill)
432
+ plt.close(fig_skill)
433
+ else:
434
+ st.info("No specific skills identified in the job description for a detailed skill match breakdown.")
435
+
436
+ # Top Keywords Plot
437
+ fig_keywords = create_top_keywords_plot(analysis_results['top_cv_keywords'], analysis_results['top_jd_keywords'])
438
+ st.pyplot(fig_keywords)
439
+ plt.close(fig_keywords)
440
+
441
+ st.markdown("---")
442
+ st.subheader("πŸ“ Detailed Breakdown")
443
+
444
+ st.markdown("#### Skills Analysis")
445
+ st.write(f"**βœ… Matched Skills:**", ", ".join(analysis_results['matched_skills']) if analysis_results['matched_skills'] else "None found matching job description.")
446
+ st.write(f"**❌ Missing Skills (from Job Description):**", ", ".join(analysis_results['missing_skills']) if analysis_results['missing_skills'] else "πŸ₯³ None! Your CV has all specified skills.")
447
+ st.write(f"**πŸ’‘ Extra Skills in CV (not in Job Description):**", ", ".join(analysis_results['extra_skills_in_cv']) if analysis_results['extra_skills_in_cv'] else "None. (This is often fine, showing broader capability.)")
448
+
449
+ st.markdown("#### Keyword Relevance (Top TF-IDF Terms)")
450
+ st.write(f"**🀝 Top Common Keywords:**", ", ".join(analysis_results['common_keywords']) if analysis_results['common_keywords'] else "No significant common keywords beyond skills.")
451
+ st.write(f"**πŸ” Top Keywords in Your CV:**", ", ".join(analysis_results['top_cv_keywords']) if analysis_results['top_cv_keywords'] else "N/A")
452
+ st.write(f"**🎯 Top Keywords in Job Description:**", ", ".join(analysis_results['top_jd_keywords']) if analysis_results['top_jd_keywords'] else "N/A")
453
+
454
+
455
+ st.markdown("#### Experience & Education Comparison")
456
+ st.write(f"**πŸ‘€ Your CV's Experience:** `{analysis_results['cv_years_experience']}` years")
457
+ st.write(f"**πŸ’Ό Job's Required Experience:** `{analysis_results['jd_years_experience']}` years")
458
+ st.info(f"**Status:** {analysis_results['experience_match_status']}")
459
+
460
+ st.write(f"**πŸŽ“ Your CV's Education:** `{analysis_results['cv_education_level']}`")
461
+ st.write(f"**πŸ“š Job's Required Education:** `{analysis_results['jd_education_level']}`")
462
+ st.info(f"**Status:** {analysis_results['education_match_status']}")
463
+
464
+
465
+ except Exception as e:
466
+ st.error(f"An unexpected error occurred during analysis: {e}")
467
+ st.exception(e) # Show full traceback in Streamlit debug logs
468
+
469
+ st.markdown("---")
470
+ st.markdown("Developed with ❀️ for Data Science by your mentor")