Spaces:
Build error
Build error
| 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") |