DreamStream-1 commited on
Commit
aba5fd5
·
verified ·
1 Parent(s): 94b2ddb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -31
app.py CHANGED
@@ -6,7 +6,9 @@ from PyPDF2 import PdfReader
6
  import docx
7
  import re
8
  import google.generativeai as genai
 
9
  import concurrent.futures
 
10
 
11
  # Load pre-trained embedding model for basic analysis
12
  sentence_model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
@@ -82,27 +84,40 @@ def extract_text_from_file(file_path):
82
  return ""
83
 
84
  def analyze_with_gemini(resume_text, job_desc):
85
- # Modified prompt to have Gemini calculate match percentage
86
  prompt = f"""
87
- Analyze the following resume and calculate the overall match percentage for the job description.
88
  Resume: {resume_text}
89
  Job Description: {job_desc}
90
-
91
- Provide:
92
  1. Candidate Name
93
  2. Email Address
94
  3. Contact Number
95
  4. Relevant Skills
96
  5. Educational Background
97
- 6. Leadership Experience (years)
98
  7. Management Experience (years)
99
- 8. Calculated Overall Match Percentage
100
-
101
- The Overall Match Percentage should represent how well the resume matches the job description, considering leadership, management, and skills.
102
  """
103
  response = genai.GenerativeModel('gemini-1.5-flash').generate_content(prompt)
104
  return response.text.strip()
105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  def extract_candidate_details(gemini_response):
107
  name_pattern = r"Candidate Name\s*[:\-]?\s*(.*?)(?=\n|$)"
108
  email_pattern = r"Email Address\s*[:\-]?\s*(.*?)(?=\n|$)"
@@ -118,6 +133,46 @@ def extract_candidate_details(gemini_response):
118
 
119
  return name, email, contact
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  def process_resume(resume, job_desc, progress_callback):
122
  resume_text = extract_text_from_file(resume.name)
123
 
@@ -127,23 +182,20 @@ def process_resume(resume, job_desc, progress_callback):
127
  "Candidate Name": "N/A",
128
  "Email": "N/A",
129
  "Contact": "N/A",
130
- "Overall Match Percentage": "0%",
131
  "Gemini Analysis": "Failed to extract text from resume."
132
  }
133
 
134
  try:
135
  gemini_analysis = analyze_with_gemini(resume_text, job_desc)
 
 
 
136
  name, email, contact = extract_candidate_details(gemini_analysis)
137
-
138
- # Extract the match percentage directly from Gemini response
139
- match_percentage_pattern = r"Overall Match Percentage\s*[:\-]?\s*(\d+)%"
140
- match_percentage_match = re.search(match_percentage_pattern, gemini_analysis)
141
- match_percentage = match_percentage_match.group(1) if match_percentage_match else "0"
142
-
143
  except Exception as e:
144
  gemini_analysis = f"Gemini analysis failed: {str(e)}"
145
  name, email, contact = "N/A", "N/A", "N/A"
146
- match_percentage = "0"
147
 
148
  progress_callback(1) # Update progress for this resume
149
 
@@ -152,7 +204,7 @@ def process_resume(resume, job_desc, progress_callback):
152
  "Candidate Name": name,
153
  "Email": email,
154
  "Contact": contact,
155
- "Overall Match Percentage": f"{match_percentage}%",
156
  "Gemini Analysis": gemini_analysis
157
  }
158
 
@@ -174,6 +226,9 @@ def analyze_resumes(resumes, job_desc):
174
  resume_count_message = f"{len(resumes)} resume(s) uploaded."
175
  return pd.DataFrame(results), resume_count_message
176
 
 
 
 
177
  # Gradio Interface with Submit Button and Progress Bar
178
  iface = gr.Interface(
179
  fn=analyze_resumes,
@@ -181,21 +236,12 @@ iface = gr.Interface(
181
  gr.File(label="Upload Resumes (PDF, DOCX, TXT)", file_count="multiple"),
182
  gr.Textbox(label="Job Description", lines=5)
183
  ],
184
- outputs=[
185
- gr.Dataframe(headers=["Resume", "Candidate Name", "Email", "Contact", "Overall Match Percentage", "Gemini Analysis"]),
186
- gr.Textbox(label="Status Message")
187
- ],
188
- live=True,
189
- title="Resume Analyzer with Leadership and Management Focus",
190
- description="Upload resumes and a job description to calculate match percentages based on leadership, management, and skills.",
191
- allow_flagging="never",
192
- theme="default"
193
  )
194
 
195
- # Add download option for the DataFrame
196
- def download_results(results_df):
197
- return results_df.to_csv(index=False)
198
-
199
  iface.add_component(gr.File(label="Download Results", file_output=download_results, visible=True))
200
 
201
- iface.launch(debug=True)
 
6
  import docx
7
  import re
8
  import google.generativeai as genai
9
+ import time
10
  import concurrent.futures
11
+ from fuzzywuzzy import fuzz
12
 
13
  # Load pre-trained embedding model for basic analysis
14
  sentence_model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
 
84
  return ""
85
 
86
  def analyze_with_gemini(resume_text, job_desc):
 
87
  prompt = f"""
88
+ Analyze the resume with respect to the job description.
89
  Resume: {resume_text}
90
  Job Description: {job_desc}
91
+ Extract:
 
92
  1. Candidate Name
93
  2. Email Address
94
  3. Contact Number
95
  4. Relevant Skills
96
  5. Educational Background
97
+ 6. Team Leadership Experience (years)
98
  7. Management Experience (years)
99
+ 8. Management Skills (e.g. strategic planning, team management, project management, etc.)
100
+ 9. Match Percentage (leadership and management focus)
101
+ Provide a summary of qualifications in 5 bullet points.
102
  """
103
  response = genai.GenerativeModel('gemini-1.5-flash').generate_content(prompt)
104
  return response.text.strip()
105
 
106
+ def extract_management_details(gemini_response):
107
+ leadership_exp_pattern = r"Team Leadership Experience \(years\):\s*(\d+)"
108
+ management_exp_pattern = r"Management Experience \(years\):\s*(\d+)"
109
+ management_skills_pattern = r"Management Skills\s*[:\-]?\s*(.*?)(?=\n|$)"
110
+
111
+ leadership_match = re.search(leadership_exp_pattern, gemini_response)
112
+ management_match = re.search(management_exp_pattern, gemini_response)
113
+ skills_match = re.search(management_skills_pattern, gemini_response)
114
+
115
+ leadership_years = int(leadership_match.group(1)) if leadership_match else 0
116
+ management_years = int(management_match.group(1)) if management_match else 0
117
+ skills = skills_match.group(1) if skills_match else ""
118
+
119
+ return leadership_years, management_years, skills
120
+
121
  def extract_candidate_details(gemini_response):
122
  name_pattern = r"Candidate Name\s*[:\-]?\s*(.*?)(?=\n|$)"
123
  email_pattern = r"Email Address\s*[:\-]?\s*(.*?)(?=\n|$)"
 
133
 
134
  return name, email, contact
135
 
136
+ def calculate_role_score(role_keywords):
137
+ seniority_score = 0
138
+ role_hierarchy = {
139
+ "CEO": 5,
140
+ "CIO": 5,
141
+ "Director": 4,
142
+ "VP": 4,
143
+ "Manager": 3,
144
+ "Team Lead": 2,
145
+ "Junior": 1
146
+ }
147
+
148
+ for keyword, score in role_hierarchy.items():
149
+ if fuzz.partial_ratio(keyword.lower(), role_keywords.lower()) > 80:
150
+ seniority_score = max(seniority_score, score)
151
+
152
+ return seniority_score
153
+
154
+ def calculate_advanced_match(leadership_years, management_years, skills, required_skills, role_keywords, max_leadership_exp=10, max_management_exp=10):
155
+ leadership_weight = 0.35
156
+ management_weight = 0.35
157
+ skills_weight = 0.2
158
+ role_weight = 0.1
159
+
160
+ leadership_score = min(leadership_years / max_leadership_exp, 1.0) * 100
161
+ management_score = min(management_years / max_management_exp, 1.0) * 100
162
+
163
+ role_score = calculate_role_score(role_keywords)
164
+ role_score = role_score * 100
165
+
166
+ skills_matched = sum(1 for skill in required_skills if fuzz.partial_ratio(skill.lower(), skills.lower()) > 80)
167
+ total_skills = len(required_skills)
168
+ skill_match_score = (skills_matched / total_skills) * 100
169
+
170
+ overall_match = (leadership_score * leadership_weight) + \
171
+ (management_score * management_weight) + \
172
+ (skill_match_score * skills_weight) + \
173
+ (role_score * role_weight)
174
+ return round(overall_match, 2)
175
+
176
  def process_resume(resume, job_desc, progress_callback):
177
  resume_text = extract_text_from_file(resume.name)
178
 
 
182
  "Candidate Name": "N/A",
183
  "Email": "N/A",
184
  "Contact": "N/A",
185
+ "Overall Match Percentage": 0.0,
186
  "Gemini Analysis": "Failed to extract text from resume."
187
  }
188
 
189
  try:
190
  gemini_analysis = analyze_with_gemini(resume_text, job_desc)
191
+ leadership_years, management_years, skills = extract_management_details(gemini_analysis)
192
+ role_keywords = gemini_analysis.lower()
193
+ overall_match = calculate_advanced_match(leadership_years, management_years, skills, required_skills, role_keywords)
194
  name, email, contact = extract_candidate_details(gemini_analysis)
 
 
 
 
 
 
195
  except Exception as e:
196
  gemini_analysis = f"Gemini analysis failed: {str(e)}"
197
  name, email, contact = "N/A", "N/A", "N/A"
198
+ overall_match = 0.0
199
 
200
  progress_callback(1) # Update progress for this resume
201
 
 
204
  "Candidate Name": name,
205
  "Email": email,
206
  "Contact": contact,
207
+ "Overall Match Percentage": f"{overall_match}%",
208
  "Gemini Analysis": gemini_analysis
209
  }
210
 
 
226
  resume_count_message = f"{len(resumes)} resume(s) uploaded."
227
  return pd.DataFrame(results), resume_count_message
228
 
229
+ def download_results(results):
230
+ return results.to_csv(index=False)
231
+
232
  # Gradio Interface with Submit Button and Progress Bar
233
  iface = gr.Interface(
234
  fn=analyze_resumes,
 
236
  gr.File(label="Upload Resumes (PDF, DOCX, TXT)", file_count="multiple"),
237
  gr.Textbox(label="Job Description", lines=5)
238
  ],
239
+ outputs=[gr.Dataframe(), gr.Textbox()],
240
+ live=False, # Disable auto-running during input
241
+ allow_flagging="never"
 
 
 
 
 
 
242
  )
243
 
244
+ # Add the file download option to the interface
 
 
 
245
  iface.add_component(gr.File(label="Download Results", file_output=download_results, visible=True))
246
 
247
+ iface.launch()