CR7CAD commited on
Commit
4110522
·
verified ·
1 Parent(s): a739933

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -138
app.py CHANGED
@@ -315,185 +315,222 @@ def summarize_resume_text(resume_text):
315
  #####################################
316
  def analyze_google_fit(resume_summary):
317
  """
318
- Analyze how well the candidate fits Google's requirements with detailed category breakdowns.
 
319
  """
320
- start_time = time.time()
321
-
322
- # Define Google's key skill categories with more detailed keywords
323
- google_keywords = {
324
- "technical_skills": ["python", "java", "c++", "javascript", "go", "sql", "algorithms", "data structures",
325
- "coding", "software development", "git", "programming", "backend", "frontend", "full-stack"],
326
- "advanced_tech": ["machine learning", "ai", "artificial intelligence", "cloud", "data science", "big data",
327
- "tensorflow", "deep learning", "distributed systems", "kubernetes", "microservices"],
328
- "problem_solving": ["problem solving", "analytical", "critical thinking", "troubleshooting", "debugging",
329
- "optimization", "scalability", "system design", "complexity", "efficiency"],
330
- "innovation": ["innovation", "creative", "creativity", "design thinking", "research", "novel solutions",
331
- "patents", "publications", "unique approaches", "cutting-edge"],
332
- "soft_skills": ["team", "leadership", "collaboration", "communication", "agile", "project management",
333
- "mentoring", "cross-functional", "presentation", "stakeholder management"]
334
- }
335
 
336
- # Category weights with descriptive labels
337
- category_weights = {
338
- "technical_skills": {"weight": 0.35, "label": "Technical Programming Skills"},
339
- "advanced_tech": {"weight": 0.25, "label": "Advanced Technology Knowledge"},
340
- "problem_solving": {"weight": 0.20, "label": "Problem Solving Abilities"},
341
- "innovation": {"weight": 0.10, "label": "Innovation Mindset"},
342
- "soft_skills": {"weight": 0.10, "label": "Collaboration & Leadership"}
343
- }
344
 
345
- resume_lower = resume_summary.lower()
 
346
 
347
- # Calculate category scores and store detailed information
348
- category_scores = {}
349
- category_details = {}
350
- found_skills = {}
351
 
352
- for category, keywords in google_keywords.items():
353
- # Find the specific matching keywords for feedback
354
- category_matches = [keyword for keyword in keywords if keyword in resume_lower]
355
- found_skills[category] = category_matches
356
-
357
- # Count matches but cap at a reasonable level
358
- matches = len(category_matches)
359
- total_keywords = len(keywords)
360
-
361
- # Calculate raw percentage for this category
362
- raw_percentage = int((matches / total_keywords) * 100)
363
-
364
- # Apply logarithmic scaling for more realistic scores
365
- if matches == 0:
366
- adjusted_score = 0.0
367
- else:
368
- # Logarithmic scaling to prevent perfect scores
369
- adjusted_score = min(0.95, (math.log(matches + 1) / math.log(min(total_keywords, 8) + 1)))
370
-
371
- # Store both raw and adjusted scores for feedback
372
- category_scores[category] = adjusted_score
373
- category_details[category] = {
374
- "raw_percentage": raw_percentage,
375
- "adjusted_score": int(adjusted_score * 100),
376
- "matching_keywords": category_matches,
377
- "total_keywords": total_keywords,
378
- "matches": matches
379
- }
380
-
381
- # Calculate weighted score
382
- weighted_score = sum(score * category_weights[category]["weight"] for category, score in category_scores.items())
383
-
384
- # Apply final curve to keep scores in a realistic range
385
- match_percentage = min(92, max(35, int(weighted_score * 100)))
386
-
387
- # Find top strengths and areas for improvement
388
- strengths = [(category_weights[cat]["label"], details["adjusted_score"])
389
- for cat, details in category_details.items()
390
- if details["adjusted_score"] >= 60]
391
-
392
- weaknesses = [(category_weights[cat]["label"], details["adjusted_score"])
393
- for cat, details in category_details.items()
394
- if details["adjusted_score"] < 50]
395
-
396
- # Sort strengths and weaknesses by score
397
- strengths.sort(key=lambda x: x[1], reverse=True)
398
- weaknesses.sort(key=lambda x: x[1])
399
-
400
- # Create a more detailed prompt for assessment
401
- strength_text = ", ".join([f"{s[0]}" for s in strengths[:3]]) if strengths else "limited applicable skills"
402
- weakness_text = ", ".join([f"{w[0]}" for w in weaknesses[:3]]) if weaknesses else "no obvious weaknesses"
403
-
404
- # Extract key resume elements
405
- skills_match = re.search(r'Skills:.*?(?=\n\n|$)', resume_summary, re.DOTALL)
406
- skills_text = skills_match.group(0) if skills_match else ""
407
-
408
- work_match = re.search(r'Previous Work Experience:.*?(?=\n\n|$)', resume_summary, re.DOTALL)
409
- work_text = work_match.group(0) if work_match else ""
410
-
411
- # List specific matching skills for more detailed assessment
412
- specific_skills = []
413
- for category, matches in found_skills.items():
414
- if matches:
415
- specific_skills.extend(matches[:3]) # Take up to 3 skills from each category
416
 
417
- specific_skills_text = ", ".join(specific_skills[:8]) if specific_skills else "limited identifiable skills"
 
 
418
 
 
419
  prompt = f"""
420
- Write a detailed assessment of a job candidate for Google.
421
- Resume highlights: Skills in {specific_skills_text}. {work_text[:200]}
422
- Strengths: {strength_text}
423
- Areas for improvement: {weakness_text}
424
- Match percentage: {match_percentage}%
425
-
426
- Write a detailed 3-5 sentence assessment beginning with "This candidate". Be specific about skills, experiences,
427
- strengths, weaknesses, and how they align with Google. Mention specific technical skills where relevant.
 
 
 
 
 
 
 
428
  """
429
 
430
  try:
431
- # Generate the assessment
432
  assessment_results = models['evaluator'](
433
  prompt,
434
- max_length=350, # Longer assessment
435
  do_sample=True,
436
- temperature=0.7, # Higher temperature for more detailed output
437
  num_return_sequences=3
438
  )
439
 
440
  # Find the best response
441
- assessment = None
442
  for result in assessment_results:
443
  text = result['generated_text'].strip()
444
 
445
- # Remove prompt artifacts
446
- text = re.sub(r'Write a detailed assessment.*?Match percentage:.*?%', '', text, flags=re.DOTALL)
447
- text = re.sub(r'Write a detailed 3-5 sentence assessment.*?', '', text, flags=re.DOTALL)
448
 
449
- # Check if it looks valid
450
- if "this candidate" in text.lower() and len(text) > 100:
451
- assessment = text
452
  break
453
 
454
- # If no good response was found, fall back to manual assessment
455
- if not assessment:
456
- assessment = generate_detailed_manual_assessment(resume_summary, strengths, weaknesses, specific_skills, match_percentage)
 
 
 
 
 
 
 
 
 
 
 
 
 
457
 
458
  except Exception as e:
459
- # Fallback to detailed manual assessment
460
- assessment = generate_detailed_manual_assessment(resume_summary, strengths, weaknesses, specific_skills, match_percentage)
461
- print(f"Error in assessment generation: {e}")
462
 
463
  # Final cleanup
 
 
 
464
  assessment = assessment.strip()
465
- if not assessment.startswith("This candidate"):
466
- assessment = f"This candidate {assessment}"
467
 
468
- execution_time = time.time() - start_time
 
 
 
469
 
470
  return assessment, match_percentage, category_details, execution_time
471
 
472
- def generate_detailed_manual_assessment(resume_summary, strengths, weaknesses, specific_skills, match_percentage):
 
473
  """
474
- Generate a detailed manual assessment when the model fails.
 
475
  """
476
- # Start with strengths
477
- if strengths:
478
- assessment = f"This candidate demonstrates proficiency in {', '.join([s[0] for s in strengths[:2]])}. "
479
- if specific_skills:
480
- assessment += f"Their experience with {', '.join(specific_skills[:4])} aligns with Google's technical requirements. "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  else:
482
- assessment = "This candidate has limited alignment with Google's key requirements based on the resume provided. "
483
- if specific_skills:
484
- assessment += f"While they have some experience with {', '.join(specific_skills[:3])}, these skills alone may not be sufficient. "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485
 
486
- # Add weaknesses
487
- if weaknesses:
488
- assessment += f"To improve their candidacy for Google, they should focus on developing stronger {' and '.join([w[0].lower() for w in weaknesses[:2]])}. "
 
 
 
 
489
 
490
- # Add conclusion with match percentage
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  if match_percentage >= 70:
492
- assessment += f"Overall, they show good potential for certain roles at Google with a {match_percentage}% match to requirements."
493
  elif match_percentage >= 50:
494
- assessment += f"With targeted skill development, they may become a stronger candidate for Google, currently showing a {match_percentage}% match."
495
  else:
496
- assessment += f"Significant skill development would be needed before they could be considered a strong Google candidate, with a current match of {match_percentage}%."
497
 
498
  return assessment
499
 
 
315
  #####################################
316
  def analyze_google_fit(resume_summary):
317
  """
318
+ Analyze how well the candidate fits Google's requirements.
319
+ Only modifying the T5 prompt to get better expert assessments.
320
  """
321
+ # [Keep all the existing code for score calculation unchanged]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
 
323
+ # Get more specific information for a better prompt
324
+ # Get top skills across all categories (up to 5 total)
325
+ all_matching_skills = []
326
+ for category, matches in found_skills.items():
327
+ if matches:
328
+ all_matching_skills.extend(matches)
 
 
329
 
330
+ top_skills = list(set(all_matching_skills))[:5] # Remove duplicates and take top 5
331
+ skills_text = ", ".join(top_skills) if top_skills else "limited relevant skills"
332
 
333
+ # Get strongest and weakest categories for more specific feedback
334
+ categories_sorted = sorted(category_details.items(), key=lambda x: x[1]["adjusted_score"], reverse=True)
335
+ top_category = category_weights[categories_sorted[0][0]]["label"]
336
+ weak_category = category_weights[categories_sorted[-1][0]]["label"]
337
 
338
+ # Extract work experience highlights
339
+ experience_match = re.search(r'Previous Work Experience:.*?(?=\n\n|$)', resume_summary, re.DOTALL)
340
+ experience_text = experience_match.group(0) if experience_match else ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
 
342
+ # Extract just 1-2 key experiences
343
+ experiences = re.findall(r'([A-Z][^.]*?company|[A-Z][^.]*?engineer|[A-Z][^.]*?developer|[A-Z][^.]*?Google|[A-Z][^.]*?Microsoft|[A-Z][^.]*?Amazon)', experience_text)
344
+ experience_highlights = ", ".join(experiences[:2]) if experiences else "work experience"
345
 
346
+ # Create a more specific prompt for T5 that focuses on detailed assessment
347
  prompt = f"""
348
+ Generate Google candidate assessment.
349
+ Skills detected: {skills_text}.
350
+ Experience: {experience_highlights}.
351
+ Strongest area: {top_category} ({categories_sorted[0][1]["adjusted_score"]}%).
352
+ Weakest area: {weak_category} ({categories_sorted[-1][1]["adjusted_score"]}%).
353
+ Overall match: {match_percentage}%.
354
+
355
+ Write a detailed 3-4 sentence assessment for this Google applicant.
356
+ Start with "This candidate" and include:
357
+ 1. Specific strengths relating to Google's needs
358
+ 2. Technical skills evaluation
359
+ 3. Areas for improvement
360
+ 4. Overall Google fit assessment
361
+
362
+ This candidate
363
  """
364
 
365
  try:
366
+ # Generate the assessment using T5
367
  assessment_results = models['evaluator'](
368
  prompt,
369
+ max_length=300,
370
  do_sample=True,
371
+ temperature=0.7,
372
  num_return_sequences=3
373
  )
374
 
375
  # Find the best response
376
+ best_assessment = None
377
  for result in assessment_results:
378
  text = result['generated_text'].strip()
379
 
380
+ # Clean up and check if valid
381
+ text = re.sub(r'Generate Google candidate assessment.*?Overall match:.*?%\.', '', text, flags=re.DOTALL)
382
+ text = re.sub(r'Write a detailed.*?This candidate', 'This candidate', text, flags=re.DOTALL)
383
 
384
+ # Check if it's a good response
385
+ if text.lower().startswith("this candidate") and len(text) > 100 and "1." not in text and "2." not in text:
386
+ best_assessment = text
387
  break
388
 
389
+ # Use the best response or the first one if none were ideal
390
+ if best_assessment:
391
+ assessment = best_assessment
392
+ else:
393
+ # Use first response but clean it up
394
+ text = assessment_results[0]['generated_text']
395
+ text = re.sub(r'Generate Google candidate assessment.*?Overall match:.*?%\.', '', text, flags=re.DOTALL)
396
+ text = re.sub(r'Write a detailed.*?This candidate', 'This candidate', text, flags=re.DOTALL)
397
+
398
+ # Remove numbering if present
399
+ text = re.sub(r'\d\.\s', '', text)
400
+
401
+ if not text.lower().startswith("this candidate"):
402
+ text = "This candidate " + text
403
+
404
+ assessment = text
405
 
406
  except Exception as e:
407
+ # Fall back to manual assessment
408
+ print(f"Error in T5 assessment generation: {e}")
409
+ assessment = f"""This candidate demonstrates some skills relevant to Google, particularly in {top_category}. Their experience with {skills_text} could be valuable, though they would benefit from strengthening their {weak_category}. Based on the resume analysis, they appear to be a {match_percentage}% match for Google's requirements."""
410
 
411
  # Final cleanup
412
+ # Remove any remaining artifacts or formatting
413
+ assessment = re.sub(r'\n+', ' ', assessment)
414
+ assessment = re.sub(r'\s+', ' ', assessment)
415
  assessment = assessment.strip()
 
 
416
 
417
+ # Make sure percentages are consistent
418
+ assessment = re.sub(r'\b\d{1,2}%\b', f"{match_percentage}%", assessment)
419
+
420
+ # [Keep the return statement and rest of function the same]
421
 
422
  return assessment, match_percentage, category_details, execution_time
423
 
424
+
425
+ def generate_expert_assessment(resume_summary, match_percentage, category_details, found_skills):
426
  """
427
+ Generate a comprehensive expert assessment based on the resume analysis.
428
+ This is a specialized function to create high-quality, specific assessments.
429
  """
430
+ # Sort categories by score to identify top strengths and weaknesses
431
+ categories = list(category_details.keys())
432
+ categories.sort(key=lambda cat: category_details[cat]["adjusted_score"], reverse=True)
433
+
434
+ # Identify top strengths (top 2 categories)
435
+ top_strengths = categories[:2]
436
+
437
+ # Identify main weaknesses (bottom 2 categories, but only if score is below 50%)
438
+ weaknesses = [cat for cat in categories if category_details[cat]["adjusted_score"] < 50]
439
+
440
+ # Extract relevant skills for top strengths (up to 3 skills per strength)
441
+ strength_skills = []
442
+ for category in top_strengths:
443
+ matches = found_skills[category][:3] if found_skills[category] else []
444
+ strength_skills.extend(matches)
445
+
446
+ # Extract experience snippets from resume
447
+ experience_match = re.search(r'Previous Work Experience:(.*?)(?=\n\n|$)', resume_summary, re.DOTALL)
448
+ experience_text = experience_match.group(1) if experience_match else ""
449
+
450
+ # Find relevant company names or roles that might be impressive
451
+ company_pattern = r'\b(Google|Microsoft|Amazon|Apple|Facebook|Meta|Twitter|LinkedIn|Uber|Airbnb|Netflix|Oracle|IBM|Intel|Adobe|Salesforce)\b'
452
+ companies = re.findall(company_pattern, experience_text, re.IGNORECASE)
453
+
454
+ # Determine the expertise level based on score
455
+ if match_percentage >= 75:
456
+ expertise_level = "strong"
457
+ elif match_percentage >= 60:
458
+ expertise_level = "solid"
459
+ elif match_percentage >= 45:
460
+ expertise_level = "moderate"
461
  else:
462
+ expertise_level = "limited"
463
+
464
+ # Start building assessment
465
+ assessment = f"This candidate demonstrates {expertise_level} potential for Google, with particular strengths in "
466
+
467
+ # Add strengths with specific skills
468
+ if top_strengths:
469
+ strength_labels = []
470
+ for strength in top_strengths:
471
+ label = {"technical_skills": "technical programming",
472
+ "advanced_tech": "advanced technology",
473
+ "problem_solving": "problem-solving",
474
+ "innovation": "innovation",
475
+ "soft_skills": "collaboration and leadership"}[strength]
476
+ strength_labels.append(label)
477
+
478
+ assessment += f"{' and '.join(strength_labels)}. "
479
+
480
+ # Add specific skills if available
481
+ if strength_skills:
482
+ assessment += f"Their experience with {', '.join(strength_skills[:4])} "
483
+
484
+ # Add relevance to Google
485
+ if any(skill in ['machine learning', 'ai', 'python', 'java', 'c++', 'cloud'] for skill in strength_skills):
486
+ assessment += "directly aligns with Google's technical requirements. "
487
+ else:
488
+ assessment += "is relevant to Google's technology stack. "
489
+ else:
490
+ assessment += "few areas that align closely with Google's requirements. "
491
 
492
+ # Add context from work experience if relevant companies found
493
+ if companies:
494
+ unique_companies = list(set([c.lower() for c in companies]))
495
+ if len(unique_companies) > 1:
496
+ assessment += f"Their experience at companies like {', '.join(unique_companies[:2])} provides valuable industry context. "
497
+ else:
498
+ assessment += f"Their experience at {unique_companies[0]} provides relevant industry context. "
499
 
500
+ # Add weaknesses and improvement suggestions
501
+ if weaknesses:
502
+ assessment += "However, to improve their candidacy, they should strengthen their "
503
+
504
+ weakness_labels = []
505
+ for weakness in weaknesses[:2]: # Only mention top 2 weaknesses
506
+ label = {"technical_skills": "technical programming skills",
507
+ "advanced_tech": "knowledge of advanced technologies",
508
+ "problem_solving": "problem-solving capabilities",
509
+ "innovation": "innovation mindset",
510
+ "soft_skills": "teamwork and collaboration abilities"}[weakness]
511
+ weakness_labels.append(label)
512
+
513
+ assessment += f"{' and '.join(weakness_labels)}, "
514
+
515
+ # Add specific improvement suggestion
516
+ if "technical_skills" in weaknesses:
517
+ assessment += "particularly by building projects with modern languages like Python, Java, or Go. "
518
+ elif "advanced_tech" in weaknesses:
519
+ assessment += "ideally by gaining exposure to machine learning, cloud systems, or distributed computing. "
520
+ elif "problem_solving" in weaknesses:
521
+ assessment += "by practicing algorithmic problems and system design challenges. "
522
+ elif "innovation" in weaknesses:
523
+ assessment += "through projects that demonstrate creative thinking and novel solutions. "
524
+ elif "soft_skills" in weaknesses:
525
+ assessment += "by highlighting collaborative projects and leadership experiences. "
526
+
527
+ # Add final evaluation with match percentage
528
  if match_percentage >= 70:
529
+ assessment += f"Overall, this candidate shows good alignment with Google's culture of innovation and technical excellence, with a {match_percentage}% match to the company's requirements."
530
  elif match_percentage >= 50:
531
+ assessment += f"With these improvements, the candidate could become more competitive for Google positions, currently showing a {match_percentage}% match to the company's requirements."
532
  else:
533
+ assessment += f"Significant development in these areas would be needed before they could be considered a strong Google candidate, with a current match of {match_percentage}% to requirements."
534
 
535
  return assessment
536