Update app.py
Browse files
app.py
CHANGED
@@ -7,6 +7,7 @@ import re
|
|
7 |
import google.generativeai as genai
|
8 |
import pandas as pd
|
9 |
import time
|
|
|
10 |
|
11 |
# Load pre-trained embedding model for basic analysis
|
12 |
sentence_model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
|
@@ -151,6 +152,44 @@ def calculate_overall_match(leadership_years, management_years, skills, required
|
|
151 |
overall_match = (leadership_score * leadership_weight) + (management_score * management_weight) + (skill_score * skills_weight)
|
152 |
return round(overall_match, 2)
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
def process_resumes(job_desc_file, resumes):
|
155 |
if not job_desc_file or not resumes:
|
156 |
return "Please upload a job description and resumes for analysis."
|
@@ -162,43 +201,17 @@ def process_resumes(job_desc_file, resumes):
|
|
162 |
job_desc = extract_text_from_file(job_desc_file)
|
163 |
|
164 |
results = []
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
"Candidate Name": "N/A",
|
172 |
-
"Email": "N/A",
|
173 |
-
"Contact": "N/A",
|
174 |
-
"Overall Match Percentage": 0.0,
|
175 |
-
"Gemini Analysis": "Failed to extract text from resume."
|
176 |
-
})
|
177 |
-
continue
|
178 |
-
|
179 |
-
# Detailed analysis with Gemini API
|
180 |
-
try:
|
181 |
-
gemini_analysis = analyze_with_gemini(resume_text, job_desc)
|
182 |
-
# Extract leadership and management details
|
183 |
-
leadership_years, management_years, skills = extract_management_details(gemini_analysis)
|
184 |
-
# Calculate overall match percentage
|
185 |
-
overall_match = calculate_overall_match(leadership_years, management_years, skills, required_skills)
|
186 |
-
# Extract candidate details
|
187 |
-
name, email, contact = extract_candidate_details(gemini_analysis)
|
188 |
-
except Exception as e:
|
189 |
-
gemini_analysis = f"Gemini analysis failed: {str(e)}"
|
190 |
-
name, email, contact = "N/A", "N/A", "N/A"
|
191 |
-
overall_match = 0.0
|
192 |
-
|
193 |
-
results.append({
|
194 |
-
"Resume": resume.name,
|
195 |
-
"Candidate Name": name,
|
196 |
-
"Email": email,
|
197 |
-
"Contact": contact,
|
198 |
-
"Overall Match Percentage": f"{overall_match}%",
|
199 |
-
"Gemini Analysis": gemini_analysis
|
200 |
-
})
|
201 |
|
|
|
|
|
|
|
|
|
202 |
# Create a pandas DataFrame for better formatting and downloadable output
|
203 |
df = pd.DataFrame(results)
|
204 |
|
|
|
7 |
import google.generativeai as genai
|
8 |
import pandas as pd
|
9 |
import time
|
10 |
+
import concurrent.futures
|
11 |
|
12 |
# Load pre-trained embedding model for basic analysis
|
13 |
sentence_model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
|
|
|
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):
|
156 |
+
resume_text = extract_text_from_file(resume.name)
|
157 |
+
|
158 |
+
if not resume_text.strip():
|
159 |
+
return {
|
160 |
+
"Resume": resume.name,
|
161 |
+
"Candidate Name": "N/A",
|
162 |
+
"Email": "N/A",
|
163 |
+
"Contact": "N/A",
|
164 |
+
"Overall Match Percentage": 0.0,
|
165 |
+
"Gemini Analysis": "Failed to extract text from resume."
|
166 |
+
}
|
167 |
+
|
168 |
+
# Detailed analysis with Gemini API
|
169 |
+
try:
|
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:
|
178 |
+
gemini_analysis = f"Gemini analysis failed: {str(e)}"
|
179 |
+
name, email, contact = "N/A", "N/A", "N/A"
|
180 |
+
overall_match = 0.0
|
181 |
+
|
182 |
+
progress_callback(1) # Update progress for this resume
|
183 |
+
|
184 |
+
return {
|
185 |
+
"Resume": resume.name,
|
186 |
+
"Candidate Name": name,
|
187 |
+
"Email": email,
|
188 |
+
"Contact": contact,
|
189 |
+
"Overall Match Percentage": f"{overall_match}%",
|
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."
|
|
|
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 |
|