Linked_in_Enhancer_gradio / agents /analyzer_agent.py
Akshay Chame
Sync files from GitHub repository
5e5e890
raw
history blame
10.6 kB
# Profile Analysis Agent
import re
from typing import Dict, Any, List
from collections import Counter
class AnalyzerAgent:
"""Agent responsible for analyzing LinkedIn profiles and providing insights"""
def __init__(self):
self.action_words = [
'led', 'managed', 'developed', 'created', 'implemented', 'designed',
'built', 'improved', 'increased', 'reduced', 'optimized', 'delivered',
'achieved', 'launched', 'established', 'coordinated', 'executed'
]
def analyze_profile(self, profile_data: Dict[str, Any], job_description: str = "") -> Dict[str, Any]:
"""
Analyze a LinkedIn profile and provide comprehensive insights
Args:
profile_data (Dict[str, Any]): Extracted profile data
job_description (str): Optional job description for matching analysis
Returns:
Dict[str, Any]: Analysis results with scores and recommendations
"""
if not profile_data:
return self._empty_analysis()
try:
# Calculate completeness score
completeness_score = self._calculate_completeness(profile_data)
# Analyze keywords
keyword_analysis = self._analyze_keywords(profile_data, job_description)
# Assess content quality
content_quality = self._assess_content_quality(profile_data)
# Identify strengths and weaknesses
strengths = self._identify_strengths(profile_data)
weaknesses = self._identify_weaknesses(profile_data)
# Calculate job match if job description provided
job_match_score = 0
if job_description:
job_match_score = self._calculate_job_match(profile_data, job_description)
return {
'completeness_score': completeness_score,
'keyword_analysis': keyword_analysis,
'content_quality': content_quality,
'strengths': strengths,
'weaknesses': weaknesses,
'job_match_score': job_match_score,
'recommendations': self._generate_recommendations(profile_data, weaknesses),
'overall_rating': self._calculate_overall_rating(completeness_score, content_quality, job_match_score)
}
except Exception as e:
print(f"Error in profile analysis: {str(e)}")
return self._empty_analysis()
def _calculate_completeness(self, profile_data: Dict[str, Any]) -> float:
"""Calculate profile completeness percentage"""
score = 0
total_points = 10
# Basic information (2 points)
if profile_data.get('name'): score += 1
if profile_data.get('headline'): score += 1
# About section (2 points)
about = profile_data.get('about', '')
if about and len(about) > 50: score += 1
if about and len(about) > 200: score += 1
# Experience (2 points)
experience = profile_data.get('experience', [])
if len(experience) >= 1: score += 1
if len(experience) >= 2: score += 1
# Education (1 point)
if profile_data.get('education'): score += 1
# Skills (2 points)
skills = profile_data.get('skills', [])
if len(skills) >= 5: score += 1
if len(skills) >= 10: score += 1
# Location (1 point)
if profile_data.get('location'): score += 1
return (score / total_points) * 100
def _analyze_keywords(self, profile_data: Dict[str, Any], job_description: str) -> Dict[str, Any]:
"""Analyze keywords in profile vs job description"""
profile_text = self._extract_all_text(profile_data).lower()
# Extract common tech keywords
tech_keywords = [
'python', 'javascript', 'react', 'node.js', 'sql', 'mongodb',
'aws', 'docker', 'kubernetes', 'git', 'agile', 'scrum'
]
found_keywords = []
for keyword in tech_keywords:
if keyword.lower() in profile_text:
found_keywords.append(keyword)
# Analyze job description keywords if provided
missing_keywords = []
if job_description:
job_keywords = re.findall(r'\b[a-zA-Z]{3,}\b', job_description.lower())
job_keyword_freq = Counter(job_keywords)
for keyword, freq in job_keyword_freq.most_common(10):
if keyword not in profile_text and len(keyword) > 3:
missing_keywords.append(keyword)
return {
'found_keywords': found_keywords,
'missing_keywords': missing_keywords[:5], # Top 5 missing
'keyword_density': len(found_keywords)
}
def _assess_content_quality(self, profile_data: Dict[str, Any]) -> Dict[str, Any]:
"""Assess the quality of content"""
about_section = profile_data.get('about', '')
headline = profile_data.get('headline', '')
return {
'headline_length': len(headline),
'about_length': len(about_section),
'has_quantified_achievements': self._has_numbers(about_section),
'uses_action_words': self._has_action_words(about_section)
}
def _identify_strengths(self, profile_data: Dict[str, Any]) -> List[str]:
"""Identify profile strengths"""
strengths = []
if len(profile_data.get('experience', [])) >= 3:
strengths.append("Good work experience history")
if len(profile_data.get('skills', [])) >= 10:
strengths.append("Comprehensive skills list")
if len(profile_data.get('about', '')) > 200:
strengths.append("Detailed about section")
return strengths
def _identify_weaknesses(self, profile_data: Dict[str, Any]) -> List[str]:
"""Identify areas for improvement"""
weaknesses = []
if not profile_data.get('about') or len(profile_data.get('about', '')) < 100:
weaknesses.append("About section needs improvement")
if len(profile_data.get('skills', [])) < 5:
weaknesses.append("Limited skills listed")
if not self._has_numbers(profile_data.get('about', '')):
weaknesses.append("Lacks quantified achievements")
return weaknesses
def _calculate_job_match(self, profile_data: Dict[str, Any], job_description: str) -> float:
"""Calculate how well profile matches job description"""
if not job_description:
return 0
profile_text = self._extract_all_text(profile_data).lower()
job_text = job_description.lower()
# Extract keywords from job description
job_keywords = set(re.findall(r'\b[a-zA-Z]{4,}\b', job_text))
# Count matches
matches = 0
for keyword in job_keywords:
if keyword in profile_text:
matches += 1
return min((matches / len(job_keywords)) * 100, 100) if job_keywords else 0
def _extract_all_text(self, profile_data: Dict[str, Any]) -> str:
"""Extract all text from profile for analysis"""
text_parts = []
# Add basic info
text_parts.append(profile_data.get('headline', ''))
text_parts.append(profile_data.get('about', ''))
# Add experience descriptions
for exp in profile_data.get('experience', []):
text_parts.append(exp.get('description', ''))
text_parts.append(exp.get('title', ''))
# Add skills
text_parts.extend(profile_data.get('skills', []))
return ' '.join(text_parts)
def _has_numbers(self, text: str) -> bool:
"""Check if text contains numbers/metrics"""
return bool(re.search(r'\d+', text))
def _has_action_words(self, text: str) -> bool:
"""Check if text contains action words"""
text_lower = text.lower()
return any(word in text_lower for word in self.action_words)
def _generate_recommendations(self, profile_data: Dict[str, Any], weaknesses: List[str]) -> List[str]:
"""Generate specific recommendations based on analysis"""
recommendations = []
for weakness in weaknesses:
if "about section" in weakness.lower():
recommendations.append("Add a compelling about section with 150-300 words describing your expertise")
elif "skills" in weakness.lower():
recommendations.append("Add more relevant skills to reach at least 10 skills")
elif "quantified" in weakness.lower():
recommendations.append("Include specific numbers and metrics in your descriptions")
return recommendations
def _calculate_overall_rating(self, completeness: float, content_quality: Dict[str, Any], job_match: float) -> str:
"""Calculate overall profile rating"""
score = completeness * 0.4
# Add content quality score
if content_quality.get('has_quantified_achievements'):
score += 10
if content_quality.get('uses_action_words'):
score += 10
if content_quality.get('about_length', 0) > 150:
score += 10
# Add job match if available
if job_match > 0:
score += job_match * 0.3
if score >= 80:
return "Excellent"
elif score >= 60:
return "Good"
elif score >= 40:
return "Fair"
else:
return "Needs Improvement"
def _empty_analysis(self) -> Dict[str, Any]:
"""Return empty analysis structure"""
return {
'completeness_score': 0,
'keyword_analysis': {'found_keywords': [], 'missing_keywords': [], 'keyword_density': 0},
'content_quality': {'headline_length': 0, 'about_length': 0, 'has_quantified_achievements': False, 'uses_action_words': False},
'strengths': [],
'weaknesses': ['Profile data not available'],
'job_match_score': 0,
'recommendations': ['Please provide valid profile data'],
'overall_rating': 'Unknown'
}