Skip to content

Pro Scorer

ProScorer

ProScorer(ml_config=None)

Bases: BaseScorer

Professional ATS scorer with ML-powered semantic analysis.

The ProScorer provides comprehensive resume evaluation using machine learning models for semantic understanding. It evaluates multiple dimensions:

  • Keywords (15%): Semantic and fuzzy matching of job keywords
  • Skills (20%): Required and preferred skills matching
  • Experience (15%): Years of experience and job title relevance
  • Education (10%): Educational requirements matching
  • Certifications (10%): Required certifications
  • Location (5%): Geographic location matching
  • Job Title (10%): Relevance of past job titles
  • Achievements (10%): Semantic analysis of achievements
  • Summary (5%): Executive summary relevance

The scorer uses sentence transformers for semantic embeddings and spaCy for text analysis, enabling understanding of context and meaning beyond exact matches.

Attributes:

Name Type Description
ml_config

Configuration for ML models (embedding model, spaCy model, etc.)

embedding_model

Model for generating text embeddings

semantic_matcher

Matcher for semantic similarity calculations

text_analyzer

spaCy-based text analyzer

keyword_analyzer

Analyzer for keyword matching with semantic support

skills_analyzer

Analyzer for skills matching

experience_analyzer

Analyzer for work experience evaluation

education_analyzer

Analyzer for education matching

certification_analyzer

Analyzer for certification matching

location_analyzer

Analyzer for location matching

achievements_analyzer

Analyzer for achievements evaluation

weights

Dictionary mapping score categories to their weights

Example
from at_scorer.ml import MLConfig

# Use default config
scorer = ProScorer()

# Or customize ML config
config = MLConfig(
    embedding_model="all-mpnet-base-v2",
    use_gpu=True,
    similarity_threshold=0.75
)
scorer = ProScorer(ml_config=config)

result = scorer.score(resume_data, job_description)
print(f"Overall score: {result.overall_score}")
print(f"Breakdown: {result.breakdown}")
print(f"Recommendations: {result.recommendations}")

Initialize the ProScorer with ML models and analyzers.

Sets up all necessary ML models and analyzers based on the provided configuration. If no config is provided, uses default MLConfig settings.

Parameters:

Name Type Description Default
ml_config MLConfig | None

Optional ML configuration. If None, uses default MLConfig().

None
Source code in at_scorer/scorers/pro.py
def __init__(self, ml_config: MLConfig | None = None):
    """Initialize the ProScorer with ML models and analyzers.

    Sets up all necessary ML models and analyzers based on the provided configuration.
    If no config is provided, uses default MLConfig settings.

    Args:
        ml_config: Optional ML configuration. If None, uses default MLConfig().
    """
    self.ml_config = ml_config or MLConfig()
    self.embedding_model = EmbeddingModel(
        model_name=self.ml_config.embedding_model,
        device="cuda" if self.ml_config.use_gpu else None,
        cache_embeddings=self.ml_config.cache_embeddings,
    )
    self.semantic_matcher = SemanticMatcher(
        embedding_model=self.embedding_model, threshold=self.ml_config.similarity_threshold
    )
    self.text_analyzer = TextAnalyzer(model_name=self.ml_config.spacy_model)

    self.keyword_analyzer = KeywordAnalyzer(self.semantic_matcher)
    self.skills_analyzer = SkillsAnalyzer(self.semantic_matcher)
    self.experience_analyzer = ExperienceAnalyzer(self.semantic_matcher)
    self.education_analyzer = EducationAnalyzer(self.semantic_matcher)
    self.certification_analyzer = CertificationAnalyzer(self.semantic_matcher)
    self.location_analyzer = LocationAnalyzer(self.semantic_matcher)
    self.achievements_analyzer = AchievementsAnalyzer(self.semantic_matcher)

    self.weights = {
        "keyword": 0.15,
        "skills": 0.20,
        "experience": 0.15,
        "education": 0.10,
        "certification": 0.10,
        "location": 0.05,
        "job_title": 0.10,
        "achievements": 0.10,
        "summary": 0.05,
    }

Functions

score
score(resume, job)

Score a resume against a job description using comprehensive ML-powered analysis.

Performs multi-dimensional evaluation of the resume across 9 different categories using semantic understanding and traditional matching techniques. The final score is a weighted combination of all category scores.

Parameters:

Name Type Description Default
resume ResumeData

The resume data to be scored, containing all relevant sections.

required
job JobDescription

The job description to score against (structured or text-based).

required

Returns:

Type Description
ScoreResult

ScoreResult containing: - overall_score: Weighted score (0-100) combining all categories - breakdown: Detailed scores for each category (0-100 scale) - recommendations: Actionable suggestions for improvement - matched_keywords: Keywords semantically or exactly matched - matched_skills: Skills that match job requirements - missing_skills: Required skills not found in the resume

Note

The scoring process involves: 1. Normalizing the job description to structured format 2. Running multiple analyzers in parallel where possible 3. Calculating weighted overall score from category scores 4. Generating recommendations based on gaps

Source code in at_scorer/scorers/pro.py
def score(self, resume: ResumeData, job: JobDescription) -> ScoreResult:
    """Score a resume against a job description using comprehensive ML-powered analysis.

    Performs multi-dimensional evaluation of the resume across 9 different categories
    using semantic understanding and traditional matching techniques. The final score
    is a weighted combination of all category scores.

    Args:
        resume: The resume data to be scored, containing all relevant sections.
        job: The job description to score against (structured or text-based).

    Returns:
        ScoreResult containing:
            - overall_score: Weighted score (0-100) combining all categories
            - breakdown: Detailed scores for each category (0-100 scale)
            - recommendations: Actionable suggestions for improvement
            - matched_keywords: Keywords semantically or exactly matched
            - matched_skills: Skills that match job requirements
            - missing_skills: Required skills not found in the resume

    Note:
        The scoring process involves:
        1. Normalizing the job description to structured format
        2. Running multiple analyzers in parallel where possible
        3. Calculating weighted overall score from category scores
        4. Generating recommendations based on gaps
    """
    job_struct = self._normalize_job(job)
    resume_text = resume.aggregate_text()
    job_text = self._job_text(job_struct)

    keyword_score, matched_keywords, missing_keywords = self.keyword_analyzer.analyze(
        resume_text, job_struct.keywords
    )
    (
        skills_score,
        matched_skills,
        missing_skills,
        matched_preferred,
    ) = self.skills_analyzer.analyze(
        resume.skills, job_struct.required_skills, job_struct.preferred_skills
    )
    years_score, title_score = self.experience_analyzer.analyze(
        resume.work_experience, job_struct.required_experience_years, job_struct.title
    )
    education_score = self.education_analyzer.analyze(
        resume.education, job_struct.required_education
    )
    certification_score, matched_certs, missing_certs = self.certification_analyzer.analyze(
        resume.certifications, job_struct.required_certifications
    )
    location_str = None
    if resume.contact_information and resume.contact_information.location:
        loc = resume.contact_information.location
        parts = [loc.city, loc.state, loc.country]
        location_str = " ".join(p for p in parts if p)
    location_score = self.location_analyzer.analyze(location_str, job_struct.location)
    achievements_score = self.achievements_analyzer.analyze(
        self._collect_achievements(resume), job_text
    )
    summary_score = self.semantic_matcher.similarity(resume.executive_summary or "", job_text)

    scores = {
        "keyword": keyword_score,
        "skills": skills_score,
        "experience": years_score,
        "education": education_score,
        "certification": certification_score,
        "location": location_score,
        "job_title": title_score,
        "achievements": achievements_score,
        "summary": summary_score,
    }

    overall = weighted_score(scores, self.weights)
    breakdown = ScoreBreakdown(
        keyword_score=keyword_score * 100,
        skills_score=skills_score * 100,
        experience_score=years_score * 100,
        education_score=education_score * 100,
        certification_score=certification_score * 100,
        location_score=location_score * 100,
        job_title_score=title_score * 100,
        achievements_score=achievements_score * 100,
        summary_score=summary_score * 100,
    )

    recommendations = self._recommendations(
        missing_keywords, missing_skills, missing_certs, job_struct
    )

    return ScoreResult(
        overall_score=self._to_score_int(overall),
        breakdown=breakdown,
        recommendations=recommendations,
        matched_keywords=matched_keywords,
        matched_skills=matched_skills + matched_preferred,
        missing_skills=missing_skills,
    )