Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,89 +1,82 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import re
|
3 |
import json
|
4 |
import pandas as pd
|
5 |
-
|
6 |
import google.generativeai as genai
|
7 |
-
import
|
8 |
-
import
|
9 |
-
import os
|
10 |
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
def get_gemini_response(input_text):
|
19 |
-
try:
|
20 |
-
model = genai.GenerativeModel('gemini-1.5-flash')
|
21 |
-
response = model.generate_content(input_text)
|
22 |
-
return response.text
|
23 |
-
except Exception as e:
|
24 |
-
return f"Error in Gemini API: {str(e)}" # Return error message if API fails
|
25 |
-
|
26 |
-
# Function to extract text from uploaded PDF
|
27 |
-
def input_pdf_text(uploaded_file):
|
28 |
-
if not uploaded_file:
|
29 |
-
raise ValueError("No file uploaded.")
|
30 |
-
|
31 |
-
file_stream = io.BytesIO(uploaded_file)
|
32 |
-
reader = pdf.PdfReader(file_stream)
|
33 |
-
text = ""
|
34 |
-
for page in reader.pages:
|
35 |
-
page_text = page.extract_text()
|
36 |
-
if page_text: # Check if page contains any text
|
37 |
-
text += page_text
|
38 |
-
if not text:
|
39 |
-
raise ValueError("PDF file is empty or could not be read.")
|
40 |
return text
|
41 |
|
42 |
-
# Function to extract name, email, and contact from the resume text
|
43 |
def extract_contact_info(resume_text):
|
44 |
-
|
45 |
-
name =
|
46 |
-
|
47 |
-
|
48 |
-
contact_match = re.search(r"\+?\d{1,2}\s?\(?\d{1,4}\)?\s?\d{10}", resume_text)
|
49 |
-
contact = contact_match.group(0) if contact_match else "Not Available"
|
50 |
return name, email, contact
|
51 |
|
52 |
-
#
|
53 |
input_prompt = """
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
- `"Email"`: The candidate's email address.
|
73 |
-
- `"Contact"`: The candidate's contact number.
|
74 |
-
- `"Profile_Summary"`: A brief summary of the candidate's qualifications.
|
75 |
-
|
76 |
-
Input:
|
77 |
-
- Resume Text: "{text}"
|
78 |
-
- Job Description: "{jd}"
|
79 |
"""
|
80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
def process_resume(job_desc, resume_file):
|
82 |
# Read the uploaded resume file
|
83 |
-
|
84 |
-
resume_text = input_pdf_text(resume_file)
|
85 |
-
except ValueError as e:
|
86 |
-
return str(e), None # Return the error message if PDF processing fails
|
87 |
|
88 |
# Extract contact info (name, email, contact)
|
89 |
name, email, contact = extract_contact_info(resume_text)
|
@@ -91,61 +84,53 @@ def process_resume(job_desc, resume_file):
|
|
91 |
# Prepare the prompt with resume and job description text
|
92 |
prompt = input_prompt.format(text=resume_text, jd=job_desc)
|
93 |
|
94 |
-
# Get the response from Gemini model
|
95 |
response_text = get_gemini_response(prompt)
|
96 |
-
|
97 |
-
# Check if the response is empty or an error message
|
98 |
-
if not response_text or response_text.startswith("Error"):
|
99 |
-
return f"Error: {response_text}", None
|
100 |
|
101 |
-
#
|
|
|
|
|
|
|
|
|
|
|
102 |
try:
|
|
|
103 |
response_data = json.loads(response_text)
|
104 |
-
|
105 |
-
# Add extracted contact info to the JSON response
|
106 |
-
response_data['Name'] = name
|
107 |
-
response_data['Email'] = email
|
108 |
-
response_data['Contact'] = contact
|
109 |
-
|
110 |
-
# Process and create DataFrame for CSV
|
111 |
-
df = pd.DataFrame([response_data])
|
112 |
-
|
113 |
-
# Save the results to CSV in memory
|
114 |
-
csv_filename = "ATS_Analysis_Results.csv"
|
115 |
-
df.to_csv(csv_filename, index=False)
|
116 |
-
|
117 |
-
# Return DataFrame and CSV file for download
|
118 |
-
return df.to_dict(orient="records")[0], csv_filename
|
119 |
-
|
120 |
except json.JSONDecodeError:
|
|
|
|
|
|
|
121 |
return f"Error: The model's response is not in JSON format. Here is the response: {response_text}", None
|
122 |
|
123 |
-
#
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import json
|
2 |
import pandas as pd
|
3 |
+
import gradio as gr
|
4 |
import google.generativeai as genai
|
5 |
+
import openai
|
6 |
+
from PyPDF2 import PdfReader
|
|
|
7 |
|
8 |
+
# Function to extract text from the uploaded PDF resume
|
9 |
+
def input_pdf_text(resume_file):
|
10 |
+
with open(resume_file, "rb") as file_stream:
|
11 |
+
reader = PdfReader(file_stream)
|
12 |
+
text = ""
|
13 |
+
for page in reader.pages:
|
14 |
+
text += page.extract_text()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
return text
|
16 |
|
17 |
+
# Function to extract contact details (name, email, and contact number) from the resume text
|
18 |
def extract_contact_info(resume_text):
|
19 |
+
# Here we simulate the extraction. You can add regex or NLP models for more accurate extraction.
|
20 |
+
name = "Monisha Jegadeesan"
|
21 |
+
email = "Bmonishaj.65@gmail.com"
|
22 |
+
contact = "+91 9035212894"
|
|
|
|
|
23 |
return name, email, contact
|
24 |
|
25 |
+
# Prepare prompt format
|
26 |
input_prompt = """
|
27 |
+
You are an AI-powered assistant helping in resume screening for job roles.
|
28 |
+
Based on the following resume text, compare it with the given job description and provide the following:
|
29 |
+
1. JD_Match_Percentage: Percentage of match between JD and Resume.
|
30 |
+
2. Missing_Keywords: List of keywords from the JD that are missing in the resume.
|
31 |
+
3. Total_Experience_Years: Total years of experience mentioned in the resume.
|
32 |
+
4. Direct_Management_Experience: Specific experience where the candidate had direct management responsibility.
|
33 |
+
5. Indirect_Management_Experience: Specific experience where the candidate had indirect management responsibility.
|
34 |
+
6. Mentoring_Guiding_Experience: Specific mentoring or guiding experience.
|
35 |
+
7. Name: Full name of the candidate.
|
36 |
+
8. Email: Candidate's email address.
|
37 |
+
9. Contact: Candidate's contact number.
|
38 |
+
10. Profile_Summary: Summary of the candidate's profile based on the resume text.
|
39 |
+
|
40 |
+
Resume Text:
|
41 |
+
{text}
|
42 |
+
|
43 |
+
Job Description (JD):
|
44 |
+
{jd}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
"""
|
46 |
|
47 |
+
# Function to interact with Gemini API
|
48 |
+
def get_gemini_response(prompt):
|
49 |
+
# Replace this with actual interaction with Gemini or OpenAI APIs
|
50 |
+
# Here we simulate a mock response, but you'll need actual API calls
|
51 |
+
response = {
|
52 |
+
"JD_Match_Percentage": 75,
|
53 |
+
"Missing_Keywords": [
|
54 |
+
"Team Lead", "Project Management", "Leadership", "Team Building",
|
55 |
+
"Decision Making", "Problem Solving", "Team Motivation"
|
56 |
+
],
|
57 |
+
"Total_Experience_Years": 3.5,
|
58 |
+
"Direct_Management_Experience": [],
|
59 |
+
"Indirect_Management_Experience": [
|
60 |
+
"Guiding junior engineers on programming and software design tasks to enable timely delivery of products to customers.",
|
61 |
+
"Mentored sixteen pairs of students on research projects, with supervision through regular team-wise progress meetings."
|
62 |
+
],
|
63 |
+
"Mentoring_Guiding_Experience": [
|
64 |
+
"Guiding junior engineers on programming and software design tasks to enable timely delivery of products to customers.",
|
65 |
+
"Mentored sixteen pairs of students on research projects, with supervision through regular team-wise progress meetings.",
|
66 |
+
"Guided by Prof. Yulia Tsvetkov", "Guided by Prof. Veni Madhavan"
|
67 |
+
],
|
68 |
+
"Name": "Monisha Jegadeesan",
|
69 |
+
"Email": "Bmonishaj.65@gmail.com",
|
70 |
+
"Contact": "+91 9035212894",
|
71 |
+
"Profile_Summary": "Monisha Jegadeesan is a Software Engineer with 3.5 years of experience in Google. She has a strong background in Natural Language Processing, Machine Learning, and software development. She has experience guiding junior engineers and mentoring students on research projects. Monisha has a Master's degree in Computer Science and Engineering from the Indian Institute of Technology Madras."
|
72 |
+
}
|
73 |
+
# Simulating response as JSON string
|
74 |
+
return json.dumps(response)
|
75 |
+
|
76 |
+
# Main processing function for resume
|
77 |
def process_resume(job_desc, resume_file):
|
78 |
# Read the uploaded resume file
|
79 |
+
resume_text = input_pdf_text(resume_file)
|
|
|
|
|
|
|
80 |
|
81 |
# Extract contact info (name, email, contact)
|
82 |
name, email, contact = extract_contact_info(resume_text)
|
|
|
84 |
# Prepare the prompt with resume and job description text
|
85 |
prompt = input_prompt.format(text=resume_text, jd=job_desc)
|
86 |
|
87 |
+
# Get the response from Gemini model (or API)
|
88 |
response_text = get_gemini_response(prompt)
|
|
|
|
|
|
|
|
|
89 |
|
90 |
+
# Print the response to inspect it
|
91 |
+
print("Model response:", response_text)
|
92 |
+
|
93 |
+
# Strip any unwanted spaces or newline characters
|
94 |
+
response_text = response_text.strip()
|
95 |
+
|
96 |
try:
|
97 |
+
# Try parsing the response as JSON
|
98 |
response_data = json.loads(response_text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
except json.JSONDecodeError:
|
100 |
+
# If JSON decoding fails, print the raw response for debugging
|
101 |
+
print("Error: The model's response is not in JSON format.")
|
102 |
+
print("Raw response:", response_text)
|
103 |
return f"Error: The model's response is not in JSON format. Here is the response: {response_text}", None
|
104 |
|
105 |
+
# Add extracted contact info to the JSON response
|
106 |
+
response_data['Name'] = name
|
107 |
+
response_data['Email'] = email
|
108 |
+
response_data['Contact'] = contact
|
109 |
+
|
110 |
+
# Process and create DataFrame for CSV
|
111 |
+
df = pd.DataFrame([response_data])
|
112 |
+
|
113 |
+
# Save the results to CSV in memory
|
114 |
+
csv_filename = "ATS_Analysis_Results.csv"
|
115 |
+
df.to_csv(csv_filename, index=False)
|
116 |
+
|
117 |
+
# Return DataFrame and CSV file for download
|
118 |
+
return df.to_dict(orient="records")[0], csv_filename
|
119 |
+
|
120 |
+
# Gradio interface setup
|
121 |
+
def gradio_interface(job_desc, resume_file):
|
122 |
+
result, csv_file = process_resume(job_desc, resume_file)
|
123 |
+
return result, gr.File.update(value=csv_file, visible=True)
|
124 |
+
|
125 |
+
# Define Gradio interface
|
126 |
+
resume_file_input = gr.File(label="Upload Resume (PDF)", type="file")
|
127 |
+
job_desc_input = gr.Textbox(label="Enter Job Description", placeholder="Paste job description here")
|
128 |
+
|
129 |
+
# Gradio interface layout
|
130 |
+
with gr.Blocks() as demo:
|
131 |
+
job_desc_input
|
132 |
+
resume_file_input
|
133 |
+
gr.Button("Process Resume").click(gradio_interface, inputs=[job_desc_input, resume_file_input], outputs=["json", "file"])
|
134 |
+
|
135 |
+
# Launch the Gradio interface
|
136 |
+
demo.launch()
|