CR7CAD commited on
Commit
3e9d890
Β·
verified Β·
1 Parent(s): ca31f44

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -67
app.py CHANGED
@@ -38,13 +38,11 @@ def load_models():
38
  # Load smaller summarization model for speed
39
  models['summarizer'] = pipeline("summarization", model="facebook/bart-large-cnn", max_length=130)
40
 
41
- # Load TinyLlama model for evaluation
42
  models['evaluator'] = pipeline(
43
- "text-generation",
44
- model="TinyLlama/TinyLlama-1.1B-Chat-v1.0",
45
- max_new_tokens=200,
46
- do_sample=True,
47
- temperature=0.7
48
  )
49
 
50
  return models
@@ -305,85 +303,94 @@ def summarize_resume_text(resume_text):
305
  return formatted_summary, execution_time
306
 
307
  #####################################
308
- # Function: Evaluate Google Fit with TinyLlama
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  #####################################
310
  @st.cache_data(show_spinner=False)
311
  def evaluate_google_fit(candidate_summary, _evaluator=None):
312
  """
313
- Use TinyLlama to evaluate how well the candidate matches with Google's requirements.
 
314
  """
315
  start_time = time.time()
316
 
317
  evaluator = _evaluator or models['evaluator']
318
 
319
- # Format the chat prompt for TinyLlama's chat format
320
- prompt = f"""<|im_start|>system
321
- You are an expert technical recruiter at Google. Your task is to evaluate how well a candidate's profile matches with Google's hiring requirements. Be focused and specific in your evaluation.
322
- <|im_end|>
323
-
324
- <|im_start|>user
325
- I need to evaluate if this candidate is a good fit for Google. Please:
326
- 1. Score the candidate's fit for Google from 0-100
327
- 2. Write a brief evaluation (2-3 sentences) explaining why they would or wouldn't be a good fit
328
- 3. Mention 1-2 specific strengths relevant to Google
329
- 4. Mention 1 specific area where they might need improvement to better fit Google's requirements
330
 
331
- Candidate Profile:
332
- {candidate_summary}
333
 
334
- Google's Requirements:
335
- {GOOGLE_DESCRIPTION}
336
- <|im_end|>
337
 
338
- <|im_start|>assistant
339
  """
340
 
341
- # Generate the response
342
- response = evaluator(prompt)[0]['generated_text']
343
 
344
- # Extract just the assistant's response after the prompt
345
- assistant_response_start = response.find("<|im_start|>assistant") + len("<|im_start|>assistant")
346
- assistant_response = response[assistant_response_start:].strip()
 
347
 
348
- # Remove any trailing tag if present
349
- if "<|im_end|>" in assistant_response:
350
- assistant_response = assistant_response.split("<|im_end|>")[0].strip()
351
 
352
- # Try to extract the score from the response
353
- score_match = re.search(r'(\d{1,3})/100|score:?\s*(\d{1,3})|rating:?\s*(\d{1,3})|suitability:?\s*(\d{1,3})',
354
- assistant_response.lower())
355
 
356
- if score_match:
357
- # Find the first group that matched and isn't None
358
- for group in score_match.groups():
359
- if group is not None:
360
- score = int(group)
361
- normalized_score = min(100, max(0, score)) / 100 # Ensure it's in 0-1 range
362
- break
363
- else:
364
- normalized_score = 0.5 # Default if no group was extracted
365
- else:
366
- # If no explicit score, try to infer from sentiments
367
- positive_words = ['excellent', 'perfect', 'outstanding', 'ideal', 'great', 'strong']
368
- negative_words = ['poor', 'inadequate', 'insufficient', 'lacks', 'mismatch', 'weak']
369
-
370
- positive_count = sum(assistant_response.lower().count(word) for word in positive_words)
371
- negative_count = sum(assistant_response.lower().count(word) for word in negative_words)
372
-
373
- if positive_count > negative_count * 2:
374
- normalized_score = 0.85
375
- elif positive_count > negative_count:
376
- normalized_score = 0.7
377
- elif negative_count > positive_count * 2:
378
- normalized_score = 0.3
379
- elif negative_count > positive_count:
380
- normalized_score = 0.4
381
- else:
382
- normalized_score = 0.5
383
 
384
  execution_time = time.time() - start_time
385
 
386
- return normalized_score, assistant_response, execution_time
387
 
388
  #####################################
389
  # Main Streamlit Interface - with Progress Reporting
@@ -453,7 +460,7 @@ if uploaded_file is not None and st.button("Analyze My Google Fit"):
453
  else:
454
  st.error(f"**Google Match Score:** {score_percent}% πŸ”")
455
 
456
- # Display the full evaluation
457
  st.markdown("### Feedback from Google AI Recruiter")
458
  st.markdown(evaluation)
459
 
@@ -469,9 +476,9 @@ if uploaded_file is not None and st.button("Analyze My Google Fit"):
469
  """)
470
  elif fit_score >= 0.60:
471
  st.markdown("""
472
- - Focus on strengthening the improvement areas mentioned in the evaluation
473
  - Work on projects that demonstrate your skills in Google's key technology areas
474
- - Consider taking additional courses in areas where Google has shown interest
475
  """)
476
  else:
477
  st.markdown("""
 
38
  # Load smaller summarization model for speed
39
  models['summarizer'] = pipeline("summarization", model="facebook/bart-large-cnn", max_length=130)
40
 
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
 
48
  return models
 
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
 
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
 
 
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("""