DreamStream-1 commited on
Commit
bf3038a
·
verified ·
1 Parent(s): 42f608d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -51
app.py CHANGED
@@ -1,11 +1,11 @@
 
1
  import gradio as gr
 
2
  from sentence_transformers import SentenceTransformer, util
3
- import os
4
  from PyPDF2 import PdfReader
5
  import docx
6
  import re
7
  import google.generativeai as genai
8
- import pandas as pd
9
  import time
10
  import concurrent.futures
11
 
@@ -133,23 +133,50 @@ def extract_candidate_details(gemini_response):
133
 
134
  return name, email, contact
135
 
136
- def calculate_overall_match(leadership_years, management_years, skills, required_skills, max_leadership_exp=10, max_management_exp=10):
137
- # Assign weight to leadership, management, and relevant skills
138
- leadership_weight = 0.4 # 40% weight to leadership
139
- management_weight = 0.4 # 40% weight to management
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  skills_weight = 0.2 # 20% weight to skills
 
141
 
142
- # Normalize years of experience to 100% scale (if maximum years of experience is 10 years)
143
  leadership_score = min(leadership_years / max_leadership_exp, 1.0) * 100
144
  management_score = min(management_years / max_management_exp, 1.0) * 100
145
 
146
- # Calculate skill match (based on whether any required skills are present in the resume)
147
- skill_match = any(skill.lower() in skills.lower() for skill in required_skills)
 
148
 
149
- skill_score = 100 if skill_match else 0
 
 
 
150
 
151
  # Calculate the overall match score
152
- overall_match = (leadership_score * leadership_weight) + (management_score * management_weight) + (skill_score * skills_weight)
 
 
 
153
  return round(overall_match, 2)
154
 
155
  def process_resume(resume, job_desc, progress_callback):
@@ -170,8 +197,9 @@ def process_resume(resume, job_desc, progress_callback):
170
  gemini_analysis = analyze_with_gemini(resume_text, job_desc)
171
  # Extract leadership and management details
172
  leadership_years, management_years, skills = extract_management_details(gemini_analysis)
173
- # Calculate overall match percentage
174
- overall_match = calculate_overall_match(leadership_years, management_years, skills, required_skills)
 
175
  # Extract candidate details
176
  name, email, contact = extract_candidate_details(gemini_analysis)
177
  except Exception as e:
@@ -190,48 +218,36 @@ def process_resume(resume, job_desc, progress_callback):
190
  "Gemini Analysis": gemini_analysis
191
  }
192
 
193
- def process_resumes(job_desc_file, resumes):
194
- if not job_desc_file or not resumes:
195
- return "Please upload a job description and resumes for analysis."
196
-
197
- if len(resumes) > MAX_RESUMES:
198
- return f"Please upload no more than {MAX_RESUMES} resumes."
199
-
200
- # Load job description text
201
- job_desc = extract_text_from_file(job_desc_file)
202
-
203
  results = []
204
- total_resumes = len(resumes)
205
-
206
- with concurrent.futures.ThreadPoolExecutor() as executor:
207
- future_to_resume = {
208
- executor.submit(process_resume, resume, job_desc, lambda p: None): resume for resume in resumes
209
- }
210
-
211
- for future in concurrent.futures.as_completed(future_to_resume):
212
- result = future.result()
213
- results.append(result)
214
 
215
- # Create a pandas DataFrame for better formatting and downloadable output
216
- df = pd.DataFrame(results)
217
-
218
- # Output the DataFrame as a CSV file for download
219
- output_file = "/tmp/analysis_results.csv"
220
- df.to_csv(output_file, index=False)
 
 
 
 
 
 
221
 
222
- return df, output_file
 
223
 
224
  # Gradio Interface
225
- job_desc_input = gr.File(label="Upload Job Description (TXT, PDF, DOCX)", type="filepath")
226
- resumes_input = gr.Files(label="Upload Resumes (TXT, PDF, DOCX)", type="filepath")
227
- results_output = gr.Textbox(label="Analysis Results", lines=30)
228
-
229
- interface = gr.Interface(
230
- fn=process_resumes,
231
- inputs=[job_desc_input, resumes_input],
232
- outputs=[results_output, gr.File(label="Download Results CSV")],
233
- title="Resume Analysis with Gemini API",
234
- description="Upload a job description and resumes to evaluate candidates' leadership and management match."
235
  )
236
 
237
- interface.launch()
 
1
+ import os
2
  import gradio as gr
3
+ import pandas as pd
4
  from sentence_transformers import SentenceTransformer, util
 
5
  from PyPDF2 import PdfReader
6
  import docx
7
  import re
8
  import google.generativeai as genai
 
9
  import time
10
  import concurrent.futures
11
 
 
133
 
134
  return name, email, contact
135
 
136
+ def calculate_role_score(role_keywords):
137
+ # Score based on the seniority of the leadership role
138
+ seniority_score = 0
139
+ role_hierarchy = {
140
+ "CEO": 5,
141
+ "CIO": 5,
142
+ "Director": 4,
143
+ "VP": 4,
144
+ "Manager": 3,
145
+ "Team Lead": 2,
146
+ "Junior": 1
147
+ }
148
+
149
+ for keyword, score in role_hierarchy.items():
150
+ if keyword.lower() in role_keywords.lower():
151
+ seniority_score = max(seniority_score, score) # Highest score from role hierarchy
152
+
153
+ return seniority_score
154
+
155
+ def calculate_advanced_match(leadership_years, management_years, skills, required_skills, role_keywords, max_leadership_exp=10, max_management_exp=10):
156
+ # Assign weights for leadership, management, and skills
157
+ leadership_weight = 0.35 # 35% weight to leadership
158
+ management_weight = 0.35 # 35% weight to management
159
  skills_weight = 0.2 # 20% weight to skills
160
+ role_weight = 0.1 # 10% weight to role seniority
161
 
162
+ # Normalize years of experience to a 100% scale
163
  leadership_score = min(leadership_years / max_leadership_exp, 1.0) * 100
164
  management_score = min(management_years / max_management_exp, 1.0) * 100
165
 
166
+ # Adjust for role seniority
167
+ role_score = calculate_role_score(role_keywords) # Role score based on seniority of role
168
+ role_score = role_score * 100 # Normalize role score to 100 scale
169
 
170
+ # Calculate skill match: percentage of required skills found in the resume
171
+ skills_matched = sum(1 for skill in required_skills if skill.lower() in skills.lower())
172
+ total_skills = len(required_skills)
173
+ skill_match_score = (skills_matched / total_skills) * 100
174
 
175
  # Calculate the overall match score
176
+ overall_match = (leadership_score * leadership_weight) + \
177
+ (management_score * management_weight) + \
178
+ (skill_match_score * skills_weight) + \
179
+ (role_score * role_weight)
180
  return round(overall_match, 2)
181
 
182
  def process_resume(resume, job_desc, progress_callback):
 
197
  gemini_analysis = analyze_with_gemini(resume_text, job_desc)
198
  # Extract leadership and management details
199
  leadership_years, management_years, skills = extract_management_details(gemini_analysis)
200
+ # Calculate overall match percentage using enhanced calculation
201
+ role_keywords = gemini_analysis.lower()
202
+ overall_match = calculate_advanced_match(leadership_years, management_years, skills, required_skills, role_keywords)
203
  # Extract candidate details
204
  name, email, contact = extract_candidate_details(gemini_analysis)
205
  except Exception as e:
 
218
  "Gemini Analysis": gemini_analysis
219
  }
220
 
221
+ # Main Gradio UI
222
+ def analyze_resumes(resumes, job_desc):
223
+ progress = gr.Progress()
 
 
 
 
 
 
 
224
  results = []
 
 
 
 
 
 
 
 
 
 
225
 
226
+ # Check for maximum number of resumes
227
+ if len(resumes) > MAX_RESUMES:
228
+ return "Error: Cannot upload more than 10 resumes."
229
+
230
+ # Process resumes concurrently
231
+ with concurrent.futures.ThreadPoolExecutor() as executor:
232
+ futures = []
233
+ for resume in resumes:
234
+ futures.append(executor.submit(process_resume, resume, job_desc, progress.update))
235
+
236
+ for future in concurrent.futures.as_completed(futures):
237
+ results.append(future.result())
238
 
239
+ resume_count_message = f"{len(resumes)} resume(s) uploaded."
240
+ return pd.DataFrame(results), resume_count_message
241
 
242
  # Gradio Interface
243
+ iface = gr.Interface(
244
+ fn=analyze_resumes,
245
+ inputs=[
246
+ gr.File(label="Upload Resumes (PDF, DOCX, TXT)", file_count="multiple"),
247
+ gr.Textbox(label="Job Description", lines=5)
248
+ ],
249
+ outputs=["dataframe", "text"],
250
+ live=True
 
 
251
  )
252
 
253
+ iface.launch()