import streamlit as st from PyPDF2 import PdfReader from docx import Document from sentence_transformers import SentenceTransformer, util from fpdf import FPDF import tempfile import os # Load model embedder = SentenceTransformer("all-MiniLM-L6-v2") # File readers def read_pdf(file): reader = PdfReader(file) return "\n".join(page.extract_text() for page in reader.pages if page.extract_text()) def read_docx(file): doc = Document(file) return "\n".join([para.text for para in doc.paragraphs]) def read_txt(file): return file.read().decode("utf-8") # PDF generator def generate_pdf(text, template): pdf = FPDF() pdf.add_page() if template == "Modern": pdf.set_font("Arial", "B", 14) pdf.set_text_color(50, 50, 50) elif template == "Classic": pdf.set_font("Times", "", 12) pdf.set_text_color(0, 0, 0) elif template == "Creative": pdf.set_font("Courier", "I", 12) pdf.set_text_color(80, 40, 120) lines = text.split("\n") for line in lines: try: pdf.cell(0, 10, txt=line.encode("latin-1", "replace").decode("latin-1"), ln=True) except: pdf.cell(0, 10, txt="...", ln=True) tmp_path = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") pdf.output(tmp_path.name) return tmp_path.name # Skill extraction (simple keyword matching for demo) def extract_skills(text): keywords = ["Python", "Machine Learning", "Deep Learning", "Research", "Data Analysis", "Communication", "Teamwork"] return [kw for kw in keywords if kw.lower() in text.lower()] # App layout st.title("Smart Resume Optimizer & Generator") st.markdown("Upload your **Resume** and paste your **Job or Scholarship Description** to get a customized version!") resume_file = st.file_uploader("Upload Resume (PDF, DOCX, TXT)", type=["pdf", "docx", "txt"]) job_description = st.text_area("Paste Job or Scholarship Description Here", height=200) if st.button("Submit"): if resume_file and job_description: # Extract resume text ext = resume_file.name.split(".")[-1] if ext == "pdf": resume_text = read_pdf(resume_file) elif ext == "docx": resume_text = read_docx(resume_file) elif ext == "txt": resume_text = read_txt(resume_file) else: st.error("Unsupported file format") st.stop() # Embeddings and Fit Score resume_emb = embedder.encode(resume_text, convert_to_tensor=True) job_emb = embedder.encode(job_description, convert_to_tensor=True) fit_score = util.cos_sim(resume_emb, job_emb).item() fit_percent = round(fit_score * 100, 2) # Skill Suggestions resume_skills = extract_skills(resume_text) job_skills = extract_skills(job_description) missing_skills = list(set(job_skills) - set(resume_skills)) # Optimized Resume Text optimized_text = resume_text + "\n\n---\nAdditional Section:\n" optimized_text += f"This resume was optimized based on the job description. Fit Score: {fit_percent}%.\n" if missing_skills: optimized_text += "To improve fit, consider highlighting these skills: " + ", ".join(missing_skills) else: optimized_text += "Your resume already includes all the key skills for this role!" st.success("✅ Your updated resume is ready!") st.session_state.optimized_text = optimized_text # Store in session st.session_state.show_preview = True st.session_state.fit_score = fit_percent st.session_state.missing_skills = missing_skills else: st.warning("Please upload a resume and enter job/scholarship details.") # Preview and download if st.session_state.get("show_preview"): st.subheader("Preview Your Resume") template = st.selectbox("Choose Template", ["Modern", "Classic", "Creative"]) if st.button("Preview"): pdf_path = generate_pdf(st.session_state.optimized_text, template) with open(pdf_path, "rb") as f: st.download_button("📄 Download Resume", f, file_name="optimized_resume.pdf")