CR7CAD commited on
Commit
8e90008
Β·
verified Β·
1 Parent(s): de6503f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +127 -89
app.py CHANGED
@@ -41,7 +41,7 @@ def load_models():
41
  # Load T5-small model for evaluation
42
  models['evaluator'] = pipeline(
43
  "text2text-generation",
44
- model="microsoft/DialoGPT-small",
45
  max_length=200
46
  )
47
 
@@ -303,94 +303,121 @@ def summarize_resume_text(resume_text):
303
  return formatted_summary, execution_time
304
 
305
  #####################################
306
- # Function: Calculate Google Match Score
307
  #####################################
308
  def calculate_google_match_score(candidate_summary):
309
  """
310
- Calculate a match score based on skills and experience in the candidate summary
311
  compared with what Google requires.
 
 
 
 
 
312
  """
313
- # Key skills and keywords that Google values
314
- google_keywords = {
315
- "high_value": [
316
- "python", "java", "c++", "go", "javascript",
317
- "algorithms", "data structures", "system design",
318
- "artificial intelligence", "machine learning", "problem solving",
319
- "cloud computing", "cybersecurity", "ux/ui"
320
- ],
321
- "medium_value": [
322
- "react", "angular", "node.js", "sql", "nosql", "git",
323
- "agile", "scrum", "docker", "kubernetes", "aws", "azure",
324
- "analytics", "automation", "leadership", "teamwork"
325
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  }
327
 
328
  summary_lower = candidate_summary.lower()
329
 
330
- # Count occurrences of high and medium value keywords
331
- high_value_count = sum(summary_lower.count(keyword) for keyword in google_keywords["high_value"])
332
- medium_value_count = sum(summary_lower.count(keyword) for keyword in google_keywords["medium_value"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
 
334
- # Calculate a weighted score
335
- score = (high_value_count * 2 + medium_value_count) / (len(google_keywords["high_value"]) * 2 + len(google_keywords["medium_value"]))
336
 
337
- # Normalize to 0-1 range
338
- normalized_score = min(1.0, max(0.0, score * 2.5))
339
 
340
- return normalized_score
 
 
 
 
 
341
 
342
  #####################################
343
- # Function: Evaluate Google Fit with T5
344
  #####################################
345
  @st.cache_data(show_spinner=False)
346
- def evaluate_google_fit(candidate_summary, _evaluator=None):
347
  """
348
- Use T5-small model to evaluate how well the candidate matches with Google's requirements.
349
- Uses third-person tone in the evaluation.
350
  """
351
  start_time = time.time()
352
 
353
  evaluator = _evaluator or models['evaluator']
354
 
355
- # Calculate a match score
356
- match_score = calculate_google_match_score(candidate_summary)
357
- score_percent = int(match_score * 100)
 
358
 
359
- # Create a template for the T5 prompt
360
- # T5 works well with task prefixes
361
  prompt = f"""
362
- Evaluate in third-person tone if this candidate is a good fit for Google based on the resume summary and Google's requirements.
363
- Mention specific skills that match or don't match. Keep it concise.
364
-
365
- Resume Summary: {candidate_summary[:500]}
366
-
367
- Google Requirements: {GOOGLE_DESCRIPTION[:500]}
368
-
369
- Score: {score_percent}/100
370
  """
371
 
372
- # Generate the evaluation
373
- evaluation_result = evaluator(prompt)[0]['generated_text']
374
-
375
- # Ensure the output uses third-person tone
376
- # T5-small may not always follow instructions perfectly, so we'll check and adjust
377
- first_person_pronouns = ["i ", "i'm", "i am", "my ", "mine ", "we ", "our "]
378
- second_person_pronouns = ["you ", "your ", "yours "]
379
 
380
- evaluation_lower = evaluation_result.lower()
381
-
382
- # If the model used first or second person, prepend a third-person context
383
- if any(pronoun in evaluation_lower for pronoun in first_person_pronouns + second_person_pronouns):
384
- evaluation_result = f"The candidate {evaluation_result}"
385
-
386
- # Ensure evaluation starts with third-person phrasing if it doesn't already
387
- if not any(evaluation_result.lower().startswith(phrase) for phrase in
388
- ["this candidate", "the candidate", "candidate", "this applicant", "the applicant"]):
389
- evaluation_result = f"This candidate {evaluation_result}"
390
 
391
  execution_time = time.time() - start_time
392
 
393
- return match_score, evaluation_result, execution_time
394
 
395
  #####################################
396
  # Main Streamlit Interface - with Progress Reporting
@@ -398,10 +425,10 @@ Score: {score_percent}/100
398
  st.title("Google Resume Match Analyzer")
399
  st.markdown(
400
  """
401
- Upload your resume file in **.docx**, **.doc**, or **.txt** format to see how well the candidate matchs with Google's hiring requirements. The app performs the following tasks:
402
- 1. Extracts text from candidate's resume.
403
  2. Uses AI to generate a structured candidate summary.
404
- 3. Evaluates whether candidates fit for Google or not, providing a match score and specific feedback.
405
  """
406
  )
407
 
@@ -413,7 +440,7 @@ with st.expander("Google's Requirements", expanded=False):
413
  uploaded_file = st.file_uploader("Upload your resume (.docx, .doc, or .txt)", type=["docx", "doc", "txt"])
414
 
415
  # Process button with optimized flow
416
- if uploaded_file is not None and st.button("Analyze Google Fit"):
417
  # Create a placeholder for the progress bar
418
  progress_bar = st.progress(0)
419
  status_text = st.empty()
@@ -429,17 +456,18 @@ if uploaded_file is not None and st.button("Analyze Google Fit"):
429
  # Step 2: Generate summary
430
  status_text.text("Step 2/3: Analyzing resume and generating summary...")
431
  summary, summarization_time = summarize_resume_text(resume_text)
432
- progress_bar.progress(75)
433
 
434
  # Display summary
435
- st.subheader("Candidate Resume Summary")
436
  st.markdown(summary)
437
  st.info(f"Summary generated in {summarization_time:.2f} seconds")
438
 
439
- # Step 3: Evaluate Google fit
440
- status_text.text("Step 3/3: Evaluating your fit for Google...")
441
- fit_score, evaluation, evaluation_time = evaluate_google_fit(
442
- summary, _evaluator=models['evaluator']
 
443
  )
444
  progress_bar.progress(100)
445
 
@@ -449,40 +477,50 @@ if uploaded_file is not None and st.button("Analyze Google Fit"):
449
  # Display Google fit results
450
  st.subheader("Google Fit Assessment")
451
 
452
- # Display score with appropriate color and emoji
453
- score_percent = int(fit_score * 100)
454
- if fit_score >= 0.85:
455
- st.success(f"**Google Match Score:** {score_percent}% 🌟")
456
- elif fit_score >= 0.70:
457
- st.success(f"**Google Match Score:** {score_percent}% βœ…")
458
- elif fit_score >= 0.50:
459
- st.warning(f"**Google Match Score:** {score_percent}% ⚠️")
460
  else:
461
- st.error(f"**Google Match Score:** {score_percent}% πŸ”")
462
 
463
- # Display the evaluation in third-person tone
464
- st.markdown("### Feedback from Google AI Recruiter")
465
- st.markdown(evaluation)
466
-
467
- st.info(f"Evaluation completed in {evaluation_time:.2f} seconds")
 
 
 
 
468
 
469
  # Add potential next steps based on the score
470
  st.subheader("Recommended Next Steps")
471
- if fit_score >= 0.80:
 
 
 
 
472
  st.markdown("""
473
  - Consider applying for positions at Google that match your experience
474
  - Prepare for technical interviews by practicing algorithms and system design
475
  - Review Google's interview process and STAR method for behavioral questions
476
  """)
477
- elif fit_score >= 0.60:
478
- st.markdown("""
479
- - Focus on strengthening the areas mentioned in the evaluation
 
480
  - Work on projects that demonstrate your skills in Google's key technology areas
481
  - Consider taking additional courses in algorithms, system design, or other Google focus areas
482
  """)
483
  else:
484
- st.markdown("""
485
- - Build experience in areas matching Google's requirements
 
486
  - Develop projects showcasing problem-solving abilities and technical skills
487
  - Consider gaining more experience before applying, or target specific Google roles that better match your profile
488
  """)
 
41
  # Load T5-small model for evaluation
42
  models['evaluator'] = pipeline(
43
  "text2text-generation",
44
+ model="google-t5/t5-small",
45
  max_length=200
46
  )
47
 
 
303
  return formatted_summary, execution_time
304
 
305
  #####################################
306
+ # Function: Calculate Google Match Score - Detailed Breakdown
307
  #####################################
308
  def calculate_google_match_score(candidate_summary):
309
  """
310
+ Calculate a detailed match score breakdown based on skills and experience in the candidate summary
311
  compared with what Google requires.
312
+
313
+ Returns:
314
+ - overall_score: A normalized score between 0 and 1
315
+ - category_scores: A dictionary with scores for each category
316
+ - score_breakdown: A formatted string explanation of the scoring
317
  """
318
+ # Define categories that Google values with specific keywords
319
+ google_categories = {
320
+ "Technical Skills": {
321
+ "keywords": ["python", "java", "c++", "go", "javascript", "sql", "nosql",
322
+ "algorithms", "data structures", "system design"],
323
+ "weight": 0.35
324
+ },
325
+ "Advanced Technologies": {
326
+ "keywords": ["artificial intelligence", "machine learning", "cloud computing",
327
+ "ai", "ml", "cloud", "data science", "big data",
328
+ "tensorflow", "pytorch", "deep learning"],
329
+ "weight": 0.25
330
+ },
331
+ "Problem Solving": {
332
+ "keywords": ["problem solving", "algorithms", "analytical", "critical thinking",
333
+ "debugging", "troubleshooting", "optimization"],
334
+ "weight": 0.20
335
+ },
336
+ "Innovation & Creativity": {
337
+ "keywords": ["innovation", "creative", "creativity", "novel", "cutting-edge",
338
+ "research", "design thinking", "innovative"],
339
+ "weight": 0.10
340
+ },
341
+ "Teamwork & Leadership": {
342
+ "keywords": ["team", "leadership", "collaborate", "collaboration", "communication",
343
+ "mentoring", "lead", "coordinate", "agile", "scrum"],
344
+ "weight": 0.10
345
+ }
346
  }
347
 
348
  summary_lower = candidate_summary.lower()
349
 
350
+ # Calculate scores for each category
351
+ category_scores = {}
352
+ for category, details in google_categories.items():
353
+ keywords = details["keywords"]
354
+ max_possible = len(keywords) # Maximum possible matches
355
+
356
+ # Count matches (unique keywords found)
357
+ matches = sum(1 for keyword in keywords if keyword in summary_lower)
358
+
359
+ # Calculate category score (0-1 range)
360
+ if max_possible > 0:
361
+ raw_score = matches / max_possible
362
+ # Apply a curve to reward having more matches
363
+ category_scores[category] = min(1.0, raw_score * 1.5)
364
+ else:
365
+ category_scores[category] = 0
366
+
367
+ # Calculate weighted overall score
368
+ overall_score = sum(
369
+ score * google_categories[category]["weight"]
370
+ for category, score in category_scores.items()
371
+ )
372
 
373
+ # Ensure overall score is in 0-1 range
374
+ overall_score = min(1.0, max(0.0, overall_score))
375
 
376
+ # Create score breakdown explanation
377
+ score_breakdown = "**Score Breakdown by Category:**\n\n"
378
 
379
+ for category, score in category_scores.items():
380
+ percentage = int(score * 100)
381
+ weight = int(google_categories[category]["weight"] * 100)
382
+ score_breakdown += f"β€’ **{category}** ({weight}% of total): {percentage}%\n"
383
+
384
+ return overall_score, category_scores, score_breakdown
385
 
386
  #####################################
387
+ # Function: Generate Aspect-Based Feedback with T5
388
  #####################################
389
  @st.cache_data(show_spinner=False)
390
+ def generate_aspect_feedback(candidate_summary, category_scores, _evaluator=None):
391
  """
392
+ Use T5-small model to generate feedback on the candidate's strongest and weakest areas
393
+ for Google, based on the category scores.
394
  """
395
  start_time = time.time()
396
 
397
  evaluator = _evaluator or models['evaluator']
398
 
399
+ # Sort categories by score
400
+ sorted_categories = sorted(category_scores.items(), key=lambda x: x[1], reverse=True)
401
+ top_categories = sorted_categories[:2]
402
+ bottom_categories = sorted_categories[-2:]
403
 
404
+ # Create a prompt for T5
 
405
  prompt = f"""
406
+ Generate specific third-person feedback on the candidate's fit for Google.
407
+ Focus on these strengths: {', '.join([cat for cat, _ in top_categories])}.
408
+ And these improvement areas: {', '.join([cat for cat, _ in bottom_categories])}.
 
 
 
 
 
409
  """
410
 
411
+ # Generate focused feedback
412
+ feedback = evaluator(prompt)[0]['generated_text']
 
 
 
 
 
413
 
414
+ # Ensure third-person tone
415
+ if not any(feedback.lower().startswith(start) for start in ["the candidate", "this candidate"]):
416
+ feedback = f"This candidate {feedback}"
 
 
 
 
 
 
 
417
 
418
  execution_time = time.time() - start_time
419
 
420
+ return feedback, execution_time
421
 
422
  #####################################
423
  # Main Streamlit Interface - with Progress Reporting
 
425
  st.title("Google Resume Match Analyzer")
426
  st.markdown(
427
  """
428
+ Upload your resume file in **.docx**, **.doc**, or **.txt** format to see how well you match with Google's hiring requirements. The app performs the following tasks:
429
+ 1. Extracts text from your resume.
430
  2. Uses AI to generate a structured candidate summary.
431
+ 3. Evaluates your fit for Google across key hiring criteria with a detailed score breakdown.
432
  """
433
  )
434
 
 
440
  uploaded_file = st.file_uploader("Upload your resume (.docx, .doc, or .txt)", type=["docx", "doc", "txt"])
441
 
442
  # Process button with optimized flow
443
+ if uploaded_file is not None and st.button("Analyze My Google Fit"):
444
  # Create a placeholder for the progress bar
445
  progress_bar = st.progress(0)
446
  status_text = st.empty()
 
456
  # Step 2: Generate summary
457
  status_text.text("Step 2/3: Analyzing resume and generating summary...")
458
  summary, summarization_time = summarize_resume_text(resume_text)
459
+ progress_bar.progress(50)
460
 
461
  # Display summary
462
+ st.subheader("Your Resume Summary")
463
  st.markdown(summary)
464
  st.info(f"Summary generated in {summarization_time:.2f} seconds")
465
 
466
+ # Step 3: Calculate scores and generate feedback
467
+ status_text.text("Step 3/3: Calculating Google fit scores...")
468
+ overall_score, category_scores, score_breakdown = calculate_google_match_score(summary)
469
+ feedback, feedback_time = generate_aspect_feedback(
470
+ summary, category_scores, _evaluator=models['evaluator']
471
  )
472
  progress_bar.progress(100)
473
 
 
477
  # Display Google fit results
478
  st.subheader("Google Fit Assessment")
479
 
480
+ # Display overall score with appropriate color and emoji
481
+ score_percent = int(overall_score * 100)
482
+ if overall_score >= 0.85:
483
+ st.success(f"**Overall Google Match Score:** {score_percent}% 🌟")
484
+ elif overall_score >= 0.70:
485
+ st.success(f"**Overall Google Match Score:** {score_percent}% βœ…")
486
+ elif overall_score >= 0.50:
487
+ st.warning(f"**Overall Google Match Score:** {score_percent}% ⚠️")
488
  else:
489
+ st.error(f"**Overall Google Match Score:** {score_percent}% πŸ”")
490
 
491
+ # Display score breakdown
492
+ st.markdown("### Score Calculation")
493
+ st.markdown(score_breakdown)
494
+
495
+ # Display focused feedback
496
+ st.markdown("### Expert Assessment")
497
+ st.markdown(feedback)
498
+
499
+ st.info(f"Assessment completed in {feedback_time:.2f} seconds")
500
 
501
  # Add potential next steps based on the score
502
  st.subheader("Recommended Next Steps")
503
+
504
+ # Find the weakest categories
505
+ weakest_categories = sorted(category_scores.items(), key=lambda x: x[1])[:2]
506
+
507
+ if overall_score >= 0.80:
508
  st.markdown("""
509
  - Consider applying for positions at Google that match your experience
510
  - Prepare for technical interviews by practicing algorithms and system design
511
  - Review Google's interview process and STAR method for behavioral questions
512
  """)
513
+ elif overall_score >= 0.60:
514
+ improvement_areas = ", ".join([cat for cat, _ in weakest_categories])
515
+ st.markdown(f"""
516
+ - Focus on strengthening these areas: {improvement_areas}
517
  - Work on projects that demonstrate your skills in Google's key technology areas
518
  - Consider taking additional courses in algorithms, system design, or other Google focus areas
519
  """)
520
  else:
521
+ improvement_areas = ", ".join([cat for cat, _ in weakest_categories])
522
+ st.markdown(f"""
523
+ - Build experience in these critical areas: {improvement_areas}
524
  - Develop projects showcasing problem-solving abilities and technical skills
525
  - Consider gaining more experience before applying, or target specific Google roles that better match your profile
526
  """)