Spaces:
Running
Running
Update app.py
#1
by
akshayparmar
- opened
app.py
CHANGED
|
@@ -1,114 +1,129 @@
|
|
| 1 |
-
import os
|
| 2 |
-
import streamlit as st
|
| 3 |
-
from dotenv import load_dotenv
|
| 4 |
-
from PIL import Image
|
| 5 |
-
import google.generativeai as genai
|
| 6 |
-
from pdf2image import convert_from_path
|
| 7 |
-
import pytesseract
|
| 8 |
-
import pdfplumber
|
| 9 |
-
|
| 10 |
-
# Load environment variables
|
| 11 |
-
load_dotenv()
|
| 12 |
-
|
| 13 |
-
# Configure Google Gemini AI
|
| 14 |
-
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
|
| 15 |
-
|
| 16 |
-
# Function to extract text from PDF
|
| 17 |
-
def extract_text_from_pdf(pdf_path):
|
| 18 |
-
text = ""
|
| 19 |
-
try:
|
| 20 |
-
# Try direct text extraction
|
| 21 |
-
with pdfplumber.open(pdf_path) as pdf:
|
| 22 |
-
for page in pdf.pages:
|
| 23 |
-
page_text = page.extract_text()
|
| 24 |
-
if page_text:
|
| 25 |
-
text += page_text
|
| 26 |
-
|
| 27 |
-
if text.strip():
|
| 28 |
-
return text.strip()
|
| 29 |
-
except Exception as e:
|
| 30 |
-
print(f"Direct text extraction failed: {e}")
|
| 31 |
-
|
| 32 |
-
# Fallback to OCR for image-based PDFs
|
| 33 |
-
print("Falling back to OCR for image-based PDF.")
|
| 34 |
-
try:
|
| 35 |
-
images = convert_from_path(pdf_path)
|
| 36 |
-
for image in images:
|
| 37 |
-
page_text = pytesseract.image_to_string(image)
|
| 38 |
-
text += page_text + "\n"
|
| 39 |
-
except Exception as e:
|
| 40 |
-
print(f"OCR failed: {e}")
|
| 41 |
-
|
| 42 |
-
return text.strip()
|
| 43 |
-
|
| 44 |
-
# Function to get response from Gemini AI
|
| 45 |
-
def analyze_resume(resume_text, job_description=None):
|
| 46 |
-
if not resume_text:
|
| 47 |
-
return {"error": "Resume text is required for analysis."}
|
| 48 |
-
|
| 49 |
-
model = genai.GenerativeModel("gemini-
|
| 50 |
-
|
| 51 |
-
base_prompt = f"""
|
| 52 |
-
You are an experienced HR with Technical Experience in the field of any one job role from Data Science, Data Analyst, DevOPS, Machine Learning Engineer, Prompt Engineer, AI Engineer, Full Stack Web Development, Big Data Engineering, Marketing Analyst, Human Resource Manager, Software Developer your task is to review the provided resume.
|
| 53 |
-
Please share your professional evaluation on whether the candidate's profile aligns with the role.ALso mention Skills he already have and siggest some skills to imorve his resume , alos suggest some course he might take to improve the skills.Highlight the strengths and weaknesses.
|
| 54 |
-
|
| 55 |
-
Resume:
|
| 56 |
-
{resume_text}
|
| 57 |
-
"""
|
| 58 |
-
|
| 59 |
-
if job_description:
|
| 60 |
-
base_prompt += f"""
|
| 61 |
-
Additionally, compare this resume to the following job description:
|
| 62 |
-
|
| 63 |
-
Job Description:
|
| 64 |
-
{job_description}
|
| 65 |
-
|
| 66 |
-
Highlight the strengths and weaknesses of the applicant in relation to the specified job requirements.
|
| 67 |
-
"""
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import streamlit as st
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
from PIL import Image
|
| 5 |
+
import google.generativeai as genai
|
| 6 |
+
from pdf2image import convert_from_path
|
| 7 |
+
import pytesseract
|
| 8 |
+
import pdfplumber
|
| 9 |
+
|
| 10 |
+
# Load environment variables
|
| 11 |
+
load_dotenv()
|
| 12 |
+
|
| 13 |
+
# Configure Google Gemini AI
|
| 14 |
+
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
|
| 15 |
+
|
| 16 |
+
# Function to extract text from PDF
|
| 17 |
+
def extract_text_from_pdf(pdf_path):
|
| 18 |
+
text = ""
|
| 19 |
+
try:
|
| 20 |
+
# Try direct text extraction
|
| 21 |
+
with pdfplumber.open(pdf_path) as pdf:
|
| 22 |
+
for page in pdf.pages:
|
| 23 |
+
page_text = page.extract_text()
|
| 24 |
+
if page_text:
|
| 25 |
+
text += page_text
|
| 26 |
+
|
| 27 |
+
if text.strip():
|
| 28 |
+
return text.strip()
|
| 29 |
+
except Exception as e:
|
| 30 |
+
print(f"Direct text extraction failed: {e}")
|
| 31 |
+
|
| 32 |
+
# Fallback to OCR for image-based PDFs
|
| 33 |
+
print("Falling back to OCR for image-based PDF.")
|
| 34 |
+
try:
|
| 35 |
+
images = convert_from_path(pdf_path)
|
| 36 |
+
for image in images:
|
| 37 |
+
page_text = pytesseract.image_to_string(image)
|
| 38 |
+
text += page_text + "\n"
|
| 39 |
+
except Exception as e:
|
| 40 |
+
print(f"OCR failed: {e}")
|
| 41 |
+
|
| 42 |
+
return text.strip()
|
| 43 |
+
|
| 44 |
+
# Function to get response from Gemini AI
|
| 45 |
+
def analyze_resume(resume_text, job_description=None, linkedin_profile=None, location=None):
|
| 46 |
+
if not resume_text:
|
| 47 |
+
return {"error": "Resume text is required for analysis."}
|
| 48 |
+
|
| 49 |
+
model = genai.GenerativeModel("gemini-2.5-flash")
|
| 50 |
+
|
| 51 |
+
base_prompt = f"""
|
| 52 |
+
You are an experienced HR with Technical Experience in the field of any one job role from Data Science, Data Analyst, DevOPS, Machine Learning Engineer, Prompt Engineer, AI Engineer, Full Stack Web Development, Big Data Engineering, Marketing Analyst, Human Resource Manager, Software Developer your task is to review the provided resume.
|
| 53 |
+
Please share your professional evaluation on whether the candidate's profile aligns with the role.ALso mention Skills he already have and siggest some skills to imorve his resume , alos suggest some course he might take to improve the skills.Highlight the strengths and weaknesses.
|
| 54 |
+
|
| 55 |
+
Resume:
|
| 56 |
+
{resume_text}
|
| 57 |
+
"""
|
| 58 |
+
|
| 59 |
+
if job_description:
|
| 60 |
+
base_prompt += f"""
|
| 61 |
+
Additionally, compare this resume to the following job description:
|
| 62 |
+
|
| 63 |
+
Job Description:
|
| 64 |
+
{job_description}
|
| 65 |
+
|
| 66 |
+
Highlight the strengths and weaknesses of the applicant in relation to the specified job requirements.
|
| 67 |
+
"""
|
| 68 |
+
|
| 69 |
+
if linkedin_profile:
|
| 70 |
+
base_prompt += f"""
|
| 71 |
+
Additionally, compare this resume & use this following LinkedIn Profile Link: and also Find the 5 most relevant recent job postings based on the resume recieved from resume advisor and location preference. This is the preferred location: {location} .
|
| 72 |
+
Use the tools to gather relevant content and shortlist the 5 most relevant, recent, job openings
|
| 73 |
+
|
| 74 |
+
LinkedIn Profile:
|
| 75 |
+
{linkedin_profile}
|
| 76 |
+
|
| 77 |
+
Highlight the bullet point list of the 5 job openings, with the appropriate links and detailed description about each job, in markdown format.
|
| 78 |
+
"""
|
| 79 |
+
|
| 80 |
+
response = model.generate_content(base_prompt)
|
| 81 |
+
|
| 82 |
+
analysis = response.text.strip()
|
| 83 |
+
return analysis
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
# Streamlit app
|
| 87 |
+
|
| 88 |
+
st.set_page_config(page_title="Resume Analyzer", layout="wide")
|
| 89 |
+
# Title
|
| 90 |
+
st.title("AI Resume Analyzer")
|
| 91 |
+
st.write("Analyze your resume and match it with job descriptions using Google Gemini AI.")
|
| 92 |
+
|
| 93 |
+
col1 , col2 , col3 , col4 = st.columns(4)
|
| 94 |
+
with col1:
|
| 95 |
+
uploaded_file = st.file_uploader("Upload your resume (PDF)", type=["pdf"])
|
| 96 |
+
with col2:
|
| 97 |
+
job_description = st.text_area("Enter Job Description:", placeholder="Paste the job description here...")
|
| 98 |
+
with col3:
|
| 99 |
+
linkedin_profile = st.text_area("Enter LinkedIn Profile:", placeholder="Paste the LinkedIn Profile here...")
|
| 100 |
+
with col4:
|
| 101 |
+
location = st.text_area("Location:", placeholder="Paste the Location here...")
|
| 102 |
+
|
| 103 |
+
if uploaded_file is not None:
|
| 104 |
+
st.success("Resume uploaded successfully!")
|
| 105 |
+
else:
|
| 106 |
+
st.warning("Please upload a resume in PDF format.")
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
st.markdown("<div style= 'padding-top: 10px;'></div>", unsafe_allow_html=True)
|
| 110 |
+
if uploaded_file:
|
| 111 |
+
# Save uploaded file locally for processing
|
| 112 |
+
with open("uploaded_resume.pdf", "wb") as f:
|
| 113 |
+
f.write(uploaded_file.getbuffer())
|
| 114 |
+
# Extract text from PDF
|
| 115 |
+
resume_text = extract_text_from_pdf("uploaded_resume.pdf")
|
| 116 |
+
|
| 117 |
+
if st.button("Analyze Resume"):
|
| 118 |
+
with st.spinner("Analyzing resume..."):
|
| 119 |
+
try:
|
| 120 |
+
# Analyze resume
|
| 121 |
+
analysis = analyze_resume(resume_text, job_description, linkedin_profile, location)
|
| 122 |
+
st.success("Analysis complete!")
|
| 123 |
+
st.write(analysis)
|
| 124 |
+
except Exception as e:
|
| 125 |
+
st.error(f"Analysis failed: {e}")
|
| 126 |
+
|
| 127 |
+
#Footer
|
| 128 |
+
st.markdown("---")
|
| 129 |
+
st.markdown("""<p style= 'text-align: center;' >Powered by <b>Streamlit</b> and <b>Google Gemini AI</b> | Developed by <a href="https://www.linkedin.com/in/dutta-sujoy/" target="_blank" style='text-decoration: none; color: #FFFFFF'><b>Sujoy Dutta</b></a></p>""", unsafe_allow_html=True)
|