Spaces:
Sleeping
Sleeping
import streamlit as st | |
import google.generativeai as genai | |
from docx import Document | |
import PyPDF2 | |
# πΉ Streamlit UI | |
st.set_page_config(page_title="ATS Resume Optimizer", layout="wide") | |
st.title("π ATS-Compliant Resume Optimizer") | |
# πΉ Configure Google Gemini API | |
GOOGLE_API_KEY = st.secrets["GEMINI_API_KEY"] | |
genai.configure(api_key=GOOGLE_API_KEY) | |
model = genai.GenerativeModel("gemini-1.5-pro") | |
# πΉ Resume Upload | |
st.subheader("Upload Your Resume") | |
uploaded_file = st.file_uploader("Upload Resume (PDF or DOCX)", type=["pdf", "docx"]) | |
# πΉ Job Description Input | |
st.subheader("Paste Job Description") | |
job_description = st.text_area("Enter Job Description", height=150) | |
def extract_text_from_resume(uploaded_file): | |
"""Extract raw text from resume (PDF/DOCX)""" | |
if not uploaded_file: | |
return "" | |
try: | |
if uploaded_file.type == "application/pdf": | |
pdf_reader = PyPDF2.PdfReader(uploaded_file) | |
return "\n".join(page.extract_text() for page in pdf_reader.pages if page.extract_text()) | |
elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document": | |
doc = Document(uploaded_file) | |
return "\n".join(paragraph.text for paragraph in doc.paragraphs if paragraph.text) | |
except Exception as e: | |
st.error(f"β Error processing resume: {e}") | |
return "" | |
return "" | |
# πΉ Process Resume & JD | |
def generate_optimized_resume(resume_text, job_description): | |
""" | |
Uses LLM to enhance the resume for ATS optimization. | |
- Extracts JD keywords & integrates them into the resume | |
- Optimizes Professional Summary, Skills, Work Experience, and Projects | |
- Ensures ATS compliance with structured formatting | |
""" | |
prompt = f""" | |
You are an AI Career Assistant specializing in ATS-optimized resumes. | |
πΉ **TASK:** Modify the user's resume to align with the provided job description (JD). | |
πΉ **GOAL:** Ensure **keyword integration**, structured formatting, and ATS compliance while maintaining originality. | |
**π Job Description (JD):** | |
{job_description} | |
**π Original Resume:** | |
{resume_text} | |
--- | |
**πΉ PROCESS:** | |
1οΈβ£ **Extract Keywords from JD** β Identify essential skills, technologies, and job-related terms. | |
2οΈβ£ **Enhance Key Resume Sections:** | |
- **Professional Summary:** Rewrite using extracted JD keywords. | |
- **Skills Section:** Categorize into 6 key areas; list as comma-separated values. | |
- **Work Experience:** Naturally integrate JD keywords & **quantify achievements** (e.g., "Improved efficiency by 30%"). | |
- **Projects:** Highlight relevant projects & **technologies/tools used**. | |
3οΈβ£ **Ensure Structured, ATS-Friendly Formatting** β Use clean, readable formatting without tables/graphics. | |
4οΈβ£ **Adaptability Statement (if needed)** β Add: _"Although my resume wasnβt selected earlier, I am confident in learning & delivering results."_ | |
--- | |
**π OUTPUT FORMAT (Plain Text):** | |
Return the **fully optimized resume** in a clean, readable format, ensuring ATS compliance. | |
""" | |
# Call Gemini API | |
model = genai.GenerativeModel("gemini-1.5-pro") | |
response = model.generate_content(prompt) | |
return response.text if response else "β Error generating resume." | |
# πΉ Enhance Resume Button | |
if st.button("π Enhance Resume"): | |
if uploaded_file and job_description.strip(): | |
with st.spinner("Optimizing your resume..."): | |
resume_text = extract_text_from_resume(uploaded_file) | |
enhanced_resume = generate_optimized_resume(resume_text, job_description) | |
# β Display Enhanced Resume | |
st.subheader("π Optimized Resume") | |
st.text_area("Your ATS-Optimized Resume:", enhanced_resume, height=400) | |
# β Download Option | |
st.download_button( | |
label="π₯ Download Optimized Resume", | |
data=enhanced_resume, | |
file_name="optimized_resume.txt", | |
mime="text/plain" | |
) | |
else: | |
st.warning("β οΈ Please upload a resume and provide a job description.") | |