import streamlit as st import google.generativeai as genai import os import PyPDF2 as pdf from dotenv import load_dotenv import json import re import time load_dotenv() genai.configure(api_key=os.getenv('GOOGLE_API_KEY')) def get_gemeni_response(input_text): model = genai.GenerativeModel('gemini-pro') response = model.generate_content(input_text) return response.text def input_pdf_text(upload_file): reader = pdf.PdfReader(upload_file) text = "" for page in range(len(reader.pages)): page_text = reader.pages[page].extract_text() text += str(page_text) return text def parse_response(response): """Validate and parse JSON response string.""" # Ensure response is JSON-like with regex before parsing if re.match(r'^\{.*\}$', response.strip(), re.DOTALL): try: return json.loads(response) except json.JSONDecodeError: return None return None # Enhanced Prompt Engineering input_prompt = """ Act as a highly skilled ATS (Applicant Tracking System) expert with strong knowledge of software engineering, data science, analytics, and big data engineering. Your goal is to analyze the resume content and compare it to the provided job description. Provide the following: 1. An overall Job Description (JD) Match percentage. 2. Top missing keywords or phrases relevant to the job description. 3. A summary of the profile, highlighting strengths and areas for improvement. Structure the output as a JSON with the following keys: - "JD Match": percentage match as a string with "%" sign. - "MissingKeywords": a list of missing but important keywords. - "ProfileSummary": a summary as a single string. Example format: {{"JD Match":"85%", "MissingKeywords":["data analysis", "team leadership"], "ProfileSummary":"Highly skilled engineer with 10 years of experience in data engineering."}} resume: {text} description: {jd} """ # Streamlit app setup st.title('Smart ATS') st.write( "Welcome! This tool helps you improve your resume's alignment with the job description, ensuring it is optimized for ATS.") # Job Description input jd = st.text_area("Paste the Job Description:", help="Paste the job description you want your resume to match.") # Resume upload uploaded_file = st.file_uploader("Upload your Resume (PDF format only):", type="pdf", help="Ensure your resume is in PDF format for analysis.") # Display submit button with progress submit = st.button("Analyze Resume") if submit: if uploaded_file is not None and jd: # Show loading spinner while processing with st.spinner("Analyzing your resume, please wait..."): text = input_pdf_text(uploaded_file) response = get_gemeni_response(input_prompt.format(text=text, jd=jd)) # Retry parsing up to 2 times response_dict = None for _ in range(2): response_dict = parse_response(response) if response_dict: break time.sleep(1) # Slight delay before retrying if response_dict: # Display Job Description Match st.subheader("Job Description Match") st.metric(label="Matching Score", value=response_dict.get("JD Match", "N/A")) # Display Missing Keywords st.subheader("Top Missing Keywords") missing_keywords = response_dict.get("MissingKeywords", []) if missing_keywords: st.write(", ".join(missing_keywords)) else: st.write("All key terms are covered!") # Display Profile Summary st.subheader("Profile Summary") st.text(response_dict.get("ProfileSummary", "No summary available.")) # Generate downloadable report st.download_button( label="Download ATS Report", data=json.dumps(response_dict, indent=4), file_name="ATS_Analysis_Report.json", mime="application/json" ) else: st.error("Error parsing response. Please try again.") st.write(response) # Display raw response for debugging elif not jd: st.warning("Please paste a job description.") else: st.warning("Please upload your resume in PDF format.")